2 TDA8261 8PSK/QPSK tuner driver
3 Copyright (C) Manu Abraham (abraham.manu@gmail.com)
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <linux/init.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
25 #include "dvb_frontend.h"
28 struct tda8261_state
{
29 struct dvb_frontend
*fe
;
30 struct i2c_adapter
*i2c
;
31 const struct tda8261_config
*config
;
38 static int tda8261_read(struct tda8261_state
*state
, u8
*buf
)
40 const struct tda8261_config
*config
= state
->config
;
42 struct i2c_msg msg
= { .addr
= config
->addr
, .flags
= I2C_M_RD
,.buf
= buf
, .len
= 2 };
44 if ((err
= i2c_transfer(state
->i2c
, &msg
, 1)) != 1)
45 printk("%s: read error, err=%d\n", __func__
, err
);
50 static int tda8261_write(struct tda8261_state
*state
, u8
*buf
)
52 const struct tda8261_config
*config
= state
->config
;
54 struct i2c_msg msg
= { .addr
= config
->addr
, .flags
= 0, .buf
= buf
, .len
= 4 };
56 if ((err
= i2c_transfer(state
->i2c
, &msg
, 1)) != 1)
57 printk("%s: write error, err=%d\n", __func__
, err
);
62 static int tda8261_get_status(struct dvb_frontend
*fe
, u32
*status
)
64 struct tda8261_state
*state
= fe
->tuner_priv
;
70 if ((err
= tda8261_read(state
, &result
)) < 0) {
71 printk("%s: I/O Error\n", __func__
);
74 if ((result
>> 6) & 0x01) {
75 printk("%s: Tuner Phase Locked\n", __func__
);
82 static const u32 div_tab
[] = { 2000, 1000, 500, 250, 125 }; /* kHz */
83 static const u8 ref_div
[] = { 0x00, 0x01, 0x02, 0x05, 0x07 };
85 static int tda8261_get_state(struct dvb_frontend
*fe
,
86 enum tuner_param param
,
87 struct tuner_state
*tstate
)
89 struct tda8261_state
*state
= fe
->tuner_priv
;
93 case DVBFE_TUNER_FREQUENCY
:
94 tstate
->frequency
= state
->frequency
;
96 case DVBFE_TUNER_BANDWIDTH
:
97 tstate
->bandwidth
= 40000000; /* FIXME! need to calculate Bandwidth */
100 printk("%s: Unknown parameter (param=%d)\n", __func__
, param
);
108 static int tda8261_set_state(struct dvb_frontend
*fe
,
109 enum tuner_param param
,
110 struct tuner_state
*tstate
)
112 struct tda8261_state
*state
= fe
->tuner_priv
;
113 const struct tda8261_config
*config
= state
->config
;
114 u32 frequency
, N
, status
= 0;
118 if (param
& DVBFE_TUNER_FREQUENCY
) {
120 * N = Max VCO Frequency / Channel Spacing
121 * Max VCO Frequency = VCO frequency + (channel spacing - 1)
122 * (to account for half channel spacing on either side)
124 frequency
= tstate
->frequency
;
125 if ((frequency
< 950000) || (frequency
> 2150000)) {
126 printk("%s: Frequency beyond limits, frequency=%d\n", __func__
, frequency
);
129 N
= (frequency
+ (div_tab
[config
->step_size
] - 1)) / div_tab
[config
->step_size
];
130 printk("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
131 __func__
, config
->step_size
, div_tab
[config
->step_size
], N
, N
);
133 buf
[0] = (N
>> 8) & 0xff;
135 buf
[2] = (0x01 << 7) | ((ref_div
[config
->step_size
] & 0x07) << 1);
137 if (frequency
< 1450000)
139 if (frequency
< 2000000)
141 if (frequency
< 2150000)
145 if ((err
= tda8261_write(state
, buf
)) < 0) {
146 printk("%s: I/O Error\n", __func__
);
149 /* sleep for some time */
150 printk("%s: Waiting to Phase LOCK\n", __func__
);
153 if ((err
= tda8261_get_status(fe
, &status
)) < 0) {
154 printk("%s: I/O Error\n", __func__
);
158 printk("%s: Tuner Phase locked: status=%d\n", __func__
, status
);
159 state
->frequency
= frequency
; /* cache successful state */
161 printk("%s: No Phase lock: status=%d\n", __func__
, status
);
164 printk("%s: Unknown parameter (param=%d)\n", __func__
, param
);
171 static int tda8261_release(struct dvb_frontend
*fe
)
173 struct tda8261_state
*state
= fe
->tuner_priv
;
175 fe
->tuner_priv
= NULL
;
180 static struct dvb_tuner_ops tda8261_ops
= {
184 // .tuner_name = NULL,
185 .frequency_min
= 950000,
186 .frequency_max
= 2150000,
190 .set_state
= tda8261_set_state
,
191 .get_state
= tda8261_get_state
,
192 .get_status
= tda8261_get_status
,
193 .release
= tda8261_release
196 struct dvb_frontend
*tda8261_attach(struct dvb_frontend
*fe
,
197 const struct tda8261_config
*config
,
198 struct i2c_adapter
*i2c
)
200 struct tda8261_state
*state
= NULL
;
202 if ((state
= kzalloc(sizeof (struct tda8261_state
), GFP_KERNEL
)) == NULL
)
205 state
->config
= config
;
208 fe
->tuner_priv
= state
;
209 fe
->ops
.tuner_ops
= tda8261_ops
;
211 fe
->ops
.tuner_ops
.info
.frequency_step
= div_tab
[config
->step_size
];
212 // fe->ops.tuner_ops.tuner_name = &config->buf;
214 // printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
215 // __func__, fe->ops.tuner_ops.tuner_name);
216 printk("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__
);
225 EXPORT_SYMBOL(tda8261_attach
);
226 MODULE_PARM_DESC(verbose
, "Set verbosity level");
228 MODULE_AUTHOR("Manu Abraham");
229 MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
230 MODULE_LICENSE("GPL");