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>
24 #include <linux/slab.h>
26 #include "dvb_frontend.h"
29 struct tda8261_state
{
30 struct dvb_frontend
*fe
;
31 struct i2c_adapter
*i2c
;
32 const struct tda8261_config
*config
;
39 static int tda8261_read(struct tda8261_state
*state
, u8
*buf
)
41 const struct tda8261_config
*config
= state
->config
;
43 struct i2c_msg msg
= { .addr
= config
->addr
, .flags
= I2C_M_RD
,.buf
= buf
, .len
= 1 };
45 if ((err
= i2c_transfer(state
->i2c
, &msg
, 1)) != 1)
46 pr_err("%s: read error, err=%d\n", __func__
, err
);
51 static int tda8261_write(struct tda8261_state
*state
, u8
*buf
)
53 const struct tda8261_config
*config
= state
->config
;
55 struct i2c_msg msg
= { .addr
= config
->addr
, .flags
= 0, .buf
= buf
, .len
= 4 };
57 if ((err
= i2c_transfer(state
->i2c
, &msg
, 1)) != 1)
58 pr_err("%s: write error, err=%d\n", __func__
, err
);
63 static int tda8261_get_status(struct dvb_frontend
*fe
, u32
*status
)
65 struct tda8261_state
*state
= fe
->tuner_priv
;
71 if ((err
= tda8261_read(state
, &result
)) < 0) {
72 pr_err("%s: I/O Error\n", __func__
);
75 if ((result
>> 6) & 0x01) {
76 pr_debug("%s: Tuner Phase Locked\n", __func__
);
83 static const u32 div_tab
[] = { 2000, 1000, 500, 250, 125 }; /* kHz */
84 static const u8 ref_div
[] = { 0x00, 0x01, 0x02, 0x05, 0x07 };
86 static int tda8261_get_state(struct dvb_frontend
*fe
,
87 enum tuner_param param
,
88 struct tuner_state
*tstate
)
90 struct tda8261_state
*state
= fe
->tuner_priv
;
94 case DVBFE_TUNER_FREQUENCY
:
95 tstate
->frequency
= state
->frequency
;
97 case DVBFE_TUNER_BANDWIDTH
:
98 tstate
->bandwidth
= 40000000; /* FIXME! need to calculate Bandwidth */
101 pr_err("%s: Unknown parameter (param=%d)\n", __func__
, param
);
109 static int tda8261_set_state(struct dvb_frontend
*fe
,
110 enum tuner_param param
,
111 struct tuner_state
*tstate
)
113 struct tda8261_state
*state
= fe
->tuner_priv
;
114 const struct tda8261_config
*config
= state
->config
;
115 u32 frequency
, N
, status
= 0;
119 if (param
& DVBFE_TUNER_FREQUENCY
) {
121 * N = Max VCO Frequency / Channel Spacing
122 * Max VCO Frequency = VCO frequency + (channel spacing - 1)
123 * (to account for half channel spacing on either side)
125 frequency
= tstate
->frequency
;
126 if ((frequency
< 950000) || (frequency
> 2150000)) {
127 pr_warn("%s: Frequency beyond limits, frequency=%d\n", __func__
, frequency
);
130 N
= (frequency
+ (div_tab
[config
->step_size
] - 1)) / div_tab
[config
->step_size
];
131 pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
132 __func__
, config
->step_size
, div_tab
[config
->step_size
], N
, N
);
134 buf
[0] = (N
>> 8) & 0xff;
136 buf
[2] = (0x01 << 7) | ((ref_div
[config
->step_size
] & 0x07) << 1);
138 if (frequency
< 1450000)
140 else if (frequency
< 2000000)
142 else if (frequency
< 2150000)
146 if ((err
= tda8261_write(state
, buf
)) < 0) {
147 pr_err("%s: I/O Error\n", __func__
);
150 /* sleep for some time */
151 pr_debug("%s: Waiting to Phase LOCK\n", __func__
);
154 if ((err
= tda8261_get_status(fe
, &status
)) < 0) {
155 pr_err("%s: I/O Error\n", __func__
);
159 pr_debug("%s: Tuner Phase locked: status=%d\n", __func__
, status
);
160 state
->frequency
= frequency
; /* cache successful state */
162 pr_debug("%s: No Phase lock: status=%d\n", __func__
, status
);
165 pr_err("%s: Unknown parameter (param=%d)\n", __func__
, param
);
172 static int tda8261_release(struct dvb_frontend
*fe
)
174 struct tda8261_state
*state
= fe
->tuner_priv
;
176 fe
->tuner_priv
= NULL
;
181 static struct dvb_tuner_ops tda8261_ops
= {
185 // .tuner_name = NULL,
186 .frequency_min
= 950000,
187 .frequency_max
= 2150000,
191 .set_state
= tda8261_set_state
,
192 .get_state
= tda8261_get_state
,
193 .get_status
= tda8261_get_status
,
194 .release
= tda8261_release
197 struct dvb_frontend
*tda8261_attach(struct dvb_frontend
*fe
,
198 const struct tda8261_config
*config
,
199 struct i2c_adapter
*i2c
)
201 struct tda8261_state
*state
= NULL
;
203 if ((state
= kzalloc(sizeof (struct tda8261_state
), GFP_KERNEL
)) == NULL
)
206 state
->config
= config
;
209 fe
->tuner_priv
= state
;
210 fe
->ops
.tuner_ops
= tda8261_ops
;
212 fe
->ops
.tuner_ops
.info
.frequency_step
= div_tab
[config
->step_size
];
213 // fe->ops.tuner_ops.tuner_name = &config->buf;
215 // printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
216 // __func__, fe->ops.tuner_ops.tuner_name);
217 pr_info("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__
);
226 EXPORT_SYMBOL(tda8261_attach
);
228 MODULE_AUTHOR("Manu Abraham");
229 MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
230 MODULE_LICENSE("GPL");