root/sound/soc/codecs/ssm4567.c

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

DEFINITIONS

This source file includes following definitions.
  1. ssm4567_readable_reg
  2. ssm4567_writeable_reg
  3. ssm4567_volatile_reg
  4. ssm4567_hw_params
  5. ssm4567_mute
  6. ssm4567_set_tdm_slot
  7. ssm4567_set_dai_fmt
  8. ssm4567_set_power
  9. ssm4567_set_bias_level
  10. ssm4567_i2c_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * SSM4567 amplifier audio driver
   4  *
   5  * Copyright 2014 Google Chromium project.
   6  *  Author: Anatol Pomozov <anatol@chromium.org>
   7  *
   8  * Based on code copyright/by:
   9  *   Copyright 2013 Analog Devices Inc.
  10  */
  11 
  12 #include <linux/acpi.h>
  13 #include <linux/module.h>
  14 #include <linux/init.h>
  15 #include <linux/i2c.h>
  16 #include <linux/regmap.h>
  17 #include <linux/slab.h>
  18 #include <sound/core.h>
  19 #include <sound/pcm.h>
  20 #include <sound/pcm_params.h>
  21 #include <sound/soc.h>
  22 #include <sound/initval.h>
  23 #include <sound/tlv.h>
  24 
  25 #define SSM4567_REG_POWER_CTRL          0x00
  26 #define SSM4567_REG_AMP_SNS_CTRL                0x01
  27 #define SSM4567_REG_DAC_CTRL            0x02
  28 #define SSM4567_REG_DAC_VOLUME          0x03
  29 #define SSM4567_REG_SAI_CTRL_1          0x04
  30 #define SSM4567_REG_SAI_CTRL_2          0x05
  31 #define SSM4567_REG_SAI_PLACEMENT_1             0x06
  32 #define SSM4567_REG_SAI_PLACEMENT_2             0x07
  33 #define SSM4567_REG_SAI_PLACEMENT_3             0x08
  34 #define SSM4567_REG_SAI_PLACEMENT_4             0x09
  35 #define SSM4567_REG_SAI_PLACEMENT_5             0x0a
  36 #define SSM4567_REG_SAI_PLACEMENT_6             0x0b
  37 #define SSM4567_REG_BATTERY_V_OUT               0x0c
  38 #define SSM4567_REG_LIMITER_CTRL_1              0x0d
  39 #define SSM4567_REG_LIMITER_CTRL_2              0x0e
  40 #define SSM4567_REG_LIMITER_CTRL_3              0x0f
  41 #define SSM4567_REG_STATUS_1            0x10
  42 #define SSM4567_REG_STATUS_2            0x11
  43 #define SSM4567_REG_FAULT_CTRL          0x12
  44 #define SSM4567_REG_PDM_CTRL            0x13
  45 #define SSM4567_REG_MCLK_RATIO          0x14
  46 #define SSM4567_REG_BOOST_CTRL_1                0x15
  47 #define SSM4567_REG_BOOST_CTRL_2                0x16
  48 #define SSM4567_REG_SOFT_RESET          0xff
  49 
  50 /* POWER_CTRL */
  51 #define SSM4567_POWER_APWDN_EN          BIT(7)
  52 #define SSM4567_POWER_BSNS_PWDN         BIT(6)
  53 #define SSM4567_POWER_VSNS_PWDN         BIT(5)
  54 #define SSM4567_POWER_ISNS_PWDN         BIT(4)
  55 #define SSM4567_POWER_BOOST_PWDN                BIT(3)
  56 #define SSM4567_POWER_AMP_PWDN          BIT(2)
  57 #define SSM4567_POWER_VBAT_ONLY         BIT(1)
  58 #define SSM4567_POWER_SPWDN                     BIT(0)
  59 
  60 /* DAC_CTRL */
  61 #define SSM4567_DAC_HV                  BIT(7)
  62 #define SSM4567_DAC_MUTE                BIT(6)
  63 #define SSM4567_DAC_HPF                 BIT(5)
  64 #define SSM4567_DAC_LPM                 BIT(4)
  65 #define SSM4567_DAC_FS_MASK     0x7
  66 #define SSM4567_DAC_FS_8000_12000       0x0
  67 #define SSM4567_DAC_FS_16000_24000      0x1
  68 #define SSM4567_DAC_FS_32000_48000      0x2
  69 #define SSM4567_DAC_FS_64000_96000      0x3
  70 #define SSM4567_DAC_FS_128000_192000    0x4
  71 
  72 /* SAI_CTRL_1 */
  73 #define SSM4567_SAI_CTRL_1_BCLK                 BIT(6)
  74 #define SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK       (0x3 << 4)
  75 #define SSM4567_SAI_CTRL_1_TDM_BLCKS_32         (0x0 << 4)
  76 #define SSM4567_SAI_CTRL_1_TDM_BLCKS_48         (0x1 << 4)
  77 #define SSM4567_SAI_CTRL_1_TDM_BLCKS_64         (0x2 << 4)
  78 #define SSM4567_SAI_CTRL_1_FSYNC                BIT(3)
  79 #define SSM4567_SAI_CTRL_1_LJ                   BIT(2)
  80 #define SSM4567_SAI_CTRL_1_TDM                  BIT(1)
  81 #define SSM4567_SAI_CTRL_1_PDM                  BIT(0)
  82 
  83 /* SAI_CTRL_2 */
  84 #define SSM4567_SAI_CTRL_2_AUTO_SLOT            BIT(3)
  85 #define SSM4567_SAI_CTRL_2_TDM_SLOT_MASK        0x7
  86 #define SSM4567_SAI_CTRL_2_TDM_SLOT(x)          (x)
  87 
  88 struct ssm4567 {
  89         struct regmap *regmap;
  90 };
  91 
  92 static const struct reg_default ssm4567_reg_defaults[] = {
  93         { SSM4567_REG_POWER_CTRL,       0x81 },
  94         { SSM4567_REG_AMP_SNS_CTRL, 0x09 },
  95         { SSM4567_REG_DAC_CTRL, 0x32 },
  96         { SSM4567_REG_DAC_VOLUME, 0x40 },
  97         { SSM4567_REG_SAI_CTRL_1, 0x00 },
  98         { SSM4567_REG_SAI_CTRL_2, 0x08 },
  99         { SSM4567_REG_SAI_PLACEMENT_1, 0x01 },
 100         { SSM4567_REG_SAI_PLACEMENT_2, 0x20 },
 101         { SSM4567_REG_SAI_PLACEMENT_3, 0x32 },
 102         { SSM4567_REG_SAI_PLACEMENT_4, 0x07 },
 103         { SSM4567_REG_SAI_PLACEMENT_5, 0x07 },
 104         { SSM4567_REG_SAI_PLACEMENT_6, 0x07 },
 105         { SSM4567_REG_BATTERY_V_OUT, 0x00 },
 106         { SSM4567_REG_LIMITER_CTRL_1, 0xa4 },
 107         { SSM4567_REG_LIMITER_CTRL_2, 0x73 },
 108         { SSM4567_REG_LIMITER_CTRL_3, 0x00 },
 109         { SSM4567_REG_STATUS_1, 0x00 },
 110         { SSM4567_REG_STATUS_2, 0x00 },
 111         { SSM4567_REG_FAULT_CTRL, 0x30 },
 112         { SSM4567_REG_PDM_CTRL, 0x40 },
 113         { SSM4567_REG_MCLK_RATIO, 0x11 },
 114         { SSM4567_REG_BOOST_CTRL_1, 0x03 },
 115         { SSM4567_REG_BOOST_CTRL_2, 0x00 },
 116         { SSM4567_REG_SOFT_RESET, 0x00 },
 117 };
 118 
 119 
 120 static bool ssm4567_readable_reg(struct device *dev, unsigned int reg)
 121 {
 122         switch (reg) {
 123         case SSM4567_REG_POWER_CTRL ... SSM4567_REG_BOOST_CTRL_2:
 124                 return true;
 125         default:
 126                 return false;
 127         }
 128 
 129 }
 130 
 131 static bool ssm4567_writeable_reg(struct device *dev, unsigned int reg)
 132 {
 133         switch (reg) {
 134         case SSM4567_REG_POWER_CTRL ... SSM4567_REG_SAI_PLACEMENT_6:
 135         case SSM4567_REG_LIMITER_CTRL_1 ... SSM4567_REG_LIMITER_CTRL_3:
 136         case SSM4567_REG_FAULT_CTRL ... SSM4567_REG_BOOST_CTRL_2:
 137         /* The datasheet states that soft reset register is read-only,
 138          * but logically it is write-only. */
 139         case SSM4567_REG_SOFT_RESET:
 140                 return true;
 141         default:
 142                 return false;
 143         }
 144 }
 145 
 146 static bool ssm4567_volatile_reg(struct device *dev, unsigned int reg)
 147 {
 148         switch (reg) {
 149         case SSM4567_REG_BATTERY_V_OUT:
 150         case SSM4567_REG_STATUS_1 ... SSM4567_REG_STATUS_2:
 151         case SSM4567_REG_SOFT_RESET:
 152                 return true;
 153         default:
 154                 return false;
 155         }
 156 }
 157 
 158 static const DECLARE_TLV_DB_MINMAX_MUTE(ssm4567_vol_tlv, -7125, 2400);
 159 
 160 static const struct snd_kcontrol_new ssm4567_snd_controls[] = {
 161         SOC_SINGLE_TLV("Master Playback Volume", SSM4567_REG_DAC_VOLUME, 0,
 162                 0xff, 1, ssm4567_vol_tlv),
 163         SOC_SINGLE("DAC Low Power Mode Switch", SSM4567_REG_DAC_CTRL, 4, 1, 0),
 164         SOC_SINGLE("DAC High Pass Filter Switch", SSM4567_REG_DAC_CTRL,
 165                 5, 1, 0),
 166 };
 167 
 168 static const struct snd_kcontrol_new ssm4567_amplifier_boost_control =
 169         SOC_DAPM_SINGLE("Switch", SSM4567_REG_POWER_CTRL, 1, 1, 1);
 170 
 171 static const struct snd_soc_dapm_widget ssm4567_dapm_widgets[] = {
 172         SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM4567_REG_POWER_CTRL, 2, 1),
 173         SND_SOC_DAPM_SWITCH("Amplifier Boost", SSM4567_REG_POWER_CTRL, 3, 1,
 174                 &ssm4567_amplifier_boost_control),
 175 
 176         SND_SOC_DAPM_SIGGEN("Sense"),
 177 
 178         SND_SOC_DAPM_PGA("Current Sense", SSM4567_REG_POWER_CTRL, 4, 1, NULL, 0),
 179         SND_SOC_DAPM_PGA("Voltage Sense", SSM4567_REG_POWER_CTRL, 5, 1, NULL, 0),
 180         SND_SOC_DAPM_PGA("VBAT Sense", SSM4567_REG_POWER_CTRL, 6, 1, NULL, 0),
 181 
 182         SND_SOC_DAPM_OUTPUT("OUT"),
 183 };
 184 
 185 static const struct snd_soc_dapm_route ssm4567_routes[] = {
 186         { "OUT", NULL, "Amplifier Boost" },
 187         { "Amplifier Boost", "Switch", "DAC" },
 188         { "OUT", NULL, "DAC" },
 189 
 190         { "Current Sense", NULL, "Sense" },
 191         { "Voltage Sense", NULL, "Sense" },
 192         { "VBAT Sense", NULL, "Sense" },
 193         { "Capture Sense", NULL, "Current Sense" },
 194         { "Capture Sense", NULL, "Voltage Sense" },
 195         { "Capture Sense", NULL, "VBAT Sense" },
 196 };
 197 
 198 static int ssm4567_hw_params(struct snd_pcm_substream *substream,
 199         struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 200 {
 201         struct snd_soc_component *component = dai->component;
 202         struct ssm4567 *ssm4567 = snd_soc_component_get_drvdata(component);
 203         unsigned int rate = params_rate(params);
 204         unsigned int dacfs;
 205 
 206         if (rate >= 8000 && rate <= 12000)
 207                 dacfs = SSM4567_DAC_FS_8000_12000;
 208         else if (rate >= 16000 && rate <= 24000)
 209                 dacfs = SSM4567_DAC_FS_16000_24000;
 210         else if (rate >= 32000 && rate <= 48000)
 211                 dacfs = SSM4567_DAC_FS_32000_48000;
 212         else if (rate >= 64000 && rate <= 96000)
 213                 dacfs = SSM4567_DAC_FS_64000_96000;
 214         else if (rate >= 128000 && rate <= 192000)
 215                 dacfs = SSM4567_DAC_FS_128000_192000;
 216         else
 217                 return -EINVAL;
 218 
 219         return regmap_update_bits(ssm4567->regmap, SSM4567_REG_DAC_CTRL,
 220                                 SSM4567_DAC_FS_MASK, dacfs);
 221 }
 222 
 223 static int ssm4567_mute(struct snd_soc_dai *dai, int mute)
 224 {
 225         struct ssm4567 *ssm4567 = snd_soc_component_get_drvdata(dai->component);
 226         unsigned int val;
 227 
 228         val = mute ? SSM4567_DAC_MUTE : 0;
 229         return regmap_update_bits(ssm4567->regmap, SSM4567_REG_DAC_CTRL,
 230                         SSM4567_DAC_MUTE, val);
 231 }
 232 
 233 static int ssm4567_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
 234         unsigned int rx_mask, int slots, int width)
 235 {
 236         struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai);
 237         unsigned int blcks;
 238         int slot;
 239         int ret;
 240 
 241         if (tx_mask == 0)
 242                 return -EINVAL;
 243 
 244         if (rx_mask && rx_mask != tx_mask)
 245                 return -EINVAL;
 246 
 247         slot = __ffs(tx_mask);
 248         if (tx_mask != BIT(slot))
 249                 return -EINVAL;
 250 
 251         switch (width) {
 252         case 32:
 253                 blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_32;
 254                 break;
 255         case 48:
 256                 blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_48;
 257                 break;
 258         case 64:
 259                 blcks = SSM4567_SAI_CTRL_1_TDM_BLCKS_64;
 260                 break;
 261         default:
 262                 return -EINVAL;
 263         }
 264 
 265         ret = regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_2,
 266                 SSM4567_SAI_CTRL_2_AUTO_SLOT | SSM4567_SAI_CTRL_2_TDM_SLOT_MASK,
 267                 SSM4567_SAI_CTRL_2_TDM_SLOT(slot));
 268         if (ret)
 269                 return ret;
 270 
 271         return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1,
 272                 SSM4567_SAI_CTRL_1_TDM_BLCKS_MASK, blcks);
 273 }
 274 
 275 static int ssm4567_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 276 {
 277         struct ssm4567 *ssm4567 = snd_soc_dai_get_drvdata(dai);
 278         unsigned int ctrl1 = 0;
 279         bool invert_fclk;
 280 
 281         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 282         case SND_SOC_DAIFMT_CBS_CFS:
 283                 break;
 284         default:
 285                 return -EINVAL;
 286         }
 287 
 288         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 289         case SND_SOC_DAIFMT_NB_NF:
 290                 invert_fclk = false;
 291                 break;
 292         case SND_SOC_DAIFMT_IB_NF:
 293                 ctrl1 |= SSM4567_SAI_CTRL_1_BCLK;
 294                 invert_fclk = false;
 295                 break;
 296         case SND_SOC_DAIFMT_NB_IF:
 297                 ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
 298                 invert_fclk = true;
 299                 break;
 300         case SND_SOC_DAIFMT_IB_IF:
 301                 ctrl1 |= SSM4567_SAI_CTRL_1_BCLK;
 302                 invert_fclk = true;
 303                 break;
 304         default:
 305                 return -EINVAL;
 306         }
 307 
 308         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 309         case SND_SOC_DAIFMT_I2S:
 310                 break;
 311         case SND_SOC_DAIFMT_LEFT_J:
 312                 ctrl1 |= SSM4567_SAI_CTRL_1_LJ;
 313                 invert_fclk = !invert_fclk;
 314                 break;
 315         case SND_SOC_DAIFMT_DSP_A:
 316                 ctrl1 |= SSM4567_SAI_CTRL_1_TDM;
 317                 break;
 318         case SND_SOC_DAIFMT_DSP_B:
 319                 ctrl1 |= SSM4567_SAI_CTRL_1_TDM | SSM4567_SAI_CTRL_1_LJ;
 320                 break;
 321         case SND_SOC_DAIFMT_PDM:
 322                 ctrl1 |= SSM4567_SAI_CTRL_1_PDM;
 323                 break;
 324         default:
 325                 return -EINVAL;
 326         }
 327 
 328         if (invert_fclk)
 329                 ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
 330 
 331         return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1,
 332                         SSM4567_SAI_CTRL_1_BCLK |
 333                         SSM4567_SAI_CTRL_1_FSYNC |
 334                         SSM4567_SAI_CTRL_1_LJ |
 335                         SSM4567_SAI_CTRL_1_TDM |
 336                         SSM4567_SAI_CTRL_1_PDM,
 337                         ctrl1);
 338 }
 339 
 340 static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable)
 341 {
 342         int ret = 0;
 343 
 344         if (!enable) {
 345                 ret = regmap_update_bits(ssm4567->regmap,
 346                         SSM4567_REG_POWER_CTRL,
 347                         SSM4567_POWER_SPWDN, SSM4567_POWER_SPWDN);
 348                 regcache_mark_dirty(ssm4567->regmap);
 349         }
 350 
 351         regcache_cache_only(ssm4567->regmap, !enable);
 352 
 353         if (enable) {
 354                 ret = regmap_write(ssm4567->regmap, SSM4567_REG_SOFT_RESET,
 355                         0x00);
 356                 if (ret)
 357                         return ret;
 358 
 359                 ret = regmap_update_bits(ssm4567->regmap,
 360                         SSM4567_REG_POWER_CTRL,
 361                         SSM4567_POWER_SPWDN, 0x00);
 362                 regcache_sync(ssm4567->regmap);
 363         }
 364 
 365         return ret;
 366 }
 367 
 368 static int ssm4567_set_bias_level(struct snd_soc_component *component,
 369         enum snd_soc_bias_level level)
 370 {
 371         struct ssm4567 *ssm4567 = snd_soc_component_get_drvdata(component);
 372         int ret = 0;
 373 
 374         switch (level) {
 375         case SND_SOC_BIAS_ON:
 376                 break;
 377         case SND_SOC_BIAS_PREPARE:
 378                 break;
 379         case SND_SOC_BIAS_STANDBY:
 380                 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
 381                         ret = ssm4567_set_power(ssm4567, true);
 382                 break;
 383         case SND_SOC_BIAS_OFF:
 384                 ret = ssm4567_set_power(ssm4567, false);
 385                 break;
 386         }
 387 
 388         return ret;
 389 }
 390 
 391 static const struct snd_soc_dai_ops ssm4567_dai_ops = {
 392         .hw_params      = ssm4567_hw_params,
 393         .digital_mute   = ssm4567_mute,
 394         .set_fmt        = ssm4567_set_dai_fmt,
 395         .set_tdm_slot   = ssm4567_set_tdm_slot,
 396 };
 397 
 398 static struct snd_soc_dai_driver ssm4567_dai = {
 399         .name = "ssm4567-hifi",
 400         .playback = {
 401                 .stream_name = "Playback",
 402                 .channels_min = 1,
 403                 .channels_max = 1,
 404                 .rates = SNDRV_PCM_RATE_8000_192000,
 405                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
 406                         SNDRV_PCM_FMTBIT_S32,
 407         },
 408         .capture = {
 409                 .stream_name = "Capture Sense",
 410                 .channels_min = 1,
 411                 .channels_max = 1,
 412                 .rates = SNDRV_PCM_RATE_8000_192000,
 413                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |
 414                         SNDRV_PCM_FMTBIT_S32,
 415         },
 416         .ops = &ssm4567_dai_ops,
 417 };
 418 
 419 static const struct snd_soc_component_driver ssm4567_component_driver = {
 420         .set_bias_level         = ssm4567_set_bias_level,
 421         .controls               = ssm4567_snd_controls,
 422         .num_controls           = ARRAY_SIZE(ssm4567_snd_controls),
 423         .dapm_widgets           = ssm4567_dapm_widgets,
 424         .num_dapm_widgets       = ARRAY_SIZE(ssm4567_dapm_widgets),
 425         .dapm_routes            = ssm4567_routes,
 426         .num_dapm_routes        = ARRAY_SIZE(ssm4567_routes),
 427         .use_pmdown_time        = 1,
 428         .endianness             = 1,
 429         .non_legacy_dai_naming  = 1,
 430 };
 431 
 432 static const struct regmap_config ssm4567_regmap_config = {
 433         .val_bits = 8,
 434         .reg_bits = 8,
 435 
 436         .max_register = SSM4567_REG_SOFT_RESET,
 437         .readable_reg = ssm4567_readable_reg,
 438         .writeable_reg = ssm4567_writeable_reg,
 439         .volatile_reg = ssm4567_volatile_reg,
 440 
 441         .cache_type = REGCACHE_RBTREE,
 442         .reg_defaults = ssm4567_reg_defaults,
 443         .num_reg_defaults = ARRAY_SIZE(ssm4567_reg_defaults),
 444 };
 445 
 446 static int ssm4567_i2c_probe(struct i2c_client *i2c,
 447         const struct i2c_device_id *id)
 448 {
 449         struct ssm4567 *ssm4567;
 450         int ret;
 451 
 452         ssm4567 = devm_kzalloc(&i2c->dev, sizeof(*ssm4567), GFP_KERNEL);
 453         if (ssm4567 == NULL)
 454                 return -ENOMEM;
 455 
 456         i2c_set_clientdata(i2c, ssm4567);
 457 
 458         ssm4567->regmap = devm_regmap_init_i2c(i2c, &ssm4567_regmap_config);
 459         if (IS_ERR(ssm4567->regmap))
 460                 return PTR_ERR(ssm4567->regmap);
 461 
 462         ret = regmap_write(ssm4567->regmap, SSM4567_REG_SOFT_RESET, 0x00);
 463         if (ret)
 464                 return ret;
 465 
 466         ret = ssm4567_set_power(ssm4567, false);
 467         if (ret)
 468                 return ret;
 469 
 470         return devm_snd_soc_register_component(&i2c->dev, &ssm4567_component_driver,
 471                         &ssm4567_dai, 1);
 472 }
 473 
 474 static const struct i2c_device_id ssm4567_i2c_ids[] = {
 475         { "ssm4567", 0 },
 476         { }
 477 };
 478 MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids);
 479 
 480 #ifdef CONFIG_OF
 481 static const struct of_device_id ssm4567_of_match[] = {
 482         { .compatible = "adi,ssm4567", },
 483         { }
 484 };
 485 MODULE_DEVICE_TABLE(of, ssm4567_of_match);
 486 #endif
 487 
 488 #ifdef CONFIG_ACPI
 489 
 490 static const struct acpi_device_id ssm4567_acpi_match[] = {
 491         { "INT343B", 0 },
 492         {},
 493 };
 494 MODULE_DEVICE_TABLE(acpi, ssm4567_acpi_match);
 495 
 496 #endif
 497 
 498 static struct i2c_driver ssm4567_driver = {
 499         .driver = {
 500                 .name = "ssm4567",
 501                 .of_match_table = of_match_ptr(ssm4567_of_match),
 502                 .acpi_match_table = ACPI_PTR(ssm4567_acpi_match),
 503         },
 504         .probe = ssm4567_i2c_probe,
 505         .id_table = ssm4567_i2c_ids,
 506 };
 507 module_i2c_driver(ssm4567_driver);
 508 
 509 MODULE_DESCRIPTION("ASoC SSM4567 driver");
 510 MODULE_AUTHOR("Anatol Pomozov <anatol@chromium.org>");
 511 MODULE_LICENSE("GPL");

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