linux/sound/soc/codecs/sta529.c
<<
>>
Prefs
   1/*
   2 * ASoC codec driver for spear platform
   3 *
   4 * sound/soc/codecs/sta529.c -- spear ALSA Soc codec driver
   5 *
   6 * Copyright (C) 2012 ST Microelectronics
   7 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
   8 *
   9 * This file is licensed under the terms of the GNU General Public
  10 * License version 2. This program is licensed "as is" without any
  11 * warranty of any kind, whether express or implied.
  12 */
  13
  14#include <linux/clk.h>
  15#include <linux/init.h>
  16#include <linux/i2c.h>
  17#include <linux/io.h>
  18#include <linux/module.h>
  19#include <linux/moduleparam.h>
  20#include <linux/pm.h>
  21#include <linux/regmap.h>
  22#include <linux/slab.h>
  23
  24#include <sound/core.h>
  25#include <sound/initval.h>
  26#include <sound/pcm.h>
  27#include <sound/pcm_params.h>
  28#include <sound/soc.h>
  29#include <sound/soc-dapm.h>
  30#include <sound/tlv.h>
  31
  32/* STA529 Register offsets */
  33#define  STA529_FFXCFG0         0x00
  34#define  STA529_FFXCFG1         0x01
  35#define  STA529_MVOL            0x02
  36#define  STA529_LVOL            0x03
  37#define  STA529_RVOL            0x04
  38#define  STA529_TTF0            0x05
  39#define  STA529_TTF1            0x06
  40#define  STA529_TTP0            0x07
  41#define  STA529_TTP1            0x08
  42#define  STA529_S2PCFG0         0x0A
  43#define  STA529_S2PCFG1         0x0B
  44#define  STA529_P2SCFG0         0x0C
  45#define  STA529_P2SCFG1         0x0D
  46#define  STA529_PLLCFG0         0x14
  47#define  STA529_PLLCFG1         0x15
  48#define  STA529_PLLCFG2         0x16
  49#define  STA529_PLLCFG3         0x17
  50#define  STA529_PLLPFE          0x18
  51#define  STA529_PLLST           0x19
  52#define  STA529_ADCCFG          0x1E /*mic_select*/
  53#define  STA529_CKOCFG          0x1F
  54#define  STA529_MISC            0x20
  55#define  STA529_PADST0          0x21
  56#define  STA529_PADST1          0x22
  57#define  STA529_FFXST           0x23
  58#define  STA529_PWMIN1          0x2D
  59#define  STA529_PWMIN2          0x2E
  60#define  STA529_POWST           0x32
  61
  62#define STA529_MAX_REGISTER     0x32
  63
  64#define STA529_RATES            (SNDRV_PCM_RATE_8000 | \
  65                                SNDRV_PCM_RATE_11025 | \
  66                                SNDRV_PCM_RATE_16000 | \
  67                                SNDRV_PCM_RATE_22050 | \
  68                                SNDRV_PCM_RATE_32000 | \
  69                                SNDRV_PCM_RATE_44100 | \
  70                                SNDRV_PCM_RATE_48000)
  71
  72#define STA529_FORMAT           (SNDRV_PCM_FMTBIT_S16_LE | \
  73                                SNDRV_PCM_FMTBIT_S24_LE | \
  74                                SNDRV_PCM_FMTBIT_S32_LE)
  75#define S2PC_VALUE              0x98
  76#define CLOCK_OUT               0x60
  77#define DATA_FORMAT_MSK         0x0E
  78#define LEFT_J_DATA_FORMAT      0x00
  79#define I2S_DATA_FORMAT         0x02
  80#define RIGHT_J_DATA_FORMAT     0x04
  81#define CODEC_MUTE_VAL          0x80
  82
  83#define POWER_CNTLMSAK          0x40
  84#define POWER_STDBY             0x40
  85#define FFX_MASK                0x80
  86#define FFX_OFF                 0x80
  87#define POWER_UP                0x00
  88#define FFX_CLK_ENB             0x01
  89#define FFX_CLK_DIS             0x00
  90#define FFX_CLK_MSK             0x01
  91#define PLAY_FREQ_RANGE_MSK     0x70
  92#define CAP_FREQ_RANGE_MSK      0x0C
  93#define PDATA_LEN_MSK           0xC0
  94#define BCLK_TO_FS_MSK          0x30
  95#define AUDIO_MUTE_MSK          0x80
  96
  97static const struct reg_default sta529_reg_defaults[] = {
  98        { 0,  0x35 },     /* R0   - FFX Configuration reg 0 */
  99        { 1,  0xc8 },     /* R1   - FFX Configuration reg 1 */
 100        { 2,  0x50 },     /* R2   - Master Volume */
 101        { 3,  0x00 },     /* R3   - Left Volume */
 102        { 4,  0x00 },     /* R4  -  Right Volume */
 103        { 10, 0xb2 },     /* R10  - S2P Config Reg 0 */
 104        { 11, 0x41 },     /* R11  - S2P Config Reg 1 */
 105        { 12, 0x92 },     /* R12  - P2S Config Reg 0 */
 106        { 13, 0x41 },     /* R13  - P2S Config Reg 1 */
 107        { 30, 0xd2 },     /* R30  - ADC Config Reg */
 108        { 31, 0x40 },     /* R31  - clock Out Reg */
 109        { 32, 0x21 },     /* R32  - Misc Register */
 110};
 111
 112struct sta529 {
 113        struct regmap *regmap;
 114};
 115
 116static bool sta529_readable(struct device *dev, unsigned int reg)
 117{
 118        switch (reg) {
 119
 120        case STA529_FFXCFG0:
 121        case STA529_FFXCFG1:
 122        case STA529_MVOL:
 123        case STA529_LVOL:
 124        case STA529_RVOL:
 125        case STA529_S2PCFG0:
 126        case STA529_S2PCFG1:
 127        case STA529_P2SCFG0:
 128        case STA529_P2SCFG1:
 129        case STA529_ADCCFG:
 130        case STA529_CKOCFG:
 131        case STA529_MISC:
 132                return true;
 133        default:
 134                return false;
 135        }
 136}
 137
 138
 139static const char *pwm_mode_text[] = { "Binary", "Headphone", "Ternary",
 140        "Phase-shift"};
 141
 142static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -9150, 50, 0);
 143static const DECLARE_TLV_DB_SCALE(master_vol_tlv, -12750, 50, 0);
 144static const SOC_ENUM_SINGLE_DECL(pwm_src, STA529_FFXCFG1, 4, pwm_mode_text);
 145
 146static const struct snd_kcontrol_new sta529_snd_controls[] = {
 147        SOC_DOUBLE_R_TLV("Digital Playback Volume", STA529_LVOL, STA529_RVOL, 0,
 148                        127, 0, out_gain_tlv),
 149        SOC_SINGLE_TLV("Master Playback Volume", STA529_MVOL, 0, 127, 1,
 150                        master_vol_tlv),
 151        SOC_ENUM("PWM Select", pwm_src),
 152};
 153
 154static int sta529_set_bias_level(struct snd_soc_codec *codec, enum
 155                snd_soc_bias_level level)
 156{
 157        struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
 158
 159        switch (level) {
 160        case SND_SOC_BIAS_ON:
 161        case SND_SOC_BIAS_PREPARE:
 162                snd_soc_update_bits(codec, STA529_FFXCFG0, POWER_CNTLMSAK,
 163                                POWER_UP);
 164                snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK,
 165                                FFX_CLK_ENB);
 166                break;
 167        case SND_SOC_BIAS_STANDBY:
 168                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
 169                        regcache_sync(sta529->regmap);
 170                snd_soc_update_bits(codec, STA529_FFXCFG0,
 171                                        POWER_CNTLMSAK, POWER_STDBY);
 172                /* Making FFX output to zero */
 173                snd_soc_update_bits(codec, STA529_FFXCFG0, FFX_MASK,
 174                                FFX_OFF);
 175                snd_soc_update_bits(codec, STA529_MISC, FFX_CLK_MSK,
 176                                FFX_CLK_DIS);
 177                break;
 178        case SND_SOC_BIAS_OFF:
 179                break;
 180        }
 181
 182        /*
 183         * store the label for powers down audio subsystem for suspend.This is
 184         * used by soc core layer
 185         */
 186        codec->dapm.bias_level = level;
 187
 188        return 0;
 189
 190}
 191
 192static int sta529_hw_params(struct snd_pcm_substream *substream,
 193                struct snd_pcm_hw_params *params,
 194                struct snd_soc_dai *dai)
 195{
 196        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 197        struct snd_soc_codec *codec = rtd->codec;
 198        int pdata, play_freq_val, record_freq_val;
 199        int bclk_to_fs_ratio;
 200
 201        switch (params_format(params)) {
 202        case SNDRV_PCM_FORMAT_S16_LE:
 203                pdata = 1;
 204                bclk_to_fs_ratio = 0;
 205                break;
 206        case SNDRV_PCM_FORMAT_S24_LE:
 207                pdata = 2;
 208                bclk_to_fs_ratio = 1;
 209                break;
 210        case SNDRV_PCM_FORMAT_S32_LE:
 211                pdata = 3;
 212                bclk_to_fs_ratio = 2;
 213                break;
 214        default:
 215                dev_err(codec->dev, "Unsupported format\n");
 216                return -EINVAL;
 217        }
 218
 219        switch (params_rate(params)) {
 220        case 8000:
 221        case 11025:
 222                play_freq_val = 0;
 223                record_freq_val = 2;
 224                break;
 225        case 16000:
 226        case 22050:
 227                play_freq_val = 1;
 228                record_freq_val = 0;
 229                break;
 230
 231        case 32000:
 232        case 44100:
 233        case 48000:
 234                play_freq_val = 2;
 235                record_freq_val = 0;
 236                break;
 237        default:
 238                dev_err(codec->dev, "Unsupported rate\n");
 239                return -EINVAL;
 240        }
 241
 242        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 243                snd_soc_update_bits(codec, STA529_S2PCFG1, PDATA_LEN_MSK,
 244                                pdata << 6);
 245                snd_soc_update_bits(codec, STA529_S2PCFG1, BCLK_TO_FS_MSK,
 246                                bclk_to_fs_ratio << 4);
 247                snd_soc_update_bits(codec, STA529_MISC, PLAY_FREQ_RANGE_MSK,
 248                                play_freq_val << 4);
 249        } else {
 250                snd_soc_update_bits(codec, STA529_P2SCFG1, PDATA_LEN_MSK,
 251                                pdata << 6);
 252                snd_soc_update_bits(codec, STA529_P2SCFG1, BCLK_TO_FS_MSK,
 253                                bclk_to_fs_ratio << 4);
 254                snd_soc_update_bits(codec, STA529_MISC, CAP_FREQ_RANGE_MSK,
 255                                record_freq_val << 2);
 256        }
 257
 258        return 0;
 259}
 260
 261static int sta529_mute(struct snd_soc_dai *dai, int mute)
 262{
 263        u8 val = 0;
 264
 265        if (mute)
 266                val |= CODEC_MUTE_VAL;
 267
 268        snd_soc_update_bits(dai->codec, STA529_FFXCFG0, AUDIO_MUTE_MSK, val);
 269
 270        return 0;
 271}
 272
 273static int sta529_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
 274{
 275        struct snd_soc_codec *codec = codec_dai->codec;
 276        u8 mode = 0;
 277
 278        /* interface format */
 279        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 280        case SND_SOC_DAIFMT_LEFT_J:
 281                mode = LEFT_J_DATA_FORMAT;
 282                break;
 283        case SND_SOC_DAIFMT_I2S:
 284                mode = I2S_DATA_FORMAT;
 285                break;
 286        case SND_SOC_DAIFMT_RIGHT_J:
 287                mode = RIGHT_J_DATA_FORMAT;
 288                break;
 289        default:
 290                return -EINVAL;
 291        }
 292
 293        snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode);
 294
 295        return 0;
 296}
 297
 298static const struct snd_soc_dai_ops sta529_dai_ops = {
 299        .hw_params      =       sta529_hw_params,
 300        .set_fmt        =       sta529_set_dai_fmt,
 301        .digital_mute   =       sta529_mute,
 302};
 303
 304static struct snd_soc_dai_driver sta529_dai = {
 305        .name = "sta529-audio",
 306        .playback = {
 307                .stream_name = "Playback",
 308                .channels_min = 2,
 309                .channels_max = 2,
 310                .rates = STA529_RATES,
 311                .formats = STA529_FORMAT,
 312        },
 313        .capture = {
 314                .stream_name = "Capture",
 315                .channels_min = 2,
 316                .channels_max = 2,
 317                .rates = STA529_RATES,
 318                .formats = STA529_FORMAT,
 319        },
 320        .ops    = &sta529_dai_ops,
 321};
 322
 323static int sta529_probe(struct snd_soc_codec *codec)
 324{
 325        struct sta529 *sta529 = snd_soc_codec_get_drvdata(codec);
 326        int ret;
 327
 328        codec->control_data = sta529->regmap;
 329        ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
 330
 331        if (ret < 0) {
 332                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 333                return ret;
 334        }
 335        sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 336
 337        return 0;
 338}
 339
 340/* power down chip */
 341static int sta529_remove(struct snd_soc_codec *codec)
 342{
 343        sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
 344
 345        return 0;
 346}
 347
 348static int sta529_suspend(struct snd_soc_codec *codec)
 349{
 350        sta529_set_bias_level(codec, SND_SOC_BIAS_OFF);
 351
 352        return 0;
 353}
 354
 355static int sta529_resume(struct snd_soc_codec *codec)
 356{
 357        sta529_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 358
 359        return 0;
 360}
 361
 362static const struct snd_soc_codec_driver sta529_codec_driver = {
 363        .probe = sta529_probe,
 364        .remove = sta529_remove,
 365        .set_bias_level = sta529_set_bias_level,
 366        .suspend = sta529_suspend,
 367        .resume = sta529_resume,
 368        .controls = sta529_snd_controls,
 369        .num_controls = ARRAY_SIZE(sta529_snd_controls),
 370};
 371
 372static const struct regmap_config sta529_regmap = {
 373        .reg_bits = 8,
 374        .val_bits = 8,
 375
 376        .max_register = STA529_MAX_REGISTER,
 377        .readable_reg = sta529_readable,
 378
 379        .cache_type = REGCACHE_RBTREE,
 380        .reg_defaults = sta529_reg_defaults,
 381        .num_reg_defaults = ARRAY_SIZE(sta529_reg_defaults),
 382};
 383
 384static int sta529_i2c_probe(struct i2c_client *i2c,
 385                            const struct i2c_device_id *id)
 386{
 387        struct sta529 *sta529;
 388        int ret;
 389
 390        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 391                return -EINVAL;
 392
 393        sta529 = devm_kzalloc(&i2c->dev, sizeof(struct sta529), GFP_KERNEL);
 394        if (sta529 == NULL) {
 395                dev_err(&i2c->dev, "Can not allocate memory\n");
 396                return -ENOMEM;
 397        }
 398
 399        sta529->regmap = devm_regmap_init_i2c(i2c, &sta529_regmap);
 400        if (IS_ERR(sta529->regmap)) {
 401                ret = PTR_ERR(sta529->regmap);
 402                dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
 403                return ret;
 404        }
 405
 406        i2c_set_clientdata(i2c, sta529);
 407
 408        ret = snd_soc_register_codec(&i2c->dev,
 409                        &sta529_codec_driver, &sta529_dai, 1);
 410        if (ret != 0)
 411                dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
 412
 413        return ret;
 414}
 415
 416static int sta529_i2c_remove(struct i2c_client *client)
 417{
 418        snd_soc_unregister_codec(&client->dev);
 419
 420        return 0;
 421}
 422
 423static const struct i2c_device_id sta529_i2c_id[] = {
 424        { "sta529", 0 },
 425        { }
 426};
 427MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
 428
 429static struct i2c_driver sta529_i2c_driver = {
 430        .driver = {
 431                .name = "sta529",
 432                .owner = THIS_MODULE,
 433        },
 434        .probe          = sta529_i2c_probe,
 435        .remove         = sta529_i2c_remove,
 436        .id_table       = sta529_i2c_id,
 437};
 438
 439module_i2c_driver(sta529_i2c_driver);
 440
 441MODULE_DESCRIPTION("ASoC STA529 codec driver");
 442MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
 443MODULE_LICENSE("GPL");
 444