diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/sgtl5000.c | 71 | ||||
-rw-r--r-- | sound/soc/codecs/sgtl5000.h | 9 |
2 files changed, 62 insertions, 18 deletions
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 39810b713d5f..f99dd0673f57 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -35,8 +35,15 @@ #define SGTL5000_DAP_REG_OFFSET 0x0100 #define SGTL5000_MAX_REG_OFFSET 0x013A +/* + * The Manual recommends a VAG ramp delay 200-400 ms. + * For Toradex SoM Apalis TK1 v1.2A the optimal up/down delay is 500 ms. + * For Toradex SoM Apalis iMX6D/Q v1.1B the optimal delay + * is 600 ms for ramp up and 500 ms ramp down. + */ + /* Delay for the VAG ramp up */ -#define SGTL5000_VAG_POWERUP_DELAY 500 /* ms */ +#define SGTL5000_VAG_POWERUP_DELAY 600 /* ms */ /* Delay for the VAG ramp down */ #define SGTL5000_VAG_POWERDOWN_DELAY 500 /* ms */ @@ -106,6 +113,13 @@ enum sgtl5000_micbias_resistor { SGTL5000_MICBIAS_8K = 8, }; +enum { + I2S_LRCLK_STRENGTH_DISABLE, + I2S_LRCLK_STRENGTH_LOW, + I2S_LRCLK_STRENGTH_MEDIUM, + I2S_LRCLK_STRENGTH_HIGH, +}; + enum { HP_POWER_EVENT, DAC_POWER_EVENT, @@ -125,6 +139,7 @@ struct sgtl5000_priv { int revision; u8 micbias_resistor; u8 micbias_voltage; + u8 lrclk_strength; u16 mute_state[LAST_POWER_EVENT + 1]; }; @@ -572,32 +587,42 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { .put = dac_put_volsw, }, + /* ADC Capture */ SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0), SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)", - SGTL5000_CHIP_ANA_ADC_CTRL, - 8, 1, 0, capture_6db_attenuate), - SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), + SGTL5000_CHIP_ANA_ADC_CTRL, + SGTL5000_ADC_VOL_M6DB, 1, 0, capture_6db_attenuate), + SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, + SGTL5000_ADC_ZCD_EN, 1, 0), + SOC_SINGLE("Capture Switch", SGTL5000_CHIP_ANA_CTRL, + SGTL5000_ADC_MUTE_SHIFT, 1, 1), + + /* Headphone */ SOC_DOUBLE_TLV("Headphone Playback Volume", - SGTL5000_CHIP_ANA_HP_CTRL, - 0, 8, - 0x7f, 1, - headphone_volume), + SGTL5000_CHIP_ANA_HP_CTRL, + SGTL5000_HP_VOL_LEFT_SHIFT, + SGTL5000_HP_VOL_RIGHT_SHIFT, + 0x7f, 1, + headphone_volume), SOC_SINGLE("Headphone Playback Switch", SGTL5000_CHIP_ANA_CTRL, - 4, 1, 1), + SGTL5000_HP_MUTE_SHIFT, 1, 1), SOC_SINGLE("Headphone Playback ZC Switch", SGTL5000_CHIP_ANA_CTRL, - 5, 1, 0), + SGTL5000_HP_ZCD_EN, 1, 0), + /* Microphone */ SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL, - 0, 3, 0, mic_gain_tlv), + SGTL5000_MIC_GAIN_SHIFT, 3, 0, mic_gain_tlv), + /* Lineout */ SOC_DOUBLE_TLV("Lineout Playback Volume", SGTL5000_CHIP_LINE_OUT_VOL, SGTL5000_LINE_OUT_VOL_LEFT_SHIFT, SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT, 0x1f, 1, lineout_volume), - SOC_SINGLE("Lineout Playback Switch", SGTL5000_CHIP_ANA_CTRL, 8, 1, 1), + SOC_SINGLE("Lineout Playback Switch", SGTL5000_CHIP_ANA_CTRL, + SGTL5000_LINE_MUTE_SHIFT, 1, 1), }; /* mute the codec used by alsa core */ @@ -1277,7 +1302,9 @@ static int sgtl5000_enable_regulators(struct i2c_client *client) static int sgtl5000_probe(struct snd_soc_codec *codec) { int ret; + u16 reg; struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); + unsigned int zcd_mask = SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN; /* power up sgtl5000 */ ret = sgtl5000_set_power_regs(codec); @@ -1286,7 +1313,7 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) /* enable small pop, introduce 400ms delay in turning off */ snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, - SGTL5000_SMALL_POP, 1); + SGTL5000_SMALL_POP, SGTL5000_SMALL_POP); /* disable short cut detector */ snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); @@ -1306,11 +1333,11 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) SGTL5000_DAC_MUTE_RIGHT | SGTL5000_DAC_MUTE_LEFT); - snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f); + reg = ((sgtl5000->lrclk_strength) << SGTL5000_PAD_I2S_LRCLK_SHIFT | 0x5f); + snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, reg); - snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL, - SGTL5000_HP_ZCD_EN | - SGTL5000_ADC_ZCD_EN); + snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_CTRL, + zcd_mask, zcd_mask); snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL, SGTL5000_BIAS_R_MASK, @@ -1341,6 +1368,9 @@ static struct snd_soc_codec_driver sgtl5000_driver = { .probe = sgtl5000_probe, .remove = sgtl5000_remove, .set_bias_level = sgtl5000_set_bias_level, + .reg_cache_size = SGTL5000_MAX_REG_OFFSET, + .reg_word_size = sizeof(u16), + .reg_cache_step = 2, .suspend_bias_off = true, .component_driver = { .controls = sgtl5000_snd_controls, @@ -1535,6 +1565,13 @@ static int sgtl5000_i2c_probe(struct i2c_client *client, } } + sgtl5000->lrclk_strength = I2S_LRCLK_STRENGTH_LOW; + if (!of_property_read_u32(np, "lrclk-strength", &value)) { + if (value > I2S_LRCLK_STRENGTH_HIGH) + value = I2S_LRCLK_STRENGTH_LOW; + sgtl5000->lrclk_strength = value; + } + /* Ensure sgtl5000 will start with sane register values */ sgtl5000_fill_defaults(client); diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 22f3442af982..75cc78670e04 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -237,6 +237,7 @@ * SGTL5000_CHIP_ANA_CTRL */ #define SGTL5000_LINE_OUT_MUTE 0x0100 +#define SGTL5000_LINE_MUTE_SHIFT 8 #define SGTL5000_HP_SEL_MASK 0x0040 #define SGTL5000_HP_SEL_SHIFT 6 #define SGTL5000_HP_SEL_WIDTH 1 @@ -244,6 +245,7 @@ #define SGTL5000_HP_SEL_LINE_IN 0x1 #define SGTL5000_HP_ZCD_EN 0x0020 #define SGTL5000_HP_MUTE 0x0010 +#define SGTL5000_HP_MUTE_SHIFT 4 #define SGTL5000_ADC_SEL_MASK 0x0004 #define SGTL5000_ADC_SEL_SHIFT 2 #define SGTL5000_ADC_SEL_WIDTH 1 @@ -251,6 +253,7 @@ #define SGTL5000_ADC_SEL_LINE_IN 0x1 #define SGTL5000_ADC_ZCD_EN 0x0002 #define SGTL5000_ADC_MUTE 0x0001 +#define SGTL5000_ADC_MUTE_SHIFT 0 /* * SGTL5000_CHIP_LINREG_CTRL @@ -276,7 +279,7 @@ #define SGTL5000_BIAS_CTRL_MASK 0x000e #define SGTL5000_BIAS_CTRL_SHIFT 1 #define SGTL5000_BIAS_CTRL_WIDTH 3 -#define SGTL5000_SMALL_POP 1 +#define SGTL5000_SMALL_POP 0x0001 /* * SGTL5000_CHIP_MIC_CTRL @@ -338,10 +341,14 @@ #define SGTL5000_ADC_STEREO 0x0040 #define SGTL5000_REFTOP_POWERUP 0x0020 #define SGTL5000_HP_POWERUP 0x0010 +#define SGTL5000_HP_POWERUP_SHIFT 4 #define SGTL5000_DAC_POWERUP 0x0008 +#define SGTL5000_DAC_POWERUP_SHIFT 3 #define SGTL5000_CAPLESS_HP_POWERUP 0x0004 #define SGTL5000_ADC_POWERUP 0x0002 +#define SGTL5000_ADC_POWERUP_SHIFT 1 #define SGTL5000_LINE_OUT_POWERUP 0x0001 +#define SGTL5000_LINE_OUT_POWERUP_SHIFT 0 /* * SGTL5000_CHIP_PLL_CTRL |