linux/sound/soc/codecs/rk3328_codec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// rk3328 ALSA SoC Audio driver
   4//
   5// Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
   6
   7#include <linux/clk.h>
   8#include <linux/delay.h>
   9#include <linux/device.h>
  10#include <linux/module.h>
  11#include <linux/of.h>
  12#include <linux/platform_device.h>
  13#include <linux/pm_runtime.h>
  14#include <linux/regmap.h>
  15#include <linux/mfd/syscon.h>
  16#include <sound/dmaengine_pcm.h>
  17#include <sound/pcm_params.h>
  18#include "rk3328_codec.h"
  19
  20/*
  21 * volume setting
  22 * 0: -39dB
  23 * 26: 0dB
  24 * 31: 6dB
  25 * Step: 1.5dB
  26 */
  27#define OUT_VOLUME      (0x18)
  28#define RK3328_GRF_SOC_CON2     (0x0408)
  29#define RK3328_GRF_SOC_CON10    (0x0428)
  30#define INITIAL_FREQ    (11289600)
  31
  32struct rk3328_codec_priv {
  33        struct regmap *regmap;
  34        struct regmap *grf;
  35        struct clk *mclk;
  36        struct clk *pclk;
  37        unsigned int sclk;
  38        int spk_depop_time; /* msec */
  39};
  40
  41static const struct reg_default rk3328_codec_reg_defaults[] = {
  42        { CODEC_RESET, 0x03 },
  43        { DAC_INIT_CTRL1, 0x00 },
  44        { DAC_INIT_CTRL2, 0x50 },
  45        { DAC_INIT_CTRL3, 0x0e },
  46        { DAC_PRECHARGE_CTRL, 0x01 },
  47        { DAC_PWR_CTRL, 0x00 },
  48        { DAC_CLK_CTRL, 0x00 },
  49        { HPMIX_CTRL, 0x00 },
  50        { HPOUT_CTRL, 0x00 },
  51        { HPOUTL_GAIN_CTRL, 0x00 },
  52        { HPOUTR_GAIN_CTRL, 0x00 },
  53        { HPOUT_POP_CTRL, 0x11 },
  54};
  55
  56static int rk3328_codec_reset(struct rk3328_codec_priv *rk3328)
  57{
  58        regmap_write(rk3328->regmap, CODEC_RESET, 0x00);
  59        mdelay(10);
  60        regmap_write(rk3328->regmap, CODEC_RESET, 0x03);
  61
  62        return 0;
  63}
  64
  65static int rk3328_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  66{
  67        struct rk3328_codec_priv *rk3328 =
  68                snd_soc_component_get_drvdata(dai->component);
  69        unsigned int val;
  70
  71        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  72        case SND_SOC_DAIFMT_CBS_CFS:
  73                val = PIN_DIRECTION_IN | DAC_I2S_MODE_SLAVE;
  74                break;
  75        case SND_SOC_DAIFMT_CBM_CFM:
  76                val = PIN_DIRECTION_OUT | DAC_I2S_MODE_MASTER;
  77                break;
  78        default:
  79                return -EINVAL;
  80        }
  81
  82        regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL1,
  83                           PIN_DIRECTION_MASK | DAC_I2S_MODE_MASK, val);
  84
  85        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  86        case SND_SOC_DAIFMT_DSP_A:
  87        case SND_SOC_DAIFMT_DSP_B:
  88                val = DAC_MODE_PCM;
  89                break;
  90        case SND_SOC_DAIFMT_I2S:
  91                val = DAC_MODE_I2S;
  92                break;
  93        case SND_SOC_DAIFMT_RIGHT_J:
  94                val = DAC_MODE_RJM;
  95                break;
  96        case SND_SOC_DAIFMT_LEFT_J:
  97                val = DAC_MODE_LJM;
  98                break;
  99        default:
 100                return -EINVAL;
 101        }
 102
 103        regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2,
 104                           DAC_MODE_MASK, val);
 105
 106        return 0;
 107}
 108
 109static void rk3328_analog_output(struct rk3328_codec_priv *rk3328, int mute)
 110{
 111        unsigned int val = BIT(17);
 112
 113        if (mute)
 114                val |= BIT(1);
 115
 116        regmap_write(rk3328->grf, RK3328_GRF_SOC_CON10, val);
 117}
 118
 119static int rk3328_digital_mute(struct snd_soc_dai *dai, int mute)
 120{
 121        struct rk3328_codec_priv *rk3328 =
 122                snd_soc_component_get_drvdata(dai->component);
 123        unsigned int val;
 124
 125        if (mute)
 126                val = HPOUTL_MUTE | HPOUTR_MUTE;
 127        else
 128                val = HPOUTL_UNMUTE | HPOUTR_UNMUTE;
 129
 130        regmap_update_bits(rk3328->regmap, HPOUT_CTRL,
 131                           HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK, val);
 132
 133        return 0;
 134}
 135
 136static int rk3328_codec_power_on(struct rk3328_codec_priv *rk3328, int wait_ms)
 137{
 138        regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 139                           DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_PRECHARGE);
 140        mdelay(10);
 141        regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 142                           DAC_CHARGE_CURRENT_ALL_MASK,
 143                           DAC_CHARGE_CURRENT_ALL_ON);
 144        mdelay(wait_ms);
 145
 146        return 0;
 147}
 148
 149static int rk3328_codec_power_off(struct rk3328_codec_priv *rk3328, int wait_ms)
 150{
 151        regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 152                           DAC_CHARGE_XCHARGE_MASK, DAC_CHARGE_DISCHARGE);
 153        mdelay(10);
 154        regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 155                           DAC_CHARGE_CURRENT_ALL_MASK,
 156                           DAC_CHARGE_CURRENT_ALL_ON);
 157        mdelay(wait_ms);
 158
 159        return 0;
 160}
 161
 162static const struct rk3328_reg_msk_val playback_open_list[] = {
 163        { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_ON },
 164        { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
 165          DACL_PATH_REFV_ON | DACR_PATH_REFV_ON },
 166        { DAC_PWR_CTRL, HPOUTL_ZERO_CROSSING_MASK | HPOUTR_ZERO_CROSSING_MASK,
 167          HPOUTL_ZERO_CROSSING_ON | HPOUTR_ZERO_CROSSING_ON },
 168        { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
 169          HPOUTR_POP_WORK | HPOUTL_POP_WORK },
 170        { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_EN | HPMIXR_EN },
 171        { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
 172          HPMIXL_INIT_EN | HPMIXR_INIT_EN },
 173        { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_EN | HPOUTR_EN },
 174        { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
 175          HPOUTL_INIT_EN | HPOUTR_INIT_EN },
 176        { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
 177          DACL_REFV_ON | DACR_REFV_ON },
 178        { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
 179          DACL_CLK_ON | DACR_CLK_ON },
 180        { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_ON | DACR_ON },
 181        { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
 182          DACL_INIT_ON | DACR_INIT_ON },
 183        { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
 184          DACL_SELECT | DACR_SELECT },
 185        { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
 186          HPMIXL_INIT2_EN | HPMIXR_INIT2_EN },
 187        { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
 188          HPOUTL_UNMUTE | HPOUTR_UNMUTE },
 189};
 190
 191static int rk3328_codec_open_playback(struct rk3328_codec_priv *rk3328)
 192{
 193        int i;
 194
 195        regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 196                           DAC_CHARGE_CURRENT_ALL_MASK,
 197                           DAC_CHARGE_CURRENT_I);
 198
 199        for (i = 0; i < ARRAY_SIZE(playback_open_list); i++) {
 200                regmap_update_bits(rk3328->regmap,
 201                                   playback_open_list[i].reg,
 202                                   playback_open_list[i].msk,
 203                                   playback_open_list[i].val);
 204                mdelay(1);
 205        }
 206
 207        msleep(rk3328->spk_depop_time);
 208        rk3328_analog_output(rk3328, 1);
 209
 210        regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
 211                           HPOUTL_GAIN_MASK, OUT_VOLUME);
 212        regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
 213                           HPOUTR_GAIN_MASK, OUT_VOLUME);
 214
 215        return 0;
 216}
 217
 218static const struct rk3328_reg_msk_val playback_close_list[] = {
 219        { HPMIX_CTRL, HPMIXL_INIT2_MASK | HPMIXR_INIT2_MASK,
 220          HPMIXL_INIT2_DIS | HPMIXR_INIT2_DIS },
 221        { DAC_SELECT, DACL_SELECT_MASK | DACR_SELECT_MASK,
 222          DACL_UNSELECT | DACR_UNSELECT },
 223        { HPOUT_CTRL, HPOUTL_MUTE_MASK | HPOUTR_MUTE_MASK,
 224          HPOUTL_MUTE | HPOUTR_MUTE },
 225        { HPOUT_CTRL, HPOUTL_INIT_MASK | HPOUTR_INIT_MASK,
 226          HPOUTL_INIT_DIS | HPOUTR_INIT_DIS },
 227        { HPOUT_CTRL, HPOUTL_MASK | HPOUTR_MASK, HPOUTL_DIS | HPOUTR_DIS },
 228        { HPMIX_CTRL, HPMIXL_MASK | HPMIXR_MASK, HPMIXL_DIS | HPMIXR_DIS },
 229        { DAC_CLK_CTRL, DACL_MASK | DACR_MASK, DACL_OFF | DACR_OFF },
 230        { DAC_CLK_CTRL, DACL_CLK_MASK | DACR_CLK_MASK,
 231          DACL_CLK_OFF | DACR_CLK_OFF },
 232        { DAC_CLK_CTRL, DACL_REFV_MASK | DACR_REFV_MASK,
 233          DACL_REFV_OFF | DACR_REFV_OFF },
 234        { HPOUT_POP_CTRL, HPOUTR_POP_MASK | HPOUTL_POP_MASK,
 235          HPOUTR_POP_XCHARGE | HPOUTL_POP_XCHARGE },
 236        { DAC_PWR_CTRL, DACL_PATH_REFV_MASK | DACR_PATH_REFV_MASK,
 237          DACL_PATH_REFV_OFF | DACR_PATH_REFV_OFF },
 238        { DAC_PWR_CTRL, DAC_PWR_MASK, DAC_PWR_OFF },
 239        { HPMIX_CTRL, HPMIXL_INIT_MASK | HPMIXR_INIT_MASK,
 240          HPMIXL_INIT_DIS | HPMIXR_INIT_DIS },
 241        { DAC_CLK_CTRL, DACL_INIT_MASK | DACR_INIT_MASK,
 242          DACL_INIT_OFF | DACR_INIT_OFF },
 243};
 244
 245static int rk3328_codec_close_playback(struct rk3328_codec_priv *rk3328)
 246{
 247        size_t i;
 248
 249        rk3328_analog_output(rk3328, 0);
 250
 251        regmap_update_bits(rk3328->regmap, HPOUTL_GAIN_CTRL,
 252                           HPOUTL_GAIN_MASK, 0);
 253        regmap_update_bits(rk3328->regmap, HPOUTR_GAIN_CTRL,
 254                           HPOUTR_GAIN_MASK, 0);
 255
 256        for (i = 0; i < ARRAY_SIZE(playback_close_list); i++) {
 257                regmap_update_bits(rk3328->regmap,
 258                                   playback_close_list[i].reg,
 259                                   playback_close_list[i].msk,
 260                                   playback_close_list[i].val);
 261                mdelay(1);
 262        }
 263
 264        /* Workaround for silence when changed Fs 48 -> 44.1kHz */
 265        rk3328_codec_reset(rk3328);
 266
 267        regmap_update_bits(rk3328->regmap, DAC_PRECHARGE_CTRL,
 268                           DAC_CHARGE_CURRENT_ALL_MASK,
 269                           DAC_CHARGE_CURRENT_ALL_ON);
 270
 271        return 0;
 272}
 273
 274static int rk3328_hw_params(struct snd_pcm_substream *substream,
 275                            struct snd_pcm_hw_params *params,
 276                            struct snd_soc_dai *dai)
 277{
 278        struct rk3328_codec_priv *rk3328 =
 279                snd_soc_component_get_drvdata(dai->component);
 280        unsigned int val = 0;
 281
 282        switch (params_format(params)) {
 283        case SNDRV_PCM_FORMAT_S16_LE:
 284                val = DAC_VDL_16BITS;
 285                break;
 286        case SNDRV_PCM_FORMAT_S20_3LE:
 287                val = DAC_VDL_20BITS;
 288                break;
 289        case SNDRV_PCM_FORMAT_S24_LE:
 290                val = DAC_VDL_24BITS;
 291                break;
 292        case SNDRV_PCM_FORMAT_S32_LE:
 293                val = DAC_VDL_32BITS;
 294                break;
 295        default:
 296                return -EINVAL;
 297        }
 298        regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL2, DAC_VDL_MASK, val);
 299
 300        val = DAC_WL_32BITS | DAC_RST_DIS;
 301        regmap_update_bits(rk3328->regmap, DAC_INIT_CTRL3,
 302                           DAC_WL_MASK | DAC_RST_MASK, val);
 303
 304        return 0;
 305}
 306
 307static int rk3328_pcm_startup(struct snd_pcm_substream *substream,
 308                              struct snd_soc_dai *dai)
 309{
 310        struct rk3328_codec_priv *rk3328 =
 311                snd_soc_component_get_drvdata(dai->component);
 312
 313        return rk3328_codec_open_playback(rk3328);
 314}
 315
 316static void rk3328_pcm_shutdown(struct snd_pcm_substream *substream,
 317                                struct snd_soc_dai *dai)
 318{
 319        struct rk3328_codec_priv *rk3328 =
 320                snd_soc_component_get_drvdata(dai->component);
 321
 322        rk3328_codec_close_playback(rk3328);
 323}
 324
 325static const struct snd_soc_dai_ops rk3328_dai_ops = {
 326        .hw_params = rk3328_hw_params,
 327        .set_fmt = rk3328_set_dai_fmt,
 328        .digital_mute = rk3328_digital_mute,
 329        .startup = rk3328_pcm_startup,
 330        .shutdown = rk3328_pcm_shutdown,
 331};
 332
 333static struct snd_soc_dai_driver rk3328_dai[] = {
 334        {
 335                .name = "rk3328-hifi",
 336                .id = RK3328_HIFI,
 337                .playback = {
 338                        .stream_name = "HIFI Playback",
 339                        .channels_min = 1,
 340                        .channels_max = 2,
 341                        .rates = SNDRV_PCM_RATE_8000_96000,
 342                        .formats = (SNDRV_PCM_FMTBIT_S16_LE |
 343                                    SNDRV_PCM_FMTBIT_S20_3LE |
 344                                    SNDRV_PCM_FMTBIT_S24_LE |
 345                                    SNDRV_PCM_FMTBIT_S32_LE),
 346                },
 347                .capture = {
 348                        .stream_name = "HIFI Capture",
 349                        .channels_min = 2,
 350                        .channels_max = 8,
 351                        .rates = SNDRV_PCM_RATE_8000_96000,
 352                        .formats = (SNDRV_PCM_FMTBIT_S16_LE |
 353                                    SNDRV_PCM_FMTBIT_S20_3LE |
 354                                    SNDRV_PCM_FMTBIT_S24_LE |
 355                                    SNDRV_PCM_FMTBIT_S32_LE),
 356                },
 357                .ops = &rk3328_dai_ops,
 358        },
 359};
 360
 361static int rk3328_codec_probe(struct snd_soc_component *component)
 362{
 363        struct rk3328_codec_priv *rk3328 =
 364                snd_soc_component_get_drvdata(component);
 365
 366        rk3328_codec_reset(rk3328);
 367        rk3328_codec_power_on(rk3328, 0);
 368
 369        return 0;
 370}
 371
 372static void rk3328_codec_remove(struct snd_soc_component *component)
 373{
 374        struct rk3328_codec_priv *rk3328 =
 375                snd_soc_component_get_drvdata(component);
 376
 377        rk3328_codec_close_playback(rk3328);
 378        rk3328_codec_power_off(rk3328, 0);
 379}
 380
 381static const struct snd_soc_component_driver soc_codec_rk3328 = {
 382        .probe = rk3328_codec_probe,
 383        .remove = rk3328_codec_remove,
 384};
 385
 386static bool rk3328_codec_write_read_reg(struct device *dev, unsigned int reg)
 387{
 388        switch (reg) {
 389        case CODEC_RESET:
 390        case DAC_INIT_CTRL1:
 391        case DAC_INIT_CTRL2:
 392        case DAC_INIT_CTRL3:
 393        case DAC_PRECHARGE_CTRL:
 394        case DAC_PWR_CTRL:
 395        case DAC_CLK_CTRL:
 396        case HPMIX_CTRL:
 397        case DAC_SELECT:
 398        case HPOUT_CTRL:
 399        case HPOUTL_GAIN_CTRL:
 400        case HPOUTR_GAIN_CTRL:
 401        case HPOUT_POP_CTRL:
 402                return true;
 403        default:
 404                return false;
 405        }
 406}
 407
 408static bool rk3328_codec_volatile_reg(struct device *dev, unsigned int reg)
 409{
 410        switch (reg) {
 411        case CODEC_RESET:
 412                return true;
 413        default:
 414                return false;
 415        }
 416}
 417
 418static const struct regmap_config rk3328_codec_regmap_config = {
 419        .reg_bits = 32,
 420        .reg_stride = 4,
 421        .val_bits = 32,
 422        .max_register = HPOUT_POP_CTRL,
 423        .writeable_reg = rk3328_codec_write_read_reg,
 424        .readable_reg = rk3328_codec_write_read_reg,
 425        .volatile_reg = rk3328_codec_volatile_reg,
 426        .reg_defaults = rk3328_codec_reg_defaults,
 427        .num_reg_defaults = ARRAY_SIZE(rk3328_codec_reg_defaults),
 428        .cache_type = REGCACHE_FLAT,
 429};
 430
 431static int rk3328_platform_probe(struct platform_device *pdev)
 432{
 433        struct device_node *rk3328_np = pdev->dev.of_node;
 434        struct rk3328_codec_priv *rk3328;
 435        struct resource *res;
 436        struct regmap *grf;
 437        void __iomem *base;
 438        int ret = 0;
 439
 440        rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
 441        if (!rk3328)
 442                return -ENOMEM;
 443
 444        grf = syscon_regmap_lookup_by_phandle(rk3328_np,
 445                                              "rockchip,grf");
 446        if (IS_ERR(grf)) {
 447                dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
 448                return PTR_ERR(grf);
 449        }
 450        rk3328->grf = grf;
 451        /* enable i2s_acodec_en */
 452        regmap_write(grf, RK3328_GRF_SOC_CON2,
 453                     (BIT(14) << 16 | BIT(14)));
 454
 455        ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
 456                                   &rk3328->spk_depop_time);
 457        if (ret < 0) {
 458                dev_info(&pdev->dev, "spk_depop_time use default value.\n");
 459                rk3328->spk_depop_time = 200;
 460        }
 461
 462        rk3328_analog_output(rk3328, 0);
 463
 464        rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
 465        if (IS_ERR(rk3328->mclk))
 466                return PTR_ERR(rk3328->mclk);
 467
 468        ret = clk_prepare_enable(rk3328->mclk);
 469        if (ret)
 470                return ret;
 471        clk_set_rate(rk3328->mclk, INITIAL_FREQ);
 472
 473        rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
 474        if (IS_ERR(rk3328->pclk)) {
 475                dev_err(&pdev->dev, "can't get acodec pclk\n");
 476                return PTR_ERR(rk3328->pclk);
 477        }
 478
 479        ret = clk_prepare_enable(rk3328->pclk);
 480        if (ret < 0) {
 481                dev_err(&pdev->dev, "failed to enable acodec pclk\n");
 482                return ret;
 483        }
 484
 485        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 486        base = devm_ioremap_resource(&pdev->dev, res);
 487        if (IS_ERR(base))
 488                return PTR_ERR(base);
 489
 490        rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 491                                               &rk3328_codec_regmap_config);
 492        if (IS_ERR(rk3328->regmap))
 493                return PTR_ERR(rk3328->regmap);
 494
 495        platform_set_drvdata(pdev, rk3328);
 496
 497        return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
 498                                               rk3328_dai,
 499                                               ARRAY_SIZE(rk3328_dai));
 500}
 501
 502static const struct of_device_id rk3328_codec_of_match[] = {
 503                { .compatible = "rockchip,rk3328-codec", },
 504                {},
 505};
 506MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
 507
 508static struct platform_driver rk3328_codec_driver = {
 509        .driver = {
 510                   .name = "rk3328-codec",
 511                   .of_match_table = of_match_ptr(rk3328_codec_of_match),
 512        },
 513        .probe = rk3328_platform_probe,
 514};
 515module_platform_driver(rk3328_codec_driver);
 516
 517MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
 518MODULE_DESCRIPTION("ASoC rk3328 codec driver");
 519MODULE_LICENSE("GPL v2");
 520