Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci Add coram(4).



details:   https://anonhg.NetBSD.org/src/rev/f1e325f5f4f3
branches:  trunk
changeset: 767953:f1e325f5f4f3
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Thu Aug 04 14:43:55 2011 +0000

description:
Add coram(4).

A driver for CX23885-based TV cards, such as the
Hauppauge WinTV HVR-1250 "Coram" board.

Currently only supports ATSC 8VSB reception.

diffstat:

 sys/dev/pci/coram.c      |  962 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/coramvar.h   |   99 ++++
 sys/dev/pci/cx23885reg.h |  117 +++++
 sys/dev/pci/files.pci    |    7 +-
 4 files changed, 1184 insertions(+), 1 deletions(-)

diffs (truncated from 1208 to 300 lines):

diff -r 588d11ec6f22 -r f1e325f5f4f3 sys/dev/pci/coram.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/coram.c       Thu Aug 04 14:43:55 2011 +0000
@@ -0,0 +1,962 @@
+/* $NetBSD: coram.c,v 1.1 2011/08/04 14:43:55 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: coram.c,v 1.1 2011/08/04 14:43:55 jakllsch Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+
+#include <sys/bus.h>
+
+#include <dev/dtv/dtvif.h>
+
+#include <dev/pci/cx23885reg.h>
+#include <dev/pci/coramvar.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/i2c/i2cvar.h>
+#include <dev/i2c/at24cxxvar.h>
+
+#include <dev/i2c/cx24227var.h>
+#include <dev/i2c/mt2131var.h>
+
+static int coram_match(device_t, cfdata_t, void *);
+static void coram_attach(device_t, device_t, void *);
+static bool coram_resume(device_t, const pmf_qual_t *);
+static int coram_intr(void *);
+
+static int coram_iic_exec(void *, i2c_op_t, i2c_addr_t,
+    const void *, size_t, void *, size_t, int);
+static int coram_iic_acquire_bus(void *, int);
+static void coram_iic_release_bus(void *, int);
+static int coram_iic_read(struct coram_iic_softc *, i2c_op_t, i2c_addr_t,
+    const void *, size_t, void *, size_t, int);
+static int coram_iic_write(struct coram_iic_softc *, i2c_op_t, i2c_addr_t,
+    const void *, size_t, void *, size_t, int);
+
+static void coram_dtv_get_devinfo(void *, struct dvb_frontend_info *);
+static int coram_dtv_open(void *, int);
+static void coram_dtv_close(void *);
+static int coram_dtv_set_tuner(void *, const struct dvb_frontend_parameters *);
+static fe_status_t coram_dtv_get_status(void *);
+static uint16_t coram_dtv_get_signal_strength(void *);
+static uint16_t coram_dtv_get_snr(void *);
+static int coram_dtv_start_transfer(void *);
+static int coram_dtv_stop_transfer(void *);
+
+static int coram_mpeg_attach(struct coram_softc *);
+static int coram_mpeg_reset(struct coram_softc *);
+static void * coram_mpeg_malloc(struct coram_softc *, size_t);
+static int coram_allocmem(struct coram_softc *, size_t, size_t, struct coram_dma *);
+static void coram_mpeg_free(struct coram_softc *, void *);
+static int coram_mpeg_halt(struct coram_softc *);
+static int coram_freemem(struct coram_softc *, struct coram_dma *);
+static int coram_mpeg_trigger(struct coram_softc *, void *);
+static int coram_risc_buffer(struct coram_softc *, uint32_t, uint32_t);
+static int coram_risc_field(struct coram_softc *, uint32_t *, uint32_t);
+static int coram_sram_ch_setup(struct coram_softc *, struct coram_sram_ch *, uint32_t);
+static int coram_mpeg_intr(struct coram_softc *);
+
+CFATTACH_DECL_NEW(coram, sizeof(struct coram_softc),
+    coram_match, coram_attach, NULL, NULL);
+
+#define CORAM_SRAM_CH6 0
+
+#define CORAM_TS_PKTSIZE        (188 * 8)
+
+static struct coram_sram_ch coram_sram_chs[] = {
+       [CORAM_SRAM_CH6] = {
+               .csc_cmds= 0x10140,
+               .csc_iq = 0x10500,
+               .csc_iqsz = 0x40,
+               .csc_cdt = 0x10600,
+               .csc_cdtsz = 0x10,
+               .csc_fifo = 0x6000,
+               .csc_fifosz = 0x1000,
+               .csc_risc = 0x10800,
+               .csc_riscsz = 0x800,
+               .csc_ptr1 = DMA5_PTR1,
+               .csc_ptr2 = DMA5_PTR2,
+               .csc_cnt1 = DMA5_CNT1,
+               .csc_cnt2 = DMA5_CNT2,
+       },
+};
+
+//#define PCI_PRODUCT_CONEXANT_CX23885 0x8852
+
+static const struct dtv_hw_if coram_dtv_if = {
+       .get_devinfo = coram_dtv_get_devinfo,
+       .open = coram_dtv_open,
+       .close = coram_dtv_close,
+       .set_tuner = coram_dtv_set_tuner,
+       .get_status = coram_dtv_get_status,
+       .get_signal_strength = coram_dtv_get_signal_strength,
+       .get_snr = coram_dtv_get_snr,
+       .start_transfer = coram_dtv_start_transfer,
+       .stop_transfer = coram_dtv_stop_transfer,
+};
+
+static int
+coram_match(device_t parent, cfdata_t match, void *v)
+{
+       const struct pci_attach_args *pa = v;
+
+       if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CONEXANT)
+               return 0;
+
+       switch (PCI_PRODUCT(pa->pa_id)) {
+       case PCI_PRODUCT_CONEXANT_CX23885:
+               return 1;
+       }
+
+       /* XXX only match supported boards */
+
+       return 0;
+}
+
+static void
+coram_attach(device_t parent, device_t self, void *v)
+{
+       struct coram_softc *sc;
+       const struct pci_attach_args *pa = v;
+       pci_intr_handle_t ih;
+       pcireg_t reg;
+       const char *intrstr;
+       char devinfo[76];
+       struct coram_iic_softc *cic;
+       struct i2cbus_attach_args iba;
+       uint32_t value;
+
+       sc = device_private(self);
+
+       sc->sc_dev = self;
+
+       aprint_naive("\n");
+
+       reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
+
+       sc->sc_vendor = PCI_VENDOR(reg);
+       sc->sc_product = PCI_PRODUCT(reg);
+
+       pci_devinfo(reg, pa->pa_class, 0, devinfo, sizeof(devinfo));
+       aprint_normal(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(pa->pa_class));
+
+       if (pci_mapreg_map(pa, CX23885_MMBASE, PCI_MAPREG_TYPE_MEM, 0,
+                          &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) {
+               aprint_error_dev(self, "couldn't map memory space\n");
+               return;
+       }
+
+       sc->sc_dmat = pa->pa_dmat;
+
+       if (pci_intr_map(pa, &ih)) {
+               aprint_error_dev(self, "couldn't map interrupt\n");
+               return;
+       }
+       intrstr = pci_intr_string(pa->pa_pc, ih);
+       sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_VM,
+           coram_intr, (void *)self);
+       if (sc->sc_ih == NULL) {
+               aprint_error_dev(self, "couldn't establish interrupt");
+               if (intrstr != NULL)
+                       aprint_error(" at %s", intrstr);
+               aprint_error("\n");
+               return;
+       }
+       aprint_normal_dev(self, "interrupting at %s\n", intrstr);
+
+       /* set master */
+       reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+       reg |= PCI_COMMAND_MASTER_ENABLE;
+       pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
+
+       int i;
+
+       /* I2C */
+       for(i = 0; i < I2C_NUM; i++) {
+               cic = &sc->sc_iic[i];
+
+               cic->cic_sc = sc;
+               if(bus_space_subregion(sc->sc_memt, sc->sc_memh, I2C_BASE + (I2C_SIZE * i), I2C_SIZE, &cic->cic_regh))
+                       panic("failed to subregion i2c");
+
+               mutex_init(&cic->cic_busmutex, MUTEX_DRIVER, IPL_NONE);
+               cic->cic_i2c.ic_cookie = cic;
+               cic->cic_i2c.ic_acquire_bus = coram_iic_acquire_bus;
+               cic->cic_i2c.ic_release_bus = coram_iic_release_bus;
+               cic->cic_i2c.ic_exec = coram_iic_exec;
+
+#if 1
+               /* attach iic(4) */
+               memset(&iba, 0, sizeof(iba));
+               iba.iba_tag = &cic->cic_i2c;
+               iba.iba_type = I2C_TYPE_SMBUS;
+               config_found_ia(self, "i2cbus", &iba, iicbus_print);
+#endif
+       }
+
+       /* HVR1250 GPIO */
+       value = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x110010);
+#if 1
+       value &= ~0x00010001;
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value);
+       delay(5000);
+#endif
+       value |= 0x00010001;
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value);
+
+#if 0
+       int i;
+       uint8_t foo[256];
+       uint8_t bar;
+       bar = 0;
+//     seeprom_bootstrap_read(&sc->sc_i2c, 0x50, 0, 256, foo, 256);
+
+       iic_acquire_bus(&sc->sc_i2c, I2C_F_POLL);
+       iic_exec(&sc->sc_i2c, I2C_OP_READ_WITH_STOP, 0x50, &bar, 1, foo, 256, I2C_F_POLL);
+       iic_release_bus(&sc->sc_i2c, I2C_F_POLL);
+
+       printf("\n");
+       for ( i = 0; i < 256; i++) {
+               if ( (i % 8) == 0 )
+                       printf("%02x: ", i);
+
+               printf("%02x", foo[i]);
+
+               if ( (i % 8) == 7 )
+                       printf("\n");
+               else
+                       printf(" ");
+       }
+       printf("\n");
+#endif
+
+       sc->sc_demod = cx24227_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x19);
+       if ( sc->sc_demod == NULL )
+               panic("no demod");
+
+       sc->sc_tuner = mt2131_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x61);
+       if ( sc->sc_tuner == NULL )
+               panic("no tuner");
+
+       coram_mpeg_attach(sc);
+
+       if (!pmf_device_register(self, NULL, coram_resume))
+               aprint_error_dev(self, "couldn't establish power handler\n");
+
+       return;
+}
+
+static int
+coram_intr(void *v)
+{
+       device_t self = v;
+       struct coram_softc *sc;
+       uint32_t val;
+
+       sc = device_private(self);
+
+       val = bus_space_read_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSTAT );
+       if (val == 0)
+               return 0; /* not ours */
+
+       /* vid c */
+       if (val & __BIT(2))
+               coram_mpeg_intr(sc);



Home | Main Index | Thread Index | Old Index