void pcm_play_dma_init(void)
{
    bitset32(&CGU_PERI, CGU_I2SOUT_APB_CLOCK_ENABLE);
    I2SOUT_CONTROL = (1<<6) | (1<<3);  /* enable dma, stereo */

    audiohw_preinit();
    pcm_dma_apply_settings();
}
void pcm_rec_dma_init(void)
{
    bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE);

    I2SIN_MASK = 0; /* disables all interrupts */

    /* 14 bits samples, i2c clk src = I2SOUTIF, sdata src = AFE,
     * data valid at positive edge of SCLK */
    I2SIN_CONTROL = (1<<5) | (1<<2);
}
static void LCD_SPI_start(void)
{
    bitset32(&CLKCON, 0x40000);   /* enable SPI clock */
    LCD_SPI_SS(false);
    SPCON0=0x3E;
    SPPRE0=24;

    reset_LCD(true);
    LCD_SPI_SS(true);
}
示例#4
0
int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
{
#ifdef SANSA_FUZEV2
    bitclr32(&CCU_IO, 1<<12);
#endif
    int ret = i2c_read_data(fm_i2c_bus, address, -1, buf, count);
#ifdef SANSA_FUZEV2
    bitset32(&CCU_IO, 1<<12);
#endif
    return ret;
}
示例#5
0
static void as3525_dbop_init(void)
{
    bitset32(&CCU_IO, 1<<12);
    CGU_DBOP |= (1<<4) | (1<<3) | AS3525_DBOP_DIV;
    DBOP_TIMPOL_01 = 0xE12FE12F;
    DBOP_TIMPOL_23 = 0xE12F0036;
    DBOP_CTRL = 0x41004;
    DBOP_TIMPOL_23 = 0x60036;
    DBOP_CTRL = 0x51004;
    DBOP_TIMPOL_01 = 0x60036;
    DBOP_TIMPOL_23 = 0xA12FE037;
}
void pcm_rec_lock(void)
{
    int oldlevel = disable_irq_save();

    if (++rec_locked == 1)
    {
        bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE);
        VIC_INT_EN_CLEAR = INTERRUPT_I2SIN;
        I2SIN_MASK = 0; /* disables all interrupts */
    }

    restore_irq(oldlevel);
}
void dma_resume_channel(int channel)
{
    /* Resume - must reinit to where it left off (so the docs say) */
    unsigned long control = DMAC_CH_CONTROL(channel);
    if ((control & 0x7ff) == 0)
        return; /* empty */

    DMAC_INT_TC_CLEAR = (1<<channel);
    DMAC_INT_ERR_CLEAR = (1<<channel);
    DMAC_CH_SRC_ADDR(channel) = DMAC_CH_SRC_ADDR(channel);
    DMAC_CH_DST_ADDR(channel) = DMAC_CH_DST_ADDR(channel);
    DMAC_CH_LLI(channel) = DMAC_CH_LLI(channel);
    DMAC_CH_CONTROL(channel) = control;
    bitset32(&DMAC_CH_CONFIGURATION(channel), (1<<0));
}
示例#8
0
int lcd_hw_init(void)
{
/* DBOP initialisation, do what OF does */
    bitset32(&CCU_IO, 1<<12); /* ?? */
    CGU_DBOP |= /*(1<<3)*/ 0x18 | AS3525_DBOP_DIV;

    DBOP_CTRL      = 0x51004;
    DBOP_TIMPOL_01 = 0x36A12F;
    DBOP_TIMPOL_23 = 0xE037E037;

    GPIOB_DIR |= (1<<2)|(1<<5);
    GPIOB_PIN(5) = (1<<5);

    return 0;
}
示例#9
0
bool sdma_channel_init(unsigned int channel,
                       struct channel_descriptor *cd_p,
                       struct buffer_descriptor *base_bd_p)
{
    struct channel_control_block *ccb_p;

    if (channel == 0 || channel >= CH_NUM ||
        cd_p == NULL || base_bd_p == NULL)
        return false;

    ccb_p = &ccb_array[channel];

