mt2131.c revision 1.7 1 1.7 thorpej /* $NetBSD: mt2131.c,v 1.7 2019/12/23 18:57:30 thorpej 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.7 thorpej __KERNEL_RCSID(0, "$NetBSD: mt2131.c,v 1.7 2019/12/23 18:57:30 thorpej 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.7 thorpej ret = iic_acquire_bus(t, 0);
89 1.7 thorpej if (ret == 0) {
90 1.7 thorpej ret = iic_exec(t, I2C_OP_READ_WITH_STOP, a, &cmd, 1, ®, 1,
91 1.7 thorpej 0);
92 1.7 thorpej iic_release_bus(t, 0);
93 1.7 thorpej }
94 1.1 jakllsch
95 1.1 jakllsch if (ret) {
96 1.3 jakllsch device_printf(parent, "%s(): read fail\n", __func__);
97 1.1 jakllsch return NULL;
98 1.1 jakllsch }
99 1.1 jakllsch
100 1.3 jakllsch if ((reg & 0xfe) != 0x3e) {
101 1.3 jakllsch device_printf(parent, "%s(): chip id %02x unknown\n",
102 1.3 jakllsch __func__, reg);
103 1.1 jakllsch return NULL;
104 1.3 jakllsch }
105 1.1 jakllsch
106 1.1 jakllsch sc = kmem_alloc(sizeof(*sc), KM_SLEEP);
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.7 thorpej rv = iic_acquire_bus(sc->tag, 0);
160 1.7 thorpej if (rv == 0) {
161 1.7 thorpej rv = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr, b, 7,
162 1.7 thorpej NULL, 0, 0);
163 1.7 thorpej iic_release_bus(sc->tag, 0);
164 1.7 thorpej }
165 1.1 jakllsch
166 1.1 jakllsch regval = (fr - 27501) / 55000;
167 1.1 jakllsch
168 1.1 jakllsch if(regval > 0x13)
169 1.1 jakllsch regval = 0x13;
170 1.1 jakllsch
171 1.1 jakllsch rv = mt2131_write(sc, UPC_1, regval);
172 1.1 jakllsch
173 1.1 jakllsch if (rv != 0)
174 1.3 jakllsch device_printf(sc->parent, "%s write failed\n", __func__);
175 1.1 jakllsch
176 1.1 jakllsch sc->frequency = (o1 - o2 - IF2) * 1000;
177 1.1 jakllsch
178 1.3 jakllsch for (i = 0; i < 100; i++) {
179 1.3 jakllsch kpause("mt2131", true, 1, NULL);
180 1.1 jakllsch
181 1.1 jakllsch rv = mt2131_read(sc, 0x08, ®val);
182 1.3 jakllsch if (rv != 0)
183 1.3 jakllsch device_printf(sc->parent, "%s read failed\n", __func__);
184 1.1 jakllsch
185 1.1 jakllsch if (( regval & 0x88 ) == 0x88 ) {
186 1.3 jakllsch return 0;
187 1.1 jakllsch }
188 1.1 jakllsch }
189 1.1 jakllsch
190 1.3 jakllsch device_printf(sc->parent, "mt2131 not locked, %02x\n", b[1]);
191 1.3 jakllsch
192 1.1 jakllsch return rv;
193 1.1 jakllsch }
194 1.1 jakllsch
195 1.1 jakllsch static int
196 1.1 jakllsch mt2131_init(struct mt2131_softc *sc)
197 1.1 jakllsch {
198 1.1 jakllsch int ret;
199 1.1 jakllsch
200 1.7 thorpej ret = iic_acquire_bus(sc->tag, 0);
201 1.1 jakllsch if (ret)
202 1.1 jakllsch return -1;
203 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
204 1.7 thorpej mt2131_initstring, sizeof(mt2131_initstring), NULL, 0, 0);
205 1.7 thorpej iic_release_bus(sc->tag, 0);
206 1.1 jakllsch if (ret)
207 1.1 jakllsch return -1;
208 1.1 jakllsch
209 1.1 jakllsch ret = mt2131_write(sc, UPC_1, 0x09);
210 1.1 jakllsch ret = mt2131_write(sc, MISC_2, 0x47);
211 1.1 jakllsch ret = mt2131_write(sc, PWR, 0xf2);
212 1.1 jakllsch ret = mt2131_write(sc, UPC_1, 0x01);
213 1.1 jakllsch
214 1.7 thorpej ret = iic_acquire_bus(sc->tag, 0);
215 1.1 jakllsch if (ret)
216 1.1 jakllsch return -1;
217 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_WRITE_WITH_STOP, sc->addr,
218 1.1 jakllsch mt2131_agcinitstring, sizeof(mt2131_agcinitstring),
219 1.7 thorpej NULL, 0, 0);
220 1.7 thorpej iic_release_bus(sc->tag, 0);
221 1.1 jakllsch if (ret)
222 1.1 jakllsch return -1;
223 1.1 jakllsch
224 1.1 jakllsch return 0;
225 1.1 jakllsch }
226 1.1 jakllsch
227 1.1 jakllsch static int
228 1.1 jakllsch mt2131_read(struct mt2131_softc *sc, uint8_t r, uint8_t *v)
229 1.1 jakllsch {
230 1.1 jakllsch int ret;
231 1.1 jakllsch
232 1.7 thorpej ret = iic_acquire_bus(sc->tag, 0);
233 1.1 jakllsch if (ret)
234 1.1 jakllsch return ret;
235 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
236 1.7 thorpej &r, 1, v, 1, 0);
237 1.1 jakllsch
238 1.7 thorpej iic_release_bus(sc->tag, 0);
239 1.1 jakllsch
240 1.1 jakllsch return ret;
241 1.1 jakllsch }
242 1.1 jakllsch
243 1.1 jakllsch static int
244 1.1 jakllsch mt2131_write(struct mt2131_softc *sc, uint8_t a, uint8_t v)
245 1.1 jakllsch {
246 1.1 jakllsch int ret;
247 1.1 jakllsch uint8_t b[] = { a, v };
248 1.1 jakllsch
249 1.7 thorpej ret = iic_acquire_bus(sc->tag, 0);
250 1.1 jakllsch if (ret)
251 1.1 jakllsch return ret;
252 1.1 jakllsch
253 1.1 jakllsch ret = iic_exec(sc->tag, I2C_OP_READ_WITH_STOP, sc->addr,
254 1.7 thorpej b, sizeof(b), NULL, 0, 0);
255 1.1 jakllsch
256 1.7 thorpej iic_release_bus(sc->tag, 0);
257 1.1 jakllsch
258 1.1 jakllsch return ret;
259 1.1 jakllsch }
260 1.2 jmcneill
261 1.5 jmcneill MODULE(MODULE_CLASS_DRIVER, mt2131, "i2cexec");
262 1.2 jmcneill
263 1.2 jmcneill static int
264 1.2 jmcneill mt2131_modcmd(modcmd_t cmd, void *priv)
265 1.2 jmcneill {
266 1.2 jmcneill if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI)
267 1.2 jmcneill return 0;
268 1.2 jmcneill return ENOTTY;
269 1.2 jmcneill }
270