tda8290.c revision 5a0e3ad6af8660be21ca98a971cd00f331318c05
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>
245a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
267f6adeaf2d8800b66c5dd6c2cf2622dfdd68bd31Hans Verkuil#include <linux/videodev2.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
369af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehabstatic int deemphasis_50;
37b450b92e162a454b82fea6373c83e447e28ce4d6Henk Vergonetmodule_param(deemphasis_50, int, 0644);
389af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho ChehabMODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis");
399af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---------------------------------------------------------------------- */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufkystruct tda8290_priv {
43db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	struct tuner_i2c_props i2c_props;
44db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
45b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char tda8290_easy_mode;
46746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
47b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char tda827x_addr;
488c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
498c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	unsigned char ver;
508c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8290   1
518c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8295   2
528c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8275   4
538c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA8275A  8
548c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky#define TDA18271 16
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	struct tda827x_config cfg;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
59de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufkystatic int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
62de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
634e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
64db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
65de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char  enable[2] = { 0x21, 0xC0 };
660157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char disable[2] = { 0x21, 0x00 };
67de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char *msg;
68a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
69a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	if (close) {
70de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg = enable;
71db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
72de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		/* let the bridge stabilize */
73de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msleep(20);
74de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	} else {
75de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg = disable;
76db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
77de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
78a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
79a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	return 0;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufkystatic int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
844e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
865bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char  enable[2] = { 0x45, 0xc1 };
875bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char disable[2] = { 0x46, 0x00 };
885bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[3] = { 0x45, 0x01, 0x00 };
895bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char *msg;
90a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
915bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (close) {
925bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg = enable;
935bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
945bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		/* let the bridge stabilize */
955bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msleep(20);
965bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	} else {
975bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg = disable;
985bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);
995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);
1005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
1015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[2] = msg[1];
1025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[2] &= ~0x04;
1035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
1045bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msleep(5);
1055bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
1065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg[1] |= 0x04;
1075bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
1085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
109a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
110a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	return 0;
1115bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
1125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
113de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
114de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
115c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void set_audio(struct dvb_frontend *fe,
116c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		      struct analog_parameters *params)
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1184e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
119910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	char* mode;
120910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
121c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	if (params->std & V4L2_STD_MN) {
122910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x01;
123910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "MN";
124c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_B) {
125910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x02;
126910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "B";
127c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_GH) {
128910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x04;
129910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "GH";
130c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_PAL_I) {
131910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x08;
132910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "I";
133c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_DK) {
134910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x10;
135910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "DK";
136c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_SECAM_L) {
137910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x20;
138910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "L";
139c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_SECAM_LC) {
140910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x40;
141910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "LC";
142910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	} else {
143910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x10;
144910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "xx";
145910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	}
146910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
1479af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	if (params->mode == V4L2_TUNER_RADIO) {
1483f76cf8c8ed10da1ce50f821366d0dc590397069Michael Krufky		/* Set TDA8295 to FM radio; Start TDA8290 with MN values */
1493f76cf8c8ed10da1ce50f821366d0dc590397069Michael Krufky		priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01;
1509af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_dbg("setting to radio FM\n");
1519af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	} else {
1529af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_dbg("setting tda829x to system %s\n", mode);
1539af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	}
154910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky}
155910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
1564c27f1a4da4902c70b84a8bce66f8fe909fb829bMauro Carvalho Chehabstatic struct {
1579af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	unsigned char seq[2];
1589af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab} fm_mode[] = {
1599af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x01, 0x81} },	/* Put device into expert mode */
1609af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x03, 0x48} },	/* Disable NOTCH and VIDEO filters */
1619af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x04, 0x04} },	/* Disable color carrier filter (SSIF) */
1629af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x05, 0x04} },	/* ADC headroom */
1639af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x06, 0x10} },	/* group delay flat */
1649af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
1659af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x07, 0x00} },	/* use the same radio DTO values as a tda8295 */
1669af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x08, 0x00} },
1679af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x09, 0x80} },
1689af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0a, 0xda} },
1699af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0b, 0x4b} },
1709af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0c, 0x68} },
1719af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
1729af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0d, 0x00} },	/* PLL off, no video carrier detect */
1739af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x14, 0x00} },	/* disable auto mute if no video */
1749af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab};
1759af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
176c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void tda8290_set_params(struct dvb_frontend *fe,
177c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky			       struct analog_parameters *params)
178910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky{
1794e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
1804e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky
181de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char soft_reset[]  = { 0x00, 0x00 };
182b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char easy_mode[]   = { 0x01, priv->tda8290_easy_mode };
183de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char expert_mode[] = { 0x01, 0x80 };
1840157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char agc_out_on[]  = { 0x02, 0x00 };
185de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char gainset_off[] = { 0x28, 0x14 };
186de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char if_agc_spd[]  = { 0x0f, 0x88 };
187de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_6[]  = { 0x05, 0x04 };
188de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_9[]  = { 0x05, 0x02 };
189de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_12[] = { 0x05, 0x01 };
190de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char pll_bw_nom[]  = { 0x0d, 0x47 };
191de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char pll_bw_low[]  = { 0x0d, 0x27 };
192de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char gainset_2[]   = { 0x28, 0x64 };
193de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char agc_rst_on[]  = { 0x0e, 0x0b };
194de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char agc_rst_off[] = { 0x0e, 0x09 };
195de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char if_agc_set[]  = { 0x0f, 0x81 };
196de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_adc_sat  = 0x1a;
197de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_agc_stat = 0x1d;
198de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_pll_stat = 0x1b;
199de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_sat, agc_stat,
2009a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev		      pll_stat;
20158ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	int i;
202de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
203c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	set_audio(fe, params);
204910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
205ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	if (priv->cfg.config)
2067bff4b4d3ad2b9ff42b4087f409076035af1d165Hartmut Hackmann		tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
207db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
208db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
209db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
210de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	msleep(1);
211de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
2129af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	if (params->mode == V4L2_TUNER_RADIO) {
2139af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		unsigned char deemphasis[]  = { 0x13, 1 };
2149af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2159af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		/* FIXME: allow using a different deemphasis */
2169af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2179af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		if (deemphasis_50)
2189af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			deemphasis[1] = 2;
2199af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2209af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		for (i = 0; i < ARRAY_SIZE(fm_mode); i++)
2219af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2);
2229af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2239af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2);
2249af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	} else {
2259af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		expert_mode[1] = priv->tda8290_easy_mode + 0x80;
2269af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
2279af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
2289af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
2299af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		if (priv->tda8290_easy_mode & 0x60)
2309af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
2319af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		else
2329af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
2339af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
2349af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	}
235de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
2364e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
237746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
2384e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (fe->ops.tuner_ops.set_analog_params)
239c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		fe->ops.tuner_ops.set_analog_params(fe, params);
240746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
24158ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	for (i = 0; i < 3; i++) {
242db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
243db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
24458ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		if (pll_stat & 0x80) {
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_agc_stat, 1);
248db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
24958ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
25058ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			break;
25158ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		} else {
25258ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			tuner_dbg("tda8290 not locked, no signal?\n");
25358ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			msleep(100);
25458ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		}
25558ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	}
256de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* adjust headroom resp. gain */
2574ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann	if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
2584ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann		tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
2594ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			   agc_stat, adc_sat, pll_stat & 0x80);
260db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
261de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msleep(100);
262db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
263db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
264db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
265db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
266de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if ((agc_stat > 115) || !(pll_stat & 0x80)) {
2674ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
2684ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann				   agc_stat, pll_stat & 0x80);
269746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky			if (priv->cfg.agcf)
2704e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky				priv->cfg.agcf(fe);
271de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msleep(100);
272db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);
273db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);
274db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
275db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
276de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			if((agc_stat > 115) || !(pll_stat & 0x80)) {
277de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
278db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
279db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky				tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
280de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				msleep(100);
281de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			}
282de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
283de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
285de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* l/ l' deadlock? */
286b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	if(priv->tda8290_easy_mode & 0x60) {
287db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);
288db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);
289db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);
290db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);
291de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if ((adc_sat > 20) || !(pll_stat & 0x80)) {
2924ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			tuner_dbg("trying to resolve SECAM L deadlock\n");
293db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
294de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msleep(40);
295db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
296de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
297de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
298586b0cab2516640fec4dffc3049c4d8bca188f89Mauro Carvalho Chehab
2994e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
300db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
303de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
304de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
3054e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_power(struct dvb_frontend *fe, int enable)
3065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3074e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
3095bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
3115bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
3125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3135bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3145bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x01;
3155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3165bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x03;
3175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3185bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3195bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3214e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
3225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3234e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x01, 0x00 };
3255bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3265bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
3275bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
3285bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3295bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3305bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
3315bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3325bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x00; /* reset active bit */
3335bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3345bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3355bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3374e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_set_video_std(struct dvb_frontend *fe)
3385bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3394e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3405bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
3415bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3425bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3435bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3444e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 1);
3455bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	msleep(20);
3464e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 0);
3475bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3485bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3495bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
3505bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3514e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
3525bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3534e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3545bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
3555bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3565bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);
3575bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);
3585bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3595bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3605bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] &= ~0x40;
3615bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3625bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] |= 0x40;
3635bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3645bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3655bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3665bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3674e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
3685bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3694e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3705bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };
3715bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char set_gpio_val[]   = { 0x46, 0x00 };
3725bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3735bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);
3745bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);
3755bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);
3765bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);
3775bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3785bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
3795bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable) {
3815bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		set_gpio_cf[1]  |= 0x01; /* config GPIO_0 as Open Drain Out */
3825bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
3835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
3845bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
3855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
3865bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3875bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3884e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic int tda8295_has_signal(struct dvb_frontend *fe)
3895bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3904e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3915bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3925bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char hvpll_stat = 0x26;
3935bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char ret;
3945bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3955bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);
3965bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);
3975bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	return (ret & 0x01) ? 65535 : 0;
3985bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
4015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
402c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void tda8295_set_params(struct dvb_frontend *fe,
403c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky			       struct analog_parameters *params)
4045bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4054e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4075bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char blanking_mode[]     = { 0x1d, 0x00 };
4085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
409c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	set_audio(fe, params);
4105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4117e28adb2497f6b873516163e2d29210c11777613Harvey Harrison	tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
4125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4134e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 1);
4144e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 1);
4155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4165bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);
4175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);
4185bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4194e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_video_std(fe);
4205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4215bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	blanking_mode[1] = 0x03;
4225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
4235bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	msleep(20);
4245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4254e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_i2c_bridge(fe, 1);
4265bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4274e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (fe->ops.tuner_ops.set_analog_params)
428c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		fe->ops.tuner_ops.set_analog_params(fe, params);
4295bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4305bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (priv->cfg.agcf)
4314e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky		priv->cfg.agcf(fe);
4325bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4334e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (tda8295_has_signal(fe))
4345bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_dbg("tda8295 is locked\n");
4355bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
4365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_dbg("tda8295 not locked, no signal?\n");
4375bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4384e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_i2c_bridge(fe, 0);
4395bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4405bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4415bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
4425bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4434e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic int tda8290_has_signal(struct dvb_frontend *fe)
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4454e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
447910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	unsigned char i2c_get_afc[1] = { 0x1B };
448910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	unsigned char afc = 0;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
450910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
451910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);
452746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	return (afc & 0x80)? 65535:0;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
455de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
456de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4574e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_standby(struct dvb_frontend *fe)
458793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab{
4594e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4604e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky
461de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char cb1[] = { 0x30, 0xD0 };
462de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8290_standby[] = { 0x00, 0x02 };
4630157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
464b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
465de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4664e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
4678c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8275A)
468de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		cb1[1] = 0x90;
469db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	i2c_transfer(priv->i2c_props.adap, &msg, 1);
4704e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
471db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
472db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
473793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab}
474793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab
4754e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_standby(struct dvb_frontend *fe)
4765bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4774e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
4785bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4794e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 0);
4805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4815bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4824e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_init_if(struct dvb_frontend *fe)
483de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
4844e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
485db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
486de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char set_VS[] = { 0x30, 0x6F };
48758ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	unsigned char set_GP00_CF[] = { 0x20, 0x01 };
488de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char set_GP01_CF[] = { 0x20, 0x0B };
489de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4907bff4b4d3ad2b9ff42b4087f409076035af1d165Hartmut Hackmann	if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
491db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
49258ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	else
493db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
494db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
495de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann}
496de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4974e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_init_if(struct dvb_frontend *fe)
4985bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4994e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
5005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_adc_ctl[]       = { 0x33, 0x14 };
5025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_adc_ctl2[]      = { 0x34, 0x00 };
5035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg6[]      = { 0x3e, 0x63 };
5045bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg0[]      = { 0x38, 0x23 };
5055bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg7[]      = { 0x3f, 0x01 };
5065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg10[]     = { 0x42, 0x61 };
5075bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_gpio_reg0[]     = { 0x44, 0x0b };
5085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5094e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 1);
5105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5114e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 0);
5124e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_video_std(fe);
5135bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5145bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
5155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
5165bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
5175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
5185bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
5195bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
5205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
5215bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5224e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 0);
5234e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc2_out(fe, 0);
5245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
5255bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5264e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_init_tuner(struct dvb_frontend *fe)
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5284e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
529de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8275_init[]  = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
5309a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev					  0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
531de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
5329a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev					  0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
533b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
534c2f6f9d866d3ea25eebe32c6c51e47e5141669cfRicardo Cerqueira			      .buf=tda8275_init, .len = 14};
5358c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8275A)
536de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg.buf = tda8275a_init;
537de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
5384e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
539db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	i2c_transfer(priv->i2c_props.adap, &msg, 1);
5404e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
541de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann}
542de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
543de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5454e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda829x_release(struct dvb_frontend *fe)
546024cf53089f7c8e58934407f07ca2a7b5bed3b06Michael Krufky{
547a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
548a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky
549006ed1ecf2c62659e5dd902350a7eb209b8a5257Michael Krufky	/* only try to release the tuner if we've
550006ed1ecf2c62659e5dd902350a7eb209b8a5257Michael Krufky	 * attached it from within this module */
551006ed1ecf2c62659e5dd902350a7eb209b8a5257Michael Krufky	if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
552a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky		if (fe->ops.tuner_ops.release)
553a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky			fe->ops.tuner_ops.release(fe);
554024cf53089f7c8e58934407f07ca2a7b5bed3b06Michael Krufky
5554e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	kfree(fe->analog_demod_priv);
5564e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	fe->analog_demod_priv = NULL;
557910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky}
558910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
559f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufkystatic struct tda18271_config tda829x_tda18271_config = {
560f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufky	.gate    = TDA18271_GATE_ANALOG,
561f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufky};
562f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufky
5638c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufkystatic int tda829x_find_tuner(struct dvb_frontend *fe)
564de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
5658c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
566bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
567de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	int i, ret, tuners_found;
568de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	u32 tuner_addrs;
5698c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	u8 data;
5708c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
571de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
57231063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab	if (!analog_ops->i2c_gate_ctrl) {
57331063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab		printk(KERN_ERR "tda8290: no gate control were provided!\n");
57431063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab
5758c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		return -EINVAL;
57631063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab	}
577746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
578bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 1);
579db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
580de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* probe for tuner chip */
581de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	tuners_found = 0;
582de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	tuner_addrs = 0;
5838c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	for (i = 0x60; i <= 0x63; i++) {
584de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg.addr = i;
585db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
586de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if (ret == 1) {
587de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			tuners_found++;
588de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			tuner_addrs = (tuner_addrs << 8) + i;
589de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
590de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
591de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* if there is more than one tuner, we expect the right one is
592de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	   behind the bridge and we choose the highest address that doesn't
593de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	   give a response now
594de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	 */
5958c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
596bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 0);
5978c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
5988c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (tuners_found > 1)
599de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		for (i = 0; i < tuners_found; i++) {
600de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msg.addr = tuner_addrs  & 0xff;
601db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
6028c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			if (ret == 1)
603de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				tuner_addrs = tuner_addrs >> 8;
604de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			else
605de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				break;
606de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
6078c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
608de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	if (tuner_addrs == 0) {
6098c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_addrs = 0x60;
6108c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_info("could not clearly identify tuner address, "
6118c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			   "defaulting to %x\n", tuner_addrs);
612de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	} else {
613de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		tuner_addrs = tuner_addrs & 0xff;
614910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_info("setting tuner address to %x\n", tuner_addrs);
615de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
616b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	priv->tda827x_addr = tuner_addrs;
617de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	msg.addr = tuner_addrs;
618de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
619bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 1);
620db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
621910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
6228c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (ret != 1) {
6238c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_warn("tuner access failed!\n");
62431063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab		analog_ops->i2c_gate_ctrl(fe, 0);
6258c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		return -EREMOTEIO;
626de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
627746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
628255b5113b4ed683898a24e381155c081f03411f7Michael Krufky	if ((data == 0x83) || (data == 0x84)) {
6298c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver |= TDA18271;
630adcc4b3e75c5f0293806766bcc5ed0bb62d5cda0Michael Krufky		tda829x_tda18271_config.config = priv->cfg.config;
631a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky		dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
632a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky			   priv->i2c_props.adap, &tda829x_tda18271_config);
6338c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	} else {
6348c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		if ((data & 0x3c) == 0)
6358c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			priv->ver |= TDA8275;
6368c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		else
6378c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			priv->ver |= TDA8275A;
6387fd8b263678ab8430b49c99976ade681f8a78439Michael Krufky
639a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky		dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
640a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky			   priv->i2c_props.adap, &priv->cfg);
6417bff4b4d3ad2b9ff42b4087f409076035af1d165Hartmut Hackmann		priv->cfg.switch_addr = priv->i2c_props.addr;
6428c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	}
6436881647cce09931f3d787ab83b5250436427ceb9Michael Krufky	if (fe->ops.tuner_ops.init)
6446881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		fe->ops.tuner_ops.init(fe);
64563c254805e38bad4c64b5f5b0e135a2a357fa0bfMichael Krufky
6466881647cce09931f3d787ab83b5250436427ceb9Michael Krufky	if (fe->ops.tuner_ops.sleep)
6476881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		fe->ops.tuner_ops.sleep(fe);
64863c254805e38bad4c64b5f5b0e135a2a357fa0bfMichael Krufky
649bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 0);
650746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
651746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	return 0;
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6535bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
654f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufkystatic int tda8290_probe(struct tuner_i2c_props *i2c_props)
655f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky{
656f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky#define TDA8290_ID 0x89
657f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	unsigned char tda8290_id[] = { 0x1f, 0x00 };
658f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
659f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* detect tda8290 */
660f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);
661f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);
662f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
663f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8290_id[1] == TDA8290_ID) {
664ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		if (debug)
665f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
6667e28adb2497f6b873516163e2d29210c11777613Harvey Harrison			       __func__, i2c_adapter_id(i2c_props->adap),
667f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       i2c_props->addr);
668f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
669f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	}
670f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
6711f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
672f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky}
673f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
674f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufkystatic int tda8295_probe(struct tuner_i2c_props *i2c_props)
675f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky{
676f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky#define TDA8295_ID 0x8a
67719f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky#define TDA8295C2_ID 0x8b
678f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	unsigned char tda8295_id[] = { 0x2f, 0x00 };
679f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
680f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* detect tda8295 */
681f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);
682f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);
683f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
68419f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky	if ((tda8295_id[1] & 0xfe) == TDA8295_ID) {
685ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		if (debug)
68619f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n",
68719f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			       __func__, (tda8295_id[1] == TDA8295_ID) ?
68819f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			       "tda8295c1" : "tda8295c2",
68919f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			       i2c_adapter_id(i2c_props->adap),
690f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       i2c_props->addr);
691f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
692f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	}
693f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
6941f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
695f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky}
696f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
697bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufkystatic struct analog_demod_ops tda8290_ops = {
698c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	.set_params     = tda8290_set_params,
6998c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.has_signal     = tda8290_has_signal,
7008c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.standby        = tda8290_standby,
7018c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.release        = tda829x_release,
7028c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.i2c_gate_ctrl  = tda8290_i2c_bridge,
7038c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky};
7048c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
705bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufkystatic struct analog_demod_ops tda8295_ops = {
706c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	.set_params     = tda8295_set_params,
7078c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.has_signal     = tda8295_has_signal,
7088c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.standby        = tda8295_standby,
7098c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.release        = tda829x_release,
7108c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.i2c_gate_ctrl  = tda8295_i2c_bridge,
7118c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky};
7128c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
713ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkystruct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
714ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky				    struct i2c_adapter *i2c_adap, u8 i2c_addr,
715ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky				    struct tda829x_config *cfg)
7165bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
7175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	struct tda8290_priv *priv = NULL;
718ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	char *name;
7198c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
7205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
7215bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (priv == NULL)
722ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		return NULL;
7238c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	fe->analog_demod_priv = priv;
7245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
725ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	priv->i2c_props.addr     = i2c_addr;
726ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	priv->i2c_props.adap     = i2c_adap;
7272756665c28a7d2e25d92745195b5171866e12da9Michael Krufky	priv->i2c_props.name     = "tda829x";
728d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky	if (cfg)
729ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		priv->cfg.config         = cfg->lna_cfg;
7305bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
731f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8290_probe(&priv->i2c_props) == 0) {
7328c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver = TDA8290;
733bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		memcpy(&fe->ops.analog_ops, &tda8290_ops,
734bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		       sizeof(struct analog_demod_ops));
7355bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
7368c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
737f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8295_probe(&priv->i2c_props) == 0) {
7388c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver = TDA8295;
739bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		memcpy(&fe->ops.analog_ops, &tda8295_ops,
740bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		       sizeof(struct analog_demod_ops));
7415bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
7425bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
743c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky	if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) &&
744c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky	    (tda829x_find_tuner(fe) < 0))
745fa746aee336fedfe25e6945e5967399966948420Michael Krufky		goto fail;
7465bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
747ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	switch (priv->ver) {
748c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky	case TDA8290:
749c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		name = "tda8290";
750c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		break;
751c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky	case TDA8295:
752c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		name = "tda8295";
753c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		break;
754ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA8275:
755ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+75";
756ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
757ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA8275:
758ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+75";
759ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
760ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA8275A:
761ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+75a";
762ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
763ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA8275A:
764ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+75a";
765ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
766ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA18271:
767ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+18271";
768ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
769ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA18271:
770ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+18271";
771ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
772ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	default:
773ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		goto fail;
774ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	}
775ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	tuner_info("type set to %s\n", name);
776ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky
7770f2ce9834246519e483e89dbc7225fe1fcbd30a8Michael Krufky	fe->ops.analog_ops.info.name = name;
7780f2ce9834246519e483e89dbc7225fe1fcbd30a8Michael Krufky
7798c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8290) {
780439b72b69e4992e9ec34b74304f0fa95623934ebMichael Krufky		if (priv->ver & (TDA8275 | TDA8275A))
781439b72b69e4992e9ec34b74304f0fa95623934ebMichael Krufky			tda8290_init_tuner(fe);
7828c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8290_init_if(fe);
7838c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	} else if (priv->ver & TDA8295)
7848c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8295_init_if(fe);
7855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
786ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	return fe;
787fa746aee336fedfe25e6945e5967399966948420Michael Krufky
788fa746aee336fedfe25e6945e5967399966948420Michael Krufkyfail:
789fa746aee336fedfe25e6945e5967399966948420Michael Krufky	tda829x_release(fe);
790ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	return NULL;
7915bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
7928c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael KrufkyEXPORT_SYMBOL_GPL(tda829x_attach);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
794ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkyint tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
79595736034df751631657140aebe677e67d7522867Hartmut Hackmann{
796910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	struct tuner_i2c_props i2c_props = {
797ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		.adap = i2c_adap,
798ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		.addr = i2c_addr,
799910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	};
800db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
80144fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char soft_reset[]   = { 0x00, 0x00 };
80244fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char easy_mode_b[]  = { 0x01, 0x02 };
80344fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char easy_mode_g[]  = { 0x01, 0x04 };
80444fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
80595736034df751631657140aebe677e67d7522867Hartmut Hackmann	unsigned char addr_dto_lsb = 0x07;
80695736034df751631657140aebe677e67d7522867Hartmut Hackmann	unsigned char data;
807a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky#define PROBE_BUFFER_SIZE 8
808a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	unsigned char buf[PROBE_BUFFER_SIZE];
809a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	int i;
810a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky
811a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	/* rule out tda9887, which would return the same byte repeatedly */
812a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);
813a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);
814a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
815bbe1e0ba527a18e1ddda2eabb9da369e5bcf556eMichael Krufky		if (buf[i] != buf[0])
816bbe1e0ba527a18e1ddda2eabb9da369e5bcf556eMichael Krufky			break;
817a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	}
818a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky
819a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	/* all bytes are equal, not a tda829x - probably a tda9887 */
820a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	if (i == PROBE_BUFFER_SIZE)
821a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky		return -ENODEV;
82295736034df751631657140aebe677e67d7522867Hartmut Hackmann
823f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if ((tda8290_probe(&i2c_props) == 0) ||
824f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	    (tda8295_probe(&i2c_props) == 0))
825f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
826f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
827f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* fall back to old probing method */
828910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
829910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
830910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
831910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_recv(&i2c_props, &data, 1);
83295736034df751631657140aebe677e67d7522867Hartmut Hackmann	if (data == 0) {
833910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
834910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
835910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);
836910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_recv(&i2c_props, &data, 1);
83795736034df751631657140aebe677e67d7522867Hartmut Hackmann		if (data == 0x7b) {
83895736034df751631657140aebe677e67d7522867Hartmut Hackmann			return 0;
83995736034df751631657140aebe677e67d7522867Hartmut Hackmann		}
84095736034df751631657140aebe677e67d7522867Hartmut Hackmann	}
841910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
8421f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
84395736034df751631657140aebe677e67d7522867Hartmut Hackmann}
844f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael KrufkyEXPORT_SYMBOL_GPL(tda829x_probe);
845910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
8468c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael KrufkyMODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
8475bea1cd3871351d70cc7624af138f8aa68b7be77Michael KrufkyMODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
848910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael KrufkyMODULE_LICENSE("GPL");
849910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overrides for Emacs so that we follow Linus's tabbing style.
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ---------------------------------------------------------------------------
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local variables:
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * c-basic-offset: 8
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * End:
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
857