ssm4567.c 14 KB

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