mt2131.c revision 1.3 1 1.3 jakllsch /* $NetBSD: mt2131.c,v 1.3 2011/08/05 20:51:09 jakllsch 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.3 jakllsch __KERNEL_RCSID(0, "$NetBSD: mt2131.c,v 1.3 2011/08/05 20:51:09 jakllsch 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.3 jakllsch uint8_t cmd, reg;
84 1.1 jakllsch
85 1.1 jakllsch cmd = reg = 0;
86 1.1 jakllsch
87 1.1 jakllsch /* get id reg */
88 1.1 jakllsch iic_acquire_bus(t, I2C_F_POLL);
89 1.1 jakllsch ret = iic_exec(t, I2C_OP_READ_WITH_STOP, a, &cmd, 1, ®, 1, I2C_F_POLL);
90 1.1 jakllsch iic_release_bus(t, I2C_F_POLL);
91 1.1 jakllsch
92 1.1 jakllsch if (ret) {
93 1.3 jakllsch device_printf(parent, "%s(): read fail\n", __func__);
94 1.1 jakllsch return NULL;
95 1.1 jakllsch }
96 1.1 jakllsch
97 1.3 jakllsch if ((reg & 0xfe) != 0x3e) {
98 1.3 jakllsch device_printf(parent, "%s(): chip id %02x unknown\n",
99 1.3 jakllsch __func__, reg);
100 1.1 jakllsch return NULL;
101 1.3 jakllsch }
102 1.1 jakllsch
103 1.1 jakllsch sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
104 1.1 jakllsch if (sc == NULL)
105 1.1 jakllsch return NULL;
106 1.1 jakllsch
107 1.1 jakllsch sc->parent = parent;
108 1.1 jakllsch sc->tag = t;
109 1.1 jakllsch sc->addr = a;
110 1.1 jakllsch
111 1.1 jakllsch mt2131_init(sc);
112 1.1 jakllsch
113 1.1 jakllsch return sc;
114 1.1 jakllsch }
115 1.1 jakllsch
116 1.1 jakllsch void
117 1.1 jakllsch mt2131_close(struct mt2131_softc *sc)
118 1.1 jakllsch {
119 1.1 jakllsch kmem_free(sc, sizeof(*sc));
120 1.1 jakllsch }
121 1.1 jakllsch
122 1.1 jakllsch int
123 1.1 jakllsch mt2131_tune_dtv(struct mt2131_softc *sc, const struct dvb_frontend_parameters *p)
124 1.1 jakllsch {
125 1.3 jakllsch int rv, i;
126 1.1 jakllsch uint64_t o1, o2;
127 1.1 jakllsch uint64_t d1, d2;
128 1.1 jakllsch uint32_t r1, r2;
129 1.1 jakllsch uint32_t fr;
130 1.1 jakllsch uint8_t b[7];
131 1.1 jakllsch uint8_t regval;
132 1.1 jakllsch
133 1.1 jakllsch mt2131_init(sc);
134 1.1 jakllsch
135 1.1 jakllsch b[0] = 0x01;
136 1.1 jakllsch
137 1.1 jakllsch if(p->frequency != 0 &&
138 1.1 jakllsch (p->frequency < 50000000 || p->frequency > 1000000000))
139 1.1 jakllsch return EINVAL;
140 1.1 jakllsch
141 1.1 jakllsch fr = p->frequency / 1000;
142 1.1 jakllsch
143 1.1 jakllsch o1 = fr + IF1 * 1000;
144 1.1 jakllsch o2 = o1 - fr - IF2;
145 1.1 jakllsch
146 1.1 jakllsch d1 = (o1 * 8192)/REF;
147 1.1 jakllsch d2 = (o2 * 8192)/REF;
148 1.1 jakllsch
149 1.1 jakllsch r1 = d1/8192;
150 1.1 jakllsch r2 = d2/8192;
151 1.1 jakllsch
152 1.1 jakllsch b[1] = (d1 & 0x1fe0) >> 5;
153 1.1 jakllsch b[2] = (d1 & 0x001f);
154 1.1 jakllsch b[3] = r1;
155 1.1 jakllsch b[4] = (d2 & 0x1fe0) >> 5;
156 1.1 jakllsch b[5] = (d2 & 0x001f);
157 1.1 jakllsch b[6] = r2;
158 1.1 jakllsch
159 1.1 jakllsch iic_acquire_bus(sc->tag, I2C_F_POLL);
160 1.1 jakllsch rv = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr, b, 7, NULL, 0, I2C_F_POLL);
161 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
162 1.1 jakllsch
163 1.1 jakllsch regval = (fr - 27501) / 55000;
164 1.1 jakllsch
165 1.1 jakllsch if(regval > 0x13)
166 1.1 jakllsch regval = 0x13;
167 1.1 jakllsch
168 1.1 jakllsch rv = mt2131_write(sc, UPC_1, regval);
169 1.1 jakllsch
170 1.1 jakllsch if (rv != 0)
171 1.3 jakllsch device_printf(sc->parent, "%s write failed\n", __func__);
172 1.1 jakllsch
173 1.1 jakllsch sc->frequency = (o1 - o2 - IF2) * 1000;
174 1.1 jakllsch
175 1.3 jakllsch for (i = 0; i < 100; i++) {
176 1.3 jakllsch kpause("mt2131", true, 1, NULL);
177 1.1 jakllsch
178 1.1 jakllsch rv = mt2131_read(sc, 0x08, ®val);
179 1.3 jakllsch if (rv != 0)
180 1.3 jakllsch device_printf(sc->parent, "%s read failed\n", __func__);
181 1.1 jakllsch
182 1.1 jakllsch if (( regval & 0x88 ) == 0x88 ) {
183 1.3 jakllsch return 0;
184 1.1 jakllsch }
185 1.1 jakllsch }
186 1.1 jakllsch
187 1.3 jakllsch device_printf(sc->parent, "mt2131 not locked, %02x\n", b[1]);
188 1.3 jakllsch
189 1.1 jakllsch return rv;
190 1.1 jakllsch }
191 1.1 jakllsch
192 1.1 jakllsch static int
193 1.1 jakllsch mt2131_init(struct mt2131_softc *sc)
194 1.1 jakllsch {
195 1.1 jakllsch int ret;
196 1.1 jakllsch
197 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
198 1.1 jakllsch if (ret)
199 1.1 jakllsch return -1;
200 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
201 1.1 jakllsch mt2131_initstring, sizeof(mt2131_initstring), NULL, 0, I2C_F_POLL);
202 1.1 jakllsch if (ret)
203 1.1 jakllsch return -1;
204 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
205 1.1 jakllsch
206 1.1 jakllsch ret = mt2131_write(sc, UPC_1, 0x09);
207 1.1 jakllsch ret = mt2131_write(sc, MISC_2, 0x47);
208 1.1 jakllsch ret = mt2131_write(sc, PWR, 0xf2);
209 1.1 jakllsch ret = mt2131_write(sc, UPC_1, 0x01);
210 1.1 jakllsch
211 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
212 1.1 jakllsch if (ret)
213 1.1 jakllsch return -1;
214 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
215 1.1 jakllsch mt2131_agcinitstring, sizeof(mt2131_agcinitstring),
216 1.1 jakllsch NULL, 0, I2C_F_POLL);
217 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
218 1.1 jakllsch if (ret)
219 1.1 jakllsch return -1;
220 1.1 jakllsch
221 1.1 jakllsch return 0;
222 1.1 jakllsch }
223 1.1 jakllsch
224 1.1 jakllsch static int
225 1.1 jakllsch mt2131_read(struct mt2131_softc *sc, uint8_t r, uint8_t *v)
226 1.1 jakllsch {
227 1.1 jakllsch int ret;
228 1.1 jakllsch
229 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
230 1.1 jakllsch if (ret)
231 1.1 jakllsch return ret;
232 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
233 1.1 jakllsch &r, 1, v, 1, I2C_F_POLL);
234 1.1 jakllsch
235 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
236 1.1 jakllsch
237 1.1 jakllsch return ret;
238 1.1 jakllsch }
239 1.1 jakllsch
240 1.1 jakllsch static int
241 1.1 jakllsch mt2131_write(struct mt2131_softc *sc, uint8_t a, uint8_t v)
242 1.1 jakllsch {
243 1.1 jakllsch int ret;
244 1.1 jakllsch uint8_t b[] = { a, v };
245 1.1 jakllsch
246 1.1 jakllsch ret = iic_acquire_bus(sc->tag, I2C_F_POLL);
247 1.1 jakllsch if (ret)
248 1.1 jakllsch return ret;
249 1.1 jakllsch
250 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
251 1.1 jakllsch b, sizeof(b), NULL, 0, I2C_F_POLL);
252 1.1 jakllsch
253 1.1 jakllsch iic_release_bus(sc->tag, I2C_F_POLL);
254 1.1 jakllsch
255 1.1 jakllsch return ret;
256 1.1 jakllsch }
257 1.2 jmcneill
258 1.2 jmcneill MODULE(MODULE_CLASS_DRIVER, mt2131, NULL);
259 1.2 jmcneill
260 1.2 jmcneill static int
261 1.2 jmcneill mt2131_modcmd(modcmd_t cmd, void *priv)
262 1.2 jmcneill {
263 1.2 jmcneill if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
264 1.2 jmcneill return 0;
265 1.2 jmcneill return ENOTTY;
266 1.2 jmcneill }
267