Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * ASoC codec driver for spear platform
0003  *
0004  * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver
0005  *
0006  * Copyright (C) 2012 ST Microelectronics
0007  * Rajeev Kumar <rajeevkumar.linux@gmail.com>
0008  *
0009  * This file is licensed under the terms of the GNU General Public
0010  * License version 2. This program is licensed "as is" without any
0011  * warranty of any kind, whether express or implied.
0012  */
0013 
0014 #include <linux/clk.h>
0015 #include <linux/init.h>
0016 #include <linux/i2c.h>
0017 #include <linux/io.h>
0018 #include <linux/module.h>
0019 #include <linux/moduleparam.h>
0020 #include <linux/pm.h>
0021 #include <linux/regmap.h>
0022 #include <linux/slab.h>
0023 
0024 #include <sound/core.h>
0025 #include <sound/initval.h>
0026 #include <sound/pcm.h>
0027 #include <sound/pcm_params.h>
0028 #include <sound/soc.h>
0029 #include <sound/soc-dapm.h>
0030 #include <sound/tlv.h>
0031 
0032 /* STA529 Register offsets */
0033 #define  STA529_FFXCFG0     0x00
0034 #define  STA529_FFXCFG1     0x01
0035 #define  STA529_MVOL        0x02
0036 #define  STA529_LVOL        0x03
0037 #define  STA529_RVOL        0x04
0038 #define  STA529_TTF0        0x05
0039 #define  STA529_TTF1        0x06
0040 #define  STA529_TTP0        0x07
0041 #define  STA529_TTP1        0x08
0042 #define  STA529_S2PCFG0     0x0A
0043 #define  STA529_S2PCFG1     0x0B
0044 #define  STA529_P2SCFG0     0x0C
0045 #define  STA529_P2SCFG1     0x0D
0046 #define  STA529_PLLCFG0     0x14
0047 #define  STA529_PLLCFG1     0x15
0048 #define  STA529_PLLCFG2     0x16
0049 #define  STA529_PLLCFG3     0x17
0050 #define  STA529_PLLPFE      0x18
0051 #define  STA529_PLLST       0x19
0052 #define  STA529_ADCCFG      0x1E /*mic_select*/
0053 #define  STA529_CKOCFG      0x1F
0054 #define  STA529_MISC        0x20
0055 #define  STA529_PADST0      0x21
0056 #define  STA529_PADST1      0x22
0057 #define  STA529_FFXST       0x23
0058 #define  STA529_PWMIN1      0x2D
0059 #define  STA529_PWMIN2      0x2E
0060 #define  STA529_POWST       0x32
0061 
0062 #define STA529_MAX_REGISTER 0x32
0063 
0064 #define STA529_RATES        (SNDRV_PCM_RATE_8000 | \
0065                 SNDRV_PCM_RATE_11025 | \
0066                 SNDRV_PCM_RATE_16000 | \
0067                 SNDRV_PCM_RATE_22050 | \
0068                 SNDRV_PCM_RATE_32000 | \
0069                 SNDRV_PCM_RATE_44100 | \
0070                 SNDRV_PCM_RATE_48000)
0071 
0072 #define STA529_FORMAT       (SNDRV_PCM_FMTBIT_S16_LE | \
0073                 SNDRV_PCM_FMTBIT_S24_LE | \
0074                 SNDRV_PCM_FMTBIT_S32_LE)
0075 #define S2PC_VALUE      0x98
0076 #define CLOCK_OUT       0x60
0077 #define DATA_FORMAT_MSK     0x0E
0078 #define LEFT_J_DATA_FORMAT  0x00
0079 #define I2S_DATA_FORMAT     0x02
0080 #define RIGHT_J_DATA_FORMAT 0x04
0081 #define CODEC_MUTE_VAL      0x80
0082 
0083 #define POWER_CNTLMSAK      0x40
0084 #define POWER_STDBY     0x40
0085 #define FFX_MASK        0x80
0086 #define FFX_OFF         0x80
0087 #define POWER_UP        0x00
0088 #define FFX_CLK_ENB     0x01
0089 #define FFX_CLK_DIS     0x00
0090 #define FFX_CLK_MSK     0x01
0091 #define PLAY_FREQ_RANGE_MSK 0x70
0092 #define CAP_FREQ_RANGE_MSK  0x0C
0093 #define PDATA_LEN_MSK       0xC0
0094 #define BCLK_TO_FS_MSK      0x30
0095 #define AUDIO_MUTE_MSK      0x80
0096 
0097 static const struct reg_default sta529_reg_defaults[] = {
0098     { 0,  0x35 },     /* R0   - FFX Configuration reg 0 */
0099     { 1,  0xc8 },     /* R1   - FFX Configuration reg 1 */
0100     { 2,  0x50 },     /* R2   - Master Volume */
0101     { 3,  0x00 },     /* R3   - Left Volume */
0102     { 4,  0x00 },     /* R4  -  Right Volume */
0103     { 10, 0xb2 },     /* R10  - S2P Config Reg 0 */
0104     { 11, 0x41 },     /* R11  - S2P Config Reg 1 */
0105     { 12, 0x92 },     /* R12  - P2S Config Reg 0 */
0106     { 13, 0x41 },     /* R13  - P2S Config Reg 1 */
0107     { 30, 0xd2 },     /* R30  - ADC Config Reg */
0108     { 31, 0x40 },     /* R31  - clock Out Reg */
0109     { 32, 0x21 },     /* R32  - Misc Register */
0110 };
0111 
0112 struct sta529 {
0113     struct regmap *regmap;
0114 };
0115 
0116 static bool sta529_readable(struct device *dev, unsigned int reg)
0117 {
0118     switch (reg) {
0119 
0120     case STA529_FFXCFG0:
0121     case STA529_FFXCFG1:
0122     case STA529_MVOL:
0123     case STA529_LVOL:
0124     case STA529_RVOL:
0125     case STA529_S2PCFG0:
0126     case STA529_S2PCFG1:
0127     case STA529_P2SCFG0:
0128     case STA529_P2SCFG1:
0129     case STA529_ADCCFG:
0130     case STA529_CKOCFG:
0131     case STA529_MISC:
0132         return true;
0133     default:
0134         return false;
0135     }
0136 }
0137 
0138 
0139 static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
0140     "Phase-shift"};
0141 
0142 static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
0143 static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
0144 static SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
0145 
0146 static const struct snd_kcontrol_new sta529_snd_controls[] = {
0147     SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
0148             127, 0, out_gain_tlv),
0149     SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1,
0150             master_vol_tlv),
0151     SOC_ENUM("PWM Select", pwm_src),
0152 };
0153 
0154 static int sta529_set_bias_level(struct snd_soc_component *component, enum
0155         snd_soc_bias_level level)
0156 {
0157     struct sta529 *sta529 = snd_soc_component_get_drvdata(component);
0158 
0159     switch (level) {
0160     case SND_SOC_BIAS_ON:
0161     case SND_SOC_BIAS_PREPARE:
0162         snd_soc_component_update_bits(component, STA529_FFXCFG0, POWER_CNTLMSAK,
0163                 POWER_UP);
0164         snd_soc_component_update_bits(component, STA529_MISC,   FFX_CLK_MSK,
0165                 FFX_CLK_ENB);
0166         break;
0167     case SND_SOC_BIAS_STANDBY:
0168         if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
0169             regcache_sync(sta529->regmap);
0170         snd_soc_component_update_bits(component, STA529_FFXCFG0,
0171                     POWER_CNTLMSAK, POWER_STDBY);
0172         /* Making FFX output to zero */
0173         snd_soc_component_update_bits(component, STA529_FFXCFG0, FFX_MASK,
0174                 FFX_OFF);
0175         snd_soc_component_update_bits(component, STA529_MISC, FFX_CLK_MSK,
0176                 FFX_CLK_DIS);
0177         break;
0178     case SND_SOC_BIAS_OFF:
0179         break;
0180     }
0181 
0182     return 0;
0183 
0184 }
0185 
0186 static int sta529_hw_params(struct snd_pcm_substream *substream,
0187         struct snd_pcm_hw_params *params,
0188         struct snd_soc_dai *dai)
0189 {
0190     struct snd_soc_component *component = dai->component;
0191     int pdata, play_freq_val, record_freq_val;
0192     int bclk_to_fs_ratio;
0193 
0194     switch (params_width(params)) {
0195     case 16:
0196         pdata = 1;
0197         bclk_to_fs_ratio = 0;
0198         break;
0199     case 24:
0200         pdata = 2;
0201         bclk_to_fs_ratio = 1;
0202         break;
0203     case 32:
0204         pdata = 3;
0205         bclk_to_fs_ratio = 2;
0206         break;
0207     default:
0208         dev_err(component->dev, "Unsupported format\n");
0209         return -EINVAL;
0210     }
0211 
0212     switch (params_rate(params)) {
0213     case 8000:
0214     case 11025:
0215         play_freq_val = 0;
0216         record_freq_val = 2;
0217         break;
0218     case 16000:
0219     case 22050:
0220         play_freq_val = 1;
0221         record_freq_val = 0;
0222         break;
0223 
0224     case 32000:
0225     case 44100:
0226     case 48000:
0227         play_freq_val = 2;
0228         record_freq_val = 0;
0229         break;
0230     default:
0231         dev_err(component->dev, "Unsupported rate\n");
0232         return -EINVAL;
0233     }
0234 
0235     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0236         snd_soc_component_update_bits(component, STA529_S2PCFG1, PDATA_LEN_MSK,
0237                 pdata << 6);
0238         snd_soc_component_update_bits(component, STA529_S2PCFG1, BCLK_TO_FS_MSK,
0239                 bclk_to_fs_ratio << 4);
0240         snd_soc_component_update_bits(component, STA529_MISC, PLAY_FREQ_RANGE_MSK,
0241                 play_freq_val << 4);
0242     } else {
0243         snd_soc_component_update_bits(component, STA529_P2SCFG1, PDATA_LEN_MSK,
0244                 pdata << 6);
0245         snd_soc_component_update_bits(component, STA529_P2SCFG1, BCLK_TO_FS_MSK,
0246                 bclk_to_fs_ratio << 4);
0247         snd_soc_component_update_bits(component, STA529_MISC, CAP_FREQ_RANGE_MSK,
0248                 record_freq_val << 2);
0249     }
0250 
0251     return 0;
0252 }
0253 
0254 static int sta529_mute(struct snd_soc_dai *dai, int mute, int direction)
0255 {
0256     u8 val = 0;
0257 
0258     if (mute)
0259         val |= CODEC_MUTE_VAL;
0260 
0261     snd_soc_component_update_bits(dai->component, STA529_FFXCFG0, AUDIO_MUTE_MSK, val);
0262 
0263     return 0;
0264 }
0265 
0266 static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
0267 {
0268     struct snd_soc_component *component = codec_dai->component;
0269     u8 mode = 0;
0270 
0271     /* interface format */
0272     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0273     case SND_SOC_DAIFMT_LEFT_J:
0274         mode = LEFT_J_DATA_FORMAT;
0275         break;
0276     case SND_SOC_DAIFMT_I2S:
0277         mode = I2S_DATA_FORMAT;
0278         break;
0279     case SND_SOC_DAIFMT_RIGHT_J:
0280         mode = RIGHT_J_DATA_FORMAT;
0281         break;
0282     default:
0283         return -EINVAL;
0284     }
0285 
0286     snd_soc_component_update_bits(component, STA529_S2PCFG0, DATA_FORMAT_MSK, mode);
0287 
0288     return 0;
0289 }
0290 
0291 static const struct snd_soc_dai_ops sta529_dai_ops = {
0292     .hw_params  =   sta529_hw_params,
0293     .set_fmt    =   sta529_set_dai_fmt,
0294     .mute_stream    =   sta529_mute,
0295     .no_capture_mute = 1,
0296 };
0297 
0298 static struct snd_soc_dai_driver sta529_dai = {
0299     .name = "sta529-audio",
0300     .playback = {
0301         .stream_name = "Playback",
0302         .channels_min = 2,
0303         .channels_max = 2,
0304         .rates = STA529_RATES,
0305         .formats = STA529_FORMAT,
0306     },
0307     .capture = {
0308         .stream_name = "Capture",
0309         .channels_min = 2,
0310         .channels_max = 2,
0311         .rates = STA529_RATES,
0312         .formats = STA529_FORMAT,
0313     },
0314     .ops    = &sta529_dai_ops,
0315 };
0316 
0317 static const struct snd_soc_component_driver sta529_component_driver = {
0318     .set_bias_level     = sta529_set_bias_level,
0319     .controls       = sta529_snd_controls,
0320     .num_controls       = ARRAY_SIZE(sta529_snd_controls),
0321     .suspend_bias_off   = 1,
0322     .idle_bias_on       = 1,
0323     .use_pmdown_time    = 1,
0324     .endianness     = 1,
0325 };
0326 
0327 static const struct regmap_config sta529_regmap = {
0328     .reg_bits = 8,
0329     .val_bits = 8,
0330 
0331     .max_register = STA529_MAX_REGISTER,
0332     .readable_reg = sta529_readable,
0333 
0334     .cache_type = REGCACHE_RBTREE,
0335     .reg_defaults = sta529_reg_defaults,
0336     .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
0337 };
0338 
0339 static int sta529_i2c_probe(struct i2c_client *i2c)
0340 {
0341     struct sta529 *sta529;
0342     int ret;
0343 
0344     sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
0345     if (!sta529)
0346         return -ENOMEM;
0347 
0348     sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
0349     if (IS_ERR(sta529->regmap)) {
0350         ret = PTR_ERR(sta529->regmap);
0351         dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
0352         return ret;
0353     }
0354 
0355     i2c_set_clientdata(i2c, sta529);
0356 
0357     ret = devm_snd_soc_register_component(&i2c->dev,
0358             &sta529_component_driver, &sta529_dai, 1);
0359     if (ret != 0)
0360         dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
0361 
0362     return ret;
0363 }
0364 
0365 static const struct i2c_device_id sta529_i2c_id[] = {
0366     { "sta529", 0 },
0367     { }
0368 };
0369 MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
0370 
0371 static const struct of_device_id sta529_of_match[] = {
0372     { .compatible = "st,sta529", },
0373     { }
0374 };
0375 MODULE_DEVICE_TABLE(of, sta529_of_match);
0376 
0377 static struct i2c_driver sta529_i2c_driver = {
0378     .driver = {
0379         .name = "sta529",
0380         .of_match_table = sta529_of_match,
0381     },
0382     .probe_new  = sta529_i2c_probe,
0383     .id_table   = sta529_i2c_id,
0384 };
0385 
0386 module_i2c_driver(sta529_i2c_driver);
0387 
0388 MODULE_DESCRIPTION("ASoC STA529 codec driver");
0389 MODULE_AUTHOR("Rajeev Kumar <rajeevkumar.linux@gmail.com>");
0390 MODULE_LICENSE("GPL");