Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/i2c Add subdriver for Nextwave (subsequently acquire...



details:   https://anonhg.NetBSD.org/src/rev/15c0724e11f3
branches:  trunk
changeset: 767195:15c0724e11f3
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Mon Jul 11 00:30:23 2011 +0000

description:
Add subdriver for Nextwave (subsequently acquired by ATI, then AMD, and
finally Broadcom) NXT200x series of 8VSB/QAM demodulator.

Still a bit crude and only supports the NXT2004 at this point.

diffstat:

 sys/dev/i2c/files.i2c  |    6 +-
 sys/dev/i2c/nxt2k.c    |  830 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/i2c/nxt2kvar.h |   45 ++
 3 files changed, 880 insertions(+), 1 deletions(-)

diffs (truncated from 903 to 300 lines):

diff -r e7fa56b391d6 -r 15c0724e11f3 sys/dev/i2c/files.i2c
--- a/sys/dev/i2c/files.i2c     Mon Jul 11 00:01:51 2011 +0000
+++ b/sys/dev/i2c/files.i2c     Mon Jul 11 00:30:23 2011 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.i2c,v 1.35 2011/07/11 00:01:51 jakllsch Exp $
+#      $NetBSD: files.i2c,v 1.36 2011/07/11 00:30:23 jakllsch Exp $
 
 defflag        opt_i2cbus.h                            I2C_SCAN
 define i2cbus { }
@@ -26,6 +26,10 @@
 file   dev/i2c/tvpll.c                         tvpll
 file   dev/i2c/tvpll_tuners.c                  tvpll
 
+# Nextwave NXT200x demodulator
+define nxt2k: i2cexec
+file   dev/i2c/nxt2k.c                         nxt2k
+
 #
 # I2C master devices
 #
diff -r e7fa56b391d6 -r 15c0724e11f3 sys/dev/i2c/nxt2k.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/i2c/nxt2k.c       Mon Jul 11 00:30:23 2011 +0000
@@ -0,0 +1,830 @@
+/* $NetBSD: nxt2k.c,v 1.1 2011/07/11 00:30:23 jakllsch Exp $ */
+
+/*
+ * Copyright (c) 2008, 2011 Jonathan A. Kollasch
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: nxt2k.c,v 1.1 2011/07/11 00:30:23 jakllsch Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/condvar.h>
+#include <sys/mutex.h>
+
+#include <dev/firmload.h>
+
+#include <dev/i2c/nxt2kvar.h>
+
+struct nxt2k {
+       device_t        parent;
+       i2c_tag_t       tag;
+       i2c_addr_t      addr;
+       kcondvar_t      cv;
+       kmutex_t        mtx;
+       bool            loaded; /* firmware is loaded? */
+};
+
+static int nxt2k_init(struct nxt2k *);
+
+static int nxt2k_writedata(struct nxt2k *, uint8_t, uint8_t *, size_t);
+static int nxt2k_readdata(struct nxt2k *, uint8_t, uint8_t *, size_t);
+static int nxt2k_writereg(struct nxt2k *, uint8_t, uint8_t *, size_t);
+static int nxt2k_readreg(struct nxt2k*, uint8_t, uint8_t *, size_t);
+
+static int nxt2k4_init(struct nxt2k *);
+static bool nxt2k4_load_firmware(struct nxt2k *);
+static void nxt2k4_mc_init(struct nxt2k *);
+static void nxt2k_mc_start(struct nxt2k *);
+static void nxt2k_mc_stop(struct nxt2k *);
+static void nxt2k_agc_reset(struct nxt2k *);
+static uint16_t nxt2k_crc_ccit(uint16_t, uint8_t);
+
+static int
+nxt2k_writedata(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
+{
+       uint8_t buffer[384];
+       int error;
+
+       KASSERT((len + 1) <= 384);
+
+       if (iic_acquire_bus(nxt->tag, I2C_F_POLL) != 0)
+               return false;
+
+       buffer[0] = reg;
+       memcpy(&buffer[1], data, len);
+       
+       error = iic_exec(nxt->tag, I2C_OP_WRITE_WITH_STOP, nxt->addr,
+                        buffer, len + 1, NULL, 0, I2C_F_POLL);
+       
+       iic_release_bus(nxt->tag, I2C_F_POLL);
+
+       return error;
+}
+
+static int
+nxt2k_readdata(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
+{
+       int error;
+
+       if (iic_acquire_bus(nxt->tag, I2C_F_POLL) != 0)
+               return false;
+
+       error = iic_exec(nxt->tag, I2C_OP_READ_WITH_STOP, nxt->addr,
+                        &reg, 1, data, len, I2C_F_POLL);
+
+       iic_release_bus(nxt->tag, I2C_F_POLL);
+
+       return error;
+}
+
+static int
+nxt2k_writereg(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
+{
+       uint8_t attr, len2, buf;
+
+       nxt2k_writedata(nxt, 0x35, &reg, 1);
+
+       nxt2k_writedata(nxt, 0x36, data, len);
+
+       attr = 0x02;
+       if (reg & 0x80) {
+               attr = attr << 1;
+               if (reg & 0x04)
+                       attr = attr >> 1;
+       }
+       len2 = ((attr << 4) | 0x10) | len;
+       buf = 0x80;
+
+       nxt2k_writedata(nxt, 0x34, &len2, 1);
+
+       nxt2k_writedata(nxt, 0x21, &buf, 1);
+
+       nxt2k_readdata(nxt, 0x21, &buf, 1);
+
+       if (buf == 0)
+               return 0;
+
+       return -1;
+}
+
+static int
+nxt2k_readreg(struct nxt2k *nxt, uint8_t reg, uint8_t *data, size_t len)
+{
+       uint8_t buf, len2, attr;
+       int i;
+
+       nxt2k_writedata(nxt, 0x35, &reg, 1);
+
+       attr = 0x02;
+       if (reg & 0x80) {
+               attr = attr << 1;
+               if (reg & 0x04)
+                       attr = attr >> 1;
+       }
+
+       len2 = (attr << 4) | len;
+       nxt2k_writedata(nxt, 0x34, &len2, 1);
+       
+       buf = 0x80;
+       nxt2k_writedata(nxt, 0x21, &buf, 1);
+
+       for(i = 0; i < len; i++) {
+               nxt2k_readdata(nxt, 0x36+i, &data[i], 1);
+       }
+
+       return 0;
+}
+
+static void
+nxt2k_agc_reset(struct nxt2k *nxt)
+{
+       uint8_t byte;
+       nxt2k_readreg(nxt, 0x08, &byte, 1);
+       byte = 0x08;
+       nxt2k_writereg(nxt, 0x08, &byte, 1);
+       byte = 0x00;
+       nxt2k_writereg(nxt, 0x08, &byte, 1);
+       return;
+}
+
+static void
+nxt2k_mc_stop(struct nxt2k *nxt)
+{
+       int counter;
+       uint8_t stopval, buf;
+
+       /* 2k4 */
+       stopval = 0x10;
+
+       buf = 0x80;
+       nxt2k_writedata(nxt, 0x22, &buf, 1);
+
+       for(counter = 0; counter < 20; counter++) {
+               nxt2k_readdata(nxt, 0x31, &buf, 1);
+               if (buf & stopval)
+                       return;
+               mutex_enter(&nxt->mtx);
+               cv_timedwait(&nxt->cv, &nxt->mtx, mstohz(10));
+               mutex_exit(&nxt->mtx);
+       }
+
+       printf("%s timeout\n", __func__);
+       
+       return;
+}
+
+static void
+nxt2k_mc_start(struct nxt2k *nxt)
+{
+       uint8_t buf;
+       
+       buf = 0x00;
+       nxt2k_writedata(nxt, 0x22, &buf, 1);
+}
+
+static void
+nxt2k4_mc_init(struct nxt2k *nxt)
+{
+       uint8_t byte;
+       uint8_t data[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xC0};
+       int counter;
+
+       byte = 0x00;
+       nxt2k_writedata(nxt, 0x2b, &byte, 1);
+       byte = 0x70;
+       nxt2k_writedata(nxt, 0x34, &byte, 1);
+       byte = 0x04;
+       nxt2k_writedata(nxt, 0x35, &byte, 1);
+
+       nxt2k_writedata(nxt, 0x36, data, 9);
+
+       byte = 0x80;
+       nxt2k_writedata(nxt, 0x21, &byte, 1);
+
+       for(counter = 0; counter < 20; counter++) {
+               nxt2k_readdata(nxt, 0x21, &byte, 1);
+               if ( byte == 0 )
+                       return;
+               mutex_enter(&nxt->mtx);
+               cv_timedwait(&nxt->cv, &nxt->mtx, mstohz(25));
+               mutex_exit(&nxt->mtx);
+       }
+
+       printf("%s timeout\n", __func__);
+
+       return;
+}
+
+/* CRC-CCIT */
+static uint16_t
+nxt2k_crc_ccit(uint16_t crc, uint8_t byte)
+{
+       int i;
+       uint16_t input;
+       
+       input = byte << 8;
+
+       for(i = 0; i < 8; i++) {
+               if ((crc ^ input) & 0x8000)
+                       crc = (crc << 1) ^ 0x1021;
+               else
+                       crc = (crc << 1);
+               input = input << 1;
+       }
+       return crc;
+}
+
+static bool
+nxt2k4_load_firmware(struct nxt2k *nxt)
+{
+       firmware_handle_t fh;
+       uint8_t *blob;
+       size_t fwsize;
+       size_t position;
+       int error;
+       uint16_t crc;
+
+       error = firmware_open("nxt2k", "dvb-fe-nxt2004.fw", &fh);
+       if (error != 0) {
+               printf("nxt2k firmware_open fail %d\n", error);
+               return 0;



Home | Main Index | Thread Index | Old Index