Exemple #1
0
void audiohw_set_volume(int vol_l, int vol_r)
{
    /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
    vol_l = vol_tenthdb2hw(vol_l);
    vol_r = vol_tenthdb2hw(vol_r);
    wmc_write_masked(LOUTVOL, vol_l, WMC_OUT_VOL_MASK);
    wmc_write_masked(ROUTVOL, vol_r, WMC_OUT_VOL_MASK);
}
void audiohw_set_recvol(int left, int right, int type)
{
    switch (type)
    {
    case AUDIO_GAIN_LINEIN:
        wmc_write_masked(WMC_LEFT_ADC_DIGITAL_VOL, left + 239, WMC_DVOL);
        wmc_write_masked(WMC_RIGHT_ADC_DIGITAL_VOL, right + 239, WMC_DVOL);
        return;
    }
}
void audiohw_set_master_vol(int vol_l, int vol_r)
{
    /* +6 to -73dB 1dB steps (plus mute == 80levels) 7bits */
    /* 1111111 == +6dB */
    /* 1111001 == 0dB */
    /* 0110000 == -73dB */
    /* 0101111 == mute (0x2f) */
    wmc_write_masked(LOUTVOL, vol_l, WMC_OUT_VOL_MASK);
    wmc_write_masked(ROUTVOL, vol_r, WMC_OUT_VOL_MASK);
}
static void sync_prescaler(void)
{
    int prescaler = 0;

    /* Combine all prescaling into a single DAC attenuation */
    if (wmc_vol.eq_on)
        prescaler = wmc_vol.prescaler;

    if (wmc_vol.enh_3d_on)
        prescaler += wmc_vol.enh_3d_prescaler;

    wmc_write_masked(WMC_LEFT_DAC_DIGITAL_VOL, wmc_vol.dac_l - prescaler,
                     WMC_DVOL);
    wmc_write_masked(WMC_RIGHT_DAC_DIGITAL_VOL, wmc_vol.dac_r - prescaler,
                     WMC_DVOL);
}
void audiohw_postinit(void)
{
    sleep(5*HZ/4);

    /* 7. Enable other mixers as required */

    /* 8. Enable other outputs as required */

    /* 9. Set remaining registers */
    wmc_write(WMC_AUDIO_INTERFACE, WMC_WL_16 | WMC_FMT_I2S);
    wmc_write(WMC_DAC_CONTROL, WMC_DACOSR_128);

    /* No ADC, no HP filter, no popping */
    wmc_clear(WMC_ADC_CONTROL, WMC_HPFEN);

    wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
    wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);

    /* Specific to HW clocking */
    wmc_write_masked(WMC_CLOCK_GEN_CTRL, WMC_BCLKDIV_4 | WMC_MS,
                     WMC_BCLKDIV | WMC_MS | WMC_CLKSEL);
    audiohw_set_frequency(HW_FREQ_DEFAULT);

    audiohw_enable_headphone_jack(true);
}
/* Equalizer - set bandwidth for peaking filters to wide (!= 0) or
 * narrow (0); only valid for peaking filter bands 1-3. */