    /* If initialized already, should close first then init. */
    if (ccb_p->status.opened_init != 0)
        return false;

    /* Initialize channel control block. */
    ccb_p->curr_bd_ptr = base_bd_p;
    ccb_p->base_bd_ptr = base_bd_p;
    ccb_p->channel_desc = cd_p;
    ccb_p->status.error = 0;
    ccb_p->status.opened_init = 1;
    ccb_p->status.state_direction = 0;
    ccb_p->status.execute = 0;

    /* Finish any channel descriptor inits. */
    cd_p->ccb_ptr = ccb_p;
    cd_p->is_setup = 0;

    /* Do an initial setup now. */
    if (!setup_channel(ccb_p))
    {
        logf("SDMA ch init failed: %d", channel);
        cd_p->ccb_ptr = NULL;
        memset(ccb_p, 0x00, sizeof (struct channel_control_block));
        return false;
    }

    /* Enable interrupt if a callback is specified. */
    if (cd_p->callback != NULL)
        bitset32(&sdma_enabled_ints, 1ul << channel);

    /* Minimum schedulable = 1 */
    sdma_channel_set_priority(channel, 1);

    logf("SDMA ch initialized: %d", channel);
    return true;
}
示例#10
0
static void as3525v2_connect(void)
{
    logf("usb-drv: init as3525v2");
    /* 1) enable usb core clock */
    bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE);
    usb_delay();
    /* 2) enable usb phy clock */
    CCU_USB = (CCU_USB & ~(3<<24)) | (1 << 24); /* ?? */
    /* PHY clock */
    CGU_USB = 1<<5  /* enable */
        | 0 << 2
        | 0; /* source = ? (24MHz crystal?) */
    usb_delay();
    /* 3) clear "stop pclk" */
    PCGCCTL &= ~0x1;
    usb_delay();
    /* 4) clear "power clamp" */
    PCGCCTL &= ~0x4;
    usb_delay();
    /* 5) clear "reset power down module" */
    PCGCCTL &= ~0x8;
    usb_delay();
    /* 6) set "power on program done" */
    DCTL |= DCTL_pwronprgdone;
    usb_delay();
    /* 7) core soft reset */
    GRSTCTL |= GRSTCTL_csftrst;
    usb_delay();
    /* 8) hclk soft reset */
    GRSTCTL |= GRSTCTL_hsftrst;
    usb_delay();
    /* 9) flush and reset everything */
    GRSTCTL |= 0x3f;
    usb_delay();
    /* 10) force device mode*/
    GUSBCFG &= ~GUSBCFG_force_host_mode;
    GUSBCFG |= GUSBCFG_force_device_mode;
    usb_delay();
    /* 11) Do something that is probably CCU related but undocumented*/
    CCU_USB |= 0x1000;
    CCU_USB &= ~0x300000;
    usb_delay();
    /* 12) reset usb core parameters (dev addr, speed, ...) */
    DCFG = 0;
    usb_delay();
}
void pcm_rec_dma_start(void *addr, size_t size)
{
    is_recording = true;

    bitset32(&CGU_AUDIO, (1<<11));

    rec_dma_addr = addr;
    rec_dma_size = size;

    keep_sample = 0;

    /* ensure empty FIFO */
    while (!(I2SIN_RAW_STATUS & (1<<5)))
        *I2SIN_DATA;

    I2SIN_CLEAR = (1<<6) | (1<<0); /* push error, pop error */
}
void i2c_write(int addr, const unsigned char *buf, int count)
{
    if (count <= 0)
        return;

    mutex_lock(&i2c_mtx);

    /* Turn on I2C clock */
    bitset32(&CLKCON, 1 << 16);

    /* Set mode to master transmitter and enable lines */
    IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB;

    /* Set buffer start and count */
    buf_ptr = (unsigned char *)buf;
    buf_count = count;

    /* Send slave address and then data */
    SRCPND = IIC_MASK;
    INTPND = IIC_MASK;

    IICCON |= I2C_TXRX_INTENB;

    /* Load slave address into shift register */
    IICDS = addr & 0xfe;

    /* Generate START */
    IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_START | I2C_RXTX_ENB;

    if (semaphore_wait(&i2c_complete, HZ) != OBJ_WAIT_SUCCEEDED)
    {
        /* Something went wrong - stop transmission */
        int oldlevel = disable_irq_save();
        i2c_stop();
        restore_irq(oldlevel);
    }

    /* Go back to slave receive mode and disable lines */
    IICSTAT = 0;

    /* Turn off I2C clock */
    bitclr32(&CLKCON, 1 << 16);

    mutex_unlock(&i2c_mtx);
}
void pcm_play_dma_start(const void *addr, size_t size)
{
    is_playing = true;

    dma_start_addr = (void*)addr;
    dma_start_size = size;
    dma_sub_addr = dma_start_addr;
    dma_rem_size = size;

    dma_retain();

    /* force writeback */
    commit_dcache_range(dma_start_addr, dma_start_size);

    bitset32(&CGU_AUDIO, (1<<11));

    play_start_pcm();
}
static void lcd_set_power(bool powered)
{
    if (powered)
    {
        lcd_powered = false;
        lcd_write_reg(0x04, 0x00);
        lcd_enable_interface(false);
        bitclr32(&GPIO3_DR, (1 << 12));
        mc13783_clear(MC13783_REGULATOR_MODE1, MC13783_VCAMEN);
    }
    else
    {
        mc13783_set(MC13783_REGULATOR_MODE1, MC13783_VCAMEN);
        bitset32(&GPIO3_DR, (1 << 12));
        lcd_enable_interface(true);
        lcd_write_reg(0x04, 0x01);
        lcd_powered = true;
    }
}
/* LCD init */
void lcd_init_device(void)
{
#ifdef BOOTLOADER
    int i;
    /* When the Rockbox bootloader starts the framebuffer address is changed
     * but the LCD display should stay the same til an lcd_update() occurs.
     * This copies the data from the old framebuffer to the new one to make the
     * change non-visable to the user.
     */
    unsigned short *buf     = (unsigned short*)(FRAME);
    unsigned short *oldbuf  = (unsigned short*)(LCDSADDR1<<1);

    /* The Rockbox bootloader is transitioning from RGB555I to RGB565 mode
       so convert the frambuffer data accordingly */
    for(i=0; i< 320*240; i++)
    {
        *(buf++) = ((*oldbuf>>1) & 0x1F) | (*oldbuf & 0xffc0);
        oldbuf++;
    }
#endif

    /* Set pins up */
    GPHUP   &= 0x600;
    GPECON  |= 0x0A800000;
    GPEUP   |= 0x3800;
#ifdef GIGABEAT_F
    GPBUP   |= 0x181;
#endif

    bitset32(&CLKCON, 0x20);  /* enable LCD clock */

    LCD_CTRL_setup();
#ifdef GIGABEAT_F
    LCD_SPI_init();
#else
    LCD_CTRL_clock(true);
#endif

    lcd_on = true;
}
示例#16
0
/* Stop a channel from executing - cannot be resumed */
void sdma_channel_stop(unsigned int channel)
{
    struct channel_control_block *ccb_p;
    unsigned long chmsk;
    unsigned long intmsk;
    int oldstatus;
    int i;

    if (channel == 0 || channel >= CH_NUM)
        return;

    ccb_p = &ccb_array[channel];

    if (ccb_p->status.opened_init == 0)
        return;

    chmsk = 1ul << channel;

    /* Lock callback */
    oldstatus = disable_irq_save();    
    intmsk = sdma_enabled_ints;
    sdma_enabled_ints &= ~chmsk;
    restore_irq(oldstatus);

    /* Stop execution */
    for (i = ccb_p->channel_desc->bd_count - 1; i >= 0; i--)
        ccb_p->base_bd_ptr[i].mode.status &= ~BD_DONE;

    SDMA_STOP_STAT = chmsk;
    while (SDMA_STOP_STAT & chmsk);

    /* Unlock callback if it was set */
    if (intmsk & chmsk)
        bitset32(&sdma_enabled_ints, chmsk);

    logf("SDMA ch closed: %d", channel);
}
/* initialises the host lcd hardware, returns the lcd type */
static int lcd_hw_init(void)
{
    /* configure SSP */
    bitset32(&CGU_PERI, CGU_SSP_CLOCK_ENABLE);
    SSP_CPSR = 4;           /* TODO: use AS3525_SSP_PRESCALER, OF uses 8 */
    SSP_CR0 =   (0 << 8) |  /* SCR, serial clock rate divider = 1 */
                (1 << 7) |  /* SPH, phase = 1 */
                (1 << 6) |  /* SPO, polarity = 1 */
                (0 << 4) |  /* FRF, frame format = motorola SPI */
                (7 << 0);   /* DSS, data size select = 8 bits */
    SSP_CR1 =   (1 << 3) |  /* SOD, slave output disable = 1 */
                (0 << 2) |  /* MS, master/slave = master */
                (1 << 1) |  /* SSE, synchronous serial port enabled = true */
                (0 << 0);   /* LBM, loopback mode = normal */
    SSP_IMSC &= ~0xF;       /* disable interrupts */
    SSP_DMACR &= ~0x3;      /* disable DMA */

    /* GPIO A3 is ??? but needs to be set */
    GPIOA_DIR |= (1 << 3);
    GPIOA_PIN(3) = (1 << 3);

    /* configure GPIO B2 (lcd D/C#) as output */
    GPIOB_DIR |= (1<<2);

    /* configure GPIO B3 (lcd type detect) as input */
    GPIOB_DIR &= ~(1<<3);
    
    /* configure GPIO A5 (lcd reset#) as output and perform lcd reset */
    GPIOA_DIR |= (1 << 5);
    GPIOA_PIN(5) = 0;
    sleep(HZ * 50/1000);
    GPIOA_PIN(5) = (1 << 5);

    /* detect lcd type on GPIO B3 */    
    return GPIOB_PIN(3) ? 1 : 0;
}
示例#18
0
static bool setup_channel(struct channel_control_block *ccb_p)
{
    struct context_data context_buffer;
    struct channel_descriptor *cd_p;
    unsigned int channel_cfg;
    unsigned int channel;
    unsigned long pc;

    memset(&context_buffer, 0x00, sizeof (context_buffer));

    channel = ccb_p - ccb_array;
    cd_p = ccb_p->channel_desc;

    /* Obtain script start address for perihperal and transfer type */
    pc = get_script_pc(cd_p->per_type, cd_p->tran_type);

    if (pc == (unsigned short)-1)
        return false; /* Failed to find a script */

    context_buffer.channel_state.pc = pc;

    if (cd_p->per_type != SDMA_PER_MEMORY && cd_p->per_type != SDMA_PER_DSP)
    {
        /* Set peripheral DMA request mask for this channel */
        context_buffer.event_mask1 = 1ul << cd_p->event_id1;

        if (cd_p->per_type == SDMA_PER_ATA)
        {
            /* ATA has two */
            context_buffer.event_mask2 = 1ul << cd_p->event_id2;
        }

        context_buffer.shp_addr = cd_p->shp_addr;
        context_buffer.wml = cd_p->wml;
    }
    else
    {
        context_buffer.wml = SDMA_PER_ADDR_SDRAM;
    }

    /* Send channel context to SDMA core */
    commit_dcache_range(&context_buffer, sizeof (context_buffer));
    sdma_write_words((unsigned long *)&context_buffer,
                     CHANNEL_CONTEXT_ADDR(channel),
                     sizeof (context_buffer)/4);

    ccb_p->status.error = 0; /* Clear channel-wide error flag */

    if (cd_p->is_setup != 0)
        return true; /* No more to do */

    /* Obtain channel ownership configuration */
    channel_cfg = get_config(cd_p->tran_type);

    if (channel_cfg == (unsigned int)-1)
        return false;

    /* Set who owns it and thus can activate it */
    set_channel_ownership(channel, channel_cfg);

    if (channel_cfg & CH_OWNSHP_EVT)
    {
        /* Set event ID to channel activation bitmapping */
        bitset32(&SDMA_CHNENBL(cd_p->event_id1), 1ul << channel);

        if (cd_p->per_type == SDMA_PER_ATA)
        {
            /* ATA has two */
            bitset32(&SDMA_CHNENBL(cd_p->event_id2), 1ul << channel);
        }
    }

    cd_p->is_setup = 1;

    return true;
}
void pcm_rec_dma_close(void)
{
    bitset32(&CGU_PERI, CGU_I2SIN_APB_CLOCK_ENABLE);
    pcm_rec_dma_stop();
}
示例#20
0
void usb_drv_init(void)
{
    for (int i = 0; i < USB_NUM_ENDPOINTS; i++)
        for (int dir = 0; dir < 2; dir++)
            semaphore_init(&endpoints[i][dir].complete, 1, 0);

    bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE);
    CCU_USB = (CCU_USB & ~(3<<24)) | (1 << 24); /* ?? */
    /* PHY clock */
    CGU_USB = 1<<5  /* enable */
        | 0 << 2
        | 0; /* source = ? (24MHz crystal?) */

    PCGCCTL = 0;
    DCTL = DCTL_pwronprgdone | DCTL_sftdiscon;

    GRSTCTL = GRSTCTL_csftrst;
    while (GRSTCTL & GRSTCTL_csftrst);  /* Wait for OTG to ack reset */
    while (!(GRSTCTL & GRSTCTL_ahbidle));  /* Wait for OTG AHB master idle */

    GRXFSIZ = 512;
    GNPTXFSIZ = MAKE_FIFOSIZE_DATA(512);

    /* FIXME: the current code is for internal DMA only, the clip+ architecture
     *        defines the internal DMA model */
    GAHBCFG = (GAHBCFG_INT_DMA_BURST_INCR << GAHBCFG_hburstlen_bitp)
                | GAHBCFG_dma_enable | GAHBCFG_glblintrmsk;

    /* Select UTMI+ 16 */
    GUSBCFG = GUSBCFG_force_device_mode | GUSBCFG_phy_if | 7 << GUSBCFG_toutcal_bitp;

    /* Do something that is probably CCU related but undocumented*/
    CCU_USB |= 0x1000;
    CCU_USB &= ~0x300000;

    DCFG = DCFG_nzstsouthshk | DCFG_devspd_hs_phy_hs; /* Address 0, high speed */
    DCTL = DCTL_pwronprgdone;

    /* Check hardware capabilities */
    if(extract(GHWCFG2, arch) != GHWCFG2_ARCH_INTERNAL_DMA)
        panicf("usb-drv: wrong architecture (%ld)", extract(GHWCFG2, arch));
    if(extract(GHWCFG2, hs_phy_type) != GHWCFG2_PHY_TYPE_UTMI)
        panicf("usb-drv: wrong HS phy type (%ld)", extract(GHWCFG2, hs_phy_type));
    if(extract(GHWCFG2, fs_phy_type) != GHWCFG2_PHY_TYPE_UNSUPPORTED)
        panicf("usb-drv: wrong FS phy type (%ld)", extract(GHWCFG2, fs_phy_type));
    if(extract(GHWCFG4, utmi_phy_data_width) != 0x2)
        panicf("usb-drv: wrong utmi data width (%ld)", extract(GHWCFG4, utmi_phy_data_width));
    if(!(GHWCFG4 & GHWCFG4_ded_fifo_en)) /* it seems to be multiple tx fifo support */
        panicf("usb-drv: no multiple tx fifo");

    if(USB_NUM_ENDPOINTS != extract(GHWCFG2, num_ep))
        panicf("usb-drv: wrong endpoint number");

    for (int dir = 0; dir < 2; dir++)
        for (unsigned i = 0; i < num_eps(dir == DIR_OUT); i++)
        {
            int ep = ((dir == DIR_IN) ? in_ep_list : out_ep_list)[i];
            int type = (GHWCFG1 >> GHWCFG1_epdir_bitp(ep)) & GHWCFG1_epdir_bits;
            int flag = (dir == DIR_IN) ? GHWCFG1_EPDIR_IN : GHWCFG1_EPDIR_OUT;
            if(type != GHWCFG1_EPDIR_BIDIR && type != flag)
                panicf("usb-drv: EP%d not in correct direction", ep);
        }

    DOEPMSK = DEPINT_xfercompl | DEPINT_ahberr | DOEPINT_setup;
    DIEPMSK = DEPINT_xfercompl | DEPINT_ahberr | DIEPINT_timeout;
    DAINTMSK = 0xffffffff;

    reset_endpoints();

    GINTMSK = GINTMSK_usbreset
            | GINTMSK_enumdone
            | GINTMSK_inepintr
            | GINTMSK_outepintr
            | GINTMSK_disconnect;

    VIC_INT_ENABLE = INTERRUPT_USB;
}
void usb_drv_init(void)
{
    logf("usb_drv_init() !!!!\n");

    if (!initialized)
    {
        int i;
        for (i = 0; i < USB_NUM_EPS; i++)
        {
            semaphore_init(&endpoints[i][0].complete, 1, 0);
            semaphore_init(&endpoints[i][1].complete, 1, 0);
        }

        initialized = true;
    }

    usb_enable_pll();

    /* we have external power, so boost cpu */
    cpu_boost(1);

    /* length regulator: normal operation */
    ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2);

    /* AHB part */
    bitset32(&CGU_PERI, CGU_USB_CLOCK_ENABLE);

    /* reset AHB */
    CCU_SRC = CCU_SRC_USB_AHB_EN;
    CCU_SRL = CCU_SRL_MAGIC_NUMBER;
    mdelay(1);
    CCU_SRC = CCU_SRL = 0;

    USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
                 | USB_GPIO_TX_BIT_STUFF_EN
                 | USB_GPIO_XO_ON
                 | USB_GPIO_CLK_SEL10; /* 0x06180000; */

    /* bug workaround according to linux patch */
    USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */

    /* enable soft disconnect */
    USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;

    usb_phy_on();
    usb_phy_suspend();
    USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN;

    /* We don't care about SVC or SOF events */
    /* Right now we don't handle suspend, so mask those too */
    USB_DEV_INTR_MASK = USB_DEV_INTR_SVC |
                        USB_DEV_INTR_SOF |
                        USB_DEV_INTR_USB_SUSPEND |
                        USB_DEV_INTR_EARLY_SUSPEND;

    USB_DEV_CFG = USB_DEV_CFG_STAT_ACK      |
                  USB_DEV_CFG_UNI_DIR       |
                  USB_DEV_CFG_PI_16BIT      |
                  USB_DEV_CFG_HS            |
                  USB_DEV_CFG_SELF_POWERED  |
                  USB_DEV_CFG_CSR_PRG       |
                  USB_DEV_CFG_PHY_ERR_DETECT;

    USB_DEV_CTRL = USB_DEV_CTRL_DESC_UPDATE  |
                   USB_DEV_CTRL_THRES_ENABLE |
                   USB_DEV_CTRL_BURST_ENABLE |
                   USB_DEV_CTRL_BLEN_8DWORDS |
                   USB_DEV_CTRL_TLEN_8THMAXSIZE;

    USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16));    /* ep 0 */

    reset_endpoints(1);

    /* clear pending interrupts */
    USB_DEV_EP_INTR = 0xffffffff;
    USB_DEV_INTR    = 0xffffffff;

    VIC_INT_ENABLE = INTERRUPT_USB;

    usb_phy_resume();
    USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN;

    USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N
                 | USB_GPIO_TX_BIT_STUFF_EN
                 | USB_GPIO_XO_ON
                 | USB_GPIO_HS_INTR
                 | USB_GPIO_CLK_SEL10; /* 0x06180000; */

    tick_add_task(usb_tick);

    usb_enum_timeout = HZ; /* one second timeout for enumeration */
}