1 1.21 thorpej /* $NetBSD: coram.c,v 1.21 2025/09/15 13:23:03 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.21 thorpej __KERNEL_RCSID(0, "$NetBSD: coram.c,v 1.21 2025/09/15 13:23:03 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/mutex.h> 37 1.2 jmcneill #include <sys/module.h> 38 1.1 jakllsch #include <sys/bus.h> 39 1.1 jakllsch 40 1.1 jakllsch #include <dev/dtv/dtvif.h> 41 1.1 jakllsch 42 1.1 jakllsch #include <dev/pci/cx23885reg.h> 43 1.1 jakllsch #include <dev/pci/coramvar.h> 44 1.1 jakllsch 45 1.1 jakllsch #include <dev/pci/pcivar.h> 46 1.1 jakllsch #include <dev/pci/pcireg.h> 47 1.1 jakllsch #include <dev/pci/pcidevs.h> 48 1.1 jakllsch #include <dev/i2c/i2cvar.h> 49 1.1 jakllsch #include <dev/i2c/at24cxxvar.h> 50 1.1 jakllsch 51 1.1 jakllsch #include <dev/i2c/cx24227var.h> 52 1.1 jakllsch #include <dev/i2c/mt2131var.h> 53 1.1 jakllsch 54 1.4 jmcneill /* #define CORAM_DEBUG */ 55 1.5 jmcneill /* #define CORAM_ATTACH_I2C */ 56 1.4 jmcneill 57 1.7 jmcneill static const struct coram_board coram_boards[] = { 58 1.6 jmcneill { PCI_VENDOR_HAUPPAUGE, 0x7911, "Hauppauge HVR-1250" }, 59 1.6 jmcneill }; 60 1.6 jmcneill 61 1.1 jakllsch static int coram_match(device_t, cfdata_t, void *); 62 1.1 jakllsch static void coram_attach(device_t, device_t, void *); 63 1.2 jmcneill static int coram_detach(device_t, int); 64 1.8 jmcneill static int coram_rescan(device_t, const char *, const int *); 65 1.2 jmcneill static void coram_childdet(device_t, device_t); 66 1.1 jakllsch static bool coram_resume(device_t, const pmf_qual_t *); 67 1.1 jakllsch static int coram_intr(void *); 68 1.6 jmcneill static const struct coram_board * coram_board_lookup(uint16_t, uint16_t); 69 1.1 jakllsch 70 1.1 jakllsch static int coram_iic_exec(void *, i2c_op_t, i2c_addr_t, 71 1.1 jakllsch const void *, size_t, void *, size_t, int); 72 1.1 jakllsch static int coram_iic_read(struct coram_iic_softc *, i2c_op_t, i2c_addr_t, 73 1.1 jakllsch const void *, size_t, void *, size_t, int); 74 1.1 jakllsch static int coram_iic_write(struct coram_iic_softc *, i2c_op_t, i2c_addr_t, 75 1.1 jakllsch const void *, size_t, void *, size_t, int); 76 1.1 jakllsch 77 1.1 jakllsch static void coram_dtv_get_devinfo(void *, struct dvb_frontend_info *); 78 1.1 jakllsch static int coram_dtv_open(void *, int); 79 1.1 jakllsch static void coram_dtv_close(void *); 80 1.1 jakllsch static int coram_dtv_set_tuner(void *, const struct dvb_frontend_parameters *); 81 1.1 jakllsch static fe_status_t coram_dtv_get_status(void *); 82 1.1 jakllsch static uint16_t coram_dtv_get_signal_strength(void *); 83 1.1 jakllsch static uint16_t coram_dtv_get_snr(void *); 84 1.8 jmcneill static int coram_dtv_start_transfer(void *, void (*)(void *, const struct dtv_payload *), void *); 85 1.1 jakllsch static int coram_dtv_stop_transfer(void *); 86 1.1 jakllsch 87 1.1 jakllsch static int coram_mpeg_attach(struct coram_softc *); 88 1.2 jmcneill static int coram_mpeg_detach(struct coram_softc *, int); 89 1.1 jakllsch static int coram_mpeg_reset(struct coram_softc *); 90 1.1 jakllsch static void * coram_mpeg_malloc(struct coram_softc *, size_t); 91 1.1 jakllsch static int coram_allocmem(struct coram_softc *, size_t, size_t, struct coram_dma *); 92 1.1 jakllsch static void coram_mpeg_free(struct coram_softc *, void *); 93 1.1 jakllsch static int coram_mpeg_halt(struct coram_softc *); 94 1.1 jakllsch static int coram_freemem(struct coram_softc *, struct coram_dma *); 95 1.1 jakllsch static int coram_mpeg_trigger(struct coram_softc *, void *); 96 1.1 jakllsch static int coram_risc_buffer(struct coram_softc *, uint32_t, uint32_t); 97 1.1 jakllsch static int coram_risc_field(struct coram_softc *, uint32_t *, uint32_t); 98 1.1 jakllsch static int coram_sram_ch_setup(struct coram_softc *, struct coram_sram_ch *, uint32_t); 99 1.1 jakllsch static int coram_mpeg_intr(struct coram_softc *); 100 1.1 jakllsch 101 1.2 jmcneill CFATTACH_DECL2_NEW(coram, sizeof(struct coram_softc), 102 1.8 jmcneill coram_match, coram_attach, coram_detach, NULL, 103 1.8 jmcneill coram_rescan, coram_childdet); 104 1.1 jakllsch 105 1.1 jakllsch #define CORAM_SRAM_CH6 0 106 1.1 jakllsch 107 1.1 jakllsch #define CORAM_TS_PKTSIZE (188 * 8) 108 1.1 jakllsch 109 1.1 jakllsch static struct coram_sram_ch coram_sram_chs[] = { 110 1.1 jakllsch [CORAM_SRAM_CH6] = { 111 1.1 jakllsch .csc_cmds= 0x10140, 112 1.1 jakllsch .csc_iq = 0x10500, 113 1.1 jakllsch .csc_iqsz = 0x40, 114 1.1 jakllsch .csc_cdt = 0x10600, 115 1.1 jakllsch .csc_cdtsz = 0x10, 116 1.1 jakllsch .csc_fifo = 0x6000, 117 1.1 jakllsch .csc_fifosz = 0x1000, 118 1.1 jakllsch .csc_risc = 0x10800, 119 1.1 jakllsch .csc_riscsz = 0x800, 120 1.1 jakllsch .csc_ptr1 = DMA5_PTR1, 121 1.1 jakllsch .csc_ptr2 = DMA5_PTR2, 122 1.1 jakllsch .csc_cnt1 = DMA5_CNT1, 123 1.1 jakllsch .csc_cnt2 = DMA5_CNT2, 124 1.1 jakllsch }, 125 1.1 jakllsch }; 126 1.1 jakllsch 127 1.1 jakllsch static const struct dtv_hw_if coram_dtv_if = { 128 1.1 jakllsch .get_devinfo = coram_dtv_get_devinfo, 129 1.1 jakllsch .open = coram_dtv_open, 130 1.1 jakllsch .close = coram_dtv_close, 131 1.1 jakllsch .set_tuner = coram_dtv_set_tuner, 132 1.1 jakllsch .get_status = coram_dtv_get_status, 133 1.1 jakllsch .get_signal_strength = coram_dtv_get_signal_strength, 134 1.1 jakllsch .get_snr = coram_dtv_get_snr, 135 1.1 jakllsch .start_transfer = coram_dtv_start_transfer, 136 1.1 jakllsch .stop_transfer = coram_dtv_stop_transfer, 137 1.1 jakllsch }; 138 1.1 jakllsch 139 1.1 jakllsch static int 140 1.1 jakllsch coram_match(device_t parent, cfdata_t match, void *v) 141 1.1 jakllsch { 142 1.1 jakllsch const struct pci_attach_args *pa = v; 143 1.6 jmcneill pcireg_t subid; 144 1.1 jakllsch 145 1.1 jakllsch if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CONEXANT) 146 1.1 jakllsch return 0; 147 1.6 jmcneill if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CONEXANT_CX23885) 148 1.6 jmcneill return 0; 149 1.1 jakllsch 150 1.6 jmcneill subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 151 1.6 jmcneill if (coram_board_lookup(PCI_VENDOR(subid), PCI_PRODUCT(subid)) == NULL) 152 1.6 jmcneill return 0; 153 1.1 jakllsch 154 1.6 jmcneill return 1; 155 1.1 jakllsch } 156 1.1 jakllsch 157 1.1 jakllsch static void 158 1.11 chs coram_attach(device_t parent, device_t self, void *aux) 159 1.1 jakllsch { 160 1.6 jmcneill struct coram_softc *sc = device_private(self); 161 1.11 chs const struct pci_attach_args *pa = aux; 162 1.1 jakllsch pci_intr_handle_t ih; 163 1.1 jakllsch pcireg_t reg; 164 1.1 jakllsch const char *intrstr; 165 1.1 jakllsch struct coram_iic_softc *cic; 166 1.5 jmcneill uint32_t value; 167 1.5 jmcneill int i; 168 1.13 christos char intrbuf[PCI_INTRSTR_LEN]; 169 1.1 jakllsch 170 1.1 jakllsch sc->sc_dev = self; 171 1.1 jakllsch 172 1.10 drochner pci_aprint_devinfo(pa, NULL); 173 1.1 jakllsch 174 1.1 jakllsch reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 175 1.6 jmcneill sc->sc_board = coram_board_lookup(PCI_VENDOR(reg), PCI_PRODUCT(reg)); 176 1.6 jmcneill KASSERT(sc->sc_board != NULL); 177 1.1 jakllsch 178 1.1 jakllsch if (pci_mapreg_map(pa, CX23885_MMBASE, PCI_MAPREG_TYPE_MEM, 0, 179 1.1 jakllsch &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) { 180 1.1 jakllsch aprint_error_dev(self, "couldn't map memory space\n"); 181 1.1 jakllsch return; 182 1.1 jakllsch } 183 1.1 jakllsch 184 1.1 jakllsch sc->sc_dmat = pa->pa_dmat; 185 1.2 jmcneill sc->sc_pc = pa->pa_pc; 186 1.1 jakllsch 187 1.1 jakllsch if (pci_intr_map(pa, &ih)) { 188 1.1 jakllsch aprint_error_dev(self, "couldn't map interrupt\n"); 189 1.1 jakllsch return; 190 1.1 jakllsch } 191 1.13 christos intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); 192 1.16 jdolecek sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_VM, coram_intr, 193 1.16 jdolecek self, device_xname(self)); 194 1.1 jakllsch if (sc->sc_ih == NULL) { 195 1.1 jakllsch aprint_error_dev(self, "couldn't establish interrupt"); 196 1.1 jakllsch if (intrstr != NULL) 197 1.1 jakllsch aprint_error(" at %s", intrstr); 198 1.1 jakllsch aprint_error("\n"); 199 1.1 jakllsch return; 200 1.1 jakllsch } 201 1.1 jakllsch aprint_normal_dev(self, "interrupting at %s\n", intrstr); 202 1.1 jakllsch 203 1.1 jakllsch /* set master */ 204 1.1 jakllsch reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 205 1.1 jakllsch reg |= PCI_COMMAND_MASTER_ENABLE; 206 1.1 jakllsch pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 207 1.1 jakllsch 208 1.1 jakllsch /* I2C */ 209 1.1 jakllsch for(i = 0; i < I2C_NUM; i++) { 210 1.1 jakllsch cic = &sc->sc_iic[i]; 211 1.1 jakllsch 212 1.1 jakllsch cic->cic_sc = sc; 213 1.11 chs if (bus_space_subregion(sc->sc_memt, sc->sc_memh, 214 1.11 chs I2C_BASE + (I2C_SIZE * i), I2C_SIZE, &cic->cic_regh)) 215 1.1 jakllsch panic("failed to subregion i2c"); 216 1.1 jakllsch 217 1.17 thorpej iic_tag_init(&cic->cic_i2c); 218 1.1 jakllsch cic->cic_i2c.ic_cookie = cic; 219 1.1 jakllsch cic->cic_i2c.ic_exec = coram_iic_exec; 220 1.1 jakllsch 221 1.5 jmcneill #ifdef CORAM_ATTACH_I2C 222 1.1 jakllsch /* attach iic(4) */ 223 1.21 thorpej cic->cic_i2cdev = iicbus_attach(self, &cic->cic_i2c); 224 1.1 jakllsch #endif 225 1.1 jakllsch } 226 1.1 jakllsch 227 1.1 jakllsch /* HVR1250 GPIO */ 228 1.1 jakllsch value = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x110010); 229 1.1 jakllsch #if 1 230 1.1 jakllsch value &= ~0x00010001; 231 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value); 232 1.1 jakllsch delay(5000); 233 1.1 jakllsch #endif 234 1.1 jakllsch value |= 0x00010001; 235 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 0x110010, value); 236 1.1 jakllsch 237 1.1 jakllsch #if 0 238 1.1 jakllsch int i; 239 1.1 jakllsch uint8_t foo[256]; 240 1.1 jakllsch uint8_t bar; 241 1.1 jakllsch bar = 0; 242 1.1 jakllsch // seeprom_bootstrap_read(&sc->sc_i2c, 0x50, 0, 256, foo, 256); 243 1.1 jakllsch 244 1.18 thorpej iic_acquire_bus(&sc->sc_i2c, 0); 245 1.11 chs iic_exec(&sc->sc_i2c, I2C_OP_READ_WITH_STOP, 0x50, &bar, 1, foo, 256, 246 1.18 thorpej 0); 247 1.18 thorpej iic_release_bus(&sc->sc_i2c, 0); 248 1.1 jakllsch 249 1.1 jakllsch printf("\n"); 250 1.1 jakllsch for ( i = 0; i < 256; i++) { 251 1.1 jakllsch if ( (i % 8) == 0 ) 252 1.1 jakllsch printf("%02x: ", i); 253 1.1 jakllsch 254 1.1 jakllsch printf("%02x", foo[i]); 255 1.1 jakllsch 256 1.1 jakllsch if ( (i % 8) == 7 ) 257 1.1 jakllsch printf("\n"); 258 1.1 jakllsch else 259 1.1 jakllsch printf(" "); 260 1.1 jakllsch } 261 1.1 jakllsch printf("\n"); 262 1.1 jakllsch #endif 263 1.1 jakllsch 264 1.1 jakllsch sc->sc_demod = cx24227_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x19); 265 1.2 jmcneill if (sc->sc_demod == NULL) 266 1.2 jmcneill aprint_error_dev(self, "couldn't open cx24227\n"); 267 1.1 jakllsch sc->sc_tuner = mt2131_open(sc->sc_dev, &sc->sc_iic[0].cic_i2c, 0x61); 268 1.2 jmcneill if (sc->sc_tuner == NULL) 269 1.2 jmcneill aprint_error_dev(self, "couldn't open mt2131\n"); 270 1.1 jakllsch 271 1.1 jakllsch coram_mpeg_attach(sc); 272 1.1 jakllsch 273 1.1 jakllsch if (!pmf_device_register(self, NULL, coram_resume)) 274 1.1 jakllsch aprint_error_dev(self, "couldn't establish power handler\n"); 275 1.1 jakllsch 276 1.1 jakllsch return; 277 1.1 jakllsch } 278 1.1 jakllsch 279 1.1 jakllsch static int 280 1.2 jmcneill coram_detach(device_t self, int flags) 281 1.2 jmcneill { 282 1.2 jmcneill struct coram_softc *sc = device_private(self); 283 1.2 jmcneill struct coram_iic_softc *cic; 284 1.2 jmcneill unsigned int i; 285 1.2 jmcneill int error; 286 1.2 jmcneill 287 1.2 jmcneill error = coram_mpeg_detach(sc, flags); 288 1.2 jmcneill if (error) 289 1.2 jmcneill return error; 290 1.2 jmcneill 291 1.2 jmcneill if (sc->sc_tuner) 292 1.2 jmcneill mt2131_close(sc->sc_tuner); 293 1.2 jmcneill if (sc->sc_demod) 294 1.2 jmcneill cx24227_close(sc->sc_demod); 295 1.2 jmcneill for (i = 0; i < I2C_NUM; i++) { 296 1.2 jmcneill cic = &sc->sc_iic[i]; 297 1.2 jmcneill if (cic->cic_i2cdev) 298 1.2 jmcneill config_detach(cic->cic_i2cdev, flags); 299 1.17 thorpej iic_tag_fini(&cic->cic_i2c); 300 1.2 jmcneill } 301 1.2 jmcneill pmf_device_deregister(self); 302 1.2 jmcneill 303 1.2 jmcneill if (sc->sc_mems) 304 1.2 jmcneill bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems); 305 1.2 jmcneill if (sc->sc_ih) 306 1.2 jmcneill pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 307 1.2 jmcneill 308 1.2 jmcneill return 0; 309 1.2 jmcneill } 310 1.2 jmcneill 311 1.8 jmcneill static int 312 1.8 jmcneill coram_rescan(device_t self, const char *ifattr, const int *locs) 313 1.8 jmcneill { 314 1.8 jmcneill struct coram_softc *sc = device_private(self); 315 1.8 jmcneill struct dtv_attach_args daa; 316 1.8 jmcneill 317 1.8 jmcneill daa.hw = &coram_dtv_if; 318 1.8 jmcneill daa.priv = sc; 319 1.8 jmcneill 320 1.8 jmcneill if (ifattr_match(ifattr, "dtvbus") && sc->sc_dtvdev == NULL) 321 1.19 thorpej sc->sc_dtvdev = config_found(sc->sc_dev, &daa, dtv_print, 322 1.20 thorpej CFARGS(.iattr = "dtvbus")); 323 1.8 jmcneill 324 1.8 jmcneill return 0; 325 1.8 jmcneill } 326 1.8 jmcneill 327 1.2 jmcneill static void 328 1.2 jmcneill coram_childdet(device_t self, device_t child) 329 1.2 jmcneill { 330 1.2 jmcneill struct coram_softc *sc = device_private(self); 331 1.2 jmcneill struct coram_iic_softc *cic; 332 1.2 jmcneill unsigned int i; 333 1.2 jmcneill 334 1.2 jmcneill if (sc->sc_dtvdev == child) 335 1.2 jmcneill sc->sc_dtvdev = NULL; 336 1.2 jmcneill 337 1.2 jmcneill for (i = 0; i < I2C_NUM; i++) { 338 1.2 jmcneill cic = &sc->sc_iic[i]; 339 1.2 jmcneill if (cic->cic_i2cdev == child) 340 1.2 jmcneill cic->cic_i2cdev = NULL; 341 1.2 jmcneill } 342 1.2 jmcneill } 343 1.2 jmcneill 344 1.2 jmcneill static int 345 1.1 jakllsch coram_intr(void *v) 346 1.1 jakllsch { 347 1.1 jakllsch device_t self = v; 348 1.1 jakllsch struct coram_softc *sc; 349 1.1 jakllsch uint32_t val; 350 1.1 jakllsch 351 1.1 jakllsch sc = device_private(self); 352 1.1 jakllsch 353 1.1 jakllsch val = bus_space_read_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSTAT ); 354 1.1 jakllsch if (val == 0) 355 1.1 jakllsch return 0; /* not ours */ 356 1.1 jakllsch 357 1.1 jakllsch /* vid c */ 358 1.1 jakllsch if (val & __BIT(2)) 359 1.1 jakllsch coram_mpeg_intr(sc); 360 1.1 jakllsch 361 1.1 jakllsch if (val & ~__BIT(2)) 362 1.1 jakllsch printf("%s %08x\n", __func__, val); 363 1.1 jakllsch 364 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PCI_INT_STAT, val); 365 1.1 jakllsch 366 1.1 jakllsch return 1; 367 1.1 jakllsch } 368 1.1 jakllsch 369 1.6 jmcneill static const struct coram_board * 370 1.6 jmcneill coram_board_lookup(uint16_t vendor, uint16_t product) 371 1.6 jmcneill { 372 1.6 jmcneill unsigned int i; 373 1.6 jmcneill 374 1.6 jmcneill for (i = 0; i < __arraycount(coram_boards); i++) { 375 1.6 jmcneill if (coram_boards[i].vendor == vendor && 376 1.6 jmcneill coram_boards[i].product == product) { 377 1.6 jmcneill return &coram_boards[i]; 378 1.6 jmcneill } 379 1.6 jmcneill } 380 1.6 jmcneill 381 1.6 jmcneill return NULL; 382 1.6 jmcneill } 383 1.6 jmcneill 384 1.1 jakllsch #define CXDTV_TS_RISCI2 (1 << 4) 385 1.1 jakllsch #define CXDTV_TS_RISCI1 (1 << 0) 386 1.1 jakllsch 387 1.1 jakllsch #define CXDTV_TS_RISCI (CXDTV_TS_RISCI1|CXDTV_TS_RISCI2) 388 1.1 jakllsch 389 1.1 jakllsch static int 390 1.1 jakllsch coram_mpeg_intr(struct coram_softc *sc) 391 1.1 jakllsch { 392 1.1 jakllsch struct dtv_payload payload; 393 1.1 jakllsch uint32_t s, m, v; 394 1.1 jakllsch int i; 395 1.1 jakllsch 396 1.1 jakllsch s = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_INT_STAT); 397 1.1 jakllsch m = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_INT_MSK); 398 1.1 jakllsch 399 1.1 jakllsch if ((s & m) == 0) 400 1.1 jakllsch return 0; 401 1.1 jakllsch 402 1.1 jakllsch if ( (s & ~CXDTV_TS_RISCI) != 0 ) { 403 1.1 jakllsch printf("%s: unexpected TS IS %08x\n", 404 1.1 jakllsch device_xname(sc->sc_dev), s); 405 1.1 jakllsch 406 1.1 jakllsch printf("cmds:\n"); 407 1.1 jakllsch for(i = 0; i < 20; i++) 408 1.1 jakllsch { 409 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x10140 +(i*4)); 410 1.1 jakllsch printf("%06x %08x\n", 0x10140+(i*4), v); 411 1.1 jakllsch } 412 1.1 jakllsch } 413 1.1 jakllsch 414 1.8 jmcneill if (sc->sc_dtvsubmitcb == NULL) 415 1.8 jmcneill goto done; 416 1.8 jmcneill 417 1.1 jakllsch if ((s & CXDTV_TS_RISCI1) == CXDTV_TS_RISCI1) { 418 1.1 jakllsch bus_dmamap_sync(sc->sc_dmat, sc->sc_dma->map, 419 1.1 jakllsch 0, CORAM_TS_PKTSIZE, 420 1.1 jakllsch BUS_DMASYNC_POSTREAD); 421 1.1 jakllsch payload.data = KERNADDR(sc->sc_dma); 422 1.1 jakllsch payload.size = CORAM_TS_PKTSIZE; 423 1.8 jmcneill sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload); 424 1.1 jakllsch } 425 1.1 jakllsch 426 1.1 jakllsch if ((s & CXDTV_TS_RISCI2) == CXDTV_TS_RISCI2) { 427 1.1 jakllsch bus_dmamap_sync(sc->sc_dmat, sc->sc_dma->map, 428 1.1 jakllsch CORAM_TS_PKTSIZE, CORAM_TS_PKTSIZE, 429 1.1 jakllsch BUS_DMASYNC_POSTREAD); 430 1.1 jakllsch payload.data = (char *)(KERNADDR(sc->sc_dma)) + (uintptr_t)CORAM_TS_PKTSIZE; 431 1.1 jakllsch payload.size = CORAM_TS_PKTSIZE; 432 1.8 jmcneill sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload); 433 1.1 jakllsch } 434 1.1 jakllsch 435 1.8 jmcneill done: 436 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_INT_STAT, s); 437 1.1 jakllsch 438 1.1 jakllsch return 1; 439 1.1 jakllsch } 440 1.1 jakllsch 441 1.1 jakllsch static bool 442 1.1 jakllsch coram_resume(device_t dv, const pmf_qual_t *qual) 443 1.1 jakllsch { 444 1.1 jakllsch return true; 445 1.1 jakllsch } 446 1.1 jakllsch 447 1.1 jakllsch /* I2C Bus */ 448 1.1 jakllsch 449 1.1 jakllsch #define I2C_ADDR 0x0000 450 1.1 jakllsch #define I2C_WDATA 0x0004 451 1.1 jakllsch #define I2C_CTRL 0x0008 452 1.1 jakllsch #define I2C_RDATA 0x000c 453 1.1 jakllsch #define I2C_STAT 0x0010 454 1.1 jakllsch 455 1.1 jakllsch #define I2C_EXTEND (1 << 3) 456 1.1 jakllsch #define I2C_NOSTOP (1 << 4) 457 1.1 jakllsch 458 1.1 jakllsch static int 459 1.1 jakllsch coram_iic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, 460 1.1 jakllsch const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) 461 1.1 jakllsch { 462 1.1 jakllsch struct coram_iic_softc *cic; 463 1.1 jakllsch int ret; 464 1.1 jakllsch 465 1.1 jakllsch cic = cookie; 466 1.1 jakllsch 467 1.1 jakllsch if(cmdlen) { 468 1.1 jakllsch ret = coram_iic_write(cic, op, addr, cmdbuf, cmdlen, buf, len, flags); 469 1.1 jakllsch if(ret) 470 1.1 jakllsch return ret; 471 1.1 jakllsch } 472 1.1 jakllsch 473 1.1 jakllsch if(len) { 474 1.1 jakllsch ret = coram_iic_read(cic, op, addr, cmdbuf, cmdlen, buf, len, flags); 475 1.1 jakllsch if(ret) 476 1.1 jakllsch return ret; 477 1.1 jakllsch } 478 1.1 jakllsch 479 1.1 jakllsch 480 1.1 jakllsch return 0; 481 1.1 jakllsch 482 1.1 jakllsch } 483 1.1 jakllsch 484 1.1 jakllsch static int 485 1.1 jakllsch coram_iic_read(struct coram_iic_softc *cic, i2c_op_t op, i2c_addr_t addr, 486 1.1 jakllsch const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) 487 1.1 jakllsch { 488 1.1 jakllsch uint8_t *rb; 489 1.1 jakllsch uint32_t ctrl; 490 1.1 jakllsch int bn; 491 1.1 jakllsch 492 1.1 jakllsch rb = buf; 493 1.1 jakllsch 494 1.1 jakllsch for ( bn = 0; bn < len; bn++) { 495 1.1 jakllsch ctrl = (0x9d << 24) | (1 << 12) | (1 << 2) | 1; 496 1.1 jakllsch if ( bn < len - 1 ) 497 1.1 jakllsch ctrl |= I2C_NOSTOP | I2C_EXTEND; 498 1.1 jakllsch 499 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_ADDR, addr<<25); 500 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_CTRL, ctrl); 501 1.1 jakllsch 502 1.1 jakllsch while((bus_space_read_4(cic->cic_sc->sc_memt, cic->cic_regh, 503 1.1 jakllsch I2C_STAT) & 0x02)) { 504 1.1 jakllsch delay(25); 505 1.1 jakllsch } 506 1.1 jakllsch if((bus_space_read_4(cic->cic_sc->sc_memt, cic->cic_regh, 507 1.1 jakllsch I2C_STAT) & 0x01) == 0x00) { 508 1.1 jakllsch // printf("%s %d no ack\n", __func__, bn); 509 1.1 jakllsch return EIO; 510 1.1 jakllsch } 511 1.1 jakllsch 512 1.1 jakllsch rb[bn] = bus_space_read_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_RDATA); 513 1.1 jakllsch 514 1.1 jakllsch } 515 1.1 jakllsch 516 1.1 jakllsch return 0; 517 1.1 jakllsch } 518 1.1 jakllsch 519 1.1 jakllsch static int 520 1.1 jakllsch coram_iic_write(struct coram_iic_softc *cic, i2c_op_t op, i2c_addr_t addr, 521 1.1 jakllsch const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) 522 1.1 jakllsch { 523 1.1 jakllsch const uint8_t *wb; 524 1.1 jakllsch uint32_t wdata, addrreg, ctrl; 525 1.1 jakllsch int bn; 526 1.1 jakllsch 527 1.1 jakllsch wb = cmdbuf; 528 1.1 jakllsch 529 1.1 jakllsch addrreg = (addr << 25) | wb[0]; 530 1.1 jakllsch wdata = wb[0]; 531 1.1 jakllsch ctrl = (0x9d << 24) | (1 << 12) | (1 << 2); 532 1.1 jakllsch 533 1.1 jakllsch if ( cmdlen > 1 ) 534 1.1 jakllsch ctrl |= I2C_NOSTOP | I2C_EXTEND; 535 1.1 jakllsch else if (len) 536 1.1 jakllsch ctrl |= I2C_NOSTOP; 537 1.1 jakllsch 538 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_ADDR, addrreg); 539 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_WDATA, wdata); 540 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_CTRL, ctrl); 541 1.1 jakllsch 542 1.1 jakllsch while((bus_space_read_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_STAT) & 0x02)) { 543 1.1 jakllsch delay(25); } 544 1.1 jakllsch 545 1.1 jakllsch for ( bn = 1; bn < cmdlen; bn++) { 546 1.1 jakllsch ctrl = (0x9d << 24) | (1 << 12) | (1 << 2); 547 1.1 jakllsch wdata = wb[bn]; 548 1.1 jakllsch 549 1.1 jakllsch if ( bn < cmdlen - 1 ) 550 1.1 jakllsch ctrl |= I2C_NOSTOP | I2C_EXTEND; 551 1.1 jakllsch else if (len) 552 1.1 jakllsch ctrl |= I2C_NOSTOP; 553 1.1 jakllsch 554 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_ADDR, addrreg); 555 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_WDATA, wdata); 556 1.1 jakllsch bus_space_write_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_CTRL, ctrl); 557 1.1 jakllsch 558 1.1 jakllsch while((bus_space_read_4(cic->cic_sc->sc_memt, cic->cic_regh, I2C_STAT) & 0x02)) { 559 1.1 jakllsch delay(25); } 560 1.1 jakllsch } 561 1.1 jakllsch 562 1.1 jakllsch return 0; 563 1.1 jakllsch } 564 1.1 jakllsch 565 1.1 jakllsch static int 566 1.1 jakllsch coram_mpeg_attach(struct coram_softc *sc) 567 1.1 jakllsch { 568 1.1 jakllsch struct coram_sram_ch *ch; 569 1.1 jakllsch 570 1.1 jakllsch ch = &coram_sram_chs[CORAM_SRAM_CH6]; 571 1.1 jakllsch 572 1.1 jakllsch sc->sc_riscbufsz = ch->csc_riscsz; 573 1.1 jakllsch sc->sc_riscbuf = kmem_alloc(ch->csc_riscsz, KM_SLEEP); 574 1.1 jakllsch 575 1.1 jakllsch coram_mpeg_reset(sc); 576 1.1 jakllsch 577 1.1 jakllsch sc->sc_tsbuf = NULL; 578 1.1 jakllsch 579 1.8 jmcneill coram_rescan(sc->sc_dev, NULL, NULL); 580 1.1 jakllsch 581 1.1 jakllsch return (sc->sc_dtvdev != NULL); 582 1.1 jakllsch } 583 1.1 jakllsch 584 1.2 jmcneill static int 585 1.2 jmcneill coram_mpeg_detach(struct coram_softc *sc, int flags) 586 1.2 jmcneill { 587 1.2 jmcneill struct coram_sram_ch *ch = &coram_sram_chs[CORAM_SRAM_CH6]; 588 1.2 jmcneill int error; 589 1.2 jmcneill 590 1.2 jmcneill if (sc->sc_dtvdev) { 591 1.2 jmcneill error = config_detach(sc->sc_dtvdev, flags); 592 1.2 jmcneill if (error) 593 1.2 jmcneill return error; 594 1.2 jmcneill } 595 1.2 jmcneill if (sc->sc_riscbuf) { 596 1.2 jmcneill kmem_free(sc->sc_riscbuf, ch->csc_riscsz); 597 1.2 jmcneill } 598 1.2 jmcneill 599 1.2 jmcneill return 0; 600 1.2 jmcneill } 601 1.1 jakllsch 602 1.1 jakllsch static void 603 1.1 jakllsch coram_dtv_get_devinfo(void *cookie, struct dvb_frontend_info *info) 604 1.1 jakllsch { 605 1.6 jmcneill struct coram_softc *sc = cookie; 606 1.6 jmcneill 607 1.1 jakllsch memset(info, 0, sizeof(*info)); 608 1.6 jmcneill strlcpy(info->name, sc->sc_board->name, sizeof(info->name)); 609 1.1 jakllsch info->type = FE_ATSC; 610 1.1 jakllsch info->frequency_min = 54000000; 611 1.1 jakllsch info->frequency_max = 858000000; 612 1.1 jakllsch info->frequency_stepsize = 62500; 613 1.1 jakllsch info->caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB; 614 1.1 jakllsch } 615 1.1 jakllsch 616 1.1 jakllsch static int 617 1.1 jakllsch coram_dtv_open(void *cookie, int flags) 618 1.1 jakllsch { 619 1.1 jakllsch struct coram_softc *sc = cookie; 620 1.1 jakllsch 621 1.4 jmcneill #ifdef CORAM_DEBUG 622 1.1 jakllsch device_printf(sc->sc_dev, "%s\n", __func__); 623 1.4 jmcneill #endif 624 1.1 jakllsch 625 1.1 jakllsch //KASSERT(sc->sc_tsbuf == NULL); 626 1.1 jakllsch 627 1.2 jmcneill if (sc->sc_tuner == NULL || sc->sc_demod == NULL) 628 1.2 jmcneill return ENXIO; 629 1.2 jmcneill 630 1.1 jakllsch coram_mpeg_reset(sc); 631 1.1 jakllsch 632 1.1 jakllsch /* allocate two alternating DMA areas for MPEG TS packets */ 633 1.1 jakllsch sc->sc_tsbuf = coram_mpeg_malloc(sc, CORAM_TS_PKTSIZE * 2); 634 1.1 jakllsch 635 1.1 jakllsch if (sc->sc_tsbuf == NULL) 636 1.1 jakllsch return ENOMEM; 637 1.1 jakllsch 638 1.1 jakllsch return 0; 639 1.1 jakllsch } 640 1.1 jakllsch 641 1.1 jakllsch static void 642 1.1 jakllsch coram_dtv_close(void *cookie) 643 1.1 jakllsch { 644 1.1 jakllsch struct coram_softc *sc = cookie; 645 1.1 jakllsch 646 1.4 jmcneill #ifdef CORAM_DEBUG 647 1.1 jakllsch device_printf(sc->sc_dev, "%s\n", __func__); 648 1.4 jmcneill #endif 649 1.1 jakllsch 650 1.1 jakllsch coram_mpeg_halt(sc); 651 1.1 jakllsch 652 1.1 jakllsch if (sc->sc_tsbuf != NULL) { 653 1.1 jakllsch coram_mpeg_free(sc, sc->sc_tsbuf); 654 1.1 jakllsch sc->sc_tsbuf = NULL; 655 1.1 jakllsch } 656 1.1 jakllsch } 657 1.1 jakllsch 658 1.1 jakllsch static int 659 1.1 jakllsch coram_dtv_set_tuner(void *cookie, const struct dvb_frontend_parameters *params) 660 1.1 jakllsch { 661 1.1 jakllsch struct coram_softc *sc = cookie; 662 1.1 jakllsch 663 1.1 jakllsch KASSERT(sc->sc_tuner != NULL); 664 1.1 jakllsch mt2131_tune_dtv(sc->sc_tuner, params); 665 1.1 jakllsch KASSERT(sc->sc_demod != NULL); 666 1.3 jmcneill return cx24227_set_modulation(sc->sc_demod, params->u.vsb.modulation); 667 1.1 jakllsch } 668 1.1 jakllsch 669 1.1 jakllsch static fe_status_t 670 1.1 jakllsch coram_dtv_get_status(void *cookie) 671 1.1 jakllsch { 672 1.3 jmcneill struct coram_softc *sc = cookie; 673 1.3 jmcneill 674 1.3 jmcneill if (sc->sc_demod == NULL) 675 1.3 jmcneill return ENXIO; 676 1.3 jmcneill 677 1.15 maya return cx24227_get_dtv_status(sc->sc_demod); 678 1.1 jakllsch } 679 1.1 jakllsch 680 1.1 jakllsch static uint16_t 681 1.1 jakllsch coram_dtv_get_signal_strength(void *cookie) 682 1.1 jakllsch { 683 1.1 jakllsch return 0; 684 1.1 jakllsch } 685 1.1 jakllsch 686 1.1 jakllsch static uint16_t 687 1.1 jakllsch coram_dtv_get_snr(void *cookie) 688 1.1 jakllsch { 689 1.1 jakllsch return 0; 690 1.1 jakllsch } 691 1.1 jakllsch 692 1.1 jakllsch static int 693 1.8 jmcneill coram_dtv_start_transfer(void *cookie, 694 1.8 jmcneill void (*cb)(void *, const struct dtv_payload *), void *arg) 695 1.1 jakllsch { 696 1.1 jakllsch struct coram_softc *sc = cookie; 697 1.1 jakllsch 698 1.4 jmcneill #ifdef CORAM_DEBUG 699 1.1 jakllsch device_printf(sc->sc_dev, "%s\n", __func__); 700 1.4 jmcneill #endif 701 1.1 jakllsch 702 1.8 jmcneill sc->sc_dtvsubmitcb = cb; 703 1.8 jmcneill sc->sc_dtvsubmitarg = arg; 704 1.8 jmcneill 705 1.1 jakllsch coram_mpeg_trigger(sc, sc->sc_tsbuf); 706 1.1 jakllsch 707 1.1 jakllsch return 0; 708 1.1 jakllsch } 709 1.1 jakllsch 710 1.1 jakllsch static int 711 1.1 jakllsch coram_dtv_stop_transfer(void *cookie) 712 1.1 jakllsch { 713 1.1 jakllsch struct coram_softc *sc = cookie; 714 1.1 jakllsch 715 1.4 jmcneill #ifdef CORAM_DEBUG 716 1.1 jakllsch device_printf(sc->sc_dev, "%s\n", __func__); 717 1.4 jmcneill #endif 718 1.1 jakllsch 719 1.1 jakllsch coram_mpeg_halt(sc); 720 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSK, 0); 721 1.1 jakllsch 722 1.8 jmcneill sc->sc_dtvsubmitcb = NULL; 723 1.8 jmcneill sc->sc_dtvsubmitarg = NULL; 724 1.8 jmcneill 725 1.1 jakllsch return 0; 726 1.1 jakllsch } 727 1.1 jakllsch 728 1.1 jakllsch 729 1.1 jakllsch static int 730 1.1 jakllsch coram_mpeg_reset(struct coram_softc *sc) 731 1.1 jakllsch { 732 1.1 jakllsch /* hold RISC in reset */ 733 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, DEV_CNTRL2, 0); 734 1.1 jakllsch 735 1.1 jakllsch /* disable fifo + risc */ 736 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_DMA_CTL, 0); 737 1.1 jakllsch 738 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSK, 0); 739 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_INT_MSK, 0); 740 1.1 jakllsch 741 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PCI_INT_STAT, 0); 742 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_INT_STAT, 0); 743 1.1 jakllsch 744 1.1 jakllsch memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz); 745 1.1 jakllsch 746 1.1 jakllsch return 0; 747 1.1 jakllsch } 748 1.1 jakllsch 749 1.1 jakllsch static void * 750 1.1 jakllsch coram_mpeg_malloc(struct coram_softc *sc, size_t size) 751 1.1 jakllsch { 752 1.1 jakllsch struct coram_dma *p; 753 1.1 jakllsch int err; 754 1.1 jakllsch 755 1.1 jakllsch p = kmem_alloc(sizeof(struct coram_dma), KM_SLEEP); 756 1.1 jakllsch err = coram_allocmem(sc, size, 16, p); 757 1.1 jakllsch if (err) { 758 1.1 jakllsch kmem_free(p, sizeof(struct coram_dma)); 759 1.1 jakllsch return NULL; 760 1.1 jakllsch } 761 1.1 jakllsch 762 1.1 jakllsch p->next = sc->sc_dma; 763 1.1 jakllsch sc->sc_dma = p; 764 1.1 jakllsch 765 1.1 jakllsch return KERNADDR(p); 766 1.1 jakllsch } 767 1.1 jakllsch 768 1.1 jakllsch static int 769 1.1 jakllsch coram_allocmem(struct coram_softc *sc, size_t size, size_t align, 770 1.1 jakllsch struct coram_dma *p) 771 1.1 jakllsch { 772 1.1 jakllsch int err; 773 1.1 jakllsch 774 1.1 jakllsch p->size = size; 775 1.1 jakllsch err = bus_dmamem_alloc(sc->sc_dmat, p->size, align, 0, 776 1.1 jakllsch p->segs, sizeof(p->segs) / sizeof(p->segs[0]), 777 1.1 jakllsch &p->nsegs, BUS_DMA_NOWAIT); 778 1.1 jakllsch if (err) 779 1.1 jakllsch return err; 780 1.1 jakllsch err = bus_dmamem_map(sc->sc_dmat, p->segs, p->nsegs, p->size, 781 1.1 jakllsch &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 782 1.1 jakllsch if (err) 783 1.1 jakllsch goto free; 784 1.1 jakllsch err = bus_dmamap_create(sc->sc_dmat, p->size, 1, p->size, 0, 785 1.1 jakllsch BUS_DMA_NOWAIT, &p->map); 786 1.1 jakllsch if (err) 787 1.1 jakllsch goto unmap; 788 1.1 jakllsch err = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size, NULL, 789 1.1 jakllsch BUS_DMA_NOWAIT); 790 1.1 jakllsch if (err) 791 1.1 jakllsch goto destroy; 792 1.1 jakllsch 793 1.1 jakllsch return 0; 794 1.1 jakllsch destroy: 795 1.1 jakllsch bus_dmamap_destroy(sc->sc_dmat, p->map); 796 1.1 jakllsch unmap: 797 1.1 jakllsch bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 798 1.1 jakllsch free: 799 1.1 jakllsch bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs); 800 1.1 jakllsch 801 1.1 jakllsch return err; 802 1.1 jakllsch } 803 1.1 jakllsch 804 1.1 jakllsch static int 805 1.1 jakllsch coram_mpeg_halt(struct coram_softc *sc) 806 1.1 jakllsch { 807 1.1 jakllsch uint32_t v; 808 1.1 jakllsch 809 1.4 jmcneill #ifdef CORAM_DEBUG 810 1.1 jakllsch device_printf(sc->sc_dev, "%s\n", __func__); 811 1.4 jmcneill #endif 812 1.1 jakllsch 813 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_DMA_CTL, 0); 814 1.1 jakllsch 815 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSK); 816 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSK, 817 1.1 jakllsch v & __BIT(2)); 818 1.1 jakllsch 819 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_INT_MSK); 820 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_INT_MSK, 821 1.1 jakllsch v & 0); 822 1.1 jakllsch 823 1.1 jakllsch return 0; 824 1.1 jakllsch } 825 1.1 jakllsch 826 1.1 jakllsch static void 827 1.1 jakllsch coram_mpeg_free(struct coram_softc *sc, void *addr) 828 1.1 jakllsch { 829 1.1 jakllsch struct coram_dma *p; 830 1.1 jakllsch struct coram_dma **pp; 831 1.1 jakllsch 832 1.1 jakllsch for (pp = &sc->sc_dma; (p = *pp) != NULL; pp = &p->next) 833 1.1 jakllsch if (KERNADDR(p) == addr) { 834 1.1 jakllsch coram_freemem(sc, p); 835 1.1 jakllsch *pp = p->next; 836 1.1 jakllsch kmem_free(p, sizeof(struct coram_dma)); 837 1.1 jakllsch return; 838 1.1 jakllsch } 839 1.1 jakllsch 840 1.1 jakllsch printf("%s: %p is already free\n", device_xname(sc->sc_dev), addr); 841 1.1 jakllsch return; 842 1.1 jakllsch } 843 1.1 jakllsch 844 1.1 jakllsch static int 845 1.1 jakllsch coram_freemem(struct coram_softc *sc, struct coram_dma *p) 846 1.1 jakllsch { 847 1.1 jakllsch bus_dmamap_unload(sc->sc_dmat, p->map); 848 1.1 jakllsch bus_dmamap_destroy(sc->sc_dmat, p->map); 849 1.1 jakllsch bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 850 1.1 jakllsch bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs); 851 1.1 jakllsch 852 1.1 jakllsch return 0; 853 1.1 jakllsch } 854 1.1 jakllsch 855 1.1 jakllsch static int 856 1.1 jakllsch coram_mpeg_trigger(struct coram_softc *sc, void *buf) 857 1.1 jakllsch { 858 1.1 jakllsch struct coram_dma *p; 859 1.1 jakllsch struct coram_sram_ch *ch; 860 1.1 jakllsch uint32_t v; 861 1.1 jakllsch 862 1.1 jakllsch ch = &coram_sram_chs[CORAM_SRAM_CH6]; 863 1.1 jakllsch 864 1.1 jakllsch for (p = sc->sc_dma; p && KERNADDR(p) != buf; p = p->next) 865 1.1 jakllsch continue; 866 1.1 jakllsch if (p == NULL) { 867 1.1 jakllsch printf("%s: coram_mpeg_trigger: bad addr %p\n", 868 1.1 jakllsch device_xname(sc->sc_dev), buf); 869 1.1 jakllsch return ENOENT; 870 1.1 jakllsch } 871 1.1 jakllsch 872 1.1 jakllsch /* disable fifo + risc */ 873 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_DMA_CTL, 0); 874 1.1 jakllsch 875 1.1 jakllsch coram_risc_buffer(sc, CORAM_TS_PKTSIZE, 1); 876 1.1 jakllsch coram_sram_ch_setup(sc, ch, CORAM_TS_PKTSIZE); 877 1.1 jakllsch 878 1.1 jakllsch /* let me hope this bit is the same as on the 2388[0-3] */ 879 1.1 jakllsch /* software reset */ 880 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_GEN_CTL, 0x0040); 881 1.1 jakllsch delay (100*1000); 882 1.1 jakllsch 883 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_LNGTH, CORAM_TS_PKTSIZE); 884 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_HW_SOP_CTL, 0x47 << 16 | 188 << 4); 885 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_TS_CLK_EN, 1); 886 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_VLD_MISC, 0); 887 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_GEN_CTL, 12); 888 1.1 jakllsch delay (100*1000); 889 1.1 jakllsch 890 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, PAD_CTRL); 891 1.1 jakllsch v &= ~0x4; /* Clear TS2_SOP_OE */ 892 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PAD_CTRL, v); 893 1.1 jakllsch 894 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_INT_MSK); 895 1.1 jakllsch v |= 0x111111; 896 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_INT_MSK, v); 897 1.1 jakllsch 898 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_DMA_CTL); 899 1.1 jakllsch v |= 0x11; /* Enable RISC controller and FIFO */ 900 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, VID_C_DMA_CTL, v); 901 1.1 jakllsch 902 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, DEV_CNTRL2); 903 1.1 jakllsch v |= __BIT(5); /* Enable RISC controller */ 904 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, DEV_CNTRL2, v); 905 1.1 jakllsch 906 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSK); 907 1.1 jakllsch v |= 0x001f00; 908 1.1 jakllsch v |= 0x04; 909 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, PCI_INT_MSK, v); 910 1.1 jakllsch 911 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_GEN_CTL); 912 1.4 jmcneill #ifdef CORAM_DEBUG 913 1.1 jakllsch printf("%s, %06x %08x\n", __func__, VID_C_GEN_CTL, v); 914 1.4 jmcneill #endif 915 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_SOP_STATUS); 916 1.4 jmcneill #ifdef CORAM_DEBUG 917 1.1 jakllsch printf("%s, %06x %08x\n", __func__, VID_C_SOP_STATUS, v); 918 1.4 jmcneill #endif 919 1.1 jakllsch delay(100*1000); 920 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_GEN_CTL); 921 1.4 jmcneill #ifdef CORAM_DEBUG 922 1.1 jakllsch printf("%s, %06x %08x\n", __func__, VID_C_GEN_CTL, v); 923 1.4 jmcneill #endif 924 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, VID_C_SOP_STATUS); 925 1.4 jmcneill #ifdef CORAM_DEBUG 926 1.1 jakllsch printf("%s, %06x %08x\n", __func__, VID_C_SOP_STATUS, v); 927 1.4 jmcneill #endif 928 1.1 jakllsch 929 1.1 jakllsch return 0; 930 1.1 jakllsch } 931 1.1 jakllsch 932 1.1 jakllsch static int 933 1.1 jakllsch coram_risc_buffer(struct coram_softc *sc, uint32_t bpl, uint32_t lines) 934 1.1 jakllsch { 935 1.1 jakllsch uint32_t *rm; 936 1.1 jakllsch uint32_t size; 937 1.1 jakllsch 938 1.1 jakllsch size = 1 + (bpl * lines) / PAGE_SIZE + lines; 939 1.1 jakllsch size += 2; 940 1.1 jakllsch 941 1.1 jakllsch if (sc->sc_riscbuf == NULL) { 942 1.1 jakllsch return ENOMEM; 943 1.1 jakllsch } 944 1.1 jakllsch 945 1.1 jakllsch rm = (uint32_t *)sc->sc_riscbuf; 946 1.1 jakllsch coram_risc_field(sc, rm, bpl); 947 1.1 jakllsch 948 1.1 jakllsch return 0; 949 1.1 jakllsch } 950 1.1 jakllsch 951 1.1 jakllsch static int 952 1.1 jakllsch coram_risc_field(struct coram_softc *sc, uint32_t *rm, uint32_t bpl) 953 1.1 jakllsch { 954 1.1 jakllsch struct coram_dma *p; 955 1.1 jakllsch 956 1.1 jakllsch for (p = sc->sc_dma; p && KERNADDR(p) != sc->sc_tsbuf; p = p->next) 957 1.1 jakllsch continue; 958 1.1 jakllsch if (p == NULL) { 959 1.1 jakllsch printf("%s: coram_risc_field: bad addr %p\n", 960 1.1 jakllsch device_xname(sc->sc_dev), sc->sc_tsbuf); 961 1.1 jakllsch return ENOENT; 962 1.1 jakllsch } 963 1.1 jakllsch 964 1.1 jakllsch memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz); 965 1.1 jakllsch 966 1.1 jakllsch rm = sc->sc_riscbuf; 967 1.1 jakllsch 968 1.1 jakllsch /* htole32 will be done when program is copied to chip sram */ 969 1.1 jakllsch 970 1.1 jakllsch /* XXX */ 971 1.1 jakllsch *(rm++) = (CX_RISC_SYNC|0); 972 1.1 jakllsch 973 1.1 jakllsch *(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ1|bpl); 974 1.1 jakllsch *(rm++) = (DMAADDR(p) + 0 * bpl); 975 1.1 jakllsch *(rm++) = 0; /* high dword */ 976 1.1 jakllsch 977 1.1 jakllsch *(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ2|bpl); 978 1.1 jakllsch *(rm++) = (DMAADDR(p) + 1 * bpl); 979 1.1 jakllsch *(rm++) = 0; 980 1.1 jakllsch 981 1.1 jakllsch *(rm++) = (CX_RISC_JUMP|1); 982 1.1 jakllsch *(rm++) = (coram_sram_chs[CORAM_SRAM_CH6].csc_risc + 4); 983 1.1 jakllsch *(rm++) = 0; 984 1.1 jakllsch 985 1.1 jakllsch return 0; 986 1.1 jakllsch } 987 1.1 jakllsch 988 1.1 jakllsch static int 989 1.1 jakllsch coram_sram_ch_setup(struct coram_softc *sc, struct coram_sram_ch *csc, 990 1.1 jakllsch uint32_t bpl) 991 1.1 jakllsch { 992 1.1 jakllsch unsigned int i, lines; 993 1.1 jakllsch uint32_t cdt; 994 1.1 jakllsch 995 1.1 jakllsch /* XXX why round? */ 996 1.1 jakllsch bpl = (bpl + 7) & ~7; 997 1.1 jakllsch cdt = csc->csc_cdt; 998 1.1 jakllsch lines = csc->csc_fifosz / bpl; 999 1.4 jmcneill #ifdef CORAM_DEBUG 1000 1.1 jakllsch printf("%s %d lines\n", __func__, lines); 1001 1.4 jmcneill #endif 1002 1.1 jakllsch 1003 1.1 jakllsch /* fill in CDT */ 1004 1.1 jakllsch for (i = 0; i < lines; i++) { 1005 1.4 jmcneill #ifdef CORAM_DEBUG 1006 1.1 jakllsch printf("CDT ent %08x, %08x\n", cdt + (16 * i), 1007 1.1 jakllsch csc->csc_fifo + (bpl * i)); 1008 1.1 jakllsch #endif 1009 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1010 1.1 jakllsch cdt + (16 * i), csc->csc_fifo + (bpl * i)); 1011 1.1 jakllsch } 1012 1.1 jakllsch 1013 1.1 jakllsch /* copy program */ 1014 1.1 jakllsch /* converts program to little endian as it goes into sram */ 1015 1.1 jakllsch bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 1016 1.1 jakllsch csc->csc_risc, (void *)sc->sc_riscbuf, sc->sc_riscbufsz >> 2); 1017 1.1 jakllsch 1018 1.1 jakllsch /* fill in CMDS */ 1019 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1020 1.1 jakllsch csc->csc_cmds + CMDS_O_IRPC, csc->csc_risc); 1021 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1022 1.1 jakllsch csc->csc_cmds + CMDS_O_IRPC + 4, 0); 1023 1.1 jakllsch 1024 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1025 1.1 jakllsch csc->csc_cmds + CMDS_O_CDTB, csc->csc_cdt); 1026 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1027 1.1 jakllsch csc->csc_cmds + CMDS_O_CDTS, (lines * 16) >> 3); /* XXX magic */ 1028 1.1 jakllsch 1029 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1030 1.1 jakllsch csc->csc_cmds + CMDS_O_IQB, csc->csc_iq); 1031 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1032 1.1 jakllsch csc->csc_cmds + CMDS_O_IQS, 1033 1.1 jakllsch CMDS_IQS_ISRP | (csc->csc_iqsz >> 2) ); 1034 1.1 jakllsch 1035 1.1 jakllsch /* zero rest of CMDS */ 1036 1.1 jakllsch bus_space_set_region_4(sc->sc_memt, sc->sc_memh, 0x18, 0, 20); 1037 1.1 jakllsch 1038 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1039 1.1 jakllsch csc->csc_ptr1, csc->csc_fifo); 1040 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1041 1.1 jakllsch csc->csc_ptr2, cdt); 1042 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1043 1.1 jakllsch csc->csc_cnt2, (lines * 16) >> 3); 1044 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 1045 1.1 jakllsch csc->csc_cnt1, (bpl >> 3) - 1); 1046 1.1 jakllsch 1047 1.1 jakllsch return 0; 1048 1.1 jakllsch } 1049 1.2 jmcneill 1050 1.9 jmcneill MODULE(MODULE_CLASS_DRIVER, coram, "cx24227,mt2131,pci"); 1051 1.2 jmcneill 1052 1.2 jmcneill #ifdef _MODULE 1053 1.2 jmcneill #include "ioconf.c" 1054 1.2 jmcneill #endif 1055 1.2 jmcneill 1056 1.2 jmcneill static int 1057 1.2 jmcneill coram_modcmd(modcmd_t cmd, void *v) 1058 1.2 jmcneill { 1059 1.2 jmcneill int error = 0; 1060 1.2 jmcneill 1061 1.2 jmcneill switch (cmd) { 1062 1.2 jmcneill case MODULE_CMD_INIT: 1063 1.2 jmcneill #ifdef _MODULE 1064 1.2 jmcneill error = config_init_component(cfdriver_ioconf_coram, 1065 1.2 jmcneill cfattach_ioconf_coram, cfdata_ioconf_coram); 1066 1.2 jmcneill #endif 1067 1.2 jmcneill return error; 1068 1.2 jmcneill case MODULE_CMD_FINI: 1069 1.2 jmcneill #ifdef _MODULE 1070 1.2 jmcneill error = config_fini_component(cfdriver_ioconf_coram, 1071 1.2 jmcneill cfattach_ioconf_coram, cfdata_ioconf_coram); 1072 1.2 jmcneill #endif 1073 1.2 jmcneill return error; 1074 1.2 jmcneill default: 1075 1.2 jmcneill return ENOTTY; 1076 1.2 jmcneill } 1077 1.2 jmcneill } 1078