1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for Infineon tua6100 pll.
5 * (c) 2006 Andrew de Quincey
7 * Based on code found in budget-av.c, which has the following:
8 * Compiled from various sources by Michael Hunold <michael@mihu.de>
10 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
11 * Andrew de Quincey <adq_dvb@lidskialf.net>
13 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
15 * Copyright (C) 1999-2002 Ralph Metzler
16 * & Marcus Metzler for convergence integrated media GmbH
19 #include <linux/slab.h>
20 #include <linux/module.h>
21 #include <linux/dvb/frontend.h>
22 #include <asm/types.h>
29 struct i2c_adapter
*i2c
;
33 static void tua6100_release(struct dvb_frontend
*fe
)
35 kfree(fe
->tuner_priv
);
36 fe
->tuner_priv
= NULL
;
39 static int tua6100_sleep(struct dvb_frontend
*fe
)
41 struct tua6100_priv
*priv
= fe
->tuner_priv
;
43 u8 reg0
[] = { 0x00, 0x00 };
44 struct i2c_msg msg
= { .addr
= priv
->i2c_address
, .flags
= 0, .buf
= reg0
, .len
= 2 };
46 if (fe
->ops
.i2c_gate_ctrl
)
47 fe
->ops
.i2c_gate_ctrl(fe
, 1);
48 if ((ret
= i2c_transfer (priv
->i2c
, &msg
, 1)) != 1) {
49 printk("%s: i2c error\n", __func__
);
51 if (fe
->ops
.i2c_gate_ctrl
)
52 fe
->ops
.i2c_gate_ctrl(fe
, 0);
54 return (ret
== 1) ? 0 : ret
;
57 static int tua6100_set_params(struct dvb_frontend
*fe
)
59 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
60 struct tua6100_priv
*priv
= fe
->tuner_priv
;
63 u8 reg0
[] = { 0x00, 0x00 };
64 u8 reg1
[] = { 0x01, 0x00, 0x00, 0x00 };
65 u8 reg2
[] = { 0x02, 0x00, 0x00 };
66 struct i2c_msg msg0
= { .addr
= priv
->i2c_address
, .flags
= 0, .buf
= reg0
, .len
= 2 };
67 struct i2c_msg msg1
= { .addr
= priv
->i2c_address
, .flags
= 0, .buf
= reg1
, .len
= 4 };
68 struct i2c_msg msg2
= { .addr
= priv
->i2c_address
, .flags
= 0, .buf
= reg2
, .len
= 3 };
75 if (c
->frequency
< 2000000)
81 if (c
->frequency
< 1630000)
88 if (c
->frequency
>= 1525000)
92 reg2
[1] = (_R_VAL
>> 8) & 0x03;
94 if (c
->frequency
< 1455000)
96 else if (c
->frequency
< 1630000)
102 * The N divisor ratio (note: c->frequency is in kHz, but we
105 prediv
= (c
->frequency
* _R_VAL
) / (_ri
/ 1000);
106 div
= prediv
/ _P_VAL
;
107 reg1
[1] |= (div
>> 9) & 0x03;
109 reg1
[3] = (div
<< 7);
110 priv
->frequency
= ((div
* _P_VAL
) * (_ri
/ 1000)) / _R_VAL
;
112 // Finally, calculate and store the value for A
113 reg1
[3] |= (prediv
- (div
*_P_VAL
)) & 0x7f;
119 if (fe
->ops
.i2c_gate_ctrl
)
120 fe
->ops
.i2c_gate_ctrl(fe
, 1);
121 if (i2c_transfer(priv
->i2c
, &msg0
, 1) != 1)
124 if (fe
->ops
.i2c_gate_ctrl
)
125 fe
->ops
.i2c_gate_ctrl(fe
, 1);
126 if (i2c_transfer(priv
->i2c
, &msg2
, 1) != 1)
129 if (fe
->ops
.i2c_gate_ctrl
)
130 fe
->ops
.i2c_gate_ctrl(fe
, 1);
131 if (i2c_transfer(priv
->i2c
, &msg1
, 1) != 1)
134 if (fe
->ops
.i2c_gate_ctrl
)
135 fe
->ops
.i2c_gate_ctrl(fe
, 0);
140 static int tua6100_get_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
142 struct tua6100_priv
*priv
= fe
->tuner_priv
;
143 *frequency
= priv
->frequency
;
147 static const struct dvb_tuner_ops tua6100_tuner_ops
= {
149 .name
= "Infineon TUA6100",
150 .frequency_min_hz
= 950 * MHz
,
151 .frequency_max_hz
= 2150 * MHz
,
152 .frequency_step_hz
= 1 * MHz
,
154 .release
= tua6100_release
,
155 .sleep
= tua6100_sleep
,
156 .set_params
= tua6100_set_params
,
157 .get_frequency
= tua6100_get_frequency
,
160 struct dvb_frontend
*tua6100_attach(struct dvb_frontend
*fe
, int addr
, struct i2c_adapter
*i2c
)
162 struct tua6100_priv
*priv
= NULL
;
165 struct i2c_msg msg
[] = { { .addr
= addr
, .flags
= 0, .buf
= b1
, .len
= 1 },
166 { .addr
= addr
, .flags
= I2C_M_RD
, .buf
= b2
, .len
= 1 } };
169 if (fe
->ops
.i2c_gate_ctrl
)
170 fe
->ops
.i2c_gate_ctrl(fe
, 1);
171 ret
= i2c_transfer (i2c
, msg
, 2);
172 if (fe
->ops
.i2c_gate_ctrl
)
173 fe
->ops
.i2c_gate_ctrl(fe
, 0);
178 priv
= kzalloc(sizeof(struct tua6100_priv
), GFP_KERNEL
);
182 priv
->i2c_address
= addr
;
185 memcpy(&fe
->ops
.tuner_ops
, &tua6100_tuner_ops
, sizeof(struct dvb_tuner_ops
));
186 fe
->tuner_priv
= priv
;
189 EXPORT_SYMBOL(tua6100_attach
);
191 MODULE_DESCRIPTION("DVB tua6100 driver");
192 MODULE_AUTHOR("Andrew de Quincey");
193 MODULE_LICENSE("GPL");