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