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