1 1.7 thorpej /* $NetBSD: nxt2k.c,v 1.7 2019/12/31 14:27:50 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: nxt2k.c,v 1.7 2019/12/31 14:27:50 thorpej Exp $"); 31 1.1 jakllsch 32 1.1 jakllsch #include <sys/param.h> 33 1.1 jakllsch #include <sys/kernel.h> 34 1.1 jakllsch #include <sys/systm.h> 35 1.1 jakllsch #include <sys/device.h> 36 1.1 jakllsch #include <sys/kmem.h> 37 1.1 jakllsch #include <sys/condvar.h> 38 1.1 jakllsch #include <sys/mutex.h> 39 1.2 jmcneill #include <sys/module.h> 40 1.1 jakllsch 41 1.1 jakllsch #include <dev/firmload.h> 42 1.1 jakllsch 43 1.1 jakllsch #include <dev/i2c/nxt2kvar.h> 44 1.1 jakllsch 45 1.1 jakllsch struct nxt2k { 46 1.1 jakllsch device_t parent; 47 1.1 jakllsch i2c_tag_t tag; 48 1.1 jakllsch i2c_addr_t addr; 49 1.1 jakllsch kcondvar_t cv; 50 1.1 jakllsch kmutex_t mtx; 51 1.1 jakllsch bool loaded; /* firmware is loaded? */ 52 1.1 jakllsch }; 53 1.1 jakllsch 54 1.1 jakllsch static int nxt2k_init(struct nxt2k *); 55 1.1 jakllsch 56 1.1 jakllsch static int nxt2k_writedata(struct nxt2k *, uint8_t, uint8_t *, size_t); 57 1.1 jakllsch static int nxt2k_readdata(struct nxt2k *, uint8_t, uint8_t *, size_t); 58 1.1 jakllsch static int nxt2k_writereg(struct nxt2k *, uint8_t, uint8_t *, size_t); 59 1.1 jakllsch static int nxt2k_readreg(struct nxt2k*, uint8_t, uint8_t *, size_t); 60 1.1 jakllsch 61 1.1 jakllsch static int nxt2k4_init(struct nxt2k *); 62 1.1 jakllsch static bool nxt2k4_load_firmware(struct nxt2k *); 63 1.1 jakllsch static void nxt2k4_mc_init(struct nxt2k *); 64 1.1 jakllsch static void nxt2k_mc_start(struct nxt2k *); 65 1.1 jakllsch static void nxt2k_mc_stop(struct nxt2k *); 66 1.1 jakllsch static void nxt2k_agc_reset(struct nxt2k *); 67 1.1 jakllsch static uint16_t nxt2k_crc_ccit(uint16_t, uint8_t); 68 1.1 jakllsch 69 1.1 jakllsch static int 70 1.1 jakllsch nxt2k_writedata(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len) 71 1.1 jakllsch { 72 1.1 jakllsch uint8_t buffer[384]; 73 1.1 jakllsch int error; 74 1.1 jakllsch 75 1.1 jakllsch KASSERT((len + 1) <= 384); 76 1.1 jakllsch 77 1.7 thorpej if ((error = iic_acquire_bus(nxt->tag, 0)) != 0) 78 1.6 thorpej return error; 79 1.1 jakllsch 80 1.1 jakllsch buffer[0] = reg; 81 1.1 jakllsch memcpy(&buffer[1], data, len); 82 1.1 jakllsch 83 1.1 jakllsch error = iic_exec(nxt->tag, I2C_OP_WRITE_WITH_STOP, nxt->addr, 84 1.6 thorpej buffer, len + 1, NULL, 0, 0); 85 1.1 jakllsch 86 1.6 thorpej iic_release_bus(nxt->tag, 0); 87 1.1 jakllsch 88 1.1 jakllsch return error; 89 1.1 jakllsch } 90 1.1 jakllsch 91 1.1 jakllsch static int 92 1.1 jakllsch nxt2k_readdata(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len) 93 1.1 jakllsch { 94 1.1 jakllsch int error; 95 1.1 jakllsch 96 1.7 thorpej if ((error = iic_acquire_bus(nxt->tag, 0)) != 0) 97 1.6 thorpej return error; 98 1.1 jakllsch 99 1.1 jakllsch error = iic_exec(nxt->tag, I2C_OP_READ_WITH_STOP, nxt->addr, 100 1.6 thorpej ®, 1, data, len, 0); 101 1.1 jakllsch 102 1.6 thorpej iic_release_bus(nxt->tag, 0); 103 1.1 jakllsch 104 1.1 jakllsch return error; 105 1.1 jakllsch } 106 1.1 jakllsch 107 1.1 jakllsch static int 108 1.1 jakllsch nxt2k_writereg(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len) 109 1.1 jakllsch { 110 1.1 jakllsch uint8_t attr, len2, buf; 111 1.1 jakllsch 112 1.1 jakllsch nxt2k_writedata(nxt, 0x35, ®, 1); 113 1.1 jakllsch 114 1.1 jakllsch nxt2k_writedata(nxt, 0x36, data, len); 115 1.1 jakllsch 116 1.1 jakllsch attr = 0x02; 117 1.1 jakllsch if (reg & 0x80) { 118 1.1 jakllsch attr = attr << 1; 119 1.1 jakllsch if (reg & 0x04) 120 1.1 jakllsch attr = attr >> 1; 121 1.1 jakllsch } 122 1.1 jakllsch len2 = ((attr << 4) | 0x10) | len; 123 1.1 jakllsch buf = 0x80; 124 1.1 jakllsch 125 1.1 jakllsch nxt2k_writedata(nxt, 0x34, &len2, 1); 126 1.1 jakllsch 127 1.1 jakllsch nxt2k_writedata(nxt, 0x21, &buf, 1); 128 1.1 jakllsch 129 1.1 jakllsch nxt2k_readdata(nxt, 0x21, &buf, 1); 130 1.1 jakllsch 131 1.1 jakllsch if (buf == 0) 132 1.1 jakllsch return 0; 133 1.1 jakllsch 134 1.1 jakllsch return -1; 135 1.1 jakllsch } 136 1.1 jakllsch 137 1.1 jakllsch static int 138 1.1 jakllsch nxt2k_readreg(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len) 139 1.1 jakllsch { 140 1.1 jakllsch uint8_t buf, len2, attr; 141 1.2 jmcneill unsigned int i; 142 1.1 jakllsch 143 1.1 jakllsch nxt2k_writedata(nxt, 0x35, ®, 1); 144 1.1 jakllsch 145 1.1 jakllsch attr = 0x02; 146 1.1 jakllsch if (reg & 0x80) { 147 1.1 jakllsch attr = attr << 1; 148 1.1 jakllsch if (reg & 0x04) 149 1.1 jakllsch attr = attr >> 1; 150 1.1 jakllsch } 151 1.1 jakllsch 152 1.1 jakllsch len2 = (attr << 4) | len; 153 1.1 jakllsch nxt2k_writedata(nxt, 0x34, &len2, 1); 154 1.1 jakllsch 155 1.1 jakllsch buf = 0x80; 156 1.1 jakllsch nxt2k_writedata(nxt, 0x21, &buf, 1); 157 1.1 jakllsch 158 1.1 jakllsch for(i = 0; i < len; i++) { 159 1.1 jakllsch nxt2k_readdata(nxt, 0x36+i, &data[i], 1); 160 1.1 jakllsch } 161 1.1 jakllsch 162 1.1 jakllsch return 0; 163 1.1 jakllsch } 164 1.1 jakllsch 165 1.1 jakllsch static void 166 1.1 jakllsch nxt2k_agc_reset(struct nxt2k *nxt) 167 1.1 jakllsch { 168 1.1 jakllsch uint8_t byte; 169 1.1 jakllsch nxt2k_readreg(nxt, 0x08, &byte, 1); 170 1.1 jakllsch byte = 0x08; 171 1.1 jakllsch nxt2k_writereg(nxt, 0x08, &byte, 1); 172 1.1 jakllsch byte = 0x00; 173 1.1 jakllsch nxt2k_writereg(nxt, 0x08, &byte, 1); 174 1.1 jakllsch return; 175 1.1 jakllsch } 176 1.1 jakllsch 177 1.1 jakllsch static void 178 1.1 jakllsch nxt2k_mc_stop(struct nxt2k *nxt) 179 1.1 jakllsch { 180 1.1 jakllsch int counter; 181 1.1 jakllsch uint8_t stopval, buf; 182 1.1 jakllsch 183 1.1 jakllsch /* 2k4 */ 184 1.1 jakllsch stopval = 0x10; 185 1.1 jakllsch 186 1.1 jakllsch buf = 0x80; 187 1.1 jakllsch nxt2k_writedata(nxt, 0x22, &buf, 1); 188 1.1 jakllsch 189 1.1 jakllsch for(counter = 0; counter < 20; counter++) { 190 1.1 jakllsch nxt2k_readdata(nxt, 0x31, &buf, 1); 191 1.1 jakllsch if (buf & stopval) 192 1.1 jakllsch return; 193 1.1 jakllsch mutex_enter(&nxt->mtx); 194 1.1 jakllsch cv_timedwait(&nxt->cv, &nxt->mtx, mstohz(10)); 195 1.1 jakllsch mutex_exit(&nxt->mtx); 196 1.1 jakllsch } 197 1.1 jakllsch 198 1.1 jakllsch printf("%s timeout\n", __func__); 199 1.1 jakllsch 200 1.1 jakllsch return; 201 1.1 jakllsch } 202 1.1 jakllsch 203 1.1 jakllsch static void 204 1.1 jakllsch nxt2k_mc_start(struct nxt2k *nxt) 205 1.1 jakllsch { 206 1.1 jakllsch uint8_t buf; 207 1.1 jakllsch 208 1.1 jakllsch buf = 0x00; 209 1.1 jakllsch nxt2k_writedata(nxt, 0x22, &buf, 1); 210 1.1 jakllsch } 211 1.1 jakllsch 212 1.1 jakllsch static void 213 1.1 jakllsch nxt2k4_mc_init(struct nxt2k *nxt) 214 1.1 jakllsch { 215 1.1 jakllsch uint8_t byte; 216 1.1 jakllsch uint8_t data[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xC0}; 217 1.1 jakllsch int counter; 218 1.1 jakllsch 219 1.1 jakllsch byte = 0x00; 220 1.1 jakllsch nxt2k_writedata(nxt, 0x2b, &byte, 1); 221 1.1 jakllsch byte = 0x70; 222 1.1 jakllsch nxt2k_writedata(nxt, 0x34, &byte, 1); 223 1.1 jakllsch byte = 0x04; 224 1.1 jakllsch nxt2k_writedata(nxt, 0x35, &byte, 1); 225 1.1 jakllsch 226 1.1 jakllsch nxt2k_writedata(nxt, 0x36, data, 9); 227 1.1 jakllsch 228 1.1 jakllsch byte = 0x80; 229 1.1 jakllsch nxt2k_writedata(nxt, 0x21, &byte, 1); 230 1.1 jakllsch 231 1.1 jakllsch for(counter = 0; counter < 20; counter++) { 232 1.1 jakllsch nxt2k_readdata(nxt, 0x21, &byte, 1); 233 1.1 jakllsch if ( byte == 0 ) 234 1.1 jakllsch return; 235 1.1 jakllsch mutex_enter(&nxt->mtx); 236 1.1 jakllsch cv_timedwait(&nxt->cv, &nxt->mtx, mstohz(25)); 237 1.1 jakllsch mutex_exit(&nxt->mtx); 238 1.1 jakllsch } 239 1.1 jakllsch 240 1.1 jakllsch printf("%s timeout\n", __func__); 241 1.1 jakllsch 242 1.1 jakllsch return; 243 1.1 jakllsch } 244 1.1 jakllsch 245 1.1 jakllsch /* CRC-CCIT */ 246 1.1 jakllsch static uint16_t 247 1.1 jakllsch nxt2k_crc_ccit(uint16_t crc, uint8_t byte) 248 1.1 jakllsch { 249 1.1 jakllsch int i; 250 1.1 jakllsch uint16_t input; 251 1.1 jakllsch 252 1.1 jakllsch input = byte << 8; 253 1.1 jakllsch 254 1.1 jakllsch for(i = 0; i < 8; i++) { 255 1.1 jakllsch if ((crc ^ input) & 0x8000) 256 1.1 jakllsch crc = (crc << 1) ^ 0x1021; 257 1.1 jakllsch else 258 1.1 jakllsch crc = (crc << 1); 259 1.1 jakllsch input = input << 1; 260 1.1 jakllsch } 261 1.1 jakllsch return crc; 262 1.1 jakllsch } 263 1.1 jakllsch 264 1.1 jakllsch static bool 265 1.1 jakllsch nxt2k4_load_firmware(struct nxt2k *nxt) 266 1.1 jakllsch { 267 1.1 jakllsch firmware_handle_t fh; 268 1.1 jakllsch uint8_t *blob; 269 1.1 jakllsch size_t fwsize; 270 1.1 jakllsch size_t position; 271 1.1 jakllsch int error; 272 1.1 jakllsch uint16_t crc; 273 1.1 jakllsch 274 1.1 jakllsch error = firmware_open("nxt2k", "dvb-fe-nxt2004.fw", &fh); 275 1.1 jakllsch if (error != 0) { 276 1.1 jakllsch printf("nxt2k firmware_open fail %d\n", error); 277 1.1 jakllsch return 0; 278 1.1 jakllsch } 279 1.1 jakllsch 280 1.1 jakllsch fwsize = firmware_get_size(fh); 281 1.1 jakllsch printf("fwsize %zd\n", fwsize); 282 1.1 jakllsch blob = firmware_malloc(fwsize); 283 1.1 jakllsch if ( blob == NULL ) { 284 1.1 jakllsch printf("nxt2k firmware_malloc fail\n"); 285 1.1 jakllsch firmware_close(fh); 286 1.1 jakllsch return -1; 287 1.1 jakllsch } 288 1.1 jakllsch 289 1.1 jakllsch error = firmware_read(fh, 0, blob, fwsize); 290 1.1 jakllsch if (error != 0) { 291 1.1 jakllsch printf("nxt2k firmware_read fail %d\n", error); 292 1.1 jakllsch firmware_free(blob, fwsize); 293 1.1 jakllsch firmware_close(fh); 294 1.1 jakllsch return -1; 295 1.1 jakllsch } 296 1.1 jakllsch 297 1.1 jakllsch /* calculate CRC */ 298 1.1 jakllsch crc = 0; 299 1.1 jakllsch for(position = 0; position < fwsize; position++) { 300 1.1 jakllsch crc = nxt2k_crc_ccit(crc, blob[position]); 301 1.1 jakllsch } 302 1.1 jakllsch printf("nxt2k firmware crc is %02x\n", crc); 303 1.1 jakllsch 304 1.1 jakllsch uint16_t rambase; 305 1.1 jakllsch uint8_t buf[3]; 306 1.1 jakllsch 307 1.1 jakllsch rambase = 0x1000; 308 1.1 jakllsch 309 1.1 jakllsch /* hold the micro in reset while loading firmware */ 310 1.1 jakllsch buf[0] = 0x80; 311 1.1 jakllsch nxt2k_writedata(nxt, 0x2b, buf, 1); 312 1.1 jakllsch 313 1.1 jakllsch buf[0] = rambase >> 8; 314 1.1 jakllsch buf[1] = rambase & 0xFF; 315 1.1 jakllsch buf[2] = 0x81; 316 1.1 jakllsch /* write starting address */ 317 1.1 jakllsch nxt2k_writedata(nxt, 0x29, buf, 3); 318 1.1 jakllsch 319 1.1 jakllsch position = 0; 320 1.1 jakllsch 321 1.1 jakllsch size_t xfercnt; 322 1.1 jakllsch 323 1.1 jakllsch while ( position < fwsize ) { 324 1.1 jakllsch xfercnt = fwsize - position > 255 ? 255 : fwsize - position; 325 1.1 jakllsch nxt2k_writedata(nxt, 0x2c, &blob[position], xfercnt); 326 1.1 jakllsch position += xfercnt; 327 1.1 jakllsch } 328 1.1 jakllsch 329 1.1 jakllsch /* write crc */ 330 1.1 jakllsch buf[0] = crc >> 8; 331 1.1 jakllsch buf[1] = crc & 0xFF; 332 1.1 jakllsch nxt2k_writedata(nxt, 0x2c, buf, 2); 333 1.1 jakllsch 334 1.1 jakllsch /* do a read to stop things */ 335 1.1 jakllsch nxt2k_readdata(nxt, 0x2c, buf, 1); 336 1.1 jakllsch 337 1.1 jakllsch /* set transfer mode to complete */ 338 1.1 jakllsch buf[0] = 0x80; 339 1.1 jakllsch nxt2k_writedata(nxt, 0x2b, buf, 1); 340 1.1 jakllsch 341 1.1 jakllsch firmware_free(blob, fwsize); 342 1.1 jakllsch firmware_close(fh); 343 1.1 jakllsch 344 1.1 jakllsch return 1; 345 1.1 jakllsch } 346 1.1 jakllsch 347 1.1 jakllsch static int 348 1.1 jakllsch nxt2k4_init(struct nxt2k *nxt) 349 1.1 jakllsch { 350 1.1 jakllsch int success; 351 1.1 jakllsch uint8_t buf[3]; 352 1.1 jakllsch 353 1.1 jakllsch buf[0] = 0x00; 354 1.1 jakllsch nxt2k_writedata(nxt, 0x1e, buf, 1); 355 1.1 jakllsch 356 1.1 jakllsch /* try to load firmware */ 357 1.1 jakllsch nxt->loaded = nxt2k4_load_firmware(nxt); 358 1.1 jakllsch if (nxt->loaded == false) 359 1.1 jakllsch return ECANCELED; 360 1.1 jakllsch 361 1.1 jakllsch /* ensure transfer is complete */ 362 1.1 jakllsch buf[0] = 0x01; 363 1.1 jakllsch nxt2k_writedata(nxt, 0x19, buf, 1); 364 1.1 jakllsch 365 1.1 jakllsch nxt2k4_mc_init(nxt); 366 1.1 jakllsch nxt2k_mc_stop(nxt); 367 1.1 jakllsch nxt2k_mc_stop(nxt); 368 1.1 jakllsch nxt2k4_mc_init(nxt); 369 1.1 jakllsch nxt2k_mc_stop(nxt); 370 1.1 jakllsch 371 1.1 jakllsch buf[0] = 0xff; 372 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 373 1.1 jakllsch buf[0] = 0x00; 374 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 375 1.1 jakllsch 376 1.1 jakllsch buf[0] = 0xD7; 377 1.1 jakllsch nxt2k_writedata(nxt, 0xd7, buf, 1); 378 1.1 jakllsch 379 1.1 jakllsch buf[0] = 0x07; 380 1.1 jakllsch buf[1] = 0xfe; 381 1.1 jakllsch nxt2k_writedata(nxt, 0x35, buf, 2); 382 1.1 jakllsch buf[0] = 0x12; 383 1.1 jakllsch nxt2k_writedata(nxt, 0x34, buf, 1); 384 1.1 jakllsch buf[0] = 0x80; 385 1.1 jakllsch nxt2k_writedata(nxt, 0x21, buf, 1); 386 1.1 jakllsch 387 1.1 jakllsch buf[0] = 0x21; 388 1.1 jakllsch nxt2k_writedata(nxt, 0x0a, buf, 1); 389 1.1 jakllsch 390 1.1 jakllsch buf[0] = 0x01; 391 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 392 1.1 jakllsch 393 1.1 jakllsch /* fec mpeg mode */ 394 1.1 jakllsch buf[0] = 0x7E; 395 1.1 jakllsch buf[1] = 0x00; 396 1.1 jakllsch nxt2k_writedata(nxt, 0xe9, buf, 2); 397 1.1 jakllsch 398 1.1 jakllsch /* mux selection */ 399 1.1 jakllsch buf[0] = 0x00; 400 1.1 jakllsch nxt2k_writedata(nxt, 0xcc, buf, 1); 401 1.1 jakllsch 402 1.1 jakllsch /* */ 403 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 404 1.1 jakllsch buf[0] = 0x00; 405 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 406 1.1 jakllsch 407 1.1 jakllsch /* soft reset? */ 408 1.1 jakllsch nxt2k_readreg(nxt, 0x08, buf, 1); 409 1.1 jakllsch buf[0] = 0x10; 410 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 411 1.1 jakllsch nxt2k_readreg(nxt, 0x08, buf, 1); 412 1.1 jakllsch buf[0] = 0x00; 413 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 414 1.1 jakllsch 415 1.1 jakllsch /* */ 416 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 417 1.1 jakllsch buf[0] = 0x01; 418 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 419 1.1 jakllsch buf[0] = 0x70; 420 1.1 jakllsch nxt2k_writereg(nxt, 0x81, buf, 1); 421 1.1 jakllsch buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66; 422 1.1 jakllsch nxt2k_writereg(nxt, 0x82, buf, 3); 423 1.1 jakllsch 424 1.1 jakllsch nxt2k_readreg(nxt, 0x88, buf, 1); 425 1.1 jakllsch buf[0] = 0x11; 426 1.1 jakllsch nxt2k_writereg(nxt, 0x88, buf, 1); 427 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 428 1.1 jakllsch buf[0] = 0x40; 429 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 430 1.1 jakllsch 431 1.1 jakllsch nxt2k_readdata(nxt, 0x10, buf, 1); 432 1.1 jakllsch buf[0] = 0x10; 433 1.1 jakllsch nxt2k_writedata(nxt, 0x10, buf, 1); 434 1.1 jakllsch nxt2k_readdata(nxt, 0x0a, buf, 1); 435 1.1 jakllsch buf[0] = 0x21; 436 1.1 jakllsch nxt2k_writedata(nxt, 0x0a, buf, 1); 437 1.1 jakllsch 438 1.1 jakllsch nxt2k4_mc_init(nxt); 439 1.1 jakllsch 440 1.1 jakllsch buf[0] = 0x21; 441 1.1 jakllsch nxt2k_writedata(nxt, 0x0a, buf, 1); 442 1.1 jakllsch buf[0] = 0x7e; 443 1.1 jakllsch nxt2k_writedata(nxt, 0xe9, buf, 1); 444 1.1 jakllsch buf[0] = 0x00; 445 1.1 jakllsch nxt2k_writedata(nxt, 0xea, buf, 1); 446 1.1 jakllsch 447 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 448 1.1 jakllsch buf[0] = 0x00; 449 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 450 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 451 1.1 jakllsch buf[0] = 0x00; 452 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 453 1.1 jakllsch 454 1.1 jakllsch nxt2k_readreg(nxt, 0x08, buf, 1); 455 1.1 jakllsch buf[0] = 0x10; 456 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 457 1.1 jakllsch nxt2k_readreg(nxt, 0x08, buf, 1); 458 1.1 jakllsch buf[0] = 0x00; 459 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 460 1.1 jakllsch 461 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 462 1.1 jakllsch buf[0] = 0x04; 463 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 464 1.1 jakllsch buf[0] = 0x00; 465 1.1 jakllsch nxt2k_writereg(nxt, 0x81, buf, 1); 466 1.1 jakllsch buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00; 467 1.1 jakllsch nxt2k_writereg(nxt, 0x82, buf, 3); 468 1.1 jakllsch 469 1.1 jakllsch nxt2k_readreg(nxt, 0x88, buf, 1); 470 1.1 jakllsch buf[0] = 0x11; 471 1.1 jakllsch nxt2k_writereg(nxt, 0x88, buf, 1); 472 1.1 jakllsch 473 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 474 1.1 jakllsch buf[0] = 0x44; 475 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 476 1.1 jakllsch 477 1.1 jakllsch /* init tuner */ 478 1.1 jakllsch nxt2k_readdata(nxt, 0x10, buf, 1); 479 1.1 jakllsch buf[0] = 0x12; 480 1.1 jakllsch nxt2k_writedata(nxt, 0x10, buf,1); 481 1.1 jakllsch buf[0] = 0x04; 482 1.1 jakllsch nxt2k_writedata(nxt, 0x13, buf,1); 483 1.1 jakllsch buf[0] = 0x00; 484 1.1 jakllsch nxt2k_writedata(nxt, 0x16, buf,1); 485 1.1 jakllsch buf[0] = 0x04; 486 1.1 jakllsch nxt2k_writedata(nxt, 0x14, buf,1); 487 1.1 jakllsch buf[0] = 0x00; 488 1.1 jakllsch nxt2k_writedata(nxt, 0x14, buf,1); 489 1.1 jakllsch nxt2k_writedata(nxt, 0x17, buf,1); 490 1.1 jakllsch nxt2k_writedata(nxt, 0x14, buf,1); 491 1.1 jakllsch nxt2k_writedata(nxt, 0x17, buf,1); 492 1.1 jakllsch 493 1.1 jakllsch success = 1; 494 1.1 jakllsch return success; 495 1.1 jakllsch } 496 1.1 jakllsch 497 1.1 jakllsch uint16_t 498 1.1 jakllsch nxt2k_get_signal(struct nxt2k *nxt) 499 1.1 jakllsch { 500 1.1 jakllsch uint16_t temp; 501 1.1 jakllsch uint8_t b[2]; 502 1.1 jakllsch 503 1.1 jakllsch b[0] = 0x00; 504 1.1 jakllsch nxt2k_writedata(nxt, 0xa1, b, 1); 505 1.1 jakllsch 506 1.1 jakllsch nxt2k_readreg(nxt, 0xa6, b, 2); 507 1.1 jakllsch 508 1.1 jakllsch temp = (b[0] << 8) | b[1]; 509 1.1 jakllsch 510 1.1 jakllsch printf("a6: %04hx\n", temp); 511 1.1 jakllsch 512 1.1 jakllsch return 0x7fff - temp * 16; 513 1.1 jakllsch } 514 1.1 jakllsch 515 1.1 jakllsch uint16_t 516 1.1 jakllsch nxt2k_get_snr(struct nxt2k *nxt) 517 1.1 jakllsch { 518 1.1 jakllsch uint32_t tsnr; 519 1.1 jakllsch uint16_t temp, temp2; 520 1.1 jakllsch uint8_t b[2]; 521 1.1 jakllsch 522 1.1 jakllsch b[0] = 0x00; 523 1.1 jakllsch nxt2k_writedata(nxt, 0xa1, b, 1); 524 1.1 jakllsch 525 1.1 jakllsch nxt2k_readreg(nxt, 0xa6, b, 2); 526 1.1 jakllsch 527 1.1 jakllsch temp = (b[0] << 8) | b[1]; 528 1.1 jakllsch 529 1.1 jakllsch temp2 = 0x7fff - temp; 530 1.1 jakllsch 531 1.1 jakllsch printf("snr temp2: %04hx\n", temp2); 532 1.1 jakllsch 533 1.1 jakllsch if (temp2 > 0x7f00) 534 1.1 jakllsch tsnr = 1000*24+(1000*(30-24)*(temp2-0x7f00)/(0x7fff-0x7f00)); 535 1.1 jakllsch else if ( temp2 > 0x7ec0) 536 1.1 jakllsch tsnr = 1000*18+(1000*(24-18)*(temp2-0x7ec0)/(0x7f00-0x7ec0)); 537 1.1 jakllsch else if ( temp2 > 0x7c00) 538 1.1 jakllsch tsnr = 1000*12+(1000*(18-12)*(temp2-0x7c00)/(0x7ec0-0x7c00)); 539 1.1 jakllsch else 540 1.1 jakllsch tsnr = 1000*0+(1000*(12-0)*(temp2-0)/(0x7c00-0)); 541 1.1 jakllsch 542 1.1 jakllsch printf("snr tsnr: %08x\n", tsnr); 543 1.1 jakllsch 544 1.1 jakllsch return ((tsnr * 0xffff)/32000); 545 1.1 jakllsch } 546 1.1 jakllsch 547 1.1 jakllsch fe_status_t 548 1.1 jakllsch nxt2k_get_dtv_status(struct nxt2k *nxt) 549 1.1 jakllsch { 550 1.1 jakllsch uint8_t reg; 551 1.1 jakllsch fe_status_t status = 0; 552 1.1 jakllsch 553 1.1 jakllsch nxt2k_readdata(nxt, 0x31, ®, 1); 554 1.1 jakllsch if (reg & 0x20) { 555 1.1 jakllsch status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | 556 1.1 jakllsch FE_HAS_SYNC | FE_HAS_LOCK; 557 1.1 jakllsch } 558 1.1 jakllsch 559 1.1 jakllsch return status; 560 1.1 jakllsch } 561 1.1 jakllsch 562 1.1 jakllsch #if notyet 563 1.1 jakllsch int 564 1.1 jakllsch nxt2k_fe_read_ucblocks(struct nxt2k *nxt, uint32_t *ucblk) 565 1.1 jakllsch { 566 1.1 jakllsch uint8_t reg[3]; 567 1.1 jakllsch 568 1.1 jakllsch nxt2k_readreg(nxt, 0xe6, reg, 3); 569 1.1 jakllsch *ucblk = reg[2]; 570 1.1 jakllsch 571 1.1 jakllsch return 0; 572 1.1 jakllsch } 573 1.1 jakllsch 574 1.1 jakllsch int 575 1.1 jakllsch nxt2k_fe_read_ber(struct nxt2k *nxt, uint32_t *ber) 576 1.1 jakllsch { 577 1.1 jakllsch uint8_t reg[3]; 578 1.1 jakllsch 579 1.1 jakllsch nxt2k_readreg(nxt, 0xe6, reg, 3); 580 1.1 jakllsch 581 1.1 jakllsch *ber = ((reg[0] << 8) + reg[1]) * 8; 582 1.1 jakllsch 583 1.1 jakllsch return 0; 584 1.1 jakllsch } 585 1.1 jakllsch #endif 586 1.1 jakllsch 587 1.1 jakllsch static int 588 1.1 jakllsch nxt2k_fe_set_frontend(struct nxt2k *nxt, fe_modulation_t modulation) 589 1.1 jakllsch { 590 1.1 jakllsch uint8_t buf[5]; 591 1.1 jakllsch 592 1.1 jakllsch if (nxt->loaded != true) 593 1.1 jakllsch nxt2k4_init(nxt); 594 1.1 jakllsch 595 1.1 jakllsch nxt2k_mc_stop(nxt); 596 1.1 jakllsch 597 1.1 jakllsch { /* 2k4 */ 598 1.1 jakllsch /* make sure demod is set to digital */ 599 1.1 jakllsch buf[0] = 0x04; 600 1.1 jakllsch nxt2k_writedata(nxt, 0x14, buf, 1); 601 1.1 jakllsch buf[0] = 0x00; 602 1.1 jakllsch nxt2k_writedata(nxt, 0x17, buf, 1); 603 1.1 jakllsch } 604 1.1 jakllsch 605 1.1 jakllsch /* QAM/VSB punctured/non-punctured goes here */ 606 1.1 jakllsch 607 1.1 jakllsch /* tune in */ 608 1.1 jakllsch /* maybe ensure tuner managed to tune in? */ 609 1.1 jakllsch 610 1.1 jakllsch /* tuning done, reset agc */ 611 1.1 jakllsch nxt2k_agc_reset(nxt); 612 1.1 jakllsch 613 1.1 jakllsch /* set target power level */ 614 1.1 jakllsch switch (modulation) { 615 1.1 jakllsch case VSB_8: 616 1.1 jakllsch buf[0] = 0x70; 617 1.1 jakllsch break; 618 1.1 jakllsch case QAM_256: 619 1.1 jakllsch case QAM_64: 620 1.1 jakllsch buf[0] = 0x74; 621 1.1 jakllsch break; 622 1.1 jakllsch default: 623 1.1 jakllsch return EINVAL; 624 1.1 jakllsch /* NOTREACHED */ 625 1.1 jakllsch } 626 1.1 jakllsch nxt2k_writedata(nxt, 0x42, buf, 1); 627 1.1 jakllsch 628 1.1 jakllsch /* configure sdm */ 629 1.1 jakllsch buf[0] = 0x07; /* 2k4 */ 630 1.1 jakllsch nxt2k_writedata(nxt, 0x57, buf, 1); 631 1.1 jakllsch 632 1.1 jakllsch /* write sdm1 input */ 633 1.1 jakllsch buf[0] = 0x10; 634 1.1 jakllsch buf[1] = 0x00; 635 1.1 jakllsch nxt2k_writedata(nxt, 0x58, buf, 2); /* 2k4 */ 636 1.1 jakllsch 637 1.1 jakllsch /* write sdmx input */ 638 1.1 jakllsch switch (modulation) { 639 1.1 jakllsch case VSB_8: 640 1.1 jakllsch buf[0] = 0x60; 641 1.1 jakllsch break; 642 1.1 jakllsch case QAM_256: 643 1.1 jakllsch buf[0] = 0x64; 644 1.1 jakllsch break; 645 1.1 jakllsch case QAM_64: 646 1.1 jakllsch buf[0] = 0x68; 647 1.1 jakllsch break; 648 1.1 jakllsch default: 649 1.1 jakllsch return EINVAL; 650 1.1 jakllsch /* NOTREACHED */ 651 1.1 jakllsch } 652 1.1 jakllsch buf[1] = 0x00; 653 1.1 jakllsch nxt2k_writedata(nxt, 0x5c, buf, 2); /* 2k4 */ 654 1.1 jakllsch 655 1.1 jakllsch /* write adc power lpf fc */ 656 1.1 jakllsch buf[0] = 0x05; 657 1.1 jakllsch nxt2k_writedata(nxt, 0x43, buf, 1); 658 1.1 jakllsch 659 1.1 jakllsch { /* 2k4 */ 660 1.1 jakllsch buf[0] = 0x00; 661 1.1 jakllsch buf[1] = 0x00; 662 1.1 jakllsch nxt2k_writedata(nxt, 0x46, buf, 2); 663 1.1 jakllsch } 664 1.1 jakllsch 665 1.1 jakllsch /* write accumulator2 input */ 666 1.1 jakllsch buf[0] = 0x80; 667 1.1 jakllsch buf[1] = 0x00; 668 1.1 jakllsch nxt2k_writedata(nxt, 0x4b, buf, 2); /* 2k4 */ 669 1.1 jakllsch 670 1.1 jakllsch /* write kg1 */ 671 1.1 jakllsch buf[0] = 0x00; 672 1.1 jakllsch nxt2k_writedata(nxt, 0x4d, buf, 1); 673 1.1 jakllsch 674 1.1 jakllsch /* write sdm12 lpf fc */ 675 1.1 jakllsch buf[0] = 0x44; 676 1.1 jakllsch nxt2k_writedata(nxt, 0x55, buf, 1); 677 1.1 jakllsch 678 1.1 jakllsch /* write agc control reg */ 679 1.1 jakllsch buf[0] = 0x04; 680 1.1 jakllsch nxt2k_writedata(nxt, 0x41, buf, 1); 681 1.1 jakllsch 682 1.1 jakllsch { /* 2k4 */ 683 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 684 1.1 jakllsch buf[0] = 0x24; 685 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 686 1.1 jakllsch 687 1.1 jakllsch /* soft reset? */ 688 1.1 jakllsch nxt2k_readreg(nxt, 0x08, buf, 1); 689 1.1 jakllsch buf[0] = 0x10; 690 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 691 1.1 jakllsch nxt2k_readreg(nxt, 0x08, buf, 1); 692 1.1 jakllsch buf[0] = 0x00; 693 1.1 jakllsch nxt2k_writereg(nxt, 0x08, buf, 1); 694 1.1 jakllsch 695 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 696 1.1 jakllsch buf[0] = 0x04; 697 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 698 1.1 jakllsch 699 1.1 jakllsch buf[0] = 0x00; 700 1.1 jakllsch nxt2k_writereg(nxt, 0x81, buf, 1); 701 1.1 jakllsch 702 1.1 jakllsch buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00; 703 1.1 jakllsch nxt2k_writereg(nxt, 0x82, buf, 3); 704 1.1 jakllsch 705 1.1 jakllsch nxt2k_readreg(nxt, 0x88, buf, 1); 706 1.1 jakllsch buf[0] = 0x11; 707 1.1 jakllsch nxt2k_writereg(nxt, 0x88, buf, 1); 708 1.1 jakllsch 709 1.1 jakllsch nxt2k_readreg(nxt, 0x80, buf, 1); 710 1.1 jakllsch buf[0] = 0x44; 711 1.1 jakllsch nxt2k_writereg(nxt, 0x80, buf, 1); 712 1.1 jakllsch } 713 1.1 jakllsch 714 1.1 jakllsch /* write agc ucgp0 */ 715 1.1 jakllsch switch (modulation) { 716 1.1 jakllsch case VSB_8: 717 1.1 jakllsch buf[0] = 0x00; 718 1.1 jakllsch break; 719 1.1 jakllsch case QAM_64: 720 1.1 jakllsch buf[0] = 0x02; 721 1.1 jakllsch break; 722 1.1 jakllsch case QAM_256: 723 1.1 jakllsch buf[0] = 0x03; 724 1.1 jakllsch break; 725 1.1 jakllsch default: 726 1.1 jakllsch return EINVAL; 727 1.1 jakllsch /* NOTREACHED */ 728 1.1 jakllsch } 729 1.1 jakllsch nxt2k_writedata(nxt, 0x30, buf, 1); 730 1.1 jakllsch 731 1.1 jakllsch /* write agc control reg */ 732 1.1 jakllsch buf[0] = 0x00; 733 1.1 jakllsch nxt2k_writedata(nxt, 0x41, buf, 1); 734 1.1 jakllsch 735 1.1 jakllsch /* write accumulator2 input */ 736 1.1 jakllsch buf[0] = 0x80; 737 1.1 jakllsch buf[1] = 0x00; 738 1.1 jakllsch { /* 2k4 */ 739 1.1 jakllsch nxt2k_writedata(nxt, 0x49, buf, 2); 740 1.1 jakllsch nxt2k_writedata(nxt, 0x4b, buf, 2); 741 1.1 jakllsch } 742 1.1 jakllsch 743 1.1 jakllsch /* write agc control reg */ 744 1.1 jakllsch buf[0] = 0x04; 745 1.1 jakllsch nxt2k_writedata(nxt, 0x41, buf, 1); 746 1.1 jakllsch 747 1.1 jakllsch nxt2k_mc_start(nxt); 748 1.1 jakllsch 749 1.1 jakllsch { /* 2k4 */ 750 1.1 jakllsch nxt2k4_mc_init(nxt); 751 1.1 jakllsch buf[0] = 0xf0; 752 1.1 jakllsch buf[1] = 0x00; 753 1.1 jakllsch nxt2k_writedata(nxt, 0x5c, buf, 2); 754 1.1 jakllsch } 755 1.1 jakllsch 756 1.1 jakllsch /* "adjacent channel detection" code would go here */ 757 1.1 jakllsch 758 1.1 jakllsch return 0; 759 1.1 jakllsch } 760 1.1 jakllsch 761 1.1 jakllsch static int 762 1.1 jakllsch nxt2k_init(struct nxt2k *nxt) 763 1.1 jakllsch { 764 1.1 jakllsch int ret = 0; 765 1.1 jakllsch 766 1.1 jakllsch printf("%s\n", __func__); 767 1.1 jakllsch 768 1.1 jakllsch if (nxt->loaded != 1) 769 1.1 jakllsch ret = nxt2k4_init(nxt); 770 1.1 jakllsch 771 1.1 jakllsch return ret; 772 1.1 jakllsch } 773 1.1 jakllsch 774 1.1 jakllsch 775 1.1 jakllsch struct nxt2k * 776 1.1 jakllsch nxt2k_open(device_t parent, i2c_tag_t tag, i2c_addr_t addr, unsigned int if_freq) 777 1.1 jakllsch { 778 1.1 jakllsch struct nxt2k *nxt; 779 1.1 jakllsch int e; 780 1.1 jakllsch uint8_t b[5]; 781 1.1 jakllsch 782 1.1 jakllsch nxt = kmem_alloc(sizeof(*nxt), KM_SLEEP); 783 1.1 jakllsch nxt->parent = parent; 784 1.1 jakllsch nxt->tag = tag; 785 1.1 jakllsch nxt->addr = addr; 786 1.1 jakllsch 787 1.1 jakllsch /* read chip ids */ 788 1.1 jakllsch e = nxt2k_readdata(nxt, 0x00, b, 5); 789 1.1 jakllsch 790 1.1 jakllsch if (e) { 791 1.1 jakllsch printf("%s read failed %d\n", __func__, e); 792 1.1 jakllsch kmem_free(nxt, sizeof(*nxt)); 793 1.1 jakllsch return NULL; 794 1.1 jakllsch } 795 1.1 jakllsch 796 1.1 jakllsch if (b[0] != 0x05) { 797 1.1 jakllsch printf("%s unsupported %02x %02x %02x %02x %02x\n", 798 1.1 jakllsch __func__, b[0], b[1], b[2], b[3], b[4]); 799 1.1 jakllsch kmem_free(nxt, sizeof(*nxt)); 800 1.1 jakllsch return NULL; 801 1.1 jakllsch } 802 1.1 jakllsch 803 1.1 jakllsch mutex_init(&nxt->mtx, MUTEX_DEFAULT, IPL_NONE); 804 1.1 jakllsch cv_init(&nxt->cv, "nxtpl"); 805 1.1 jakllsch 806 1.1 jakllsch nxt->loaded = false; 807 1.1 jakllsch 808 1.1 jakllsch return nxt; 809 1.1 jakllsch } 810 1.1 jakllsch 811 1.1 jakllsch void 812 1.1 jakllsch nxt2k_close(struct nxt2k *nxt) 813 1.1 jakllsch { 814 1.1 jakllsch kmem_free(nxt, sizeof(*nxt)); 815 1.1 jakllsch } 816 1.1 jakllsch 817 1.1 jakllsch void 818 1.1 jakllsch nxt2k_enable(struct nxt2k *nxt, bool enable) 819 1.1 jakllsch { 820 1.1 jakllsch if (enable == true) 821 1.1 jakllsch nxt2k_init(nxt); 822 1.1 jakllsch } 823 1.1 jakllsch 824 1.1 jakllsch int 825 1.1 jakllsch nxt2k_set_modulation(struct nxt2k *nxt, fe_modulation_t modulation) 826 1.1 jakllsch { 827 1.1 jakllsch return nxt2k_fe_set_frontend(nxt, modulation); 828 1.1 jakllsch } 829 1.2 jmcneill 830 1.4 jmcneill MODULE(MODULE_CLASS_DRIVER, nxt2k, "i2cexec"); 831 1.2 jmcneill 832 1.2 jmcneill static int 833 1.2 jmcneill nxt2k_modcmd(modcmd_t cmd, void *opaque) 834 1.2 jmcneill { 835 1.2 jmcneill if (cmd == MODULE_CMD_INIT || cmd == MODULE_CMD_FINI) 836 1.2 jmcneill return 0; 837 1.2 jmcneill return ENOTTY; 838 1.2 jmcneill } 839