root/sound/soc/codecs/rk3328_codec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rk3328_codec_reset
  2. rk3328_set_dai_fmt
  3. rk3328_analog_output
  4. rk3328_digital_mute
  5. rk3328_codec_power_on
  6. rk3328_codec_power_off
  7. rk3328_codec_open_playback
  8. rk3328_codec_close_playback
  9. rk3328_hw_params
  10. rk3328_pcm_startup
  11. rk3328_pcm_shutdown
  12. rk3328_codec_probe
  13. rk3328_codec_remove
  14. rk3328_codec_write_read_reg
  15. rk3328_codec_volatile_reg
  16. rk3328_platform_probe

   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 
  32 struct 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 
  41 static 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 
  56 static 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 
  65 static 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 
 109 static 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 
 119 static 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 
 136 static 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 
 149 static 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 
 162 static 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 
 191 static 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 
 218 static 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 
 245 static 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 
 274 static 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 
 307 static 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 
 316 static 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 
 325 static 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 
 333 static 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 
 361 static 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 
 372 static 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 
 381 static const struct snd_soc_component_driver soc_codec_rk3328 = {
 382         .probe = rk3328_codec_probe,
 383         .remove = rk3328_codec_remove,
 384 };
 385 
 386 static 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 
 408 static 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 
 418 static 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 
 431 static 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 regmap *grf;
 436         void __iomem *base;
 437         int ret = 0;
 438 
 439         rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
 440         if (!rk3328)
 441                 return -ENOMEM;
 442 
 443         grf = syscon_regmap_lookup_by_phandle(rk3328_np,
 444                                               "rockchip,grf");
 445         if (IS_ERR(grf)) {
 446                 dev_err(&pdev->dev, "missing 'rockchip,grf'\n");
 447                 return PTR_ERR(grf);
 448         }
 449         rk3328->grf = grf;
 450         /* enable i2s_acodec_en */
 451         regmap_write(grf, RK3328_GRF_SOC_CON2,
 452                      (BIT(14) << 16 | BIT(14)));
 453 
 454         ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
 455                                    &rk3328->spk_depop_time);
 456         if (ret < 0) {
 457                 dev_info(&pdev->dev, "spk_depop_time use default value.\n");
 458                 rk3328->spk_depop_time = 200;
 459         }
 460 
 461         rk3328_analog_output(rk3328, 0);
 462 
 463         rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
 464         if (IS_ERR(rk3328->mclk))
 465                 return PTR_ERR(rk3328->mclk);
 466 
 467         ret = clk_prepare_enable(rk3328->mclk);
 468         if (ret)
 469                 return ret;
 470         clk_set_rate(rk3328->mclk, INITIAL_FREQ);
 471 
 472         rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
 473         if (IS_ERR(rk3328->pclk)) {
 474                 dev_err(&pdev->dev, "can't get acodec pclk\n");
 475                 return PTR_ERR(rk3328->pclk);
 476         }
 477 
 478         ret = clk_prepare_enable(rk3328->pclk);
 479         if (ret < 0) {
 480                 dev_err(&pdev->dev, "failed to enable acodec pclk\n");
 481                 return ret;
 482         }
 483 
 484         base = devm_platform_ioremap_resource(pdev, 0);
 485         if (IS_ERR(base))
 486                 return PTR_ERR(base);
 487 
 488         rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 489                                                &rk3328_codec_regmap_config);
 490         if (IS_ERR(rk3328->regmap))
 491                 return PTR_ERR(rk3328->regmap);
 492 
 493         platform_set_drvdata(pdev, rk3328);
 494 
 495         return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
 496                                                rk3328_dai,
 497                                                ARRAY_SIZE(rk3328_dai));
 498 }
 499 
 500 static const struct of_device_id rk3328_codec_of_match[] = {
 501                 { .compatible = "rockchip,rk3328-codec", },
 502                 {},
 503 };
 504 MODULE_DEVICE_TABLE(of, rk3328_codec_of_match);
 505 
 506 static struct platform_driver rk3328_codec_driver = {
 507         .driver = {
 508                    .name = "rk3328-codec",
 509                    .of_match_table = of_match_ptr(rk3328_codec_of_match),
 510         },
 511         .probe = rk3328_platform_probe,
 512 };
 513 module_platform_driver(rk3328_codec_driver);
 514 
 515 MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
 516 MODULE_DESCRIPTION("ASoC rk3328 codec driver");
 517 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */