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;
98567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1);
995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
1005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[2] = msg[1];
1015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[2] &= ~0x04;
1025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
1035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msleep(5);
1045bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
1055bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		msg[1] |= 0x04;
1065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
1075bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
108a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky
109a72dd305f99f6c6e4eff01478ae53fc80ce98fb1Michael Krufky	return 0;
1105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
1115bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
112de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
113de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
114c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void set_audio(struct dvb_frontend *fe,
115c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		      struct analog_parameters *params)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1174e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
118910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	char* mode;
119910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
120c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	if (params->std & V4L2_STD_MN) {
121910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x01;
122910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "MN";
123c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_B) {
124910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x02;
125910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "B";
126c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_GH) {
127910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x04;
128910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "GH";
129c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_PAL_I) {
130910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x08;
131910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "I";
132c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_DK) {
133910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x10;
134910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "DK";
135c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_SECAM_L) {
136910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x20;
137910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "L";
138c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	} else if (params->std & V4L2_STD_SECAM_LC) {
139910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x40;
140910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "LC";
141910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	} else {
142910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		priv->tda8290_easy_mode = 0x10;
143910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		mode = "xx";
144910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	}
145910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
1469af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	if (params->mode == V4L2_TUNER_RADIO) {
1473f76cf8c8ed10da1ce50f821366d0dc590397069Michael Krufky		/* Set TDA8295 to FM radio; Start TDA8290 with MN values */
1483f76cf8c8ed10da1ce50f821366d0dc590397069Michael Krufky		priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01;
1499af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_dbg("setting to radio FM\n");
1509af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	} else {
1519af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_dbg("setting tda829x to system %s\n", mode);
1529af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	}
153910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky}
154910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
1554c27f1a4da4902c70b84a8bce66f8fe909fb829bMauro Carvalho Chehabstatic struct {
1569af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	unsigned char seq[2];
1579af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab} fm_mode[] = {
1589af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x01, 0x81} },	/* Put device into expert mode */
1599af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x03, 0x48} },	/* Disable NOTCH and VIDEO filters */
1609af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x04, 0x04} },	/* Disable color carrier filter (SSIF) */
1619af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x05, 0x04} },	/* ADC headroom */
1629af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x06, 0x10} },	/* group delay flat */
1639af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
1649af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x07, 0x00} },	/* use the same radio DTO values as a tda8295 */
1659af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x08, 0x00} },
1669af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x09, 0x80} },
1679af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0a, 0xda} },
1689af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0b, 0x4b} },
1699af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0c, 0x68} },
1709af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
1719af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x0d, 0x00} },	/* PLL off, no video carrier detect */
1729af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	{ { 0x14, 0x00} },	/* disable auto mute if no video */
1739af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab};
1749af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
175c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void tda8290_set_params(struct dvb_frontend *fe,
176c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky			       struct analog_parameters *params)
177910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky{
1784e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
1794e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky
180de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char soft_reset[]  = { 0x00, 0x00 };
181b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	unsigned char easy_mode[]   = { 0x01, priv->tda8290_easy_mode };
182de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char expert_mode[] = { 0x01, 0x80 };
1830157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char agc_out_on[]  = { 0x02, 0x00 };
184de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char gainset_off[] = { 0x28, 0x14 };
185de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char if_agc_spd[]  = { 0x0f, 0x88 };
186de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_6[]  = { 0x05, 0x04 };
187de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_9[]  = { 0x05, 0x02 };
188de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_head_12[] = { 0x05, 0x01 };
189de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char pll_bw_nom[]  = { 0x0d, 0x47 };
190de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char pll_bw_low[]  = { 0x0d, 0x27 };
191de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char gainset_2[]   = { 0x28, 0x64 };
192de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char agc_rst_on[]  = { 0x0e, 0x0b };
193de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char agc_rst_off[] = { 0x0e, 0x09 };
194de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char if_agc_set[]  = { 0x0f, 0x81 };
195de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_adc_sat  = 0x1a;
196de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_agc_stat = 0x1d;
197de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char addr_pll_stat = 0x1b;
198de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char adc_sat, agc_stat,
1999a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev		      pll_stat;
20058ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	int i;
201de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
202c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	set_audio(fe, params);
203910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
204ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	if (priv->cfg.config)
2057bff4b4d3ad2b9ff42b4087f409076035af1d165Hartmut Hackmann		tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
206db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
207db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
208db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
209de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	msleep(1);
210de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
2119af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	if (params->mode == V4L2_TUNER_RADIO) {
2129af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		unsigned char deemphasis[]  = { 0x13, 1 };
2139af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2149af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		/* FIXME: allow using a different deemphasis */
2159af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2169af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		if (deemphasis_50)
2179af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			deemphasis[1] = 2;
2189af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2199af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		for (i = 0; i < ARRAY_SIZE(fm_mode); i++)
2209af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2);
2219af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab
2229af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2);
2239af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	} else {
2249af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		expert_mode[1] = priv->tda8290_easy_mode + 0x80;
2259af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
2269af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
2279af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
2289af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		if (priv->tda8290_easy_mode & 0x60)
2299af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
2309af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		else
2319af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
2329af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab		tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
2339af0ef27a06f3e8976b90a4ed4758e25ea0f2df5Mauro Carvalho Chehab	}
234de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
235ecb71d262b0323981e07ce415da9b7adc917990aMauro Carvalho Chehab
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++) {
242567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&priv->i2c_props,
243567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &addr_pll_stat, 1, &pll_stat, 1);
24458ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		if (pll_stat & 0x80) {
245567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			tuner_i2c_xfer_send_recv(&priv->i2c_props,
246567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &addr_adc_sat, 1,
247567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &adc_sat, 1);
248567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			tuner_i2c_xfer_send_recv(&priv->i2c_props,
249567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &addr_agc_stat, 1,
250567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &agc_stat, 1);
25158ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
25258ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			break;
25358ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		} else {
25458ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			tuner_dbg("tda8290 not locked, no signal?\n");
25558ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann			msleep(100);
25658ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann		}
25758ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	}
258de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* adjust headroom resp. gain */
2594ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann	if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
2604ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann		tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
2614ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			   agc_stat, adc_sat, pll_stat & 0x80);
262db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
263de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msleep(100);
264567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&priv->i2c_props,
265567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &addr_agc_stat, 1, &agc_stat, 1);
266567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&priv->i2c_props,
267567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &addr_pll_stat, 1, &pll_stat, 1);
268de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if ((agc_stat > 115) || !(pll_stat & 0x80)) {
2694ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
2704ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann				   agc_stat, pll_stat & 0x80);
271746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky			if (priv->cfg.agcf)
2724e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky				priv->cfg.agcf(fe);
273de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msleep(100);
274567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			tuner_i2c_xfer_send_recv(&priv->i2c_props,
275567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &addr_agc_stat, 1,
276567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &agc_stat, 1);
277567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			tuner_i2c_xfer_send_recv(&priv->i2c_props,
278567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &addr_pll_stat, 1,
279567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab						 &pll_stat, 1);
280de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			if((agc_stat > 115) || !(pll_stat & 0x80)) {
281de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
282db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
283db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky				tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
284de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				msleep(100);
285de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			}
286de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
287de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
289de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* l/ l' deadlock? */
290b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	if(priv->tda8290_easy_mode & 0x60) {
291567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&priv->i2c_props,
292567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &addr_adc_sat, 1,
293567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &adc_sat, 1);
294567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&priv->i2c_props,
295567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &addr_pll_stat, 1,
296567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &pll_stat, 1);
297de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if ((adc_sat > 20) || !(pll_stat & 0x80)) {
2984ac95af9a0bdc33f18e6a7532ac5319b2d4ab8c2Hartmut Hackmann			tuner_dbg("trying to resolve SECAM L deadlock\n");
299db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
300de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msleep(40);
301db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
302de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
303de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
304586b0cab2516640fec4dffc3049c4d8bca188f89Mauro Carvalho Chehab
3054e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
306db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
309de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
310de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
3114e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_power(struct dvb_frontend *fe, int enable)
3125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3134e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3145bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
3155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
316567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
3175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3185bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3195bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x01;
3205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3215bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x03;
3225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3235bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3255bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3264e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
3275bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3284e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3295bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x01, 0x00 };
3305bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
331567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
3325bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3335bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3345bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
3355bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] = 0x00; /* reset active bit */
3375bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3385bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3395bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3405bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3414e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_set_video_std(struct dvb_frontend *fe)
3425bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3434e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3445bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
3455bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3465bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3475bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3484e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 1);
3495bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	msleep(20);
3504e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 0);
3515bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3525bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3535bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
3545bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3554e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
3565bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3574e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3585bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
3595bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
360567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
3615bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3625bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable)
3635bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] &= ~0x40;
3645bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
3655bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		buf[1] |= 0x40;
3665bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3675bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
3685bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3695bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3704e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
3715bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3724e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3735bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };
3745bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char set_gpio_val[]   = { 0x46, 0x00 };
3755bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
376567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props,
377567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab				 &set_gpio_cf[0], 1, &set_gpio_cf[1], 1);
378567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props,
379567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab				 &set_gpio_val[0], 1, &set_gpio_val[1], 1);
3805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3815bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
3825bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (enable) {
3845bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		set_gpio_cf[1]  |= 0x01; /* config GPIO_0 as Open Drain Out */
3855bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
3865bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
3875bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
3885bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
3895bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
3905bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3914e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic int tda8295_has_signal(struct dvb_frontend *fe)
3925bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
3934e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
3945bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
3955bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char hvpll_stat = 0x26;
3965bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char ret;
3975bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
398567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
3995bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	return (ret & 0x01) ? 65535 : 0;
4005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4015bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
4035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
404c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufkystatic void tda8295_set_params(struct dvb_frontend *fe,
405c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky			       struct analog_parameters *params)
4065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4074e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4095bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	unsigned char blanking_mode[]     = { 0x1d, 0x00 };
4105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
411c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	set_audio(fe, params);
4125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4137e28adb2497f6b873516163e2d29210c11777613Harvey Harrison	tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
4145bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4154e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 1);
4164e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 1);
4175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
418567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props,
419567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab				 &blanking_mode[0], 1, &blanking_mode[1], 1);
4205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4214e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_video_std(fe);
4225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4235bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	blanking_mode[1] = 0x03;
4245bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
4255bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	msleep(20);
4265bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4274e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_i2c_bridge(fe, 1);
4285bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4294e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (fe->ops.tuner_ops.set_analog_params)
430c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky		fe->ops.tuner_ops.set_analog_params(fe, params);
4315bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4325bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (priv->cfg.agcf)
4334e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky		priv->cfg.agcf(fe);
4345bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4354e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	if (tda8295_has_signal(fe))
4365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_dbg("tda8295 is locked\n");
4375bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	else
4385bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky		tuner_dbg("tda8295 not locked, no signal?\n");
4395bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4404e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_i2c_bridge(fe, 0);
4415bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4425bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4435bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky/*---------------------------------------------------------------------*/
4445bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4454e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic int tda8290_has_signal(struct dvb_frontend *fe)
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4474e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
449910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	unsigned char i2c_get_afc[1] = { 0x1B };
450910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	unsigned char afc = 0;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
452567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&priv->i2c_props,
453567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab				 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
454746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	return (afc & 0x80)? 65535:0;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
457de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
458de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4594e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_standby(struct dvb_frontend *fe)
460793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab{
4614e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
4624e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky
463de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char cb1[] = { 0x30, 0xD0 };
464de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8290_standby[] = { 0x00, 0x02 };
4650157a9cc727dec90a7d60ad254eb899a775685a9Hartmut Hackmann	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
466b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
467de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4684e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
4698c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8275A)
470de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		cb1[1] = 0x90;
471db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	i2c_transfer(priv->i2c_props.adap, &msg, 1);
4724e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
473db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
474db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
475793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab}
476793cf9e6a54c698e109a599c8b8e303658fcaae6Mauro Carvalho Chehab
4774e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_standby(struct dvb_frontend *fe)
4785bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
4794e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
4805bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4814e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 0);
4825bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
4835bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
4844e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_init_if(struct dvb_frontend *fe)
485de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
4864e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
487db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
488de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char set_VS[] = { 0x30, 0x6F };
48958ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	unsigned char set_GP00_CF[] = { 0x20, 0x01 };
490de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char set_GP01_CF[] = { 0x20, 0x0B };
491de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4927bff4b4d3ad2b9ff42b4087f409076035af1d165Hartmut Hackmann	if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
493db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
49458ef4f924cf2824ae198b1fec3eea1e4059a021cHartmut Hackmann	else
495db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
496db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
497de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann}
498de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
4994e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8295_init_if(struct dvb_frontend *fe)
5005bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
5014e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
5025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5035bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_adc_ctl[]       = { 0x33, 0x14 };
5045bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_adc_ctl2[]      = { 0x34, 0x00 };
5055bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg6[]      = { 0x3e, 0x63 };
5065bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg0[]      = { 0x38, 0x23 };
5075bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg7[]      = { 0x3f, 0x01 };
5085bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_pll_reg10[]     = { 0x42, 0x61 };
5095bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	static unsigned char set_gpio_reg0[]     = { 0x44, 0x0b };
5105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5114e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_power(fe, 1);
5125bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5134e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_easy_mode(fe, 0);
5144e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_set_video_std(fe);
5155bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5165bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
5175bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
5185bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
5195bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
5205bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
5215bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
5225bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
5235bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5244e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc1_out(fe, 0);
5254e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8295_agc2_out(fe, 0);
5265bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
5275bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
5284e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda8290_init_tuner(struct dvb_frontend *fe)
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5304e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
531de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8275_init[]  = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
5329a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev					  0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
533de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
5349a741ec9b87ac13f13a1dfcb05979d7c785d0755Nickolay V. Shmyrev					  0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
535b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
536c2f6f9d866d3ea25eebe32c6c51e47e5141669cfRicardo Cerqueira			      .buf=tda8275_init, .len = 14};
5378c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8275A)
538de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg.buf = tda8275a_init;
539de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
5404e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 1);
541db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	i2c_transfer(priv->i2c_props.adap, &msg, 1);
5424e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	tda8290_i2c_bridge(fe, 0);
543de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann}
544de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
545de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann/*---------------------------------------------------------------------*/
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5474e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufkystatic void tda829x_release(struct dvb_frontend *fe)
548024cf53089f7c8e58934407f07ca2a7b5bed3b06Michael Krufky{
549a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
550a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky
551006ed1ecf2c62659e5dd902350a7eb209b8a5257Michael Krufky	/* only try to release the tuner if we've
552006ed1ecf2c62659e5dd902350a7eb209b8a5257Michael Krufky	 * attached it from within this module */
553006ed1ecf2c62659e5dd902350a7eb209b8a5257Michael Krufky	if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
554a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky		if (fe->ops.tuner_ops.release)
555a4f263b587573f47cc6bc7ad85e5f650169d48f6Michael Krufky			fe->ops.tuner_ops.release(fe);
556024cf53089f7c8e58934407f07ca2a7b5bed3b06Michael Krufky
5574e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	kfree(fe->analog_demod_priv);
5584e9154b8a77d0f0f8f06857162823905612a50d7Michael Krufky	fe->analog_demod_priv = NULL;
559910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky}
560910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
561f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufkystatic struct tda18271_config tda829x_tda18271_config = {
562f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufky	.gate    = TDA18271_GATE_ANALOG,
563f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufky};
564f21e0d7f0513e743b14df3197fdeeb9a9b7edbb2Michael Krufky
5658c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufkystatic int tda829x_find_tuner(struct dvb_frontend *fe)
566de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann{
5678c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct tda8290_priv *priv = fe->analog_demod_priv;
568bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
569de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	int i, ret, tuners_found;
570de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	u32 tuner_addrs;
5718c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	u8 data;
5728c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
573de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
57431063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab	if (!analog_ops->i2c_gate_ctrl) {
57531063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab		printk(KERN_ERR "tda8290: no gate control were provided!\n");
57631063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab
5778c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		return -EINVAL;
57831063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab	}
579746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
580bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 1);
581db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
582de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* probe for tuner chip */
583de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	tuners_found = 0;
584de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	tuner_addrs = 0;
5858c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	for (i = 0x60; i <= 0x63; i++) {
586de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		msg.addr = i;
587db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
588de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		if (ret == 1) {
589de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			tuners_found++;
590de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			tuner_addrs = (tuner_addrs << 8) + i;
591de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
592de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
593de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	/* if there is more than one tuner, we expect the right one is
594de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	   behind the bridge and we choose the highest address that doesn't
595de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	   give a response now
596de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	 */
5978c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
598bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 0);
5998c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
6008c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (tuners_found > 1)
601de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		for (i = 0; i < tuners_found; i++) {
602de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			msg.addr = tuner_addrs  & 0xff;
603db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky			ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
6048c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			if (ret == 1)
605de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				tuner_addrs = tuner_addrs >> 8;
606de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann			else
607de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann				break;
608de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		}
6098c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
610de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	if (tuner_addrs == 0) {
6118c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_addrs = 0x60;
6128c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_info("could not clearly identify tuner address, "
6138c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			   "defaulting to %x\n", tuner_addrs);
614de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	} else {
615de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann		tuner_addrs = tuner_addrs & 0xff;
616910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_info("setting tuner address to %x\n", tuner_addrs);
617de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
618b208319993ceff7ebfcc6bb914fe94d29e48a891Michael Krufky	priv->tda827x_addr = tuner_addrs;
619de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	msg.addr = tuner_addrs;
620de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann
621bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 1);
622db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
623910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
6248c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (ret != 1) {
6258c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tuner_warn("tuner access failed!\n");
62631063814400cd37d47f5f58a96e58596196f04b0Mauro Carvalho Chehab		analog_ops->i2c_gate_ctrl(fe, 0);
6278c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		return -EREMOTEIO;
628de48eebce8b63dbae7272ee80f4fe0eaddb61278Hartmut Hackmann	}
629746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
630255b5113b4ed683898a24e381155c081f03411f7Michael Krufky	if ((data == 0x83) || (data == 0x84)) {
6318c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver |= TDA18271;
632adcc4b3e75c5f0293806766bcc5ed0bb62d5cda0Michael Krufky		tda829x_tda18271_config.config = priv->cfg.config;
633a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky		dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
634a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky			   priv->i2c_props.adap, &tda829x_tda18271_config);
6358c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	} else {
6368c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		if ((data & 0x3c) == 0)
6378c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			priv->ver |= TDA8275;
6388c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		else
6398c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky			priv->ver |= TDA8275A;
6407fd8b263678ab8430b49c99976ade681f8a78439Michael Krufky
641a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky		dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
642a07c8779fd212dcbad886a2824ef5f8b42cd5a06Michael Krufky			   priv->i2c_props.adap, &priv->cfg);
6437bff4b4d3ad2b9ff42b4087f409076035af1d165Hartmut Hackmann		priv->cfg.switch_addr = priv->i2c_props.addr;
6448c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	}
6456881647cce09931f3d787ab83b5250436427ceb9Michael Krufky	if (fe->ops.tuner_ops.init)
6466881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		fe->ops.tuner_ops.init(fe);
64763c254805e38bad4c64b5f5b0e135a2a357fa0bfMichael Krufky
6486881647cce09931f3d787ab83b5250436427ceb9Michael Krufky	if (fe->ops.tuner_ops.sleep)
6496881647cce09931f3d787ab83b5250436427ceb9Michael Krufky		fe->ops.tuner_ops.sleep(fe);
65063c254805e38bad4c64b5f5b0e135a2a357fa0bfMichael Krufky
651bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky	analog_ops->i2c_gate_ctrl(fe, 0);
652746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky
653746d9732dbd5b95c3ba36230e2814fa2c391a311Michael Krufky	return 0;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6555bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
656f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufkystatic int tda8290_probe(struct tuner_i2c_props *i2c_props)
657f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky{
658f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky#define TDA8290_ID 0x89
659567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	u8 reg = 0x1f, id;
660567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	struct i2c_msg msg_read[] = {
66189a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
66289a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
663567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	};
664f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
665f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* detect tda8290 */
666567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
66789a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
668567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			       __func__, reg);
669567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		return -ENODEV;
670567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	}
671f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
672567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	if (id == TDA8290_ID) {
673ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		if (debug)
674f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
6757e28adb2497f6b873516163e2d29210c11777613Harvey Harrison			       __func__, i2c_adapter_id(i2c_props->adap),
676f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       i2c_props->addr);
677f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
678f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	}
6791f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
680f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky}
681f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
682f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufkystatic int tda8295_probe(struct tuner_i2c_props *i2c_props)
683f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky{
684f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky#define TDA8295_ID 0x8a
68519f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky#define TDA8295C2_ID 0x8b
686567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	u8 reg = 0x2f, id;
687567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	struct i2c_msg msg_read[] = {
68889a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
68989a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
690567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	};
691f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
69289a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson	/* detect tda8295 */
693567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
69489a8969afa300c202066c23cc5cc9e42eb81967cJarod Wilson		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
695567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			       __func__, reg);
696567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		return -ENODEV;
697567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	}
698f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
699567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	if ((id & 0xfe) == TDA8295_ID) {
700ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		if (debug)
70119f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n",
702567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab			       __func__, (id == TDA8295_ID) ?
70319f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			       "tda8295c1" : "tda8295c2",
70419f8a6c37eead7e93660813c8873ab3e387ccb63Michael Krufky			       i2c_adapter_id(i2c_props->adap),
705f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky			       i2c_props->addr);
706f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
707f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	}
708f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
7091f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
710f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky}
711f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
712bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufkystatic struct analog_demod_ops tda8290_ops = {
713c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	.set_params     = tda8290_set_params,
7148c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.has_signal     = tda8290_has_signal,
7158c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.standby        = tda8290_standby,
7168c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.release        = tda829x_release,
7178c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.i2c_gate_ctrl  = tda8290_i2c_bridge,
7188c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky};
7198c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
720bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufkystatic struct analog_demod_ops tda8295_ops = {
721c7919d520f4c9a064ae14bc4dd170c4c12ead2afMichael Krufky	.set_params     = tda8295_set_params,
7228c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.has_signal     = tda8295_has_signal,
7238c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.standby        = tda8295_standby,
7248c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.release        = tda829x_release,
7258c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	.i2c_gate_ctrl  = tda8295_i2c_bridge,
7268c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky};
7278c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
728ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkystruct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
729ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky				    struct i2c_adapter *i2c_adap, u8 i2c_addr,
730ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky				    struct tda829x_config *cfg)
7315bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky{
7325bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	struct tda8290_priv *priv = NULL;
733ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	char *name;
7348c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
7355bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
7365bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	if (priv == NULL)
737ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		return NULL;
7388c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	fe->analog_demod_priv = priv;
7395bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
740ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	priv->i2c_props.addr     = i2c_addr;
741ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	priv->i2c_props.adap     = i2c_adap;
7422756665c28a7d2e25d92745195b5171866e12da9Michael Krufky	priv->i2c_props.name     = "tda829x";
743d7cba043d7ec840d67bd5143779d1febe7d83407Michael Krufky	if (cfg)
744ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		priv->cfg.config         = cfg->lna_cfg;
7455bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
746f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8290_probe(&priv->i2c_props) == 0) {
7478c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver = TDA8290;
748bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		memcpy(&fe->ops.analog_ops, &tda8290_ops,
749bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		       sizeof(struct analog_demod_ops));
7505bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
7518c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky
752f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if (tda8295_probe(&priv->i2c_props) == 0) {
7538c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		priv->ver = TDA8295;
754bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		memcpy(&fe->ops.analog_ops, &tda8295_ops,
755bc3e5c7fc20d3c09667067878fb7a55dd9fc041dMichael Krufky		       sizeof(struct analog_demod_ops));
7565bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky	}
7575bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
7589d700a0696ae241380e8ca833bb5a358620d33f6Mauro Carvalho Chehab	if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) {
7599d700a0696ae241380e8ca833bb5a358620d33f6Mauro Carvalho Chehab		tda8295_power(fe, 1);
7609d700a0696ae241380e8ca833bb5a358620d33f6Mauro Carvalho Chehab		if (tda829x_find_tuner(fe) < 0)
7619d700a0696ae241380e8ca833bb5a358620d33f6Mauro Carvalho Chehab			goto fail;
76247ab285a960ac456506297c93322ab13c3522f5aMauro Carvalho Chehab	}
7635bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
764ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	switch (priv->ver) {
765c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky	case TDA8290:
766c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		name = "tda8290";
767c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		break;
768c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky	case TDA8295:
769c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		name = "tda8295";
770c90762799c42df203fc2c9c1a2ac39f154f8facaMichael Krufky		break;
771ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA8275:
772ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+75";
773ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
774ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA8275:
775ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+75";
776ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
777ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA8275A:
778ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+75a";
779ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
780ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA8275A:
781ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+75a";
782ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
783ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8290 | TDA18271:
784ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8290+18271";
785ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
786ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	case TDA8295 | TDA18271:
787ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		name = "tda8295+18271";
788ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		break;
789ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	default:
790ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		goto fail;
791ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	}
792ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	tuner_info("type set to %s\n", name);
793ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky
7940f2ce9834246519e483e89dbc7225fe1fcbd30a8Michael Krufky	fe->ops.analog_ops.info.name = name;
7950f2ce9834246519e483e89dbc7225fe1fcbd30a8Michael Krufky
7968c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	if (priv->ver & TDA8290) {
797439b72b69e4992e9ec34b74304f0fa95623934ebMichael Krufky		if (priv->ver & (TDA8275 | TDA8275A))
798439b72b69e4992e9ec34b74304f0fa95623934ebMichael Krufky			tda8290_init_tuner(fe);
7998c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8290_init_if(fe);
8008c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky	} else if (priv->ver & TDA8295)
8018c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael Krufky		tda8295_init_if(fe);
8025bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky
803ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	return fe;
804fa746aee336fedfe25e6945e5967399966948420Michael Krufky
805fa746aee336fedfe25e6945e5967399966948420Michael Krufkyfail:
8069d700a0696ae241380e8ca833bb5a358620d33f6Mauro Carvalho Chehab	memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops));
8079d700a0696ae241380e8ca833bb5a358620d33f6Mauro Carvalho Chehab
808fa746aee336fedfe25e6945e5967399966948420Michael Krufky	tda829x_release(fe);
809ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky	return NULL;
8105bea1cd3871351d70cc7624af138f8aa68b7be77Michael Krufky}
8118c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael KrufkyEXPORT_SYMBOL_GPL(tda829x_attach);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
813ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufkyint tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
81495736034df751631657140aebe677e67d7522867Hartmut Hackmann{
815910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	struct tuner_i2c_props i2c_props = {
816ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		.adap = i2c_adap,
817ab1660503ac3af7febfcf987648509b484d4fedaMichael Krufky		.addr = i2c_addr,
818910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	};
819db8a695658cda21eacfa2a5e3b15e8964bfb93efMichael Krufky
82044fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char soft_reset[]   = { 0x00, 0x00 };
82144fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char easy_mode_b[]  = { 0x01, 0x02 };
82244fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char easy_mode_g[]  = { 0x01, 0x04 };
82344fd06fa9002c42b367c152594cc95b7632c081dHartmut Hackmann	unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
82495736034df751631657140aebe677e67d7522867Hartmut Hackmann	unsigned char addr_dto_lsb = 0x07;
82595736034df751631657140aebe677e67d7522867Hartmut Hackmann	unsigned char data;
826a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky#define PROBE_BUFFER_SIZE 8
827a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	unsigned char buf[PROBE_BUFFER_SIZE];
828a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	int i;
829a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky
830a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	/* rule out tda9887, which would return the same byte repeatedly */
831567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&i2c_props,
832567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab				 soft_reset, 1, buf, PROBE_BUFFER_SIZE);
833a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
834bbe1e0ba527a18e1ddda2eabb9da369e5bcf556eMichael Krufky		if (buf[i] != buf[0])
835bbe1e0ba527a18e1ddda2eabb9da369e5bcf556eMichael Krufky			break;
836a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	}
837a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky
838a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	/* all bytes are equal, not a tda829x - probably a tda9887 */
839a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky	if (i == PROBE_BUFFER_SIZE)
840a818e1c8f7fcb42866a8630c508caddaa8edb331Michael Krufky		return -ENODEV;
84195736034df751631657140aebe677e67d7522867Hartmut Hackmann
842f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	if ((tda8290_probe(&i2c_props) == 0) ||
843f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	    (tda8295_probe(&i2c_props) == 0))
844f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky		return 0;
845f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky
846f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael Krufky	/* fall back to old probing method */
847910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
848910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
849567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab	tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1);
85095736034df751631657140aebe677e67d7522867Hartmut Hackmann	if (data == 0) {
851910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
852910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
853567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab		tuner_i2c_xfer_send_recv(&i2c_props,
854567aba0b7997dad5fe3fb4aeb174ee9018df8c5bMauro Carvalho Chehab					 &addr_dto_lsb, 1, &data, 1);
85595736034df751631657140aebe677e67d7522867Hartmut Hackmann		if (data == 0x7b) {
85695736034df751631657140aebe677e67d7522867Hartmut Hackmann			return 0;
85795736034df751631657140aebe677e67d7522867Hartmut Hackmann		}
85895736034df751631657140aebe677e67d7522867Hartmut Hackmann	}
859910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky	tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
8601f3a4e328549cb85aa032c4ee5dfda7886754154Michael Krufky	return -ENODEV;
86195736034df751631657140aebe677e67d7522867Hartmut Hackmann}
862f1f32849d65ab1eacfedbabb624876ac06c1af9fMichael KrufkyEXPORT_SYMBOL_GPL(tda829x_probe);
863910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
8648c125f2ceb3ec1ba01e96fffd8558ef163b40fe8Michael KrufkyMODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
8655bea1cd3871351d70cc7624af138f8aa68b7be77Michael KrufkyMODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
866910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael KrufkyMODULE_LICENSE("GPL");
867910bb3e3c5a5d8ed5028846728efc6a375d200ebMichael Krufky
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Overrides for Emacs so that we follow Linus's tabbing style.
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ---------------------------------------------------------------------------
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Local variables:
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * c-basic-offset: 8
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * End:
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
875