This source file includes following definitions.
- lookup_cb
- qm1d1b0004_set_params
- qm1d1b0004_set_config
- qm1d1b0004_init
- qm1d1b0004_probe
- qm1d1b0004_remove
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <media/dvb_frontend.h>
21 #include "qm1d1b0004.h"
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 #define QM1D1B0004_PSC_MASK (1 << 4)
58
59 #define QM1D1B0004_XTL_FREQ 4000
60 #define QM1D1B0004_LPF_FALLBACK 30000
61
62 #if 0
63 static const struct qm1d1b0004_config default_cfg = {
64 .lpf_freq = QM1D1B0004_CFG_LPF_DFLT,
65 .half_step = false,
66 };
67 #endif
68
69 struct qm1d1b0004_state {
70 struct qm1d1b0004_config cfg;
71 struct i2c_client *i2c;
72 };
73
74
75 struct qm1d1b0004_cb_map {
76 u32 frequency;
77 u8 cb;
78 };
79
80 static const struct qm1d1b0004_cb_map cb_maps[] = {
81 { 986000, 0xb2 },
82 { 1072000, 0xd2 },
83 { 1154000, 0xe2 },
84 { 1291000, 0x20 },
85 { 1447000, 0x40 },
86 { 1615000, 0x60 },
87 { 1791000, 0x80 },
88 { 1972000, 0xa0 },
89 };
90
91 static u8 lookup_cb(u32 frequency)
92 {
93 int i;
94 const struct qm1d1b0004_cb_map *map;
95
96 for (i = 0; i < ARRAY_SIZE(cb_maps); i++) {
97 map = &cb_maps[i];
98 if (frequency < map->frequency)
99 return map->cb;
100 }
101 return 0xc0;
102 }
103
104 static int qm1d1b0004_set_params(struct dvb_frontend *fe)
105 {
106 struct qm1d1b0004_state *state;
107 u32 frequency, pll, lpf_freq;
108 u16 word;
109 u8 buf[4], cb, lpf;
110 int ret;
111
112 state = fe->tuner_priv;
113 frequency = fe->dtv_property_cache.frequency;
114
115 pll = QM1D1B0004_XTL_FREQ / 4;
116 if (state->cfg.half_step)
117 pll /= 2;
118 word = DIV_ROUND_CLOSEST(frequency, pll);
119 cb = lookup_cb(frequency);
120 if (cb & QM1D1B0004_PSC_MASK)
121 word = (word << 1 & ~0x1f) | (word & 0x0f);
122
123
124 buf[0] = 0x40 | word >> 8;
125 buf[1] = word;
126
127 buf[2] = 0xe0 | state->cfg.half_step;
128 buf[3] = cb;
129 ret = i2c_master_send(state->i2c, buf, 4);
130 if (ret < 0)
131 return ret;
132
133
134 buf[0] = 0xe4 | state->cfg.half_step;
135 ret = i2c_master_send(state->i2c, buf, 1);
136 if (ret < 0)
137 return ret;
138 msleep(20);
139
140
141 lpf_freq = state->cfg.lpf_freq;
142 if (lpf_freq == QM1D1B0004_CFG_LPF_DFLT)
143 lpf_freq = fe->dtv_property_cache.symbol_rate / 1000;
144 if (lpf_freq == 0)
145 lpf_freq = QM1D1B0004_LPF_FALLBACK;
146 lpf = DIV_ROUND_UP(lpf_freq, 2000) - 2;
147 buf[0] = 0xe4 | ((lpf & 0x0c) << 1) | state->cfg.half_step;
148 buf[1] = cb | ((lpf & 0x03) << 2);
149 ret = i2c_master_send(state->i2c, buf, 2);
150 if (ret < 0)
151 return ret;
152
153
154 buf[0] = 0;
155 ret = i2c_master_recv(state->i2c, buf, 1);
156 if (ret < 0)
157 return ret;
158 return 0;
159 }
160
161
162 static int qm1d1b0004_set_config(struct dvb_frontend *fe, void *priv_cfg)
163 {
164 struct qm1d1b0004_state *state;
165
166 state = fe->tuner_priv;
167 memcpy(&state->cfg, priv_cfg, sizeof(state->cfg));
168 return 0;
169 }
170
171
172 static int qm1d1b0004_init(struct dvb_frontend *fe)
173 {
174 struct qm1d1b0004_state *state;
175 u8 buf[2] = {0xf8, 0x04};
176
177 state = fe->tuner_priv;
178 if (state->cfg.half_step)
179 buf[0] |= 0x01;
180
181 return i2c_master_send(state->i2c, buf, 2);
182 }
183
184
185 static const struct dvb_tuner_ops qm1d1b0004_ops = {
186 .info = {
187 .name = "Sharp qm1d1b0004",
188
189 .frequency_min_hz = 950 * MHz,
190 .frequency_max_hz = 2150 * MHz,
191 },
192
193 .init = qm1d1b0004_init,
194
195 .set_params = qm1d1b0004_set_params,
196 .set_config = qm1d1b0004_set_config,
197 };
198
199 static int
200 qm1d1b0004_probe(struct i2c_client *client, const struct i2c_device_id *id)
201 {
202 struct dvb_frontend *fe;
203 struct qm1d1b0004_config *cfg;
204 struct qm1d1b0004_state *state;
205 int ret;
206
207 cfg = client->dev.platform_data;
208 fe = cfg->fe;
209 i2c_set_clientdata(client, fe);
210
211 fe->tuner_priv = kzalloc(sizeof(struct qm1d1b0004_state), GFP_KERNEL);
212 if (!fe->tuner_priv) {
213 ret = -ENOMEM;
214 goto err_mem;
215 }
216
217 memcpy(&fe->ops.tuner_ops, &qm1d1b0004_ops, sizeof(fe->ops.tuner_ops));
218
219 state = fe->tuner_priv;
220 state->i2c = client;
221 ret = qm1d1b0004_set_config(fe, cfg);
222 if (ret != 0)
223 goto err_priv;
224
225 dev_info(&client->dev, "Sharp QM1D1B0004 attached.\n");
226 return 0;
227
228 err_priv:
229 kfree(fe->tuner_priv);
230 err_mem:
231 fe->tuner_priv = NULL;
232 return ret;
233 }
234
235 static int qm1d1b0004_remove(struct i2c_client *client)
236 {
237 struct dvb_frontend *fe;
238
239 fe = i2c_get_clientdata(client);
240 kfree(fe->tuner_priv);
241 fe->tuner_priv = NULL;
242 return 0;
243 }
244
245
246 static const struct i2c_device_id qm1d1b0004_id[] = {
247 {"qm1d1b0004", 0},
248 {}
249 };
250
251 MODULE_DEVICE_TABLE(i2c, qm1d1b0004_id);
252
253 static struct i2c_driver qm1d1b0004_driver = {
254 .driver = {
255 .name = "qm1d1b0004",
256 },
257 .probe = qm1d1b0004_probe,
258 .remove = qm1d1b0004_remove,
259 .id_table = qm1d1b0004_id,
260 };
261
262 module_i2c_driver(qm1d1b0004_driver);
263
264 MODULE_DESCRIPTION("Sharp QM1D1B0004");
265 MODULE_AUTHOR("Akihiro Tsukada");
266 MODULE_LICENSE("GPL");