linux/sound/soc/sunxi/sun50i-codec-analog.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * This driver supports the analog controls for the internal codec
   4 * found in Allwinner's A64 SoC.
   5 *
   6 * Copyright (C) 2016 Chen-Yu Tsai <wens@csie.org>
   7 * Copyright (C) 2017 Marcus Cooper <codekipper@gmail.com>
   8 * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com>
   9 *
  10 * Based on sun8i-codec-analog.c
  11 *
  12 */
  13
  14#include <linux/io.h>
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/of.h>
  18#include <linux/of_device.h>
  19#include <linux/platform_device.h>
  20#include <linux/regmap.h>
  21
  22#include <sound/soc.h>
  23#include <sound/soc-dapm.h>
  24#include <sound/tlv.h>
  25
  26#include "sun8i-adda-pr-regmap.h"
  27
  28/* Codec analog control register offsets and bit fields */
  29#define SUN50I_ADDA_HP_CTRL             0x00
  30#define SUN50I_ADDA_HP_CTRL_PA_CLK_GATE         7
  31#define SUN50I_ADDA_HP_CTRL_HPPA_EN             6
  32#define SUN50I_ADDA_HP_CTRL_HPVOL               0
  33
  34#define SUN50I_ADDA_OL_MIX_CTRL         0x01
  35#define SUN50I_ADDA_OL_MIX_CTRL_MIC1            6
  36#define SUN50I_ADDA_OL_MIX_CTRL_MIC2            5
  37#define SUN50I_ADDA_OL_MIX_CTRL_PHONE           4
  38#define SUN50I_ADDA_OL_MIX_CTRL_PHONEN          3
  39#define SUN50I_ADDA_OL_MIX_CTRL_LINEINL         2
  40#define SUN50I_ADDA_OL_MIX_CTRL_DACL            1
  41#define SUN50I_ADDA_OL_MIX_CTRL_DACR            0
  42
  43#define SUN50I_ADDA_OR_MIX_CTRL         0x02
  44#define SUN50I_ADDA_OR_MIX_CTRL_MIC1            6
  45#define SUN50I_ADDA_OR_MIX_CTRL_MIC2            5
  46#define SUN50I_ADDA_OR_MIX_CTRL_PHONE           4
  47#define SUN50I_ADDA_OR_MIX_CTRL_PHONEP          3
  48#define SUN50I_ADDA_OR_MIX_CTRL_LINEINR         2
  49#define SUN50I_ADDA_OR_MIX_CTRL_DACR            1
  50#define SUN50I_ADDA_OR_MIX_CTRL_DACL            0
  51
  52#define SUN50I_ADDA_LINEOUT_CTRL0       0x05
  53#define SUN50I_ADDA_LINEOUT_CTRL0_LEN           7
  54#define SUN50I_ADDA_LINEOUT_CTRL0_REN           6
  55#define SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL      5
  56#define SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL      4
  57
  58#define SUN50I_ADDA_LINEOUT_CTRL1       0x06
  59#define SUN50I_ADDA_LINEOUT_CTRL1_VOL           0
  60
  61#define SUN50I_ADDA_MIC1_CTRL           0x07
  62#define SUN50I_ADDA_MIC1_CTRL_MIC1G             4
  63#define SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN         3
  64#define SUN50I_ADDA_MIC1_CTRL_MIC1BOOST         0
  65
  66#define SUN50I_ADDA_MIC2_CTRL           0x08
  67#define SUN50I_ADDA_MIC2_CTRL_MIC2G             4
  68#define SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN         3
  69#define SUN50I_ADDA_MIC2_CTRL_MIC2BOOST         0
  70
  71#define SUN50I_ADDA_LINEIN_CTRL         0x09
  72#define SUN50I_ADDA_LINEIN_CTRL_LINEING         0
  73
  74#define SUN50I_ADDA_MIX_DAC_CTRL        0x0a
  75#define SUN50I_ADDA_MIX_DAC_CTRL_DACAREN        7
  76#define SUN50I_ADDA_MIX_DAC_CTRL_DACALEN        6
  77#define SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN         5
  78#define SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN         4
  79#define SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE      3
  80#define SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE      2
  81#define SUN50I_ADDA_MIX_DAC_CTRL_RHPIS          1
  82#define SUN50I_ADDA_MIX_DAC_CTRL_LHPIS          0
  83
  84#define SUN50I_ADDA_L_ADCMIX_SRC        0x0b
  85#define SUN50I_ADDA_L_ADCMIX_SRC_MIC1           6
  86#define SUN50I_ADDA_L_ADCMIX_SRC_MIC2           5
  87#define SUN50I_ADDA_L_ADCMIX_SRC_PHONE          4
  88#define SUN50I_ADDA_L_ADCMIX_SRC_PHONEN         3
  89#define SUN50I_ADDA_L_ADCMIX_SRC_LINEINL        2
  90#define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL         1
  91#define SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR         0
  92
  93#define SUN50I_ADDA_R_ADCMIX_SRC        0x0c
  94#define SUN50I_ADDA_R_ADCMIX_SRC_MIC1           6
  95#define SUN50I_ADDA_R_ADCMIX_SRC_MIC2           5
  96#define SUN50I_ADDA_R_ADCMIX_SRC_PHONE          4
  97#define SUN50I_ADDA_R_ADCMIX_SRC_PHONEP         3
  98#define SUN50I_ADDA_R_ADCMIX_SRC_LINEINR        2
  99#define SUN50I_ADDA_R_ADCMIX_SRC_OMIXR          1
 100#define SUN50I_ADDA_R_ADCMIX_SRC_OMIXL          0
 101
 102#define SUN50I_ADDA_ADC_CTRL            0x0d
 103#define SUN50I_ADDA_ADC_CTRL_ADCREN             7
 104#define SUN50I_ADDA_ADC_CTRL_ADCLEN             6
 105#define SUN50I_ADDA_ADC_CTRL_ADCG               0
 106
 107#define SUN50I_ADDA_HS_MBIAS_CTRL       0x0e
 108#define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN    7
 109
 110#define SUN50I_ADDA_JACK_MIC_CTRL       0x1d
 111#define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN    5
 112
 113/* mixer controls */
 114static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = {
 115        SOC_DAPM_DOUBLE_R("DAC Playback Switch",
 116                          SUN50I_ADDA_OL_MIX_CTRL,
 117                          SUN50I_ADDA_OR_MIX_CTRL,
 118                          SUN50I_ADDA_OL_MIX_CTRL_DACL, 1, 0),
 119        SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
 120                          SUN50I_ADDA_OL_MIX_CTRL,
 121                          SUN50I_ADDA_OR_MIX_CTRL,
 122                          SUN50I_ADDA_OL_MIX_CTRL_DACR, 1, 0),
 123        SOC_DAPM_DOUBLE_R("Line In Playback Switch",
 124                          SUN50I_ADDA_OL_MIX_CTRL,
 125                          SUN50I_ADDA_OR_MIX_CTRL,
 126                          SUN50I_ADDA_OL_MIX_CTRL_LINEINL, 1, 0),
 127        SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
 128                          SUN50I_ADDA_OL_MIX_CTRL,
 129                          SUN50I_ADDA_OR_MIX_CTRL,
 130                          SUN50I_ADDA_OL_MIX_CTRL_MIC1, 1, 0),
 131        SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
 132                          SUN50I_ADDA_OL_MIX_CTRL,
 133                          SUN50I_ADDA_OR_MIX_CTRL,
 134                          SUN50I_ADDA_OL_MIX_CTRL_MIC2, 1, 0),
 135};
 136
 137/* ADC mixer controls */
 138static const struct snd_kcontrol_new sun50i_codec_adc_mixer_controls[] = {
 139        SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
 140                          SUN50I_ADDA_L_ADCMIX_SRC,
 141                          SUN50I_ADDA_R_ADCMIX_SRC,
 142                          SUN50I_ADDA_L_ADCMIX_SRC_OMIXRL, 1, 0),
 143        SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
 144                          SUN50I_ADDA_L_ADCMIX_SRC,
 145                          SUN50I_ADDA_R_ADCMIX_SRC,
 146                          SUN50I_ADDA_L_ADCMIX_SRC_OMIXRR, 1, 0),
 147        SOC_DAPM_DOUBLE_R("Line In Capture Switch",
 148                          SUN50I_ADDA_L_ADCMIX_SRC,
 149                          SUN50I_ADDA_R_ADCMIX_SRC,
 150                          SUN50I_ADDA_L_ADCMIX_SRC_LINEINL, 1, 0),
 151        SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
 152                          SUN50I_ADDA_L_ADCMIX_SRC,
 153                          SUN50I_ADDA_R_ADCMIX_SRC,
 154                          SUN50I_ADDA_L_ADCMIX_SRC_MIC1, 1, 0),
 155        SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
 156                          SUN50I_ADDA_L_ADCMIX_SRC,
 157                          SUN50I_ADDA_R_ADCMIX_SRC,
 158                          SUN50I_ADDA_L_ADCMIX_SRC_MIC2, 1, 0),
 159};
 160
 161static const DECLARE_TLV_DB_SCALE(sun50i_codec_out_mixer_pregain_scale,
 162                                  -450, 150, 0);
 163static const DECLARE_TLV_DB_RANGE(sun50i_codec_mic_gain_scale,
 164        0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
 165        1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
 166);
 167
 168static const DECLARE_TLV_DB_SCALE(sun50i_codec_hp_vol_scale, -6300, 100, 1);
 169
 170static const DECLARE_TLV_DB_RANGE(sun50i_codec_lineout_vol_scale,
 171        0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
 172        2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
 173);
 174
 175
 176/* volume / mute controls */
 177static const struct snd_kcontrol_new sun50i_a64_codec_controls[] = {
 178        SOC_SINGLE_TLV("Headphone Playback Volume",
 179                       SUN50I_ADDA_HP_CTRL,
 180                       SUN50I_ADDA_HP_CTRL_HPVOL, 0x3f, 0,
 181                       sun50i_codec_hp_vol_scale),
 182
 183        SOC_DOUBLE("Headphone Playback Switch",
 184                   SUN50I_ADDA_MIX_DAC_CTRL,
 185                   SUN50I_ADDA_MIX_DAC_CTRL_LHPPAMUTE,
 186                   SUN50I_ADDA_MIX_DAC_CTRL_RHPPAMUTE, 1, 0),
 187
 188        /* Mixer pre-gain */
 189        SOC_SINGLE_TLV("Mic1 Playback Volume", SUN50I_ADDA_MIC1_CTRL,
 190                       SUN50I_ADDA_MIC1_CTRL_MIC1G,
 191                       0x7, 0, sun50i_codec_out_mixer_pregain_scale),
 192
 193        /* Microphone Amp boost gain */
 194        SOC_SINGLE_TLV("Mic1 Boost Volume", SUN50I_ADDA_MIC1_CTRL,
 195                       SUN50I_ADDA_MIC1_CTRL_MIC1BOOST, 0x7, 0,
 196                       sun50i_codec_mic_gain_scale),
 197
 198        /* Mixer pre-gain */
 199        SOC_SINGLE_TLV("Mic2 Playback Volume",
 200                       SUN50I_ADDA_MIC2_CTRL, SUN50I_ADDA_MIC2_CTRL_MIC2G,
 201                       0x7, 0, sun50i_codec_out_mixer_pregain_scale),
 202
 203        /* Microphone Amp boost gain */
 204        SOC_SINGLE_TLV("Mic2 Boost Volume", SUN50I_ADDA_MIC2_CTRL,
 205                       SUN50I_ADDA_MIC2_CTRL_MIC2BOOST, 0x7, 0,
 206                       sun50i_codec_mic_gain_scale),
 207
 208        /* ADC */
 209        SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN50I_ADDA_ADC_CTRL,
 210                       SUN50I_ADDA_ADC_CTRL_ADCG, 0x7, 0,
 211                       sun50i_codec_out_mixer_pregain_scale),
 212
 213        /* Mixer pre-gain */
 214        SOC_SINGLE_TLV("Line In Playback Volume", SUN50I_ADDA_LINEIN_CTRL,
 215                       SUN50I_ADDA_LINEIN_CTRL_LINEING,
 216                       0x7, 0, sun50i_codec_out_mixer_pregain_scale),
 217
 218        SOC_SINGLE_TLV("Line Out Playback Volume",
 219                       SUN50I_ADDA_LINEOUT_CTRL1,
 220                       SUN50I_ADDA_LINEOUT_CTRL1_VOL, 0x1f, 0,
 221                       sun50i_codec_lineout_vol_scale),
 222
 223        SOC_DOUBLE("Line Out Playback Switch",
 224                   SUN50I_ADDA_LINEOUT_CTRL0,
 225                   SUN50I_ADDA_LINEOUT_CTRL0_LEN,
 226                   SUN50I_ADDA_LINEOUT_CTRL0_REN, 1, 0),
 227
 228};
 229
 230static const char * const sun50i_codec_hp_src_enum_text[] = {
 231        "DAC", "Mixer",
 232};
 233
 234static SOC_ENUM_DOUBLE_DECL(sun50i_codec_hp_src_enum,
 235                            SUN50I_ADDA_MIX_DAC_CTRL,
 236                            SUN50I_ADDA_MIX_DAC_CTRL_LHPIS,
 237                            SUN50I_ADDA_MIX_DAC_CTRL_RHPIS,
 238                            sun50i_codec_hp_src_enum_text);
 239
 240static const struct snd_kcontrol_new sun50i_codec_hp_src[] = {
 241        SOC_DAPM_ENUM("Headphone Source Playback Route",
 242                      sun50i_codec_hp_src_enum),
 243};
 244
 245static const char * const sun50i_codec_lineout_src_enum_text[] = {
 246        "Stereo", "Mono Differential",
 247};
 248
 249static SOC_ENUM_DOUBLE_DECL(sun50i_codec_lineout_src_enum,
 250                            SUN50I_ADDA_LINEOUT_CTRL0,
 251                            SUN50I_ADDA_LINEOUT_CTRL0_LSRC_SEL,
 252                            SUN50I_ADDA_LINEOUT_CTRL0_RSRC_SEL,
 253                            sun50i_codec_lineout_src_enum_text);
 254
 255static const struct snd_kcontrol_new sun50i_codec_lineout_src[] = {
 256        SOC_DAPM_ENUM("Line Out Source Playback Route",
 257                      sun50i_codec_lineout_src_enum),
 258};
 259
 260static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = {
 261        /* DAC */
 262        SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
 263                         SUN50I_ADDA_MIX_DAC_CTRL_DACALEN, 0),
 264        SND_SOC_DAPM_DAC("Right DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL,
 265                         SUN50I_ADDA_MIX_DAC_CTRL_DACAREN, 0),
 266        /* ADC */
 267        SND_SOC_DAPM_ADC("Left ADC", NULL, SUN50I_ADDA_ADC_CTRL,
 268                         SUN50I_ADDA_ADC_CTRL_ADCLEN, 0),
 269        SND_SOC_DAPM_ADC("Right ADC", NULL, SUN50I_ADDA_ADC_CTRL,
 270                         SUN50I_ADDA_ADC_CTRL_ADCREN, 0),
 271        /*
 272         * Due to this component and the codec belonging to separate DAPM
 273         * contexts, we need to manually link the above widgets to their
 274         * stream widgets at the card level.
 275         */
 276
 277        SND_SOC_DAPM_REGULATOR_SUPPLY("cpvdd", 0, 0),
 278        SND_SOC_DAPM_MUX("Headphone Source Playback Route",
 279                         SND_SOC_NOPM, 0, 0, sun50i_codec_hp_src),
 280        SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN50I_ADDA_HP_CTRL,
 281                             SUN50I_ADDA_HP_CTRL_HPPA_EN, 0, NULL, 0),
 282        SND_SOC_DAPM_OUTPUT("HP"),
 283
 284        SND_SOC_DAPM_MUX("Line Out Source Playback Route",
 285                         SND_SOC_NOPM, 0, 0, sun50i_codec_lineout_src),
 286        SND_SOC_DAPM_OUTPUT("LINEOUT"),
 287
 288        /* Microphone inputs */
 289        SND_SOC_DAPM_INPUT("MIC1"),
 290
 291        /* Microphone Bias */
 292        SND_SOC_DAPM_SUPPLY("MBIAS", SUN50I_ADDA_HS_MBIAS_CTRL,
 293                            SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN,
 294                            0, NULL, 0),
 295
 296        /* Mic input path */
 297        SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN50I_ADDA_MIC1_CTRL,
 298                         SUN50I_ADDA_MIC1_CTRL_MIC1AMPEN, 0, NULL, 0),
 299
 300        /* Microphone input */
 301        SND_SOC_DAPM_INPUT("MIC2"),
 302
 303        /* Microphone Bias */
 304        SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL,
 305                            SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN,
 306                            0, NULL, 0),
 307
 308        /* Mic input path */
 309        SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL,
 310                         SUN50I_ADDA_MIC2_CTRL_MIC2AMPEN, 0, NULL, 0),
 311
 312        /* Line input */
 313        SND_SOC_DAPM_INPUT("LINEIN"),
 314
 315        /* Mixers */
 316        SND_SOC_DAPM_MIXER("Left Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
 317                           SUN50I_ADDA_MIX_DAC_CTRL_LMIXEN, 0,
 318                           sun50i_a64_codec_mixer_controls,
 319                           ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
 320        SND_SOC_DAPM_MIXER("Right Mixer", SUN50I_ADDA_MIX_DAC_CTRL,
 321                           SUN50I_ADDA_MIX_DAC_CTRL_RMIXEN, 0,
 322                           sun50i_a64_codec_mixer_controls,
 323                           ARRAY_SIZE(sun50i_a64_codec_mixer_controls)),
 324        SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN50I_ADDA_ADC_CTRL,
 325                           SUN50I_ADDA_ADC_CTRL_ADCLEN, 0,
 326                           sun50i_codec_adc_mixer_controls,
 327                           ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
 328        SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN50I_ADDA_ADC_CTRL,
 329                           SUN50I_ADDA_ADC_CTRL_ADCREN, 0,
 330                           sun50i_codec_adc_mixer_controls,
 331                           ARRAY_SIZE(sun50i_codec_adc_mixer_controls)),
 332};
 333
 334static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = {
 335        /* Left Mixer Routes */
 336        { "Left Mixer", "DAC Playback Switch", "Left DAC" },
 337        { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
 338        { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
 339
 340        /* Right Mixer Routes */
 341        { "Right Mixer", "DAC Playback Switch", "Right DAC" },
 342        { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
 343        { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
 344
 345        /* Left ADC Mixer Routes */
 346        { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
 347        { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
 348        { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
 349
 350        /* Right ADC Mixer Routes */
 351        { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
 352        { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
 353        { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
 354
 355        /* ADC Routes */
 356        { "Left ADC", NULL, "Left ADC Mixer" },
 357        { "Right ADC", NULL, "Right ADC Mixer" },
 358
 359        /* Headphone Routes */
 360        { "Headphone Source Playback Route", "DAC", "Left DAC" },
 361        { "Headphone Source Playback Route", "DAC", "Right DAC" },
 362        { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
 363        { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
 364        { "Headphone Amp", NULL, "Headphone Source Playback Route" },
 365        { "Headphone Amp", NULL, "cpvdd" },
 366        { "HP", NULL, "Headphone Amp" },
 367
 368        /* Microphone Routes */
 369        { "Mic1 Amplifier", NULL, "MIC1"},
 370
 371        /* Microphone Routes */
 372        { "Mic2 Amplifier", NULL, "MIC2"},
 373        { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
 374        { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
 375        { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
 376        { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
 377
 378        /* Line-in Routes */
 379        { "Left Mixer", "Line In Playback Switch", "LINEIN" },
 380        { "Right Mixer", "Line In Playback Switch", "LINEIN" },
 381        { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
 382        { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
 383
 384        /* Line-out Routes */
 385        { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
 386        { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
 387        { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
 388        { "Line Out Source Playback Route", "Mono Differential",
 389                "Right Mixer" },
 390        { "LINEOUT", NULL, "Line Out Source Playback Route" },
 391};
 392
 393static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = {
 394        .controls               = sun50i_a64_codec_controls,
 395        .num_controls           = ARRAY_SIZE(sun50i_a64_codec_controls),
 396        .dapm_widgets           = sun50i_a64_codec_widgets,
 397        .num_dapm_widgets       = ARRAY_SIZE(sun50i_a64_codec_widgets),
 398        .dapm_routes            = sun50i_a64_codec_routes,
 399        .num_dapm_routes        = ARRAY_SIZE(sun50i_a64_codec_routes),
 400};
 401
 402static const struct of_device_id sun50i_codec_analog_of_match[] = {
 403        {
 404                .compatible = "allwinner,sun50i-a64-codec-analog",
 405        },
 406        {}
 407};
 408MODULE_DEVICE_TABLE(of, sun50i_codec_analog_of_match);
 409
 410static int sun50i_codec_analog_probe(struct platform_device *pdev)
 411{
 412        struct resource *res;
 413        struct regmap *regmap;
 414        void __iomem *base;
 415
 416        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 417        base = devm_ioremap_resource(&pdev->dev, res);
 418        if (IS_ERR(base)) {
 419                dev_err(&pdev->dev, "Failed to map the registers\n");
 420                return PTR_ERR(base);
 421        }
 422
 423        regmap = sun8i_adda_pr_regmap_init(&pdev->dev, base);
 424        if (IS_ERR(regmap)) {
 425                dev_err(&pdev->dev, "Failed to create regmap\n");
 426                return PTR_ERR(regmap);
 427        }
 428
 429        return devm_snd_soc_register_component(&pdev->dev,
 430                                               &sun50i_codec_analog_cmpnt_drv,
 431                                               NULL, 0);
 432}
 433
 434static struct platform_driver sun50i_codec_analog_driver = {
 435        .driver = {
 436                .name = "sun50i-codec-analog",
 437                .of_match_table = sun50i_codec_analog_of_match,
 438        },
 439        .probe = sun50i_codec_analog_probe,
 440};
 441module_platform_driver(sun50i_codec_analog_driver);
 442
 443MODULE_DESCRIPTION("Allwinner internal codec analog controls driver for A64");
 444MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
 445MODULE_LICENSE("GPL");
 446MODULE_ALIAS("platform:sun50i-codec-analog");
 447