void audiohw_set_eq_band_width(unsigned int band, int val)
{
    if (band < 1 || band > 3)
        return;

    wmc_write_masked(band + WMC_EQ1_LOW_SHELF,
                     (val == 0) ? 0 : WMC_EQBW, WMC_EQBW);
}
/* Equalizer - set the eq band frequency index. */
void audiohw_set_eq_band_frequency(unsigned int band, int val)
{
    if (band > 4)
        return;

    wmc_write_masked(band + WMC_EQ1_LOW_SHELF,
                     val << WMC_EQC_POS, WMC_EQC);
}
void audiohw_set_frequency(int fsel)
{
    extern const struct wmc_srctrl_entry wmc_srctrl_table[HW_NUM_FREQ];
    unsigned int plln;
    unsigned int mclkdiv;

    if ((unsigned)fsel >= HW_NUM_FREQ)
        fsel = HW_FREQ_DEFAULT;

    /* Setup filters. */
    wmc_write(WMC_ADDITIONAL_CTRL, wmc_srctrl_table[fsel].filter);

    plln = wmc_srctrl_table[fsel].plln;
    mclkdiv = wmc_srctrl_table[fsel].mclkdiv;

    if (plln != 0)
    {
        /* Using PLL to generate SYSCLK */

        /* Program PLL. */
        wmc_write(WMC_PLL_N, plln);
        wmc_write(WMC_PLL_K1, wmc_srctrl_table[fsel].pllk1);
        wmc_write(WMC_PLL_K2, wmc_srctrl_table[fsel].pllk2);
        wmc_write(WMC_PLL_K3, wmc_srctrl_table[fsel].pllk3);

        /* Turn on PLL. */
        wmc_set(WMC_POWER_MANAGEMENT1, WMC_PLLEN);

        /* Switch to PLL and set divider. */
        wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv | WMC_CLKSEL,
                         WMC_MCLKDIV | WMC_CLKSEL);
    }
    else
    {
        /* Switch away from PLL and set MCLKDIV. */
        wmc_write_masked(WMC_CLOCK_GEN_CTRL, mclkdiv,
                         WMC_MCLKDIV | WMC_CLKSEL);

        /* Turn off PLL. */
        wmc_clear(WMC_POWER_MANAGEMENT1, WMC_PLLEN);
    }
}
/* Set the depth of the 3D effect */
void audiohw_set_depth_3d(int val)
{
    wmc_vol.enh_3d_prescaler = 10*val / 15; /* -5 dB @ full setting */
    wmc_vol.enh_3d = val;

    if (!wmc_vol.enh_3d_on)
        val = 0;

    sync_prescaler();
    wmc_write_masked(WMC_3D_CONTROL, val, WMC_DEPTH3D);
}
/* Equalizer - set the eq band level -12 to +12 dB. */
void audiohw_set_eq_band_gain(unsigned int band, int val)
{
    if (band > 4)
        return;

    wmc_vol.band_gain[band] = val;

    if (!wmc_vol.eq_on)
        val = 0;

    wmc_write_masked(band + WMC_EQ1_LOW_SHELF, 12 - val, WMC_EQG);
}
void audiohw_set_headphone_vol(int vol_l, int vol_r)
{
    int prev_l = wmc_vol.vol_l;
    int prev_r = wmc_vol.vol_r;
    int dac_l, dac_r, hp_l, hp_r;
    int mix_l, mix_r, boost_l, boost_r;

    wmc_vol.vol_l = vol_l;
    wmc_vol.vol_r = vol_r;

    /* Mixers are synced to provide full volume range on both the analogue
     * and digital pathways */
    get_headphone_levels(vol_l, &dac_l, &hp_l, &mix_l, &boost_l);
    get_headphone_levels(vol_r, &dac_r, &hp_r, &mix_r, &boost_r);

    wmc_vol.dac_l = dac_l;
    wmc_vol.dac_r = dac_r;

    sync_prescaler();

    wmc_write_masked(WMC_LEFT_MIXER_CTRL, mix_l << WMC_BYPLMIXVOL_POS,
                     WMC_BYPLMIXVOL);
    wmc_write_masked(WMC_LEFT_ADC_BOOST_CTRL,
                     boost_l << WMC_L2_2BOOSTVOL_POS, WMC_L2_2BOOSTVOL);
    wmc_write_masked(WMC_LOUT1_HP_VOLUME_CTRL, hp_l, WMC_AVOL);

    wmc_write_masked(WMC_RIGHT_MIXER_CTRL, mix_r << WMC_BYPRMIXVOL_POS,
                     WMC_BYPRMIXVOL);
    wmc_write_masked(WMC_RIGHT_ADC_BOOST_CTRL,
                     boost_r << WMC_R2_2BOOSTVOL_POS, WMC_R2_2BOOSTVOL);
    wmc_write_masked(WMC_ROUT1_HP_VOLUME_CTRL, hp_r, WMC_AVOL);

    if (vol_l > 0)
    {
        /* Not muted and going up from mute level? */
        if (prev_l <= 0 && !wmc_vol.ahw_mute)
            wmc_clear(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
    }
    else
    {
        /* Going to mute level? */
        if (prev_l > 0)
            wmc_set(WMC_LOUT1_HP_VOLUME_CTRL, WMC_MUTE);
    }

    if (vol_r > 0)
    {
        /* Not muted and going up from mute level? */
        if (prev_r <= 0 && !wmc_vol.ahw_mute)
            wmc_clear(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
    }
    else
    {
        /* Going to mute level? */
        if (prev_r > 0)
            wmc_set(WMC_ROUT1_HP_VOLUME_CTRL, WMC_MUTE);
    }
}
void audiohw_set_recsrc(int source, bool recording)
{
    switch (source)
    {
    case AUDIO_SRC_PLAYBACK:
        /* Disable all audio paths but DAC */
        /* Disable ADCs */
        wmc_clear(WMC_ADC_CONTROL, WMC_HPFEN);
        wmc_clear(WMC_POWER_MANAGEMENT2, WMC_ADCENL | WMC_ADCENR);
        /* Disable bypass */
        wmc_clear(WMC_LEFT_MIXER_CTRL, WMC_BYPL2LMIX);
        wmc_clear(WMC_RIGHT_MIXER_CTRL, WMC_BYPR2RMIX);
        /* Disable IP BOOSTMIX and PGA */
        wmc_clear(WMC_POWER_MANAGEMENT2, WMC_INPPGAENL | WMC_INPPGAENR |
                  WMC_BOOSTENL | WMC_BOOSTENR);
        wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
                                  WMC_LIP2INPPGA | WMC_RIP2INPPGA |
                                  WMC_LIN2INPPGA | WMC_RIN2INPPGA);
        wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
        wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
        break;

    case AUDIO_SRC_FMRADIO:
        if (recording)
        {
            /* Disable bypass */
            wmc_clear(WMC_LEFT_MIXER_CTRL, WMC_BYPL2LMIX);
            wmc_clear(WMC_RIGHT_MIXER_CTRL, WMC_BYPR2RMIX);
            /* Enable ADCs, IP BOOSTMIX and PGA, route L/R2 through PGA */
            wmc_set(WMC_POWER_MANAGEMENT2, WMC_ADCENL | WMC_ADCENR |
                    WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL |
                    WMC_INPPGAENR);
            wmc_set(WMC_ADC_CONTROL, WMC_ADCOSR | WMC_HPFEN);
            /* PGA at 0dB with +20dB boost */
            wmc_write_masked(WMC_LEFT_INP_PGA_GAIN_CTRL, 0x10, WMC_AVOL);
            wmc_write_masked(WMC_RIGHT_INP_PGA_GAIN_CTRL, 0x10, WMC_AVOL);
            wmc_set(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
            wmc_set(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
            /* Connect L/R2 inputs to PGA */
            wmc_write_masked(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
                                             WMC_LIN2INPPGA | WMC_RIN2INPPGA,
                                             WMC_L2_2INPPGA | WMC_R2_2INPPGA |
                                             WMC_LIP2INPPGA | WMC_RIP2INPPGA |
                                             WMC_LIN2INPPGA | WMC_RIN2INPPGA);
        }
        else
        {
            /* Disable PGA and ADC, enable IP BOOSTMIX, route L/R2 directly to
             * IP BOOSTMIX */
            wmc_clear(WMC_ADC_CONTROL, WMC_HPFEN);
            wmc_write_masked(WMC_POWER_MANAGEMENT2, WMC_BOOSTENL | WMC_BOOSTENR,
                WMC_BOOSTENL | WMC_BOOSTENR | WMC_INPPGAENL |
                WMC_INPPGAENR | WMC_ADCENL | WMC_ADCENR);
            wmc_clear(WMC_INPUT_CTRL, WMC_L2_2INPPGA | WMC_R2_2INPPGA |
                                      WMC_LIP2INPPGA | WMC_RIP2INPPGA |
                                      WMC_LIN2INPPGA | WMC_RIN2INPPGA);
            wmc_clear(WMC_LEFT_ADC_BOOST_CTRL, WMC_PGABOOSTL);
            wmc_clear(WMC_RIGHT_ADC_BOOST_CTRL, WMC_PGABOOSTR);
            /* Enable bypass to L/R mixers */
            wmc_set(WMC_LEFT_MIXER_CTRL, WMC_BYPL2LMIX);
            wmc_set(WMC_RIGHT_MIXER_CTRL, WMC_BYPR2RMIX);
        }
        break;
    }
}