1 1.23 thorpej /* $NetBSD: cxdtv.c,v 1.23 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.23 thorpej __KERNEL_RCSID(0, "$NetBSD: cxdtv.c,v 1.23 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/kernel.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.6 jakllsch #include <sys/proc.h> 38 1.2 jmcneill #include <sys/module.h> 39 1.1 jakllsch #include <sys/bus.h> 40 1.1 jakllsch 41 1.1 jakllsch #include <dev/pci/pcivar.h> 42 1.1 jakllsch #include <dev/pci/pcireg.h> 43 1.1 jakllsch #include <dev/pci/pcidevs.h> 44 1.1 jakllsch #include <dev/i2c/i2cvar.h> 45 1.1 jakllsch #include <dev/i2c/i2c_bitbang.h> 46 1.1 jakllsch 47 1.1 jakllsch #include <dev/i2c/tvpllvar.h> 48 1.1 jakllsch #include <dev/i2c/tvpll_tuners.h> 49 1.1 jakllsch 50 1.1 jakllsch #include <dev/i2c/nxt2kvar.h> 51 1.2 jmcneill #include <dev/i2c/lg3303var.h> 52 1.1 jakllsch 53 1.7 jmcneill #include <dev/dtv/dtvif.h> 54 1.7 jmcneill 55 1.1 jakllsch #include <dev/pci/cxdtvreg.h> 56 1.1 jakllsch #include <dev/pci/cxdtvvar.h> 57 1.1 jakllsch #include <dev/pci/cxdtv_boards.h> 58 1.1 jakllsch 59 1.1 jakllsch #define CXDTV_MMBASE 0x10 60 1.1 jakllsch 61 1.1 jakllsch #define CXDTV_SRAM_CH_MPEG 0 62 1.1 jakllsch #define CXDTV_TS_PKTSIZE (188 * 8) 63 1.1 jakllsch 64 1.12 chs static int cxdtv_match(device_t, cfdata_t, void *); 65 1.12 chs static void cxdtv_attach(device_t, device_t, void *); 66 1.12 chs static int cxdtv_detach(device_t, int); 67 1.12 chs static int cxdtv_rescan(device_t, const char *, const int *); 68 1.12 chs static void cxdtv_childdet(device_t, device_t); 69 1.1 jakllsch static int cxdtv_intr(void *); 70 1.1 jakllsch 71 1.1 jakllsch static bool cxdtv_resume(device_t, const pmf_qual_t *); 72 1.1 jakllsch 73 1.1 jakllsch static int cxdtv_iic_send_start(void *, int); 74 1.1 jakllsch static int cxdtv_iic_send_stop(void *, int); 75 1.1 jakllsch static int cxdtv_iic_initiate_xfer(void *, i2c_addr_t, int); 76 1.1 jakllsch static int cxdtv_iic_read_byte(void *, uint8_t *, int); 77 1.1 jakllsch static int cxdtv_iic_write_byte(void *, uint8_t, int); 78 1.1 jakllsch 79 1.1 jakllsch static void cxdtv_i2cbb_set_bits(void *, uint32_t); 80 1.1 jakllsch static void cxdtv_i2cbb_set_dir(void *, uint32_t); 81 1.1 jakllsch static uint32_t cxdtv_i2cbb_read_bits(void *); 82 1.1 jakllsch 83 1.1 jakllsch static int cxdtv_sram_ch_setup(struct cxdtv_softc *, 84 1.1 jakllsch struct cxdtv_sram_ch *, uint32_t); 85 1.1 jakllsch static int cxdtv_allocmem(struct cxdtv_softc *, size_t, size_t, 86 1.1 jakllsch struct cxdtv_dma *); 87 1.1 jakllsch static int cxdtv_freemem(struct cxdtv_softc *, struct cxdtv_dma *); 88 1.1 jakllsch static int cxdtv_risc_buffer(struct cxdtv_softc *, uint32_t, uint32_t); 89 1.1 jakllsch static int cxdtv_risc_field(struct cxdtv_softc *, uint32_t *, uint32_t); 90 1.1 jakllsch 91 1.1 jakllsch static int cxdtv_mpeg_attach(struct cxdtv_softc *); 92 1.21 riastrad static void cxdtv_mpeg_detach(struct cxdtv_softc *, int flags); 93 1.1 jakllsch static int cxdtv_mpeg_intr(struct cxdtv_softc *); 94 1.1 jakllsch static int cxdtv_mpeg_reset(struct cxdtv_softc *); 95 1.1 jakllsch 96 1.1 jakllsch static int cxdtv_mpeg_trigger(struct cxdtv_softc *, void *); 97 1.1 jakllsch static int cxdtv_mpeg_halt(struct cxdtv_softc *); 98 1.1 jakllsch static void * cxdtv_mpeg_malloc(struct cxdtv_softc *, size_t); 99 1.1 jakllsch static void cxdtv_mpeg_free(struct cxdtv_softc *, void *); 100 1.1 jakllsch 101 1.1 jakllsch static void cxdtv_card_init_hd5500(struct cxdtv_softc *); 102 1.1 jakllsch static void cxdtv_card_init_hdtvwonder(struct cxdtv_softc *); 103 1.1 jakllsch 104 1.7 jmcneill /* MPEG TS Port */ 105 1.7 jmcneill static void cxdtv_dtv_get_devinfo(void *, struct dvb_frontend_info *); 106 1.7 jmcneill static int cxdtv_dtv_open(void *, int); 107 1.7 jmcneill static void cxdtv_dtv_close(void *); 108 1.7 jmcneill static int cxdtv_dtv_set_tuner(void *, const struct dvb_frontend_parameters *); 109 1.7 jmcneill static fe_status_t cxdtv_dtv_get_status(void *); 110 1.7 jmcneill static uint16_t cxdtv_dtv_get_signal_strength(void *); 111 1.7 jmcneill static uint16_t cxdtv_dtv_get_snr(void *); 112 1.7 jmcneill static int cxdtv_dtv_start_transfer(void *, 113 1.7 jmcneill void (*)(void *, const struct dtv_payload *), void *); 114 1.7 jmcneill static int cxdtv_dtv_stop_transfer(void *); 115 1.7 jmcneill 116 1.7 jmcneill static const struct dtv_hw_if cxdtv_dtv_if = { 117 1.7 jmcneill .get_devinfo = cxdtv_dtv_get_devinfo, 118 1.7 jmcneill .open = cxdtv_dtv_open, 119 1.7 jmcneill .close = cxdtv_dtv_close, 120 1.7 jmcneill .set_tuner = cxdtv_dtv_set_tuner, 121 1.7 jmcneill .get_status = cxdtv_dtv_get_status, 122 1.7 jmcneill .get_signal_strength = cxdtv_dtv_get_signal_strength, 123 1.7 jmcneill .get_snr = cxdtv_dtv_get_snr, 124 1.7 jmcneill .start_transfer = cxdtv_dtv_start_transfer, 125 1.7 jmcneill .stop_transfer = cxdtv_dtv_stop_transfer, 126 1.7 jmcneill }; 127 1.7 jmcneill 128 1.1 jakllsch const struct i2c_bitbang_ops cxdtv_i2cbb_ops = { 129 1.1 jakllsch cxdtv_i2cbb_set_bits, 130 1.1 jakllsch cxdtv_i2cbb_set_dir, 131 1.1 jakllsch cxdtv_i2cbb_read_bits, 132 1.1 jakllsch { CXDTV_I2C_C_DATACONTROL_SDA, CXDTV_I2C_C_DATACONTROL_SCL, 0, 0 } 133 1.1 jakllsch }; 134 1.1 jakllsch 135 1.1 jakllsch /* Maybe make this dynamically allocated. */ 136 1.1 jakllsch static struct cxdtv_sram_ch cxdtv_sram_chs[] = { 137 1.1 jakllsch [CXDTV_SRAM_CH_MPEG] = { 138 1.1 jakllsch .csc_cmds = 0x180200, /* CMDS for ch. 28 */ 139 1.1 jakllsch .csc_iq = 0x180340, /* after last CMDS */ 140 1.1 jakllsch .csc_iqsz = 0x40, /* 16 dwords */ 141 1.1 jakllsch .csc_cdt = 0x180380, /* after iq */ 142 1.22 andvar .csc_cdtsz = 0x40, /* cluster descriptor space */ 143 1.1 jakllsch .csc_fifo = 0x180400, /* after cdt */ 144 1.1 jakllsch .csc_fifosz = 0x001C00, /* let's just align this up */ 145 1.1 jakllsch .csc_risc = 0x182000, /* after fifo */ 146 1.1 jakllsch .csc_riscsz = 0x6000, /* room for dma programs */ 147 1.1 jakllsch .csc_ptr1 = CXDTV_DMA28_PTR1, 148 1.1 jakllsch .csc_ptr2 = CXDTV_DMA28_PTR2, 149 1.1 jakllsch .csc_cnt1 = CXDTV_DMA28_CNT1, 150 1.1 jakllsch .csc_cnt2 = CXDTV_DMA28_CNT2, 151 1.1 jakllsch }, 152 1.1 jakllsch }; 153 1.1 jakllsch 154 1.3 jmcneill CFATTACH_DECL2_NEW(cxdtv, sizeof(struct cxdtv_softc), 155 1.7 jmcneill cxdtv_match, cxdtv_attach, cxdtv_detach, NULL, 156 1.7 jmcneill cxdtv_rescan, cxdtv_childdet); 157 1.1 jakllsch 158 1.1 jakllsch static int 159 1.1 jakllsch cxdtv_match(device_t parent, cfdata_t match, void *aux) 160 1.1 jakllsch { 161 1.1 jakllsch const struct pci_attach_args *pa; 162 1.10 jmcneill pcireg_t reg; 163 1.1 jakllsch 164 1.1 jakllsch pa = aux; 165 1.1 jakllsch 166 1.1 jakllsch if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CONEXANT) 167 1.1 jakllsch return 0; 168 1.1 jakllsch 169 1.10 jmcneill if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_CONEXANT_CX2388XMPEG) 170 1.10 jmcneill return 0; 171 1.1 jakllsch 172 1.10 jmcneill reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 173 1.10 jmcneill if (cxdtv_board_lookup(PCI_VENDOR(reg), PCI_PRODUCT(reg)) == NULL) 174 1.10 jmcneill return 0; 175 1.1 jakllsch 176 1.10 jmcneill return 1; 177 1.1 jakllsch } 178 1.1 jakllsch 179 1.1 jakllsch static void 180 1.1 jakllsch cxdtv_attach(device_t parent, device_t self, void *aux) 181 1.1 jakllsch { 182 1.1 jakllsch struct cxdtv_softc *sc; 183 1.1 jakllsch const struct pci_attach_args *pa = aux; 184 1.1 jakllsch pci_intr_handle_t ih; 185 1.1 jakllsch pcireg_t reg; 186 1.1 jakllsch const char *intrstr; 187 1.14 christos char intrbuf[PCI_INTRSTR_LEN]; 188 1.1 jakllsch 189 1.1 jakllsch sc = device_private(self); 190 1.1 jakllsch 191 1.1 jakllsch sc->sc_dev = self; 192 1.3 jmcneill sc->sc_pc = pa->pa_pc; 193 1.1 jakllsch 194 1.1 jakllsch reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 195 1.1 jakllsch 196 1.1 jakllsch sc->sc_vendor = PCI_VENDOR(reg); 197 1.1 jakllsch sc->sc_product = PCI_PRODUCT(reg); 198 1.1 jakllsch 199 1.1 jakllsch sc->sc_board = cxdtv_board_lookup(sc->sc_vendor, sc->sc_product); 200 1.10 jmcneill KASSERT(sc->sc_board != NULL); 201 1.1 jakllsch 202 1.11 drochner pci_aprint_devinfo(pa, NULL); 203 1.1 jakllsch 204 1.1 jakllsch if (pci_mapreg_map(pa, CXDTV_MMBASE, PCI_MAPREG_TYPE_MEM, 0, 205 1.1 jakllsch &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems)) { 206 1.1 jakllsch aprint_error_dev(self, "couldn't map memory space\n"); 207 1.1 jakllsch return; 208 1.1 jakllsch } 209 1.1 jakllsch 210 1.1 jakllsch sc->sc_dmat = pa->pa_dmat; 211 1.1 jakllsch 212 1.1 jakllsch if (pci_intr_map(pa, &ih)) { 213 1.1 jakllsch aprint_error_dev(self, "couldn't map interrupt\n"); 214 1.1 jakllsch return; 215 1.1 jakllsch } 216 1.14 christos intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); 217 1.16 jdolecek sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_VM, cxdtv_intr, 218 1.16 jdolecek sc, device_xname(self)); 219 1.1 jakllsch if (sc->sc_ih == NULL) { 220 1.1 jakllsch aprint_error_dev(self, "couldn't establish interrupt"); 221 1.1 jakllsch if (intrstr != NULL) 222 1.1 jakllsch aprint_error(" at %s", intrstr); 223 1.1 jakllsch aprint_error("\n"); 224 1.1 jakllsch return; 225 1.1 jakllsch } 226 1.1 jakllsch aprint_normal_dev(self, "interrupting at %s\n", intrstr); 227 1.1 jakllsch 228 1.1 jakllsch /* set master */ 229 1.1 jakllsch reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 230 1.1 jakllsch reg |= PCI_COMMAND_MASTER_ENABLE; 231 1.1 jakllsch pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg); 232 1.1 jakllsch 233 1.17 thorpej iic_tag_init(&sc->sc_i2c); 234 1.1 jakllsch sc->sc_i2c.ic_cookie = sc; 235 1.1 jakllsch sc->sc_i2c.ic_send_start = cxdtv_iic_send_start; 236 1.1 jakllsch sc->sc_i2c.ic_send_stop = cxdtv_iic_send_stop; 237 1.1 jakllsch sc->sc_i2c.ic_initiate_xfer = cxdtv_iic_initiate_xfer; 238 1.1 jakllsch sc->sc_i2c.ic_read_byte = cxdtv_iic_read_byte; 239 1.1 jakllsch sc->sc_i2c.ic_write_byte = cxdtv_iic_write_byte; 240 1.1 jakllsch 241 1.1 jakllsch #if notyet 242 1.1 jakllsch /* enable i2c compatible software mode */ 243 1.1 jakllsch val = bus_space_read_4(sc->sc_memt, sc->sc_memh, 244 1.1 jakllsch CXDTV_I2C_C_DATACONTROL); 245 1.1 jakllsch val = CXDTV_I2C_C_DATACONTROL_SCL | CXDTV_I2C_C_DATACONTROL_SDA; 246 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 247 1.1 jakllsch CXDTV_I2C_C_DATACONTROL, val); 248 1.1 jakllsch #endif 249 1.1 jakllsch 250 1.1 jakllsch cxdtv_mpeg_attach(sc); 251 1.1 jakllsch 252 1.1 jakllsch /* attach other devices to iic(4) */ 253 1.23 thorpej iicbus_attach(self, &sc->sc_i2c); 254 1.1 jakllsch 255 1.1 jakllsch if (!pmf_device_register(self, NULL, cxdtv_resume)) 256 1.1 jakllsch aprint_error_dev(self, "couldn't establish power handler\n"); 257 1.1 jakllsch 258 1.1 jakllsch return; 259 1.1 jakllsch } 260 1.1 jakllsch 261 1.2 jmcneill static int 262 1.2 jmcneill cxdtv_detach(device_t self, int flags) 263 1.2 jmcneill { 264 1.3 jmcneill struct cxdtv_softc *sc = device_private(self); 265 1.3 jmcneill int error; 266 1.3 jmcneill 267 1.21 riastrad error = config_detach_children(self, flags); 268 1.3 jmcneill if (error) 269 1.3 jmcneill return error; 270 1.3 jmcneill 271 1.21 riastrad cxdtv_mpeg_detach(sc, flags); 272 1.21 riastrad 273 1.3 jmcneill if (sc->sc_ih) 274 1.3 jmcneill pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 275 1.3 jmcneill 276 1.3 jmcneill if (sc->sc_mems) 277 1.3 jmcneill bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems); 278 1.3 jmcneill 279 1.17 thorpej iic_tag_fini(&sc->sc_i2c); 280 1.3 jmcneill 281 1.3 jmcneill return 0; 282 1.3 jmcneill } 283 1.3 jmcneill 284 1.7 jmcneill static int 285 1.7 jmcneill cxdtv_rescan(device_t self, const char *ifattr, const int *locs) 286 1.7 jmcneill { 287 1.7 jmcneill struct cxdtv_softc *sc = device_private(self); 288 1.7 jmcneill struct dtv_attach_args daa; 289 1.7 jmcneill 290 1.7 jmcneill daa.hw = &cxdtv_dtv_if; 291 1.7 jmcneill daa.priv = sc; 292 1.7 jmcneill 293 1.7 jmcneill if (ifattr_match(ifattr, "dtvbus") && sc->sc_dtvdev == NULL) 294 1.19 thorpej sc->sc_dtvdev = config_found(sc->sc_dev, &daa, dtv_print, 295 1.20 thorpej CFARGS(.iattr = "dtvbus")); 296 1.7 jmcneill 297 1.7 jmcneill return 0; 298 1.7 jmcneill } 299 1.7 jmcneill 300 1.3 jmcneill static void 301 1.3 jmcneill cxdtv_childdet(device_t self, device_t child) 302 1.3 jmcneill { 303 1.3 jmcneill struct cxdtv_softc *sc = device_private(self); 304 1.3 jmcneill 305 1.3 jmcneill if (child == sc->sc_dtvdev) 306 1.3 jmcneill sc->sc_dtvdev = NULL; 307 1.2 jmcneill } 308 1.2 jmcneill 309 1.1 jakllsch static bool 310 1.1 jakllsch cxdtv_resume(device_t dv, const pmf_qual_t *qual) 311 1.1 jakllsch { 312 1.1 jakllsch /* XXX revisit */ 313 1.1 jakllsch 314 1.1 jakllsch aprint_debug_dev(dv, "%s\n", __func__); 315 1.1 jakllsch 316 1.1 jakllsch return true; 317 1.1 jakllsch } 318 1.1 jakllsch 319 1.1 jakllsch static int 320 1.1 jakllsch cxdtv_intr(void *intarg) 321 1.1 jakllsch { 322 1.1 jakllsch struct cxdtv_softc *sc = intarg; 323 1.1 jakllsch uint32_t val; 324 1.1 jakllsch 325 1.1 jakllsch val = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MSTAT); 326 1.1 jakllsch if (val == 0) { 327 1.1 jakllsch return 0; /* not ours */ 328 1.1 jakllsch } 329 1.1 jakllsch 330 1.1 jakllsch if (val & CXT_PI_TS_INT) { 331 1.1 jakllsch cxdtv_mpeg_intr(sc); 332 1.1 jakllsch } 333 1.1 jakllsch 334 1.1 jakllsch if (val & ~CXT_PI_TS_INT) { 335 1.1 jakllsch device_printf(sc->sc_dev, "%s, %08x\n", __func__, val); 336 1.1 jakllsch } 337 1.1 jakllsch 338 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_STAT, val); 339 1.1 jakllsch 340 1.1 jakllsch return 1; 341 1.1 jakllsch } 342 1.1 jakllsch 343 1.1 jakllsch /* I2C interface */ 344 1.1 jakllsch 345 1.1 jakllsch static void 346 1.1 jakllsch cxdtv_i2cbb_set_bits(void *cookie, uint32_t bits) 347 1.1 jakllsch { 348 1.1 jakllsch struct cxdtv_softc *sc = cookie; 349 1.1 jakllsch 350 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 351 1.1 jakllsch CXDTV_I2C_C_DATACONTROL, bits); 352 1.13 christos (void)bus_space_read_4(sc->sc_memt, sc->sc_memh, 353 1.1 jakllsch CXDTV_I2C_C_DATACONTROL); 354 1.1 jakllsch 355 1.1 jakllsch return; 356 1.1 jakllsch } 357 1.1 jakllsch 358 1.1 jakllsch static void 359 1.1 jakllsch cxdtv_i2cbb_set_dir(void *cookie, uint32_t bits) 360 1.1 jakllsch { 361 1.1 jakllsch return; 362 1.1 jakllsch } 363 1.1 jakllsch 364 1.1 jakllsch static uint32_t 365 1.1 jakllsch cxdtv_i2cbb_read_bits(void *cookie) 366 1.1 jakllsch { 367 1.1 jakllsch struct cxdtv_softc *sc = cookie; 368 1.1 jakllsch uint32_t value; 369 1.1 jakllsch 370 1.1 jakllsch value = bus_space_read_4(sc->sc_memt, sc->sc_memh, 371 1.1 jakllsch CXDTV_I2C_C_DATACONTROL); 372 1.1 jakllsch 373 1.1 jakllsch return value; 374 1.1 jakllsch } 375 1.1 jakllsch 376 1.1 jakllsch static int 377 1.1 jakllsch cxdtv_iic_send_start(void *cookie, int flags) 378 1.1 jakllsch { 379 1.1 jakllsch return i2c_bitbang_send_start(cookie, flags, &cxdtv_i2cbb_ops); 380 1.1 jakllsch } 381 1.1 jakllsch 382 1.1 jakllsch static int 383 1.1 jakllsch cxdtv_iic_send_stop(void *cookie, int flags) 384 1.1 jakllsch { 385 1.1 jakllsch return i2c_bitbang_send_stop(cookie, flags, &cxdtv_i2cbb_ops); 386 1.1 jakllsch } 387 1.1 jakllsch 388 1.1 jakllsch static int 389 1.1 jakllsch cxdtv_iic_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 390 1.1 jakllsch { 391 1.1 jakllsch return i2c_bitbang_initiate_xfer(cookie, addr, flags, &cxdtv_i2cbb_ops); 392 1.1 jakllsch } 393 1.1 jakllsch 394 1.1 jakllsch static int 395 1.1 jakllsch cxdtv_iic_read_byte(void *cookie, uint8_t *data, int flags) 396 1.1 jakllsch { 397 1.1 jakllsch return i2c_bitbang_read_byte(cookie, data, flags, &cxdtv_i2cbb_ops); 398 1.1 jakllsch } 399 1.1 jakllsch 400 1.1 jakllsch static int 401 1.1 jakllsch cxdtv_iic_write_byte(void *cookie, uint8_t data, int flags) 402 1.1 jakllsch { 403 1.1 jakllsch return i2c_bitbang_write_byte(cookie, data, flags, &cxdtv_i2cbb_ops); 404 1.1 jakllsch } 405 1.1 jakllsch 406 1.1 jakllsch int 407 1.1 jakllsch cxdtv_mpeg_attach(struct cxdtv_softc *sc) 408 1.1 jakllsch { 409 1.1 jakllsch struct cxdtv_sram_ch *ch; 410 1.1 jakllsch 411 1.1 jakllsch CX_DPRINTF(("cxdtv_mpeg_attach\n")); 412 1.1 jakllsch 413 1.1 jakllsch ch = &cxdtv_sram_chs[CXDTV_SRAM_CH_MPEG]; 414 1.1 jakllsch 415 1.1 jakllsch sc->sc_riscbufsz = ch->csc_riscsz; 416 1.1 jakllsch sc->sc_riscbuf = kmem_alloc(ch->csc_riscsz, KM_SLEEP); 417 1.1 jakllsch 418 1.1 jakllsch aprint_debug_dev(sc->sc_dev, "attaching frontend...\n"); 419 1.1 jakllsch 420 1.1 jakllsch switch(sc->sc_vendor) { 421 1.1 jakllsch case PCI_VENDOR_ATI: 422 1.1 jakllsch cxdtv_card_init_hdtvwonder(sc); 423 1.1 jakllsch break; 424 1.1 jakllsch case PCI_VENDOR_PCHDTV: 425 1.1 jakllsch if (sc->sc_product == PCI_PRODUCT_PCHDTV_HD5500) { 426 1.1 jakllsch cxdtv_card_init_hd5500(sc); 427 1.1 jakllsch } 428 1.1 jakllsch break; 429 1.1 jakllsch } 430 1.1 jakllsch 431 1.1 jakllsch KASSERT(sc->sc_tuner == NULL); 432 1.1 jakllsch KASSERT(sc->sc_demod == NULL); 433 1.1 jakllsch 434 1.1 jakllsch switch(sc->sc_board->cb_demod) { 435 1.1 jakllsch case CXDTV_DEMOD_NXT2004: 436 1.1 jakllsch sc->sc_demod = nxt2k_open(sc->sc_dev, &sc->sc_i2c, 0x0a, 0); 437 1.1 jakllsch break; 438 1.2 jmcneill case CXDTV_DEMOD_LG3303: 439 1.2 jmcneill sc->sc_demod = lg3303_open(sc->sc_dev, &sc->sc_i2c, 0x59, 440 1.2 jmcneill LG3303_CFG_SERIAL_INPUT); 441 1.2 jmcneill break; 442 1.1 jakllsch default: 443 1.1 jakllsch break; 444 1.1 jakllsch } 445 1.1 jakllsch 446 1.1 jakllsch switch(sc->sc_board->cb_tuner) { 447 1.1 jakllsch case CXDTV_TUNER_PLL: 448 1.1 jakllsch if (sc->sc_vendor == PCI_VENDOR_ATI) 449 1.1 jakllsch sc->sc_tuner = tvpll_open(sc->sc_dev, &sc->sc_i2c, 0x61, &tvpll_tuv1236d_pll); 450 1.1 jakllsch if (sc->sc_vendor == PCI_VENDOR_PCHDTV) 451 1.1 jakllsch sc->sc_tuner = tvpll_open(sc->sc_dev, &sc->sc_i2c, 0x61, &tvpll_tdvs_h06xf_pll); 452 1.1 jakllsch break; 453 1.1 jakllsch default: 454 1.1 jakllsch break; 455 1.1 jakllsch } 456 1.1 jakllsch 457 1.1 jakllsch KASSERT(sc->sc_tuner != NULL); 458 1.1 jakllsch KASSERT(sc->sc_demod != NULL); 459 1.1 jakllsch 460 1.7 jmcneill cxdtv_rescan(sc->sc_dev, NULL, NULL); 461 1.1 jakllsch 462 1.1 jakllsch return (sc->sc_dtvdev != NULL); 463 1.1 jakllsch } 464 1.1 jakllsch 465 1.21 riastrad void 466 1.3 jmcneill cxdtv_mpeg_detach(struct cxdtv_softc *sc, int flags) 467 1.3 jmcneill { 468 1.3 jmcneill 469 1.3 jmcneill if (sc->sc_demod) { 470 1.3 jmcneill switch (sc->sc_board->cb_demod) { 471 1.3 jmcneill case CXDTV_DEMOD_NXT2004: 472 1.3 jmcneill nxt2k_close(sc->sc_demod); 473 1.3 jmcneill break; 474 1.3 jmcneill case CXDTV_DEMOD_LG3303: 475 1.3 jmcneill lg3303_close(sc->sc_demod); 476 1.3 jmcneill break; 477 1.3 jmcneill default: 478 1.3 jmcneill break; 479 1.3 jmcneill } 480 1.3 jmcneill sc->sc_demod = NULL; 481 1.3 jmcneill } 482 1.3 jmcneill if (sc->sc_tuner) { 483 1.3 jmcneill switch (sc->sc_board->cb_tuner) { 484 1.3 jmcneill case CXDTV_TUNER_PLL: 485 1.3 jmcneill tvpll_close(sc->sc_tuner); 486 1.3 jmcneill break; 487 1.3 jmcneill default: 488 1.3 jmcneill break; 489 1.3 jmcneill } 490 1.3 jmcneill sc->sc_tuner = NULL; 491 1.3 jmcneill } 492 1.3 jmcneill 493 1.3 jmcneill if (sc->sc_riscbuf) { 494 1.3 jmcneill kmem_free(sc->sc_riscbuf, sc->sc_riscbufsz); 495 1.3 jmcneill sc->sc_riscbuf = NULL; 496 1.3 jmcneill sc->sc_riscbufsz = 0; 497 1.3 jmcneill } 498 1.3 jmcneill } 499 1.3 jmcneill 500 1.1 jakllsch static void 501 1.1 jakllsch cxdtv_dtv_get_devinfo(void *priv, struct dvb_frontend_info *info) 502 1.1 jakllsch { 503 1.1 jakllsch memset(info, 0, sizeof(*info)); 504 1.1 jakllsch strlcpy(info->name, "CX23880", sizeof(info->name)); 505 1.1 jakllsch info->type = FE_ATSC; 506 1.1 jakllsch info->frequency_min = 54000000; 507 1.1 jakllsch info->frequency_max = 858000000; 508 1.1 jakllsch info->frequency_stepsize = 62500; 509 1.1 jakllsch info->caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB; 510 1.1 jakllsch } 511 1.1 jakllsch 512 1.1 jakllsch static int 513 1.1 jakllsch cxdtv_dtv_open(void *priv, int flags) 514 1.1 jakllsch { 515 1.1 jakllsch struct cxdtv_softc *sc = priv; 516 1.1 jakllsch 517 1.1 jakllsch KASSERT(sc->sc_tsbuf == NULL); 518 1.1 jakllsch 519 1.1 jakllsch cxdtv_mpeg_reset(sc); 520 1.1 jakllsch 521 1.1 jakllsch /* allocate two alternating DMA areas for MPEG TS packets */ 522 1.1 jakllsch sc->sc_tsbuf = cxdtv_mpeg_malloc(sc, CXDTV_TS_PKTSIZE * 2); 523 1.1 jakllsch 524 1.1 jakllsch if (sc->sc_tsbuf == NULL) 525 1.6 jakllsch return ENOMEM; 526 1.1 jakllsch 527 1.1 jakllsch return 0; 528 1.1 jakllsch } 529 1.1 jakllsch 530 1.1 jakllsch static void 531 1.1 jakllsch cxdtv_dtv_close(void *priv) 532 1.1 jakllsch { 533 1.1 jakllsch struct cxdtv_softc *sc = priv; 534 1.1 jakllsch 535 1.1 jakllsch cxdtv_dtv_stop_transfer(sc); 536 1.1 jakllsch 537 1.1 jakllsch if (sc->sc_tsbuf != NULL) { 538 1.1 jakllsch cxdtv_mpeg_free(sc, sc->sc_tsbuf); 539 1.1 jakllsch sc->sc_tsbuf = NULL; 540 1.1 jakllsch } 541 1.1 jakllsch } 542 1.1 jakllsch 543 1.1 jakllsch static int 544 1.1 jakllsch cxdtv_dtv_set_tuner(void *priv, const struct dvb_frontend_parameters *params) 545 1.1 jakllsch { 546 1.1 jakllsch struct cxdtv_softc *sc = priv; 547 1.1 jakllsch int error = -1; 548 1.1 jakllsch 549 1.1 jakllsch switch(sc->sc_board->cb_tuner) { 550 1.1 jakllsch case CXDTV_TUNER_PLL: 551 1.1 jakllsch error = tvpll_tune_dtv(sc->sc_tuner, params); 552 1.1 jakllsch } 553 1.1 jakllsch if (error) 554 1.1 jakllsch goto bad; 555 1.1 jakllsch 556 1.1 jakllsch switch(sc->sc_board->cb_demod) { 557 1.1 jakllsch case CXDTV_DEMOD_NXT2004: 558 1.1 jakllsch error = nxt2k_set_modulation(sc->sc_demod, params->u.vsb.modulation); 559 1.1 jakllsch break; 560 1.2 jmcneill case CXDTV_DEMOD_LG3303: 561 1.2 jmcneill error = lg3303_set_modulation(sc->sc_demod, params->u.vsb.modulation); 562 1.2 jmcneill break; 563 1.1 jakllsch default: 564 1.1 jakllsch break; 565 1.1 jakllsch } 566 1.1 jakllsch 567 1.1 jakllsch bad: 568 1.1 jakllsch return error; 569 1.1 jakllsch } 570 1.1 jakllsch 571 1.1 jakllsch static fe_status_t 572 1.1 jakllsch cxdtv_dtv_get_status(void *priv) 573 1.1 jakllsch { 574 1.1 jakllsch struct cxdtv_softc *sc = priv; 575 1.1 jakllsch 576 1.1 jakllsch switch(sc->sc_board->cb_demod) { 577 1.1 jakllsch case CXDTV_DEMOD_NXT2004: 578 1.1 jakllsch return nxt2k_get_dtv_status(sc->sc_demod); 579 1.2 jmcneill case CXDTV_DEMOD_LG3303: 580 1.2 jmcneill return lg3303_get_dtv_status(sc->sc_demod); 581 1.1 jakllsch default: 582 1.1 jakllsch return 0; 583 1.1 jakllsch } 584 1.1 jakllsch } 585 1.1 jakllsch 586 1.1 jakllsch static uint16_t 587 1.1 jakllsch cxdtv_dtv_get_signal_strength(void *priv) 588 1.1 jakllsch { 589 1.5 jmcneill struct cxdtv_softc *sc = priv; 590 1.5 jmcneill 591 1.5 jmcneill switch(sc->sc_board->cb_demod) { 592 1.5 jmcneill case CXDTV_DEMOD_NXT2004: 593 1.5 jmcneill return 0; /* TODO */ 594 1.5 jmcneill case CXDTV_DEMOD_LG3303: 595 1.5 jmcneill return lg3303_get_signal_strength(sc->sc_demod); 596 1.5 jmcneill } 597 1.5 jmcneill 598 1.5 jmcneill return 0; 599 1.1 jakllsch } 600 1.1 jakllsch 601 1.1 jakllsch static uint16_t 602 1.1 jakllsch cxdtv_dtv_get_snr(void *priv) 603 1.1 jakllsch { 604 1.5 jmcneill struct cxdtv_softc *sc = priv; 605 1.5 jmcneill 606 1.5 jmcneill switch(sc->sc_board->cb_demod) { 607 1.5 jmcneill case CXDTV_DEMOD_NXT2004: 608 1.5 jmcneill return 0; /* TODO */ 609 1.5 jmcneill case CXDTV_DEMOD_LG3303: 610 1.5 jmcneill return lg3303_get_snr(sc->sc_demod); 611 1.5 jmcneill } 612 1.5 jmcneill 613 1.5 jmcneill return 0; 614 1.1 jakllsch } 615 1.1 jakllsch 616 1.1 jakllsch static int 617 1.7 jmcneill cxdtv_dtv_start_transfer(void *priv, 618 1.7 jmcneill void (*cb)(void *, const struct dtv_payload *), void *arg) 619 1.1 jakllsch { 620 1.1 jakllsch struct cxdtv_softc *sc = priv; 621 1.6 jakllsch 622 1.7 jmcneill sc->sc_dtvsubmitcb = cb; 623 1.7 jmcneill sc->sc_dtvsubmitarg = arg; 624 1.7 jmcneill 625 1.1 jakllsch /* allocate two alternating DMA areas for MPEG TS packets */ 626 1.1 jakllsch sc->sc_tsbuf = cxdtv_mpeg_malloc(sc, CXDTV_TS_PKTSIZE * 2); 627 1.1 jakllsch 628 1.1 jakllsch cxdtv_mpeg_trigger(sc, sc->sc_tsbuf); 629 1.1 jakllsch 630 1.1 jakllsch return 0; 631 1.1 jakllsch } 632 1.1 jakllsch 633 1.1 jakllsch static int 634 1.1 jakllsch cxdtv_dtv_stop_transfer(void *priv) 635 1.1 jakllsch { 636 1.1 jakllsch struct cxdtv_softc *sc = priv; 637 1.1 jakllsch 638 1.1 jakllsch cxdtv_mpeg_halt(sc); 639 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 0); 640 1.1 jakllsch 641 1.7 jmcneill sc->sc_dtvsubmitcb = NULL; 642 1.7 jmcneill sc->sc_dtvsubmitarg = NULL; 643 1.7 jmcneill 644 1.1 jakllsch return 0; 645 1.1 jakllsch } 646 1.1 jakllsch 647 1.1 jakllsch int 648 1.1 jakllsch cxdtv_mpeg_reset(struct cxdtv_softc *sc) 649 1.1 jakllsch { 650 1.1 jakllsch uint32_t v; 651 1.1 jakllsch 652 1.1 jakllsch CX_DPRINTF(("cxdtv_mpeg_reset\n")); 653 1.1 jakllsch 654 1.1 jakllsch v = (uint32_t)-1; 655 1.1 jakllsch 656 1.1 jakllsch /* shutdown */ 657 1.1 jakllsch /* hold RISC in reset */ 658 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_DEV_CNTRL2, 0); 659 1.1 jakllsch /* disable FIFO and RISC */ 660 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL, 0); 661 1.1 jakllsch /* mask off all interrupts */ 662 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 0); 663 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK, 0); 664 1.1 jakllsch 665 1.1 jakllsch /* clear interrupts */ 666 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_STAT, v); 667 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_STAT, v); 668 1.1 jakllsch 669 1.1 jakllsch memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz); 670 1.1 jakllsch 671 1.1 jakllsch /* XXX magic */ 672 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PDMA_STHRSH, 0x0707); 673 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PDMA_DTHRSH, 0x0707); 674 1.1 jakllsch 675 1.1 jakllsch /* reset external components*/ 676 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_SRST_IO, 0); 677 1.6 jakllsch kpause("cxdtvrst", false, MAX(1, mstohz(1)), NULL); 678 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_SRST_IO, 1); 679 1.1 jakllsch 680 1.1 jakllsch /* let error interrupts happen */ 681 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK); 682 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 683 1.1 jakllsch v | 0x00fc00); /* XXX magic */ 684 1.1 jakllsch 685 1.1 jakllsch return 0; 686 1.1 jakllsch } 687 1.1 jakllsch 688 1.1 jakllsch static int 689 1.1 jakllsch cxdtv_risc_buffer(struct cxdtv_softc *sc, uint32_t bpl, uint32_t lines) 690 1.1 jakllsch { 691 1.1 jakllsch uint32_t *rm; 692 1.1 jakllsch uint32_t size; 693 1.1 jakllsch 694 1.1 jakllsch CX_DPRINTF(("cxdtv_risc_buffer: bpl=0x%x\n", bpl)); 695 1.1 jakllsch 696 1.1 jakllsch size = 1 + (bpl * lines) / PAGE_SIZE + lines; 697 1.1 jakllsch size += 2; 698 1.1 jakllsch 699 1.1 jakllsch device_printf(sc->sc_dev, "%s: est. inst. %d\n", __func__, size); 700 1.1 jakllsch 701 1.1 jakllsch size *= 8; 702 1.1 jakllsch device_printf(sc->sc_dev, "%s: est. qword %d\n", __func__, size); 703 1.1 jakllsch 704 1.1 jakllsch if (sc->sc_riscbuf == NULL) { 705 1.1 jakllsch device_printf(sc->sc_dev, "not enough memory for RISC\n"); 706 1.1 jakllsch return ENOMEM; 707 1.1 jakllsch } 708 1.1 jakllsch 709 1.1 jakllsch rm = (uint32_t *)sc->sc_riscbuf; 710 1.1 jakllsch cxdtv_risc_field(sc, rm, bpl); 711 1.1 jakllsch 712 1.1 jakllsch return 0; 713 1.1 jakllsch } 714 1.1 jakllsch 715 1.1 jakllsch static int 716 1.1 jakllsch cxdtv_risc_field(struct cxdtv_softc *sc, uint32_t *rm, uint32_t bpl) 717 1.1 jakllsch { 718 1.1 jakllsch struct cxdtv_dma *p; 719 1.1 jakllsch 720 1.1 jakllsch CX_DPRINTF(("cxdtv_risc_field: bpl=0x%x\n", bpl)); 721 1.1 jakllsch 722 1.1 jakllsch for (p = sc->sc_dma; p && KERNADDR(p) != sc->sc_tsbuf; p = p->next) 723 1.1 jakllsch continue; 724 1.1 jakllsch if (p == NULL) { 725 1.1 jakllsch device_printf(sc->sc_dev, "cxdtv_risc_field: bad addr %p\n", 726 1.1 jakllsch sc->sc_tsbuf); 727 1.1 jakllsch return ENOENT; 728 1.1 jakllsch } 729 1.1 jakllsch 730 1.1 jakllsch memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz); 731 1.1 jakllsch 732 1.1 jakllsch rm = sc->sc_riscbuf; 733 1.1 jakllsch 734 1.9 jakllsch /* htole32 will be done when program is copied to chip SRAM */ 735 1.1 jakllsch 736 1.1 jakllsch /* XXX */ 737 1.1 jakllsch *(rm++) = (CX_RISC_SYNC|0); 738 1.1 jakllsch 739 1.1 jakllsch *(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ1|bpl); 740 1.1 jakllsch *(rm++) = (DMAADDR(p) + 0 * bpl); 741 1.1 jakllsch 742 1.1 jakllsch *(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ2|bpl); 743 1.1 jakllsch *(rm++) = (DMAADDR(p) + 1 * bpl); 744 1.1 jakllsch 745 1.1 jakllsch *(rm++) = (CX_RISC_JUMP|1); 746 1.1 jakllsch *(rm++) = (cxdtv_sram_chs[CXDTV_SRAM_CH_MPEG].csc_risc + 4); 747 1.1 jakllsch 748 1.1 jakllsch return 0; 749 1.1 jakllsch } 750 1.1 jakllsch 751 1.1 jakllsch static int 752 1.1 jakllsch cxdtv_sram_ch_setup(struct cxdtv_softc *sc, struct cxdtv_sram_ch *csc, 753 1.1 jakllsch uint32_t bpl) 754 1.1 jakllsch { 755 1.1 jakllsch unsigned int i, lines; 756 1.1 jakllsch uint32_t cdt; 757 1.1 jakllsch 758 1.1 jakllsch CX_DPRINTF(("cxdtv_sram_ch_setup: bpl=0x%x\n", bpl)); 759 1.1 jakllsch 760 1.1 jakllsch /* XXX why round? */ 761 1.1 jakllsch bpl = (bpl + 7) & ~7; 762 1.1 jakllsch CX_DPRINTF(("cxdtv_sram_ch_setup: bpl=0x%x\n", bpl)); 763 1.1 jakllsch cdt = csc->csc_cdt; 764 1.1 jakllsch lines = csc->csc_fifosz / bpl; 765 1.1 jakllsch device_printf(sc->sc_dev, "%s %d lines\n", __func__, lines); 766 1.1 jakllsch 767 1.1 jakllsch /* fill in CDT */ 768 1.1 jakllsch for (i = 0; i < lines; i++) { 769 1.1 jakllsch CX_DPRINTF(("CDT ent %08x, %08x\n", cdt + (16 * i), 770 1.1 jakllsch csc->csc_fifo + (bpl * i))); 771 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 772 1.1 jakllsch cdt + (16 * i), 773 1.1 jakllsch csc->csc_fifo + (bpl * i)); 774 1.1 jakllsch } 775 1.1 jakllsch 776 1.1 jakllsch /* copy DMA program */ 777 1.1 jakllsch 778 1.1 jakllsch /* converts program to little endian as it goes into SRAM */ 779 1.1 jakllsch bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 780 1.1 jakllsch csc->csc_risc, (void *)sc->sc_riscbuf, sc->sc_riscbufsz >> 2); 781 1.1 jakllsch 782 1.1 jakllsch /* fill in CMDS */ 783 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 784 1.1 jakllsch csc->csc_cmds + CX_CMDS_O_IRPC, csc->csc_risc); 785 1.1 jakllsch 786 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 787 1.1 jakllsch csc->csc_cmds + CX_CMDS_O_CDTB, csc->csc_cdt); 788 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 789 1.1 jakllsch csc->csc_cmds + CX_CMDS_O_CDTS, (lines * 16) >> 3); /* XXX magic */ 790 1.1 jakllsch 791 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 792 1.1 jakllsch csc->csc_cmds + CX_CMDS_O_IQB, csc->csc_iq); 793 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 794 1.1 jakllsch csc->csc_cmds + CX_CMDS_O_IQS, 795 1.1 jakllsch CX_CMDS_IQS_ISRP | (csc->csc_iqsz >> 2) ); 796 1.1 jakllsch 797 1.1 jakllsch /* zero rest of CMDS */ 798 1.1 jakllsch bus_space_set_region_4(sc->sc_memt, sc->sc_memh, 0x14, 0, 0x2c/4); 799 1.1 jakllsch 800 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 801 1.1 jakllsch csc->csc_cnt1, (bpl >> 3) - 1); 802 1.1 jakllsch 803 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 804 1.1 jakllsch csc->csc_ptr2, cdt); 805 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 806 1.1 jakllsch csc->csc_cnt2, (lines * 16) >> 3); 807 1.1 jakllsch 808 1.1 jakllsch return 0; 809 1.1 jakllsch } 810 1.1 jakllsch 811 1.1 jakllsch int 812 1.1 jakllsch cxdtv_mpeg_trigger(struct cxdtv_softc *sc, void *buf) 813 1.1 jakllsch { 814 1.1 jakllsch struct cxdtv_dma *p; 815 1.1 jakllsch struct cxdtv_sram_ch *ch; 816 1.1 jakllsch uint32_t v; 817 1.1 jakllsch 818 1.1 jakllsch ch = &cxdtv_sram_chs[CXDTV_SRAM_CH_MPEG]; 819 1.1 jakllsch 820 1.1 jakllsch for (p = sc->sc_dma; p && KERNADDR(p) != buf; p = p->next) 821 1.1 jakllsch continue; 822 1.1 jakllsch if (p == NULL) { 823 1.1 jakllsch device_printf(sc->sc_dev, "cxdtv_mpeg_trigger: bad addr %p\n", 824 1.1 jakllsch buf); 825 1.1 jakllsch return ENOENT; 826 1.1 jakllsch } 827 1.1 jakllsch 828 1.1 jakllsch CX_DPRINTF(("cxdtv_mpeg_trigger: buf=%p\n", buf)); 829 1.1 jakllsch 830 1.1 jakllsch cxdtv_risc_buffer(sc, CXDTV_TS_PKTSIZE, 1); 831 1.1 jakllsch cxdtv_sram_ch_setup(sc, ch, CXDTV_TS_PKTSIZE); 832 1.1 jakllsch 833 1.1 jakllsch /* software reset */ 834 1.1 jakllsch 835 1.1 jakllsch switch(sc->sc_vendor) { 836 1.1 jakllsch case PCI_VENDOR_ATI: 837 1.1 jakllsch /* both ATI boards with DTV are the same */ 838 1.4 jmcneill bus_space_write_4(sc->sc_memt, sc->sc_memh, 839 1.9 jakllsch CXDTV_TS_GEN_CONTROL, IPB_SW_RST); 840 1.4 jmcneill delay(100); 841 1.1 jakllsch /* parallel MPEG port */ 842 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 843 1.9 jakllsch CXDTV_PINMUX_IO, MPEG_PAR_EN); 844 1.1 jakllsch break; 845 1.1 jakllsch case PCI_VENDOR_PCHDTV: 846 1.1 jakllsch if (sc->sc_product == PCI_PRODUCT_PCHDTV_HD5500) { 847 1.4 jmcneill bus_space_write_4(sc->sc_memt, sc->sc_memh, 848 1.9 jakllsch CXDTV_TS_GEN_CONTROL, IPB_SW_RST|IPB_SMODE); 849 1.4 jmcneill delay(100); 850 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 851 1.9 jakllsch CXDTV_PINMUX_IO, 0x00); /* serial MPEG port */ 852 1.4 jmcneill /* byte-width start-of-packet */ 853 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 854 1.4 jmcneill CXDTV_HW_SOP_CONTROL, 855 1.4 jmcneill 0x47 << 16 | 188 << 4 | 1); 856 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 857 1.9 jakllsch CXDTV_TS_SOP_STATUS, IPB_SOP_BYTEWIDE); 858 1.9 jakllsch /* serial MPEG port on HD5500 */ 859 1.4 jmcneill bus_space_write_4(sc->sc_memt, sc->sc_memh, 860 1.9 jakllsch CXDTV_TS_GEN_CONTROL, IPB_SMODE); 861 1.1 jakllsch } 862 1.1 jakllsch break; 863 1.1 jakllsch default: 864 1.1 jakllsch break; 865 1.1 jakllsch } 866 1.1 jakllsch 867 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_LNGTH, 868 1.1 jakllsch CXDTV_TS_PKTSIZE); 869 1.1 jakllsch 870 1.9 jakllsch /* Configure for standard MPEG TS, 1 good packet to sync */ 871 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_HW_SOP_CONTROL, 872 1.1 jakllsch 0x47 << 16 | 188 << 4 | 1); 873 1.1 jakllsch 874 1.1 jakllsch /* zero counter */ 875 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, 876 1.1 jakllsch CXDTV_TS_GP_CNT_CNTRL, 0x03); 877 1.1 jakllsch 878 1.1 jakllsch /* enable bad packet interrupt */ 879 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_BD_PKT_STATUS, 880 1.1 jakllsch 0x1000); 881 1.1 jakllsch 882 1.1 jakllsch /* enable overflow counter */ 883 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_FIFO_OVFL_STAT, 884 1.1 jakllsch 0x1000); 885 1.1 jakllsch 886 1.1 jakllsch /* unmask TS interrupt */ 887 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK); 888 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 889 1.1 jakllsch v | CXT_PI_TS_INT); 890 1.1 jakllsch 891 1.1 jakllsch /* unmask all TS interrupts */ 892 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK); 893 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK, 894 1.1 jakllsch v | 0x1f1011); 895 1.1 jakllsch 896 1.1 jakllsch /* enable RISC DMA engine */ 897 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_DEV_CNTRL2); 898 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_DEV_CNTRL2, 899 1.1 jakllsch v | CXDTV_DEV_CNTRL2_RUN_RISC); 900 1.1 jakllsch 901 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL); 902 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL, 903 1.1 jakllsch v | CXDTV_TS_RISC_EN | CXDTV_TS_FIFO_EN); 904 1.1 jakllsch 905 1.1 jakllsch return 0; 906 1.1 jakllsch } 907 1.1 jakllsch 908 1.1 jakllsch int 909 1.1 jakllsch cxdtv_mpeg_halt(struct cxdtv_softc *sc) 910 1.1 jakllsch { 911 1.1 jakllsch uint32_t v; 912 1.1 jakllsch 913 1.1 jakllsch CX_DPRINTF(("cxdtv_mpeg_halt\n")); 914 1.1 jakllsch 915 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL); 916 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_DMA_CNTRL, 917 1.1 jakllsch v & ~(CXDTV_TS_RISC_EN|CXDTV_TS_FIFO_EN)); 918 1.1 jakllsch 919 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK); 920 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_PCI_INT_MASK, 921 1.1 jakllsch v & ~CXT_PI_TS_INT); 922 1.1 jakllsch 923 1.1 jakllsch v = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK); 924 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK, 925 1.1 jakllsch v & ~0x1f1011); 926 1.1 jakllsch 927 1.1 jakllsch return 0; 928 1.1 jakllsch } 929 1.1 jakllsch 930 1.1 jakllsch int 931 1.1 jakllsch cxdtv_mpeg_intr(struct cxdtv_softc *sc) 932 1.1 jakllsch { 933 1.1 jakllsch struct dtv_payload payload; 934 1.1 jakllsch uint32_t s, m; 935 1.1 jakllsch 936 1.1 jakllsch s = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_STAT); 937 1.1 jakllsch m = bus_space_read_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_MASK); 938 1.1 jakllsch if ((s & m) == 0) 939 1.1 jakllsch return 0; 940 1.1 jakllsch 941 1.1 jakllsch if ( (s & ~CXDTV_TS_RISCI) != 0 ) 942 1.1 jakllsch device_printf(sc->sc_dev, "unexpected TS IS %08x\n", s); 943 1.1 jakllsch 944 1.7 jmcneill if (sc->sc_dtvsubmitcb == NULL) 945 1.7 jmcneill goto done; 946 1.7 jmcneill 947 1.1 jakllsch if ((s & CXDTV_TS_RISCI1) == CXDTV_TS_RISCI1) { 948 1.1 jakllsch bus_dmamap_sync(sc->sc_dmat, sc->sc_dma->map, 949 1.1 jakllsch 0, CXDTV_TS_PKTSIZE, 950 1.1 jakllsch BUS_DMASYNC_POSTREAD); 951 1.1 jakllsch payload.data = KERNADDR(sc->sc_dma); 952 1.1 jakllsch payload.size = CXDTV_TS_PKTSIZE; 953 1.7 jmcneill sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload); 954 1.1 jakllsch } 955 1.1 jakllsch 956 1.1 jakllsch if ((s & CXDTV_TS_RISCI2) == CXDTV_TS_RISCI2) { 957 1.1 jakllsch bus_dmamap_sync(sc->sc_dmat, sc->sc_dma->map, 958 1.1 jakllsch CXDTV_TS_PKTSIZE, CXDTV_TS_PKTSIZE, 959 1.1 jakllsch BUS_DMASYNC_POSTREAD); 960 1.1 jakllsch payload.data = (char *)(KERNADDR(sc->sc_dma)) + (uintptr_t)CXDTV_TS_PKTSIZE; 961 1.1 jakllsch payload.size = CXDTV_TS_PKTSIZE; 962 1.7 jmcneill sc->sc_dtvsubmitcb(sc->sc_dtvsubmitarg, &payload); 963 1.1 jakllsch } 964 1.1 jakllsch 965 1.7 jmcneill done: 966 1.1 jakllsch bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_TS_INT_STAT, s); 967 1.1 jakllsch 968 1.1 jakllsch return 1; 969 1.1 jakllsch } 970 1.1 jakllsch 971 1.1 jakllsch static int 972 1.1 jakllsch cxdtv_allocmem(struct cxdtv_softc *sc, size_t size, size_t align, 973 1.1 jakllsch struct cxdtv_dma *p) 974 1.1 jakllsch { 975 1.1 jakllsch int err; 976 1.1 jakllsch 977 1.1 jakllsch p->size = size; 978 1.1 jakllsch err = bus_dmamem_alloc(sc->sc_dmat, p->size, align, 0, 979 1.1 jakllsch p->segs, __arraycount(p->segs), 980 1.1 jakllsch &p->nsegs, BUS_DMA_NOWAIT); 981 1.1 jakllsch if (err) 982 1.1 jakllsch return err; 983 1.1 jakllsch err = bus_dmamem_map(sc->sc_dmat, p->segs, p->nsegs, p->size, 984 1.1 jakllsch &p->addr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 985 1.1 jakllsch if (err) 986 1.1 jakllsch goto free; 987 1.1 jakllsch err = bus_dmamap_create(sc->sc_dmat, p->size, 1, p->size, 0, 988 1.1 jakllsch BUS_DMA_NOWAIT, &p->map); 989 1.1 jakllsch if (err) 990 1.1 jakllsch goto unmap; 991 1.1 jakllsch err = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size, NULL, 992 1.1 jakllsch BUS_DMA_NOWAIT); 993 1.1 jakllsch if (err) 994 1.1 jakllsch goto destroy; 995 1.1 jakllsch 996 1.1 jakllsch return 0; 997 1.1 jakllsch 998 1.1 jakllsch destroy: 999 1.1 jakllsch bus_dmamap_destroy(sc->sc_dmat, p->map); 1000 1.1 jakllsch unmap: 1001 1.1 jakllsch bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 1002 1.1 jakllsch free: 1003 1.1 jakllsch bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs); 1004 1.1 jakllsch 1005 1.1 jakllsch return err; 1006 1.1 jakllsch } 1007 1.1 jakllsch 1008 1.1 jakllsch static int 1009 1.1 jakllsch cxdtv_freemem(struct cxdtv_softc *sc, struct cxdtv_dma *p) 1010 1.1 jakllsch { 1011 1.1 jakllsch 1012 1.1 jakllsch bus_dmamap_unload(sc->sc_dmat, p->map); 1013 1.1 jakllsch bus_dmamap_destroy(sc->sc_dmat, p->map); 1014 1.1 jakllsch bus_dmamem_unmap(sc->sc_dmat, p->addr, p->size); 1015 1.1 jakllsch bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs); 1016 1.1 jakllsch 1017 1.1 jakllsch return 0; 1018 1.1 jakllsch } 1019 1.1 jakllsch 1020 1.1 jakllsch void * 1021 1.1 jakllsch cxdtv_mpeg_malloc(struct cxdtv_softc *sc, size_t size) 1022 1.1 jakllsch { 1023 1.1 jakllsch struct cxdtv_dma *p; 1024 1.1 jakllsch int err; 1025 1.1 jakllsch 1026 1.1 jakllsch p = kmem_alloc(sizeof(*p), KM_SLEEP); 1027 1.1 jakllsch err = cxdtv_allocmem(sc, size, 16, p); 1028 1.1 jakllsch if (err) { 1029 1.1 jakllsch kmem_free(p, sizeof(*p)); 1030 1.1 jakllsch device_printf(sc->sc_dev, "not enough memory\n"); 1031 1.1 jakllsch return NULL; 1032 1.1 jakllsch } 1033 1.1 jakllsch 1034 1.1 jakllsch p->next = sc->sc_dma; 1035 1.1 jakllsch sc->sc_dma = p; 1036 1.1 jakllsch 1037 1.1 jakllsch return KERNADDR(p); 1038 1.1 jakllsch } 1039 1.1 jakllsch 1040 1.1 jakllsch static void 1041 1.1 jakllsch cxdtv_mpeg_free(struct cxdtv_softc *sc, void *addr) 1042 1.1 jakllsch { 1043 1.1 jakllsch struct cxdtv_dma *p; 1044 1.1 jakllsch struct cxdtv_dma **pp; 1045 1.1 jakllsch 1046 1.1 jakllsch for (pp = &sc->sc_dma; (p = *pp) != NULL; pp = &p->next) { 1047 1.1 jakllsch if (KERNADDR(p) == addr) { 1048 1.1 jakllsch cxdtv_freemem(sc, p); 1049 1.1 jakllsch *pp = p->next; 1050 1.1 jakllsch kmem_free(p, sizeof(*p)); 1051 1.1 jakllsch return; 1052 1.1 jakllsch } 1053 1.1 jakllsch } 1054 1.1 jakllsch 1055 1.1 jakllsch device_printf(sc->sc_dev, "%p is already free\n", addr); 1056 1.1 jakllsch 1057 1.1 jakllsch return; 1058 1.1 jakllsch } 1059 1.1 jakllsch 1060 1.1 jakllsch 1061 1.1 jakllsch /* ATI HDTV Wonder */ 1062 1.1 jakllsch static void 1063 1.1 jakllsch cxdtv_card_init_hdtvwonder(struct cxdtv_softc *sc) 1064 1.1 jakllsch { 1065 1.1 jakllsch int i, x; 1066 1.1 jakllsch i2c_addr_t na; 1067 1.1 jakllsch uint8_t nb[5][2] = { 1068 1.1 jakllsch {0x10, 0x12}, {0x13, 0x04}, {0x16, 0x00}, 1069 1.1 jakllsch {0x14, 0x04}, {0x17, 0x00} 1070 1.1 jakllsch }; 1071 1.1 jakllsch 1072 1.1 jakllsch /* prepare TUV1236D/TU1236F NIM */ 1073 1.1 jakllsch 1074 1.1 jakllsch na = 0x0a; /* Nxt2004 address */ 1075 1.1 jakllsch x = 0; 1076 1.1 jakllsch 1077 1.18 thorpej iic_acquire_bus(&sc->sc_i2c, 0); 1078 1.1 jakllsch 1079 1.1 jakllsch for(i = 0; i < 5; i++) 1080 1.1 jakllsch x |= iic_exec(&sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, na, 1081 1.18 thorpej nb[i], 2, NULL, 0, 0); 1082 1.1 jakllsch 1083 1.18 thorpej iic_release_bus(&sc->sc_i2c, 0); 1084 1.1 jakllsch 1085 1.1 jakllsch if (x) 1086 1.1 jakllsch aprint_error_dev(sc->sc_dev, "HDTV Wonder tuner init failed"); 1087 1.1 jakllsch } 1088 1.1 jakllsch 1089 1.1 jakllsch /* pcHDTV HD5500 */ 1090 1.4 jmcneill #define cxdtv_write_field(_mask, _shift, _value) \ 1091 1.4 jmcneill (((_value) & (_mask)) << (_shift)) 1092 1.4 jmcneill 1093 1.4 jmcneill static void 1094 1.4 jmcneill cxdtv_write_gpio(struct cxdtv_softc *sc, uint32_t mask, uint32_t value) 1095 1.4 jmcneill { 1096 1.4 jmcneill uint32_t v = 0; 1097 1.4 jmcneill v |= cxdtv_write_field(0xff, 16, mask); 1098 1.4 jmcneill v |= cxdtv_write_field(0xff, 8, mask); 1099 1.4 jmcneill v |= cxdtv_write_field(0xff, 0, (mask & value)); 1100 1.4 jmcneill bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_GP0_IO, v); 1101 1.4 jmcneill } 1102 1.4 jmcneill 1103 1.1 jakllsch static void 1104 1.1 jakllsch cxdtv_card_init_hd5500(struct cxdtv_softc *sc) 1105 1.1 jakllsch { 1106 1.1 jakllsch /* hardware (demod) reset */ 1107 1.4 jmcneill cxdtv_write_gpio(sc, 1, 0); 1108 1.3 jmcneill delay(100000); 1109 1.4 jmcneill cxdtv_write_gpio(sc, 1, 1); 1110 1.3 jmcneill delay(200000); 1111 1.1 jakllsch } 1112 1.2 jmcneill 1113 1.8 jmcneill MODULE(MODULE_CLASS_DRIVER, cxdtv, "tvpll,nxt2k,lg3303,pci"); 1114 1.2 jmcneill 1115 1.2 jmcneill #ifdef _MODULE 1116 1.2 jmcneill #include "ioconf.c" 1117 1.2 jmcneill #endif 1118 1.2 jmcneill 1119 1.2 jmcneill static int 1120 1.2 jmcneill cxdtv_modcmd(modcmd_t cmd, void *opaque) 1121 1.2 jmcneill { 1122 1.2 jmcneill switch (cmd) { 1123 1.2 jmcneill case MODULE_CMD_INIT: 1124 1.2 jmcneill #ifdef _MODULE 1125 1.2 jmcneill return config_init_component(cfdriver_ioconf_cxdtv, 1126 1.2 jmcneill cfattach_ioconf_cxdtv, cfdata_ioconf_cxdtv); 1127 1.2 jmcneill #else 1128 1.2 jmcneill return 0; 1129 1.2 jmcneill #endif 1130 1.2 jmcneill case MODULE_CMD_FINI: 1131 1.2 jmcneill #ifdef _MODULE 1132 1.2 jmcneill return config_fini_component(cfdriver_ioconf_cxdtv, 1133 1.2 jmcneill cfattach_ioconf_cxdtv, cfdata_ioconf_cxdtv); 1134 1.2 jmcneill #else 1135 1.2 jmcneill return 0; 1136 1.2 jmcneill #endif 1137 1.2 jmcneill default: 1138 1.2 jmcneill return ENOTTY; 1139 1.2 jmcneill } 1140 1.2 jmcneill } 1141