Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* newsat - new satellite receiver driver
- *
- * (C) XXXXXXXXXXXX
- *
- */
- #ifndef _NEWSAT_H_
- #define _NEWSAT_H_
- #include <sys/types.h>
- struct sat_param {
- int pol; /* Polarisation */
- int freq; /* Frequency */
- int baud; /* Baud rate */
- int fec; /* Forward error correction */
- int mod; /* reacquire if set */
- };
- #ifdef _KERNEL
- struct newsat_softc {
- dev_t newsat_dev_t;
- device_t device;
- int initialised; /* Device is initialised */
- /* MMIO Registers */
- int regs_rid;
- struct resource *regs_res;
- bus_space_handle_t *regs_h;
- uint8_t *regs_base;
- /* IRQ */
- int irq_rid;
- struct resource *irq_res;
- void *irq_h;
- /* DMA */
- int dma_running;
- uint32_t *pagetbl_base;
- vm_offset_t pagetbl_phy_addr;
- struct {
- uint8_t *data;
- int psize;
- int size;
- unsigned long rptr, wptr, wptr_s; /* Read / write pointers */
- int head;
- int tail;
- int space;
- } ring;
- struct {
- int band, pol;
- } tuner;
- struct sat_param param;
- };
- #define CHIPR32(n) *((volatile uint32_t *) (sc->regs_base + (n)))
- #define IIC_SEND_STOP (1 << 0)
- #define IIC_ERR_ADDRESS -1
- #define IIC_ERR_DATA -2
- #define IIC_WRITE 0
- #define IIC_READ 1
- #endif /* _KERNEL */
- /* ioctls */
- #define SAT_GET_SIGNAL _IOR('x', 1, int) /* get signal meter */
- #define SAT_GET_STATUS _IOR('x', 2, int) /* get status */
- #define SAT_GET_BER _IOR('x', 3, int) /* get bit error rate */
- #define SAT_GET_AFC _IOR('x', 4, int) /* get bit error rate */
- #define SAT_ACQUIRE _IOW('x', 10, struct sat_param) /* receive signal */
- #define SAT_FIFO_SYNC _IO('x', 100) /* Reset the ring buffer */
- #define SAT_FIFO_GETENT _IOR('x', 101, int) /* Get number of pending bytes */
- #define SATSTATUS_SIGNAL (1 << 0)
- #define SATSTATUS_CARRIER (1 << 1)
- #define SATSTATUS_VITERBI (1 << 2)
- #define SATSTATUS_FSYNC (1 << 3)
- #define SATSTATUS_FRONT (1 << 4)
- #define SATSTATUS_MEASVALID (1 << 5)
- #endif /* _NEWSAT_H_ */
- /* newsat - new satellite receiver driver
- *
- * (C) XXXXXXXXXXXXXXXXXXX
- *
- */
- #include <sys/types.h>
- #include <sys/module.h>
- #include <sys/systm.h>
- #include <sys/errno.h>
- #include <sys/param.h>
- #include <sys/kernel.h>
- #include <sys/conf.h>
- #include <sys/uio.h>
- #include <sys/ioccom.h>
- #include <sys/malloc.h>
- #include <sys/bus.h> /* device_t */
- #include <machine/bus.h>
- #include <sys/rman.h>
- #include <machine/resource.h>
- #include <vm/vm.h>
- #include <vm/pmap.h>
- #include <vm/vm_kern.h>
- #include <vm/vm_extern.h>
- #include <pci/pcireg.h>
- #include <pci/pcivar.h>
- #include "newsat.h"
- #include "saa7146.h"
- #include "ves1893.h"
- /* This specifies the dimensions of the DMA ring buffer in memory */
- #define SAA_DMA_ROW_SIZE 5
- #define SAA_DMA_NUM_ROWS 4096
- /* probe,attach,detach, etc. */
- static int newsat_probe(device_t);
- static int newsat_attach(device_t);
- static int newsat_detach(device_t);
- static int newsat_shutdown(device_t);
- static device_method_t newsat_methods[] = {
- DEVMETHOD(device_probe, newsat_probe),
- DEVMETHOD(device_attach, newsat_attach),
- DEVMETHOD(device_detach, newsat_detach),
- DEVMETHOD(device_shutdown, newsat_shutdown),
- {0, 0}
- };
- static driver_t newsat_driver = {
- "newsat",
- newsat_methods,
- sizeof(struct newsat_softc)
- };
- static devclass_t newsat_devclass;
- DRIVER_MODULE(newsat, pci, newsat_driver, newsat_devclass, 0, 0);
- MODULE_VERSION(newsat, 1)
- static d_open_t newsat_open;
- static d_close_t newsat_close;
- static d_read_t newsat_read;
- static d_ioctl_t newsat_ioctl;
- static struct cdevsw newsat_cdevsw = {
- newsat_open,
- newsat_close,
- newsat_read,
- nowrite,
- newsat_ioctl,
- nopoll,
- nommap,
- nostrategy,
- "newsat",
- 33,
- nodump,
- nopsize,
- 0,
- -1
- };
- static void newsat_cleanup(device_t);
- static void newsat_intr(void *);
- static void newsat_regset(struct newsat_softc *, int, uint32_t, uint32_t);
- static void newsat_MC1_prog(struct newsat_softc *, uint16_t, uint16_t);
- static void newsat_MC2_prog(struct newsat_softc *, uint16_t, uint16_t);
- static void newsat_MC1_set(struct newsat_softc *, uint16_t);
- static void newsat_MC2_set(struct newsat_softc *, uint16_t);
- static void newsat_MC1_clear(struct newsat_softc *, uint16_t);
- static void newsat_MC2_clear(struct newsat_softc *, uint16_t);
- static void newsat_dma_start(struct newsat_softc *);
- static void newsat_dma_stop(struct newsat_softc *);
- static void newsat_dma_sync(struct newsat_softc *);
- static void newsat_dma_unlock(struct newsat_softc *);
- static int newsat_dma_getpending(struct newsat_softc *);
- static void newsat_hw_reset(struct newsat_softc *);
- static void newsat_iic_upload(struct newsat_softc *);
- static void newsat_iic_reset(struct newsat_softc *);
- static void newsat_iic_init(struct newsat_softc *);
- static int newsat_iic_wait(struct newsat_softc *);
- static int newsat_iic_address(struct newsat_softc *, int, int);
- static int newsat_iic_writeN(struct newsat_softc *, int, uint8_t *, int, int);
- static int newsat_iic_readN(struct newsat_softc *, int, uint8_t *, int, int);
- static void tuner_init(struct newsat_softc *);
- static int tuner_demod_write(struct newsat_softc *, int, int);
- static int tuner_demod_read(struct newsat_softc *, int);
- static void tuner_demod_reset(struct newsat_softc *);
- static void tuner_demod_init(struct newsat_softc *);
- static int tuner_demod_status(struct newsat_softc *);
- static int tuner_demod_sigmeter(struct newsat_softc *);
- static int tuner_demod_ber(struct newsat_softc *);
- static int tuner_demod_afc(struct newsat_softc *);
- static int tuner_demod_setbaud(struct newsat_softc *, int, int);
- static void tuner_set_pol(struct newsat_softc *, int);
- static void tuner_set_band(struct newsat_softc *, int);
- static int tuner_tuneto(struct newsat_softc *, int, int);
- /* Interrupt handler */
- static void newsat_intr(void *p)
- {
- struct newsat_softc *sc;
- sc = (struct newsat_softc *) p;
- return;
- }
- /* Probe, Attach, Detach and Shutdown subroutines */
- static int newsat_probe(device_t dev)
- {
- switch(pci_get_devid(dev)) {
- case SAA7146_PCI_ID:
- return 0;
- }
- return ENXIO;
- }
- static int newsat_attach(device_t dev)
- {
- struct newsat_softc *sc;
- int unit, error, ptr;
- u_long conf; /* config reg. */
- vm_offset_t addr; /* pagetable address */
- sc = device_get_softc(dev);
- unit = device_get_unit(dev);
- bzero(sc, sizeof(sc));
- sc->device = dev;
- /* Allocate MMIO registers */
- sc->regs_rid = PCIR_MAPS + 0x00;
- sc->regs_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->regs_rid,
- 0, ~0, 1, RF_ACTIVE);
- if(sc->regs_res == NULL) {
- device_printf(dev, "MMIO register space allocation failed\n");
- goto failed;
- }
- sc->regs_h = (bus_space_handle_t *) rman_get_bushandle(sc->regs_res);
- sc->regs_base = (u_int8_t *) sc->regs_h;
- /* Allocate interrupt */
- sc->irq_rid = 0;
- sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
- 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
- if(sc->irq_res == NULL) {
- device_printf(dev, "could not allocate interrupt\n");
- goto failed;
- }
- error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_TTY, newsat_intr,
- sc, &sc->irq_h);
- if(error) {
- device_printf(dev, "could not setup interrupt\n");
- goto failed;
- }
- sc->newsat_dev_t = make_dev(&newsat_cdevsw, unit, 0, 0, 0600,
- "newsat%d", unit);
- if(sc->newsat_dev_t == NULL) {
- device_printf(dev, "could not create device\n");
- goto failed;
- }
- /* Allocate memory for page translation table */
- addr = vm_page_alloc_contig(4096 / PAGE_SIZE, 0, ~0, PAGE_SIZE);
- if(addr == 0) {
- device_printf(dev, "could not allocate contiguous memory");
- goto failed;
- }
- sc->pagetbl_base = (uint32_t *) addr;
- sc->pagetbl_phy_addr = vtophys(addr);
- /* Allocate DMA buffer */
- sc->ring.size = 188 * SAA_DMA_ROW_SIZE * SAA_DMA_NUM_ROWS;
- sc->ring.psize = 4096 * 1024;
- sc->ring.data = (uint8_t *) malloc(sc->ring.psize, M_DEVBUF, M_WAITOK);
- if(sc->ring.data == NULL) {
- device_printf(dev, "could not allocate ring buffer\n");
- goto failed;
- }
- #define BYTESTOK(n) ((n) >> 10)
- device_printf(dev, "Using %dKB of %dKB allocated for DMA ring buffer\n",
- BYTESTOK(sc->ring.size), BYTESTOK(sc->ring.psize));
- /* Initialise the page table */
- ptr = 0;
- for(addr = 0; addr < sc->ring.psize; addr += 4096) {
- sc->pagetbl_base[ptr++] = vtophys((caddr_t) ((uint8_t *)sc->ring.data +
- addr));
- }
- /* Enable register access and bus mastering */
- conf = pci_read_config(dev, PCIR_COMMAND, 2);
- conf |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, conf, 2);
- device_printf(dev, "build date " __DATE__ " " __TIME__ "\n");
- return 0;
- failed:
- newsat_cleanup(dev);
- return ENXIO;
- }
- static int newsat_detach(device_t dev)
- {
- newsat_cleanup(dev);
- return 0;
- }
- static int newsat_shutdown(device_t dev)
- {
- newsat_cleanup(dev);
- return 0;
- }
- static void newsat_cleanup(device_t dev)
- {
- struct newsat_softc *sc;
- if((sc = device_get_softc(dev)) == NULL)
- return;
- if(sc->regs_res != NULL) {
- bus_release_resource(dev, SYS_RES_MEMORY, sc->regs_rid,
- sc->regs_res);
- sc->regs_res = NULL;
- }
- if(sc->irq_res != NULL) {
- bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
- bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
- sc->irq_res);
- sc->irq_res = NULL;
- }
- if(sc->pagetbl_base != NULL) {
- kmem_free(kernel_map, (vm_offset_t) sc->pagetbl_base, 4096);
- sc->pagetbl_base = NULL;
- }
- if(sc->ring.data != NULL) {
- free((caddr_t) sc->ring.data, M_DEVBUF);
- sc->ring.data = NULL;
- }
- if(sc->newsat_dev_t != NULL) {
- destroy_dev(sc->newsat_dev_t);
- sc->newsat_dev_t = NULL;
- }
- return;
- }
- /* Hardware interface **************************************************/
- /* register programming routines */
- static void newsat_regset(struct newsat_softc *sc, int reg,uint32_t mask,
- uint32_t bits)
- {
- CHIPR32(reg) = (CHIPR32(reg) & ~mask) | bits;
- }
- static void newsat_MC1_prog(struct newsat_softc *sc, uint16_t mask,
- uint16_t bits)
- {
- CHIPR32(SAA_MAIN_CONTROL1) = SAA_MC_MASK(mask) | SAA_MC_CONTROL(bits);
- }
- static void newsat_MC2_prog(struct newsat_softc *sc, uint16_t mask,
- uint16_t bits)
- {
- CHIPR32(SAA_MAIN_CONTROL2) = SAA_MC_MASK(mask) | SAA_MC_CONTROL(bits);
- }
- static void newsat_MC1_set(struct newsat_softc *sc, uint16_t bits)
- {
- newsat_MC1_prog(sc, bits, bits);
- }
- static void newsat_MC2_set(struct newsat_softc *sc, uint16_t bits)
- {
- newsat_MC2_prog(sc, bits, bits);
- }
- static void newsat_MC1_clear(struct newsat_softc *sc, uint16_t bits)
- {
- newsat_MC1_prog(sc, bits, 0);
- }
- static void newsat_MC2_clear(struct newsat_softc *sc, uint16_t bits)
- {
- newsat_MC2_prog(sc, bits, 0);
- }
- static void newsat_dma_start(struct newsat_softc *sc)
- {
- CHIPR32(SAA_ARB_CNTL1) = (5 << 18) | (2 << 16);
- CHIPR32(SAA_DMA3_MMU_CNTL) = SAA_MMU_PAGE_TBL_ADDR(sc->pagetbl_phy_addr) |
- SAA_MMU_PAGE_TBL_EN;
- CHIPR32(SAA_DMA3_BASE_ODD) = CHIPR32(SAA_DMA3_BASE_EVEN) = 0;
- CHIPR32(SAA_DMA3_PROT_ADDR) = sc->ring.psize;
- CHIPR32(SAA_DMA3_PITCH) = 188 * SAA_DMA_ROW_SIZE;
- CHIPR32(SAA_DMA3_NUM_LINES_BYTES) = (188 * SAA_DMA_ROW_SIZE) |
- (SAA_DMA_NUM_ROWS << 16);
- CHIPR32(SAA_D1_CONF) = 0;
- CHIPR32(SAA_D1AB_CONF) = 0;
- CHIPR32(SAA_BRS_CONF) = (1 << 30) | (1 << 29);
- newsat_MC2_set(sc, MC2_UPLOAD_DMA3 | MC2_UPLOAD_D1_A | MC2_UPLOAD_D1_B |
- MC2_UPLOAD_BRS);
- newsat_MC1_set(sc, MC1_ENABLE_DMA3 | MC1_ENABLE_VIDEO);
- tsleep(sc, PWAIT, "hwinit", hz / 2);
- newsat_dma_sync(sc);
- /* device_printf(sc->device, "dma enabled\n");*/
- sc->dma_running = 1;
- }
- static void newsat_dma_stop(struct newsat_softc *sc)
- {
- newsat_MC1_clear(sc, MC1_ENABLE_VIDEO | MC1_ENABLE_DMA3);
- newsat_dma_sync(sc);
- sc->dma_running = 0;
- }
- static void newsat_dma_sync(struct newsat_softc *sc)
- {
- sc->ring.rptr = sc->ring.wptr = sc->ring.wptr_s = CHIPR32(SAA_DMA3_PTR);
- }
- static void newsat_dma_unlock(struct newsat_softc *sc)
- {
- device_printf(sc->device, "dma_unlock called, trying to reset "
- "DMA controller (DMA3_PTR=0x%.8x)\n", CHIPR32(SAA_DMA3_PTR));
- newsat_dma_stop(sc);
- newsat_dma_start(sc);
- }
- static int newsat_dma_getpending(struct newsat_softc *sc)
- {
- sc->ring.wptr = sc->ring.wptr_s = CHIPR32(SAA_DMA3_PTR); /* FIXME */
- if(sc->ring.wptr >= sc->ring.rptr)
- return sc->ring.wptr - sc->ring.rptr;
- else
- return sc->ring.size + sc->ring.wptr - sc->ring.rptr;
- }
- static void newsat_hw_reset(struct newsat_softc *sc)
- {
- newsat_MC1_clear(sc, MC1_MASTER_RESET_NOT);
- newsat_dma_stop(sc); /* just to be sure, and to clear the dma_running flag */
- /* Set GPIO pins to tristate */
- CHIPR32(SAA_GPIO) = GPIO0(GPIO_TRISTATE) | GPIO1(GPIO_TRISTATE) |
- GPIO2(GPIO_TRISTATE) | GPIO3(GPIO_TRISTATE);
- printf("Debug hardware reset DMA3 ptr 0x%.8x\n", CHIPR32(SAA_DMA3_PTR));
- }
- /* Device handler code *************************************************/
- static int newsat_open(dev_t dev, int oflags, int devtype, struct proc *p)
- {
- struct newsat_softc *sc;
- int unit;
- unit = minor(dev);
- if((sc = devclass_get_softc(newsat_devclass, unit)) == NULL)
- return ENXIO;
- device_busy(sc->device);
- newsat_hw_reset(sc);
- newsat_iic_init(sc);
- tuner_init(sc);
- return 0;
- }
- static int newsat_close(dev_t dev, int fflags, int devtype, struct proc *p)
- {
- struct newsat_softc *sc;
- int unit;
- unit = minor(dev);
- if((sc = devclass_get_softc(newsat_devclass, unit)) == NULL)
- return ENXIO;
- device_unbusy(sc->device);
- return 0;
- }
- /* DMA Transfer */
- static int newsat_read(dev_t dev, struct uio *uio, int ioflag)
- {
- struct newsat_softc *sc;
- int unit;
- int retry, count, err = 0;
- unit = minor(dev);
- if((sc = devclass_get_softc(newsat_devclass, unit)) == NULL)
- return ENXIO;
- #define MIN(a, b) ((a < b) ? a : b)
- #define MAX(a, b) ((a > b) ? a : b)
- if(!sc->dma_running) {
- newsat_dma_start(sc);
- }
- retry = count = 0;
- while(uio->uio_resid > 0) {
- int blk = -1, chunksize;
- sc->ring.wptr = sc->ring.wptr_s = CHIPR32(SAA_DMA3_PTR); /* FIXME */
- if(sc->ring.wptr < sc->ring.size) {
- chunksize = ((sc->ring.wptr < sc->ring.rptr) ?
- sc->ring.size : sc->ring.wptr) - sc->ring.rptr;
- blk = MIN(uio->uio_resid, chunksize);
- } else {
- device_printf(sc->device, "DMA wptr > buffer size: WPTR=0x%.8lx\n",
- sc->ring.wptr);
- newsat_dma_unlock(sc);
- }
- if(blk > 0) {
- if((err = uiomove((caddr_t) (sc->ring.data + sc->ring.rptr),
- blk, uio)) != 0) goto error;
- if((sc->ring.rptr += blk) >= sc->ring.size)
- sc->ring.rptr = 0;
- retry = count = 0;
- } else {
- int sr;
- if((sr = tsleep(sc, PWAIT | PCATCH, "dmard", 1)) != EWOULDBLOCK)
- return sr;
- count++;
- if(count > 50) {
- retry++;
- device_printf(sc->device, "DMA transfer stall, retry=%d\n", retry);
- newsat_dma_unlock(sc);
- }
- if(retry >= 10) {
- device_printf(sc->device, "DMA timeout, too many retries: "
- "RPTR=0x%.8lx WPTR=0x%.8lx\n",
- sc->ring.rptr, sc->ring.wptr);
- newsat_dma_stop(sc);
- err = EIO;
- goto error;
- }
- }
- }
- return 0;
- error:
- return err;
- }
- /* ioctl */
- static int newsat_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag,
- struct proc *pr)
- {
- struct newsat_softc *sc;
- struct sat_param *param;
- int unit;
- int err;
- unit = minor(dev);
- if((sc = devclass_get_softc(newsat_devclass, unit)) == NULL)
- return ENXIO;
- param = (struct sat_param *) arg;
- switch(cmd) {
- case SAT_GET_SIGNAL:
- *((int *) arg) = tuner_demod_sigmeter(sc);
- break;
- case SAT_GET_STATUS:
- *((int *) arg) = tuner_demod_status(sc);
- break;
- case SAT_GET_BER:
- *((int *) arg) = tuner_demod_ber(sc);
- break;
- case SAT_GET_AFC:
- *((int *) arg) = tuner_demod_afc(sc);
- break;
- case SAT_ACQUIRE:
- if((param->mod) || (sc->param.mod)) {
- sc->param.pol = sc->param.freq = sc->param.baud = sc->param.fec = -1;
- }
- if((param->pol != sc->param.pol) || (param->freq != sc->param.freq)) {
- if((err = tuner_tuneto(sc, param->pol, param->freq)) < 0)
- return err;
- sc->param.pol = param->pol;
- sc->param.freq = param->freq;
- }
- if((param->baud != sc->param.baud) || (param->fec != sc->param.fec)) {
- if((err = tuner_demod_setbaud(sc, param->baud, param->fec)) < 0)
- return err;
- sc->param.baud = param->baud;
- sc->param.fec = param->fec;
- }
- sc->param.mod = 0;
- break;
- case SAT_FIFO_SYNC:
- newsat_dma_sync(sc);
- break;
- case SAT_FIFO_GETENT:
- *((int *) arg) = newsat_dma_getpending(sc);
- break;
- default:
- return ENXIO;
- }
- return 0;
- }
- /* IIC bus code ********************************************************/
- static void newsat_iic_upload(struct newsat_softc *sc)
- {
- newsat_MC2_set(sc, MC2_UPLOAD_IIC);
- }
- static void newsat_iic_reset(struct newsat_softc *sc)
- {
- int tries;
- for(tries = 0; tries < 1000; tries++) {
- int c;
- for(c = 0; c < 4; c++) {
- CHIPR32(SAA_IIC_STA) = (CHIPR32(SAA_IIC_STA) & 0xff) | IIC_ABORT;
- newsat_iic_upload(sc);
- }
- for(c = 0; c < 4; c++) {
- CHIPR32(SAA_IIC_STA) = (CHIPR32(SAA_IIC_STA) & ~0xff);
- newsat_iic_upload(sc);
- }
- if((CHIPR32(SAA_IIC_STA) & (IIC_ERR | IIC_BUSY)) == 0) {
- return;
- }
- }
- device_printf(sc->device, "iic reset failed, status 0x%.2x\n",
- CHIPR32(SAA_IIC_STA));
- }
- static int newsat_iic_wait(struct newsat_softc *sc)
- {
- int tries;
- for(tries = 0; tries < 10000000; tries++) {
- newsat_iic_upload(sc);
- if((CHIPR32(SAA_IIC_STA) & IIC_BUSY) == 0)
- return 0;
- /* tsleep(sc, PWAIT, "iic_wt", 1); */
- }
- device_printf(sc->device, "iic bus timeout (error bit was %s)\n",
- (CHIPR32(SAA_IIC_STA) & IIC_ERR) ? "set" : "clear");
- return -1;
- }
- static void newsat_iic_init(struct newsat_softc *sc)
- {
- device_printf(sc->device, "iic init\n");
- newsat_iic_reset(sc);
- }
- static int newsat_iic_address(struct newsat_softc *sc, int dev, int flags)
- {
- int rc;
- CHIPR32(SAA_IIC_TRF) = IIC_BYTE2((dev << 1) | flags) | IIC_ATTR2(ATTR_START);
- newsat_iic_upload(sc);
- if((rc = newsat_iic_wait(sc)) < 0) {
- device_printf(sc->device, "IIC addressing error (status 0x%.8x)\n",
- CHIPR32(SAA_IIC_STA));
- }
- return rc;
- }
- int newsat_iic_writeN(struct newsat_softc *sc, int dev, uint8_t *iic_data,
- int nbytes, int flags)
- {
- int ptr;
- if(newsat_iic_address(sc, dev, IIC_WRITE) < 0)
- return IIC_ERR_ADDRESS;
- for(ptr = 0; ptr < nbytes; ptr++) {
- if((ptr == (nbytes - 1)) && (flags & IIC_SEND_STOP))
- CHIPR32(SAA_IIC_TRF) = IIC_BYTE2(iic_data[ptr]) | IIC_ATTR2(ATTR_STOP);
- else
- CHIPR32(SAA_IIC_TRF) = IIC_BYTE2(iic_data[ptr]) | IIC_ATTR2(ATTR_CONT);
- newsat_iic_upload(sc);
- if(newsat_iic_wait(sc) < 0)
- return IIC_ERR_DATA;
- }
- return 0;
- }
- int newsat_iic_readN(struct newsat_softc *sc, int dev, uint8_t *iic_data,
- int nbytes, int flags)
- {
- int ptr;
- if(newsat_iic_address(sc, dev, IIC_READ) < 0)
- return IIC_ERR_ADDRESS;
- for(ptr = 0; ptr < nbytes; ptr++) {
- if((ptr == (nbytes - 1)) && (flags & IIC_SEND_STOP))
- CHIPR32(SAA_IIC_TRF) = IIC_ATTR2(ATTR_STOP);
- else
- CHIPR32(SAA_IIC_TRF) = IIC_ATTR2(ATTR_CONT);
- newsat_iic_upload(sc);
- if(newsat_iic_wait(sc) < 0)
- return IIC_ERR_DATA;
- iic_data[ptr] = IIC_GET_BYTE2(CHIPR32(SAA_IIC_TRF));
- }
- return 0;
- }
- /* Tuner code **********************************************************/
- static int tuner_demod_write(struct newsat_softc *sc, int reg, int val)
- {
- uint8_t data[3];
- data[0] = 0;
- data[1] = reg;
- data[2] = val;
- return newsat_iic_writeN(sc, VES_I2C_ADDR, (uint8_t *) &data, 3,
- IIC_SEND_STOP);
- }
- static int tuner_demod_read(struct newsat_softc *sc, int reg)
- {
- int err;
- uint8_t data[3];
- data[0] = 0;
- data[1] = reg;
- if((err = newsat_iic_writeN(sc, VES_I2C_ADDR, (uint8_t *) &data, 2, 0)) < 0)
- return err;
- if((err = newsat_iic_readN(sc, VES_I2C_ADDR, (uint8_t *) &data, 1,
- IIC_SEND_STOP)) < 0)
- return err;
- return data[0];
- }
- static void tuner_demod_reset(struct newsat_softc *sc)
- {
- newsat_regset(sc, SAA_GPIO, GPIO2_MASK, GPIO2(GPIO_LOW));
- newsat_regset(sc, SAA_GPIO, GPIO2_MASK, GPIO2(GPIO_HIGH));
- }
- static void tuner_demod_init(struct newsat_softc *sc)
- {
- int n;
- tuner_demod_reset(sc);
- for(n = 0; n < sizeof(VES_Reg); n++) {
- if(VES_Reg_Mask[n])
- tuner_demod_write(sc, n, VES_Reg[n]);
- }
- device_printf(sc->device, "VES1893 initialised\n");
- }
- static int tuner_demod_status(struct newsat_softc *sc)
- {
- return tuner_demod_read(sc, VES_SYNC);
- }
- static int tuner_demod_sigmeter(struct newsat_softc *sc)
- {
- return tuner_demod_read(sc, VES_NEST);
- }
- static int tuner_demod_ber(struct newsat_softc *sc)
- {
- int ber;
- if((ber = tuner_demod_read(sc, VES_VBER_LSB)) < 0)
- return -1;
- ber |= tuner_demod_read(sc, VES_VBER_MID) << 8;
- ber |= tuner_demod_read(sc, VES_VBER_MSB) << 16;
- return ber;
- }
- static int tuner_demod_afc(struct newsat_softc *sc)
- {
- return ((64 + tuner_demod_read(sc, VES_VAFC)) % 128) - 64;
- }
- #define REF_FREQ 90100000UL
- static int tuner_demod_setbaud(struct newsat_softc *sc, int baud, int fec)
- {
- uint32_t ves_bdr, ratio, tmp, fin;
- uint8_t ves_adconf, ves_fconf, ves_fnr, ves_bdri;
- if((baud > (REF_FREQ / 2)) || (baud < 500000))
- return ENXIO;
- #define MUL (1UL << 26)
- fin = REF_FREQ >> 4;
- tmp = baud << 6;
- ratio = tmp / fin;
- tmp = (tmp % fin) << 8;
- ratio = (ratio << 8) + tmp / fin;
- tmp = (tmp % fin) << 8;
- ratio = (ratio << 8) + tmp / fin;
- ves_fnr = 0xff;
- if(ratio < MUL / 3)
- ves_fnr = 0;
- if(ratio < (MUL * 11) / 50)
- ves_fnr = 1;
- if(ratio < MUL / 6)
- ves_fnr = 2;
- if(ratio < MUL / 9)
- ves_fnr = 3;
- if(ratio < MUL / 12)
- ves_fnr = 4;
- if(ratio < (MUL * 11) / 200)
- ves_fnr = 5;
- if(ratio < MUL / 24)
- ves_fnr = 6;
- if(ratio < (MUL * 27) / 1000)
- ves_fnr = 7;
- if(ratio < MUL / 48)
- ves_fnr = 8;
- if(ratio < (MUL * 137) / 10000)
- ves_fnr = 9;
- if(ves_fnr == 0xff) {
- ves_adconf = 0x89; /* bypass filter */
- ves_fconf = 0x80; /* default */
- ves_fnr = 0;
- } else {
- ves_adconf = 0x81;
- ves_fconf = 0x88 | (ves_fnr >> 1) | ((ves_fnr & 1) << 5);
- }
- ves_bdr = (((ratio << (ves_fnr >> 1)) >> 4) + 1) >> 1;
- ves_bdri = (((fin << 8) / ((baud << (ves_fnr >> 1)) >> 2)) + 1) >> 1;
- ves_bdri = (ves_bdri > 0xff) ? 0xff : ves_bdri;
- tuner_demod_write(sc, VES_ADCONF, ves_adconf);
- tuner_demod_write(sc, VES_FCONF, ves_fconf);
- tuner_demod_write(sc, VES_BDR_INV, ves_bdri);
- tuner_demod_write(sc, VES_BDR_MSB, ((ves_bdr >> 16) & 0x0f) | 0x00);
- tuner_demod_write(sc, VES_BDR_MID, (ves_bdr >> 8) & 0xff);
- tuner_demod_write(sc, VES_BDR_LSB, ves_bdr & 0xff);
- tuner_demod_write(sc, VES_AFC_0, 0x03);
- tuner_demod_write(sc, VES_AFC_1, 0x03);
- #if 0
- tuner_demod_write(sc, VES_CARINIT, 0x00);
- tsleep(sc, PWAIT, "demod", hz / 2);
- tuner_demod_write(sc, VES_CARINIT, 0x80);
- #endif
- return 0;
- }
- static void tuner_set_pol(struct newsat_softc *sc, int pol)
- {
- tuner_demod_write(sc, VES_TEST, VESR_LNB_POWER_EN |
- VESR_LNB_VOLTAGE_SEL(pol));
- if(sc->tuner.pol != pol)
- tsleep(sc, PWAIT, "polwt", hz / 10);
- sc->tuner.pol = pol;
- }
- static void tuner_set_band(struct newsat_softc *sc, int band)
- {
- newsat_regset(sc, SAA_GPIO, GPIO3_MASK, GPIO3(band ? GPIO_HIGH : GPIO_LOW));
- if(sc->tuner.band != band)
- tsleep(sc, PWAIT, "bandwt", hz / 10);
- sc->tuner.band = band;
- }
- #define TUNER_PLL_ADDR 0x61
- #define TUNER_LO0 9750000 /* LO for 1st IF frequency sel 1 */
- #define TUNER_LO1 10600000 /* LO for 1st IF frequency sel 2 */
- #define TUNER_IF 480000 /* 2nd IF frequency */
- #define TUNER_MIN_FREQ 950000 /* lowest 1st IF freq. */
- #define TUNER_MAX_FREQ 2150000 /* highest 1st IF freq. */
- #define TUNER_PRESCL_FREQ 2000000 /* LO prescale switch point */
- static float comptab[] = { 2000000, 1000000, 500000, 250000, 125000, 62500,
- 31250, 15625, 0, 800000, 400000, 200000, 100000,
- 50000, 25000, 12500 };
- static int tuner_tuneto(struct newsat_softc *sc, int pol, int freq)
- {
- int band, comp, prescl, prescl_en, count;
- uint8_t iic_data[6];
- if(freq > (TUNER_LO0 + TUNER_MAX_FREQ)) {
- band = 1;
- freq -= TUNER_LO1;
- } else {
- band = 0;
- freq -= TUNER_LO0;
- }
- printf("band %d\n", band);
- tuner_set_pol(sc, pol);
- tuner_set_band(sc, band);
- freq += TUNER_IF;
- prescl_en = freq > TUNER_PRESCL_FREQ;
- comp = 3;
- /* FIXME */
- prescl = (int) ((freq * 1000.0F) / comptab[comp]);
- printf("frequency %d prescl %d\n", freq, prescl);
- if(prescl_en) {
- prescl /= 2;
- }
- /* Program the PLL */
- iic_data[0] = (prescl >> 8) & 0x7f;
- iic_data[1] = prescl & 0xff;
- iic_data[2] = (1 << 7) | (((prescl >> 15) & 3) << 5) |
- (prescl_en << 4) | comp;
- iic_data[3] = (1 << 6) | (1 << 5) | (1 << 4) | 0x0;
- if(newsat_iic_writeN(sc, TUNER_PLL_ADDR, (uint8_t *) &iic_data, 4,
- IIC_SEND_STOP) < 0) {
- device_printf(sc->device, "tuner PLL write error\n");
- return EIO;
- }
- for(count = 0; count < 100; count++) {
- if(newsat_iic_readN(sc, TUNER_PLL_ADDR, (uint8_t *) &iic_data, 1,
- IIC_SEND_STOP) < 0) {
- device_printf(sc->device, "tuner PLL read error\n");
- return EIO;
- }
- if(iic_data[0] & 0x40)
- return 0;
- tsleep(sc, PWAIT, "pllwt", hz / 10);
- }
- device_printf(sc->device, "tuner PLL did not lock\n");
- return ENXIO;
- }
- static void tuner_init(struct newsat_softc *sc)
- {
- tuner_demod_init(sc);
- sc->param.mod = 1;
- /*
- tuner_set_pol(sc, 0);
- tuner_set_band(sc, 0);
- tuner_tuneto(sc, 0, 12051 * 1000);
- tuner_demod_setbaud(sc, 27500 * 1000, 8);
- device_printf(sc->device, "tuner init\n");
- printf("%x\n", tuner_demod_status(sc));
- */
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement