root/sound/soc/codecs/ssm2602.c

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

DEFINITIONS

This source file includes following definitions.
  1. ssm2602_mic_switch_event
  2. ssm2602_get_coeff
  3. ssm2602_hw_params
  4. ssm2602_startup
  5. ssm2602_mute
  6. ssm2602_set_dai_sysclk
  7. ssm2602_set_dai_fmt
  8. ssm2602_set_bias_level
  9. ssm2602_resume
  10. ssm2602_component_probe
  11. ssm2604_component_probe
  12. ssm260x_component_probe
  13. ssm2602_register_volatile
  14. ssm2602_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 //
   3 // File:         sound/soc/codecs/ssm2602.c
   4 // Author:       Cliff Cai <Cliff.Cai@analog.com>
   5 //
   6 // Created:      Tue June 06 2008
   7 // Description:  Driver for ssm2602 sound chip
   8 //
   9 // Modified:
  10 //               Copyright 2008 Analog Devices Inc.
  11 //
  12 // Bugs:         Enter bugs at http://blackfin.uclinux.org/
  13 
  14 #include <linux/delay.h>
  15 #include <linux/module.h>
  16 #include <linux/regmap.h>
  17 #include <linux/slab.h>
  18 
  19 #include <sound/pcm.h>
  20 #include <sound/pcm_params.h>
  21 #include <sound/soc.h>
  22 #include <sound/tlv.h>
  23 
  24 #include "ssm2602.h"
  25 
  26 /* codec private data */
  27 struct ssm2602_priv {
  28         unsigned int sysclk;
  29         const struct snd_pcm_hw_constraint_list *sysclk_constraints;
  30 
  31         struct regmap *regmap;
  32 
  33         enum ssm2602_type type;
  34         unsigned int clk_out_pwr;
  35 };
  36 
  37 /*
  38  * ssm2602 register cache
  39  * We can't read the ssm2602 register space when we are
  40  * using 2 wire for device control, so we cache them instead.
  41  * There is no point in caching the reset register
  42  */
  43 static const struct reg_default ssm2602_reg[SSM2602_CACHEREGNUM] = {
  44         { .reg = 0x00, .def = 0x0097 },
  45         { .reg = 0x01, .def = 0x0097 },
  46         { .reg = 0x02, .def = 0x0079 },
  47         { .reg = 0x03, .def = 0x0079 },
  48         { .reg = 0x04, .def = 0x000a },
  49         { .reg = 0x05, .def = 0x0008 },
  50         { .reg = 0x06, .def = 0x009f },
  51         { .reg = 0x07, .def = 0x000a },
  52         { .reg = 0x08, .def = 0x0000 },
  53         { .reg = 0x09, .def = 0x0000 }
  54 };
  55 
  56 
  57 /*Appending several "None"s just for OSS mixer use*/
  58 static const char *ssm2602_input_select[] = {
  59         "Line", "Mic",
  60 };
  61 
  62 static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
  63 
  64 static const struct soc_enum ssm2602_enum[] = {
  65         SOC_ENUM_SINGLE(SSM2602_APANA, 2, ARRAY_SIZE(ssm2602_input_select),
  66                         ssm2602_input_select),
  67         SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, ARRAY_SIZE(ssm2602_deemph),
  68                         ssm2602_deemph),
  69 };
  70 
  71 static const DECLARE_TLV_DB_RANGE(ssm260x_outmix_tlv,
  72         0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0),
  73         48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0)
  74 );
  75 
  76 static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0);
  77 static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0);
  78 
  79 static const struct snd_kcontrol_new ssm260x_snd_controls[] = {
  80 SOC_DOUBLE_R_TLV("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 45, 0,
  81         ssm260x_inpga_tlv),
  82 SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1),
  83 
  84 SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1),
  85 SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0),
  86 
  87 SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]),
  88 };
  89 
  90 static const struct snd_kcontrol_new ssm2602_snd_controls[] = {
  91 SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V,
  92         0, 127, 0, ssm260x_outmix_tlv),
  93 SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V,
  94         7, 1, 0),
  95 SOC_SINGLE_TLV("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1,
  96         ssm260x_sidetone_tlv),
  97 
  98 SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0),
  99 SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0),
 100 };
 101 
 102 /* Output Mixer */
 103 static const struct snd_kcontrol_new ssm260x_output_mixer_controls[] = {
 104 SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0),
 105 SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0),
 106 SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0),
 107 };
 108 
 109 static const struct snd_kcontrol_new mic_ctl =
 110         SOC_DAPM_SINGLE("Switch", SSM2602_APANA, 1, 1, 1);
 111 
 112 /* Input mux */
 113 static const struct snd_kcontrol_new ssm2602_input_mux_controls =
 114 SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]);
 115 
 116 static int ssm2602_mic_switch_event(struct snd_soc_dapm_widget *w,
 117                                 struct snd_kcontrol *kcontrol, int event)
 118 {
 119         /*
 120          * According to the ssm2603 data sheet (control register sequencing),
 121          * the digital core should be activated only after all necessary bits
 122          * in the power register are enabled, and a delay determined by the
 123          * decoupling capacitor on the VMID pin has passed. If the digital core
 124          * is activated too early, or even before the ADC is powered up, audible
 125          * artifacts appear at the beginning and end of the recorded signal.
 126          *
 127          * In practice, audible artifacts disappear well over 500 ms.
 128          */
 129         msleep(500);
 130 
 131         return 0;
 132 }
 133 
 134 static const struct snd_soc_dapm_widget ssm260x_dapm_widgets[] = {
 135 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1),
 136 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1),
 137 SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0),
 138 
 139 SND_SOC_DAPM_SUPPLY("Digital Core Power", SSM2602_ACTIVE, 0, 0, NULL, 0),
 140 
 141 SND_SOC_DAPM_OUTPUT("LOUT"),
 142 SND_SOC_DAPM_OUTPUT("ROUT"),
 143 SND_SOC_DAPM_INPUT("RLINEIN"),
 144 SND_SOC_DAPM_INPUT("LLINEIN"),
 145 };
 146 
 147 static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = {
 148 SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1,
 149         ssm260x_output_mixer_controls,
 150         ARRAY_SIZE(ssm260x_output_mixer_controls)),
 151 
 152 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls),
 153 SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1),
 154 
 155 SND_SOC_DAPM_SWITCH_E("Mic Switch", SSM2602_APANA, 1, 1, &mic_ctl,
 156                 ssm2602_mic_switch_event, SND_SOC_DAPM_PRE_PMU),
 157 
 158 SND_SOC_DAPM_OUTPUT("LHPOUT"),
 159 SND_SOC_DAPM_OUTPUT("RHPOUT"),
 160 SND_SOC_DAPM_INPUT("MICIN"),
 161 };
 162 
 163 static const struct snd_soc_dapm_widget ssm2604_dapm_widgets[] = {
 164 SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
 165         ssm260x_output_mixer_controls,
 166         ARRAY_SIZE(ssm260x_output_mixer_controls) - 1), /* Last element is the mic */
 167 };
 168 
 169 static const struct snd_soc_dapm_route ssm260x_routes[] = {
 170         {"DAC", NULL, "Digital Core Power"},
 171         {"ADC", NULL, "Digital Core Power"},
 172 
 173         {"Output Mixer", "Line Bypass Switch", "Line Input"},
 174         {"Output Mixer", "HiFi Playback Switch", "DAC"},
 175 
 176         {"ROUT", NULL, "Output Mixer"},
 177         {"LOUT", NULL, "Output Mixer"},
 178 
 179         {"Line Input", NULL, "LLINEIN"},
 180         {"Line Input", NULL, "RLINEIN"},
 181 };
 182 
 183 static const struct snd_soc_dapm_route ssm2602_routes[] = {
 184         {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
 185 
 186         {"RHPOUT", NULL, "Output Mixer"},
 187         {"LHPOUT", NULL, "Output Mixer"},
 188 
 189         {"Input Mux", "Line", "Line Input"},
 190         {"Input Mux", "Mic", "Mic Switch"},
 191         {"ADC", NULL, "Input Mux"},
 192 
 193         {"Mic Switch", NULL, "Mic Bias"},
 194 
 195         {"Mic Bias", NULL, "MICIN"},
 196 };
 197 
 198 static const struct snd_soc_dapm_route ssm2604_routes[] = {
 199         {"ADC", NULL, "Line Input"},
 200 };
 201 
 202 static const unsigned int ssm2602_rates_12288000[] = {
 203         8000, 16000, 32000, 48000, 96000,
 204 };
 205 
 206 static const struct snd_pcm_hw_constraint_list ssm2602_constraints_12288000 = {
 207         .list = ssm2602_rates_12288000,
 208         .count = ARRAY_SIZE(ssm2602_rates_12288000),
 209 };
 210 
 211 static const unsigned int ssm2602_rates_11289600[] = {
 212         8000, 11025, 22050, 44100, 88200,
 213 };
 214 
 215 static const struct snd_pcm_hw_constraint_list ssm2602_constraints_11289600 = {
 216         .list = ssm2602_rates_11289600,
 217         .count = ARRAY_SIZE(ssm2602_rates_11289600),
 218 };
 219 
 220 struct ssm2602_coeff {
 221         u32 mclk;
 222         u32 rate;
 223         u8 srate;
 224 };
 225 
 226 #define SSM2602_COEFF_SRATE(sr, bosr, usb) (((sr) << 2) | ((bosr) << 1) | (usb))
 227 
 228 /* codec mclk clock coefficients */
 229 static const struct ssm2602_coeff ssm2602_coeff_table[] = {
 230         /* 48k */
 231         {12288000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x0)},
 232         {18432000, 48000, SSM2602_COEFF_SRATE(0x0, 0x1, 0x0)},
 233         {12000000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x1)},
 234 
 235         /* 32k */
 236         {12288000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x0)},
 237         {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)},
 238         {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)},
 239 
 240         /* 16k */
 241         {12288000, 16000, SSM2602_COEFF_SRATE(0x5, 0x0, 0x0)},
 242         {18432000, 16000, SSM2602_COEFF_SRATE(0x5, 0x1, 0x0)},
 243         {12000000, 16000, SSM2602_COEFF_SRATE(0xa, 0x0, 0x1)},
 244 
 245         /* 8k */
 246         {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)},
 247         {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)},
 248         {11289600, 8000, SSM2602_COEFF_SRATE(0xb, 0x0, 0x0)},
 249         {16934400, 8000, SSM2602_COEFF_SRATE(0xb, 0x1, 0x0)},
 250         {12000000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x1)},
 251 
 252         /* 96k */
 253         {12288000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x0)},
 254         {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)},
 255         {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)},
 256 
 257         /* 11.025k */
 258         {11289600, 11025, SSM2602_COEFF_SRATE(0xc, 0x0, 0x0)},
 259         {16934400, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x0)},
 260         {12000000, 11025, SSM2602_COEFF_SRATE(0xc, 0x1, 0x1)},
 261 
 262         /* 22.05k */
 263         {11289600, 22050, SSM2602_COEFF_SRATE(0xd, 0x0, 0x0)},
 264         {16934400, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x0)},
 265         {12000000, 22050, SSM2602_COEFF_SRATE(0xd, 0x1, 0x1)},
 266 
 267         /* 44.1k */
 268         {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)},
 269         {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)},
 270         {12000000, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x1)},
 271 
 272         /* 88.2k */
 273         {11289600, 88200, SSM2602_COEFF_SRATE(0xf, 0x0, 0x0)},
 274         {16934400, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x0)},
 275         {12000000, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x1)},
 276 };
 277 
 278 static inline int ssm2602_get_coeff(int mclk, int rate)
 279 {
 280         int i;
 281 
 282         for (i = 0; i < ARRAY_SIZE(ssm2602_coeff_table); i++) {
 283                 if (ssm2602_coeff_table[i].rate == rate &&
 284                         ssm2602_coeff_table[i].mclk == mclk)
 285                         return ssm2602_coeff_table[i].srate;
 286         }
 287         return -EINVAL;
 288 }
 289 
 290 static int ssm2602_hw_params(struct snd_pcm_substream *substream,
 291         struct snd_pcm_hw_params *params,
 292         struct snd_soc_dai *dai)
 293 {
 294         struct snd_soc_component *component = dai->component;
 295         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 296         int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params));
 297         unsigned int iface;
 298 
 299         if (srate < 0)
 300                 return srate;
 301 
 302         regmap_write(ssm2602->regmap, SSM2602_SRATE, srate);
 303 
 304         /* bit size */
 305         switch (params_width(params)) {
 306         case 16:
 307                 iface = 0x0;
 308                 break;
 309         case 20:
 310                 iface = 0x4;
 311                 break;
 312         case 24:
 313                 iface = 0x8;
 314                 break;
 315         case 32:
 316                 iface = 0xc;
 317                 break;
 318         default:
 319                 return -EINVAL;
 320         }
 321         regmap_update_bits(ssm2602->regmap, SSM2602_IFACE,
 322                 IFACE_AUDIO_DATA_LEN, iface);
 323         return 0;
 324 }
 325 
 326 static int ssm2602_startup(struct snd_pcm_substream *substream,
 327                            struct snd_soc_dai *dai)
 328 {
 329         struct snd_soc_component *component = dai->component;
 330         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 331 
 332         if (ssm2602->sysclk_constraints) {
 333                 snd_pcm_hw_constraint_list(substream->runtime, 0,
 334                                    SNDRV_PCM_HW_PARAM_RATE,
 335                                    ssm2602->sysclk_constraints);
 336         }
 337 
 338         return 0;
 339 }
 340 
 341 static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
 342 {
 343         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(dai->component);
 344 
 345         if (mute)
 346                 regmap_update_bits(ssm2602->regmap, SSM2602_APDIGI,
 347                                     APDIGI_ENABLE_DAC_MUTE,
 348                                     APDIGI_ENABLE_DAC_MUTE);
 349         else
 350                 regmap_update_bits(ssm2602->regmap, SSM2602_APDIGI,
 351                                     APDIGI_ENABLE_DAC_MUTE, 0);
 352         return 0;
 353 }
 354 
 355 static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 356                 int clk_id, unsigned int freq, int dir)
 357 {
 358         struct snd_soc_component *component = codec_dai->component;
 359         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 360 
 361         if (dir == SND_SOC_CLOCK_IN) {
 362                 if (clk_id != SSM2602_SYSCLK)
 363                         return -EINVAL;
 364 
 365                 switch (freq) {
 366                 case 12288000:
 367                 case 18432000:
 368                         ssm2602->sysclk_constraints = &ssm2602_constraints_12288000;
 369                         break;
 370                 case 11289600:
 371                 case 16934400:
 372                         ssm2602->sysclk_constraints = &ssm2602_constraints_11289600;
 373                         break;
 374                 case 12000000:
 375                         ssm2602->sysclk_constraints = NULL;
 376                         break;
 377                 default:
 378                         return -EINVAL;
 379                 }
 380                 ssm2602->sysclk = freq;
 381         } else {
 382                 unsigned int mask;
 383 
 384                 switch (clk_id) {
 385                 case SSM2602_CLK_CLKOUT:
 386                         mask = PWR_CLK_OUT_PDN;
 387                         break;
 388                 case SSM2602_CLK_XTO:
 389                         mask = PWR_OSC_PDN;
 390                         break;
 391                 default:
 392                         return -EINVAL;
 393                 }
 394 
 395                 if (freq == 0)
 396                         ssm2602->clk_out_pwr |= mask;
 397                 else
 398                         ssm2602->clk_out_pwr &= ~mask;
 399 
 400                 regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
 401                         PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
 402         }
 403 
 404         return 0;
 405 }
 406 
 407 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
 408                 unsigned int fmt)
 409 {
 410         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(codec_dai->component);
 411         unsigned int iface = 0;
 412 
 413         /* set master/slave audio interface */
 414         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 415         case SND_SOC_DAIFMT_CBM_CFM:
 416                 iface |= 0x0040;
 417                 break;
 418         case SND_SOC_DAIFMT_CBS_CFS:
 419                 break;
 420         default:
 421                 return -EINVAL;
 422         }
 423 
 424         /* interface format */
 425         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 426         case SND_SOC_DAIFMT_I2S:
 427                 iface |= 0x0002;
 428                 break;
 429         case SND_SOC_DAIFMT_RIGHT_J:
 430                 break;
 431         case SND_SOC_DAIFMT_LEFT_J:
 432                 iface |= 0x0001;
 433                 break;
 434         case SND_SOC_DAIFMT_DSP_A:
 435                 iface |= 0x0013;
 436                 break;
 437         case SND_SOC_DAIFMT_DSP_B:
 438                 iface |= 0x0003;
 439                 break;
 440         default:
 441                 return -EINVAL;
 442         }
 443 
 444         /* clock inversion */
 445         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 446         case SND_SOC_DAIFMT_NB_NF:
 447                 break;
 448         case SND_SOC_DAIFMT_IB_IF:
 449                 iface |= 0x0090;
 450                 break;
 451         case SND_SOC_DAIFMT_IB_NF:
 452                 iface |= 0x0080;
 453                 break;
 454         case SND_SOC_DAIFMT_NB_IF:
 455                 iface |= 0x0010;
 456                 break;
 457         default:
 458                 return -EINVAL;
 459         }
 460 
 461         /* set iface */
 462         regmap_write(ssm2602->regmap, SSM2602_IFACE, iface);
 463         return 0;
 464 }
 465 
 466 static int ssm2602_set_bias_level(struct snd_soc_component *component,
 467                                  enum snd_soc_bias_level level)
 468 {
 469         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 470 
 471         switch (level) {
 472         case SND_SOC_BIAS_ON:
 473                 /* vref/mid on, osc and clkout on if enabled */
 474                 regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
 475                         PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
 476                         ssm2602->clk_out_pwr);
 477                 break;
 478         case SND_SOC_BIAS_PREPARE:
 479                 break;
 480         case SND_SOC_BIAS_STANDBY:
 481                 /* everything off except vref/vmid, */
 482                 regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
 483                         PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
 484                         PWR_CLK_OUT_PDN | PWR_OSC_PDN);
 485                 break;
 486         case SND_SOC_BIAS_OFF:
 487                 /* everything off */
 488                 regmap_update_bits(ssm2602->regmap, SSM2602_PWR,
 489                         PWR_POWER_OFF, PWR_POWER_OFF);
 490                 break;
 491 
 492         }
 493         return 0;
 494 }
 495 
 496 #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
 497                 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
 498                 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
 499                 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
 500                 SNDRV_PCM_RATE_96000)
 501 
 502 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
 503                 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 504 
 505 static const struct snd_soc_dai_ops ssm2602_dai_ops = {
 506         .startup        = ssm2602_startup,
 507         .hw_params      = ssm2602_hw_params,
 508         .digital_mute   = ssm2602_mute,
 509         .set_sysclk     = ssm2602_set_dai_sysclk,
 510         .set_fmt        = ssm2602_set_dai_fmt,
 511 };
 512 
 513 static struct snd_soc_dai_driver ssm2602_dai = {
 514         .name = "ssm2602-hifi",
 515         .playback = {
 516                 .stream_name = "Playback",
 517                 .channels_min = 2,
 518                 .channels_max = 2,
 519                 .rates = SSM2602_RATES,
 520                 .formats = SSM2602_FORMATS,},
 521         .capture = {
 522                 .stream_name = "Capture",
 523                 .channels_min = 2,
 524                 .channels_max = 2,
 525                 .rates = SSM2602_RATES,
 526                 .formats = SSM2602_FORMATS,},
 527         .ops = &ssm2602_dai_ops,
 528         .symmetric_rates = 1,
 529         .symmetric_samplebits = 1,
 530 };
 531 
 532 static int ssm2602_resume(struct snd_soc_component *component)
 533 {
 534         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 535 
 536         regcache_sync(ssm2602->regmap);
 537 
 538         return 0;
 539 }
 540 
 541 static int ssm2602_component_probe(struct snd_soc_component *component)
 542 {
 543         struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 544         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 545         int ret;
 546 
 547         regmap_update_bits(ssm2602->regmap, SSM2602_LOUT1V,
 548                             LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
 549         regmap_update_bits(ssm2602->regmap, SSM2602_ROUT1V,
 550                             ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
 551 
 552         ret = snd_soc_add_component_controls(component, ssm2602_snd_controls,
 553                         ARRAY_SIZE(ssm2602_snd_controls));
 554         if (ret)
 555                 return ret;
 556 
 557         ret = snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets,
 558                         ARRAY_SIZE(ssm2602_dapm_widgets));
 559         if (ret)
 560                 return ret;
 561 
 562         return snd_soc_dapm_add_routes(dapm, ssm2602_routes,
 563                         ARRAY_SIZE(ssm2602_routes));
 564 }
 565 
 566 static int ssm2604_component_probe(struct snd_soc_component *component)
 567 {
 568         struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
 569         int ret;
 570 
 571         ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets,
 572                         ARRAY_SIZE(ssm2604_dapm_widgets));
 573         if (ret)
 574                 return ret;
 575 
 576         return snd_soc_dapm_add_routes(dapm, ssm2604_routes,
 577                         ARRAY_SIZE(ssm2604_routes));
 578 }
 579 
 580 static int ssm260x_component_probe(struct snd_soc_component *component)
 581 {
 582         struct ssm2602_priv *ssm2602 = snd_soc_component_get_drvdata(component);
 583         int ret;
 584 
 585         ret = regmap_write(ssm2602->regmap, SSM2602_RESET, 0);
 586         if (ret < 0) {
 587                 dev_err(component->dev, "Failed to issue reset: %d\n", ret);
 588                 return ret;
 589         }
 590 
 591         /* set the update bits */
 592         regmap_update_bits(ssm2602->regmap, SSM2602_LINVOL,
 593                             LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
 594         regmap_update_bits(ssm2602->regmap, SSM2602_RINVOL,
 595                             RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
 596         /*select Line in as default input*/
 597         regmap_write(ssm2602->regmap, SSM2602_APANA, APANA_SELECT_DAC |
 598                         APANA_ENABLE_MIC_BOOST);
 599 
 600         switch (ssm2602->type) {
 601         case SSM2602:
 602                 ret = ssm2602_component_probe(component);
 603                 break;
 604         case SSM2604:
 605                 ret = ssm2604_component_probe(component);
 606                 break;
 607         }
 608 
 609         return ret;
 610 }
 611 
 612 static const struct snd_soc_component_driver soc_component_dev_ssm2602 = {
 613         .probe                  = ssm260x_component_probe,
 614         .resume                 = ssm2602_resume,
 615         .set_bias_level         = ssm2602_set_bias_level,
 616         .controls               = ssm260x_snd_controls,
 617         .num_controls           = ARRAY_SIZE(ssm260x_snd_controls),
 618         .dapm_widgets           = ssm260x_dapm_widgets,
 619         .num_dapm_widgets       = ARRAY_SIZE(ssm260x_dapm_widgets),
 620         .dapm_routes            = ssm260x_routes,
 621         .num_dapm_routes        = ARRAY_SIZE(ssm260x_routes),
 622         .suspend_bias_off       = 1,
 623         .idle_bias_on           = 1,
 624         .use_pmdown_time        = 1,
 625         .endianness             = 1,
 626         .non_legacy_dai_naming  = 1,
 627 };
 628 
 629 static bool ssm2602_register_volatile(struct device *dev, unsigned int reg)
 630 {
 631         return reg == SSM2602_RESET;
 632 }
 633 
 634 const struct regmap_config ssm2602_regmap_config = {
 635         .val_bits = 9,
 636         .reg_bits = 7,
 637 
 638         .max_register = SSM2602_RESET,
 639         .volatile_reg = ssm2602_register_volatile,
 640 
 641         .cache_type = REGCACHE_RBTREE,
 642         .reg_defaults = ssm2602_reg,
 643         .num_reg_defaults = ARRAY_SIZE(ssm2602_reg),
 644 };
 645 EXPORT_SYMBOL_GPL(ssm2602_regmap_config);
 646 
 647 int ssm2602_probe(struct device *dev, enum ssm2602_type type,
 648         struct regmap *regmap)
 649 {
 650         struct ssm2602_priv *ssm2602;
 651 
 652         if (IS_ERR(regmap))
 653                 return PTR_ERR(regmap);
 654 
 655         ssm2602 = devm_kzalloc(dev, sizeof(*ssm2602), GFP_KERNEL);
 656         if (ssm2602 == NULL)
 657                 return -ENOMEM;
 658 
 659         dev_set_drvdata(dev, ssm2602);
 660         ssm2602->type = type;
 661         ssm2602->regmap = regmap;
 662 
 663         return devm_snd_soc_register_component(dev, &soc_component_dev_ssm2602,
 664                 &ssm2602_dai, 1);
 665 }
 666 EXPORT_SYMBOL_GPL(ssm2602_probe);
 667 
 668 MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver");
 669 MODULE_AUTHOR("Cliff Cai");
 670 MODULE_LICENSE("GPL");

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