mt2131.c revision 1.2 1 1.2 jmcneill /* $NetBSD: mt2131.c,v 1.2 2011/08/04 22:24:29 jmcneill Exp $ */
2 1.1 jakllsch
3 1.1 jakllsch /*
4 1.1 jakllsch * Copyright (c) 2008, 2011 Jonathan A. Kollasch
5 1.1 jakllsch * All rights reserved.
6 1.1 jakllsch *
7 1.1 jakllsch * Redistribution and use in source and binary forms, with or without
8 1.1 jakllsch * modification, are permitted provided that the following conditions
9 1.1 jakllsch * are met:
10 1.1 jakllsch * 1. Redistributions of source code must retain the above copyright
11 1.1 jakllsch * notice, this list of conditions and the following disclaimer.
12 1.1 jakllsch * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jakllsch * notice, this list of conditions and the following disclaimer in the
14 1.1 jakllsch * documentation and/or other materials provided with the distribution.
15 1.1 jakllsch *
16 1.1 jakllsch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 1.1 jakllsch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 1.1 jakllsch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 1.1 jakllsch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 1.1 jakllsch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 1.1 jakllsch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 1.1 jakllsch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 1.1 jakllsch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 1.1 jakllsch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 1.1 jakllsch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 1.1 jakllsch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 1.1 jakllsch */
28 1.1 jakllsch
29 1.1 jakllsch #include <sys/cdefs.h>
30 1.2 jmcneill __KERNEL_RCSID(0, "$NetBSD: mt2131.c,v 1.2 2011/08/04 22:24:29 jmcneill Exp $");
31 1.1 jakllsch
32 1.1 jakllsch #include <sys/param.h>
33 1.1 jakllsch #include <sys/systm.h>
34 1.1 jakllsch #include <sys/device.h>
35 1.1 jakllsch #include <sys/kmem.h>
36 1.1 jakllsch #include <sys/syslog.h>
37 1.1 jakllsch #include <sys/proc.h>
38 1.2 jmcneill #include <sys/module.h>
39 1.1 jakllsch
40 1.1 jakllsch #include <dev/i2c/mt2131var.h>
41 1.1 jakllsch
42 1.1 jakllsch #define PWR 0x07
43 1.1 jakllsch #define UPC_1 0x0b
44 1.1 jakllsch #define AGC_RL 0x10
45 1.1 jakllsch #define MISC_2 0x15
46 1.1 jakllsch
47 1.1 jakllsch #define IF1 1220
48 1.1 jakllsch #define IF2 44000
49 1.1 jakllsch #define REF 16000
50 1.1 jakllsch
51 1.1 jakllsch static const uint8_t mt2131_initstring[] = {
52 1.1 jakllsch 0x01,
53 1.1 jakllsch 0x50, 0x00, 0x50, 0x80, 0x00, 0x49,
54 1.1 jakllsch 0xfa, 0x88, 0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
55 1.1 jakllsch 0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80, 0xff, 0x68,
56 1.1 jakllsch 0xa0, 0xff, 0xdd, 0x00, 0x00
57 1.1 jakllsch };
58 1.1 jakllsch
59 1.1 jakllsch static const uint8_t mt2131_agcinitstring[] = {
60 1.1 jakllsch AGC_RL,
61 1.1 jakllsch 0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
62 1.1 jakllsch };
63 1.1 jakllsch
64 1.1 jakllsch
65 1.1 jakllsch struct mt2131_softc {
66 1.1 jakllsch device_t parent;
67 1.1 jakllsch i2c_tag_t tag;
68 1.1 jakllsch i2c_addr_t addr;
69 1.1 jakllsch uint32_t frequency;
70 1.1 jakllsch uint32_t bandwidth;
71 1.1 jakllsch };
72 1.1 jakllsch
73 1.1 jakllsch static int mt2131_init(struct mt2131_softc *);
74 1.1 jakllsch
75 1.1 jakllsch static int mt2131_read(struct mt2131_softc *, uint8_t, uint8_t *);
76 1.1 jakllsch static int mt2131_write(struct mt2131_softc *, uint8_t, uint8_t);
77 1.1 jakllsch
78 1.1 jakllsch struct mt2131_softc *
79 1.1 jakllsch mt2131_open(device_t parent, i2c_tag_t t, i2c_addr_t a)
80 1.1 jakllsch {
81 1.1 jakllsch struct mt2131_softc *sc;
82 1.1 jakllsch int ret;
83 1.1 jakllsch
84 1.1 jakllsch uint8_t cmd, reg;
85 1.1 jakllsch
86 1.1 jakllsch cmd = reg = 0;
87 1.1 jakllsch
88 1.1 jakllsch printf("%s\n", __func__);
89 1.1 jakllsch
90 1.1 jakllsch /* get id reg */
91 1.1 jakllsch iic_acquire_bus(t, I2C_F_POLL);
92 1.1 jakllsch ret = iic_exec(t, I2C_OP_READ_WITH_STOP, a, &cmd, 1, ®, 1, I2C_F_POLL);
93 1.1 jakllsch iic_release_bus(t, I2C_F_POLL);
94 1.1 jakllsch
95 1.1 jakllsch if (ret) {
96 1.1 jakllsch printf("%s read fail\n", __func__);
97 1.1 jakllsch return NULL;
98 1.1 jakllsch }
99 1.1 jakllsch
100 1.1 jakllsch printf("%s %02x\n", __func__, reg);
101 1.1 jakllsch
102 1.1 jakllsch if ((reg & 0xfe) != 0x3e)
103 1.1 jakllsch return NULL;
104 1.1 jakllsch
105 1.1 jakllsch sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
106 1.1 jakllsch if (sc == NULL)
107 1.1 jakllsch return NULL;
108 1.1 jakllsch
109 1.1 jakllsch sc->parent = parent;
110 1.1 jakllsch sc->tag = t;
111 1.1 jakllsch sc->addr = a;
112 1.1 jakllsch
113 1.1 jakllsch mt2131_init(sc);
114 1.1 jakllsch
115 1.1 jakllsch return sc;
116 1.1 jakllsch }
117 1.1 jakllsch
118 1.1 jakllsch void
119 1.1 jakllsch mt2131_close(struct mt2131_softc *sc)
120 1.1 jakllsch {
121 1.1 jakllsch kmem_free(sc, sizeof(*sc));
122 1.1 jakllsch }
123 1.1 jakllsch
124 1.1 jakllsch int
125 1.1 jakllsch mt2131_tune_dtv(struct mt2131_softc *sc, const struct dvb_frontend_parameters *p)
126 1.1 jakllsch {
127 1.1 jakllsch int rv;
128 1.1 jakllsch uint64_t o1, o2;
129 1.1 jakllsch uint64_t d1, d2;
130 1.1 jakllsch uint32_t r1, r2;
131 1.1 jakllsch uint32_t fr;
132 1.1 jakllsch uint8_t b[7];
133 1.1 jakllsch uint8_t regval;
134 1.1 jakllsch
135 1.1 jakllsch mt2131_init(sc);
136 1.1 jakllsch
137 1.1 jakllsch b[0] = 0x01;
138 1.1 jakllsch
139 1.1 jakllsch if(p->frequency != 0 &&
140 1.1 jakllsch (p->frequency < 50000000 || p->frequency > 1000000000))
141 1.1 jakllsch return EINVAL;
142 1.1 jakllsch
143 1.1 jakllsch fr = p->frequency / 1000;
144 1.1 jakllsch
145 1.1 jakllsch o1 = fr + IF1 * 1000;
146 1.1 jakllsch o2 = o1 - fr - IF2;
147 1.1 jakllsch
148 1.1 jakllsch d1 = (o1 * 8192)/REF;
149 1.1 jakllsch d2 = (o2 * 8192)/REF;
150 1.1 jakllsch
151 1.1 jakllsch r1 = d1/8192;
152 1.1 jakllsch r2 = d2/8192;
153 1.1 jakllsch
154 1.1 jakllsch printf("mt2131 %lu %lu %lu %u\n", o1, d1, d1&0x1fff, r1);
155 1.1 jakllsch printf("mt2131 %lu %lu %lu %u\n", o2, d2, d2&0x1fff, r2);
156 1.1 jakllsch
157 1.1 jakllsch b[1] = (d1 & 0x1fe0) >> 5;
158 1.1 jakllsch b[2] = (d1 & 0x001f);
159 1.1 jakllsch b[3] = r1;
160 1.1 jakllsch b[4] = (d2 & 0x1fe0) >> 5;
161 1.1 jakllsch b[5] = (d2 & 0x001f);
162 1.1 jakllsch b[6] = r2;
163 1.1 jakllsch
164 1.1 jakllsch iic_acquire_bus(sc->tag, I2C_F_POLL);
165 1.1 jakllsch rv = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr, b, 7, NULL, 0, I2C_F_POLL);
166 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
167 1.1 jakllsch
168 1.1 jakllsch regval = (fr - 27501) / 55000;
169 1.1 jakllsch
170 1.1 jakllsch if(regval > 0x13)
171 1.1 jakllsch regval = 0x13;
172 1.1 jakllsch
173 1.1 jakllsch printf("mt2131 %u\n", regval);
174 1.1 jakllsch
175 1.1 jakllsch rv = mt2131_write(sc, UPC_1, regval);
176 1.1 jakllsch
177 1.1 jakllsch if (rv != 0)
178 1.1 jakllsch printf("%s\n", __func__);
179 1.1 jakllsch
180 1.1 jakllsch sc->frequency = (o1 - o2 - IF2) * 1000;
181 1.1 jakllsch printf("%s freq %d\n", __func__, sc->frequency);
182 1.1 jakllsch
183 1.1 jakllsch int i;
184 1.1 jakllsch b[0] = 0x08;
185 1.1 jakllsch
186 1.1 jakllsch for ( i = 0; i < 100; i++) {
187 1.1 jakllsch rv = mt2131_read(sc, 0x08, ®val);
188 1.1 jakllsch
189 1.1 jakllsch if (( regval & 0x88 ) == 0x88 ) {
190 1.1 jakllsch printf("mt2131 - locked\n");
191 1.1 jakllsch break;
192 1.1 jakllsch } else {
193 1.1 jakllsch printf("mt2131 - not locked - %02x\n", b[1]);
194 1.1 jakllsch }
195 1.1 jakllsch kpause("mt2131", true, 1, NULL);
196 1.1 jakllsch }
197 1.1 jakllsch
198 1.1 jakllsch return rv;
199 1.1 jakllsch }
200 1.1 jakllsch
201 1.1 jakllsch static int
202 1.1 jakllsch mt2131_init(struct mt2131_softc *sc)
203 1.1 jakllsch {
204 1.1 jakllsch int ret;
205 1.1 jakllsch
206 1.1 jakllsch printf("%s\n", __func__);
207 1.1 jakllsch
208 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
209 1.1 jakllsch if (ret)
210 1.1 jakllsch return -1;
211 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
212 1.1 jakllsch mt2131_initstring, sizeof(mt2131_initstring), NULL, 0, I2C_F_POLL);
213 1.1 jakllsch if (ret)
214 1.1 jakllsch return -1;
215 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
216 1.1 jakllsch
217 1.1 jakllsch ret = mt2131_write(sc, UPC_1, 0x09);
218 1.1 jakllsch ret = mt2131_write(sc, MISC_2, 0x47);
219 1.1 jakllsch ret = mt2131_write(sc, PWR, 0xf2);
220 1.1 jakllsch ret = mt2131_write(sc, UPC_1, 0x01);
221 1.1 jakllsch
222 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
223 1.1 jakllsch if (ret)
224 1.1 jakllsch return -1;
225 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
226 1.1 jakllsch mt2131_agcinitstring, sizeof(mt2131_agcinitstring),
227 1.1 jakllsch NULL, 0, I2C_F_POLL);
228 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
229 1.1 jakllsch if (ret)
230 1.1 jakllsch return -1;
231 1.1 jakllsch
232 1.1 jakllsch return 0;
233 1.1 jakllsch }
234 1.1 jakllsch
235 1.1 jakllsch static int
236 1.1 jakllsch mt2131_read(struct mt2131_softc *sc, uint8_t r, uint8_t *v)
237 1.1 jakllsch {
238 1.1 jakllsch int ret;
239 1.1 jakllsch
240 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
241 1.1 jakllsch if (ret)
242 1.1 jakllsch return ret;
243 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
244 1.1 jakllsch &r, 1, v, 1, I2C_F_POLL);
245 1.1 jakllsch
246 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
247 1.1 jakllsch
248 1.1 jakllsch return ret;
249 1.1 jakllsch }
250 1.1 jakllsch
251 1.1 jakllsch static int
252 1.1 jakllsch mt2131_write(struct mt2131_softc *sc, uint8_t a, uint8_t v)
253 1.1 jakllsch {
254 1.1 jakllsch int ret;
255 1.1 jakllsch uint8_t b[] = { a, v };
256 1.1 jakllsch
257 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
258 1.1 jakllsch if (ret)
259 1.1 jakllsch return ret;
260 1.1 jakllsch
261 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
262 1.1 jakllsch b, sizeof(b), NULL, 0, I2C_F_POLL);
263 1.1 jakllsch
264 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
265 1.1 jakllsch
266 1.1 jakllsch return ret;
267 1.1 jakllsch }
268 1.2 jmcneill
269 1.2 jmcneill MODULE(MODULE_CLASS_DRIVER, mt2131, NULL);
270 1.2 jmcneill
271 1.2 jmcneill static int
272 1.2 jmcneill mt2131_modcmd(modcmd_t cmd, void *priv)
273 1.2 jmcneill {
274 1.2 jmcneill if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
275 1.2 jmcneill return 0;
276 1.2 jmcneill return ENOTTY;
277 1.2 jmcneill }
278