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 <media/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_frequency(struct dvb_frontend
*fe
, u32
*frequency
)
88 struct tda8261_state
*state
= fe
->tuner_priv
;
90 *frequency
= state
->frequency
;
95 static int tda8261_set_params(struct dvb_frontend
*fe
)
97 struct dtv_frontend_properties
*c
= &fe
->dtv_property_cache
;
98 struct tda8261_state
*state
= fe
->tuner_priv
;
99 const struct tda8261_config
*config
= state
->config
;
100 u32 frequency
, N
, status
= 0;
105 * N = Max VCO Frequency / Channel Spacing
106 * Max VCO Frequency = VCO frequency + (channel spacing - 1)
107 * (to account for half channel spacing on either side)
109 frequency
= c
->frequency
;
110 if ((frequency
< 950000) || (frequency
> 2150000)) {
111 pr_warn("%s: Frequency beyond limits, frequency=%d\n",
112 __func__
, frequency
);
115 N
= (frequency
+ (div_tab
[config
->step_size
] - 1)) / div_tab
[config
->step_size
];
116 pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
117 __func__
, config
->step_size
, div_tab
[config
->step_size
], N
, N
);
119 buf
[0] = (N
>> 8) & 0xff;
121 buf
[2] = (0x01 << 7) | ((ref_div
[config
->step_size
] & 0x07) << 1);
123 if (frequency
< 1450000)
125 else if (frequency
< 2000000)
127 else if (frequency
< 2150000)
131 err
= tda8261_write(state
, buf
);
133 pr_err("%s: I/O Error\n", __func__
);
136 /* sleep for some time */
137 pr_debug("%s: Waiting to Phase LOCK\n", __func__
);
140 if ((err
= tda8261_get_status(fe
, &status
)) < 0) {
141 pr_err("%s: I/O Error\n", __func__
);
145 pr_debug("%s: Tuner Phase locked: status=%d\n", __func__
,
147 state
->frequency
= frequency
; /* cache successful state */
149 pr_debug("%s: No Phase lock: status=%d\n", __func__
, status
);
155 static void tda8261_release(struct dvb_frontend
*fe
)
157 struct tda8261_state
*state
= fe
->tuner_priv
;
159 fe
->tuner_priv
= NULL
;
163 static const struct dvb_tuner_ops tda8261_ops
= {
167 .frequency_min_hz
= 950 * MHz
,
168 .frequency_max_hz
= 2150 * MHz
,
171 .set_params
= tda8261_set_params
,
172 .get_frequency
= tda8261_get_frequency
,
173 .get_status
= tda8261_get_status
,
174 .release
= tda8261_release
177 struct dvb_frontend
*tda8261_attach(struct dvb_frontend
*fe
,
178 const struct tda8261_config
*config
,
179 struct i2c_adapter
*i2c
)
181 struct tda8261_state
*state
= NULL
;
183 if ((state
= kzalloc(sizeof (struct tda8261_state
), GFP_KERNEL
)) == NULL
)
186 state
->config
= config
;
189 fe
->tuner_priv
= state
;
190 fe
->ops
.tuner_ops
= tda8261_ops
;
192 fe
->ops
.tuner_ops
.info
.frequency_step_hz
= div_tab
[config
->step_size
] * kHz
;
194 pr_info("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__
);
203 EXPORT_SYMBOL(tda8261_attach
);
205 MODULE_AUTHOR("Manu Abraham");
206 MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
207 MODULE_LICENSE("GPL");