tegra210_dmic.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // tegra210_dmic.c - Tegra210 DMIC driver
  4. //
  5. // Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
  6. #include <linux/clk.h>
  7. #include <linux/device.h>
  8. #include <linux/math64.h>
  9. #include <linux/module.h>
  10. #include <linux/of_device.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/pm_runtime.h>
  13. #include <linux/regmap.h>
  14. #include <sound/core.h>
  15. #include <sound/pcm_params.h>
  16. #include <sound/soc.h>
  17. #include "tegra210_dmic.h"
  18. #include "tegra_cif.h"
  19. static const struct reg_default tegra210_dmic_reg_defaults[] = {
  20. { TEGRA210_DMIC_TX_INT_MASK, 0x00000001 },
  21. { TEGRA210_DMIC_TX_CIF_CTRL, 0x00007700 },
  22. { TEGRA210_DMIC_CG, 0x1 },
  23. { TEGRA210_DMIC_CTRL, 0x00000301 },
  24. /* Below enables all filters - DCR, LP and SC */
  25. { TEGRA210_DMIC_DBG_CTRL, 0xe },
  26. /* Below as per latest POR value */
  27. { TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4, 0x0 },
  28. /* LP filter is configured for pass through and used to apply gain */
  29. { TEGRA210_DMIC_LP_BIQUAD_0_COEF_0, 0x00800000 },
  30. { TEGRA210_DMIC_LP_BIQUAD_0_COEF_1, 0x0 },
  31. { TEGRA210_DMIC_LP_BIQUAD_0_COEF_2, 0x0 },
  32. { TEGRA210_DMIC_LP_BIQUAD_0_COEF_3, 0x0 },
  33. { TEGRA210_DMIC_LP_BIQUAD_0_COEF_4, 0x0 },
  34. { TEGRA210_DMIC_LP_BIQUAD_1_COEF_0, 0x00800000 },
  35. { TEGRA210_DMIC_LP_BIQUAD_1_COEF_1, 0x0 },
  36. { TEGRA210_DMIC_LP_BIQUAD_1_COEF_2, 0x0 },
  37. { TEGRA210_DMIC_LP_BIQUAD_1_COEF_3, 0x0 },
  38. { TEGRA210_DMIC_LP_BIQUAD_1_COEF_4, 0x0 },
  39. };
  40. static int __maybe_unused tegra210_dmic_runtime_suspend(struct device *dev)
  41. {
  42. struct tegra210_dmic *dmic = dev_get_drvdata(dev);
  43. regcache_cache_only(dmic->regmap, true);
  44. regcache_mark_dirty(dmic->regmap);
  45. clk_disable_unprepare(dmic->clk_dmic);
  46. return 0;
  47. }
  48. static int __maybe_unused tegra210_dmic_runtime_resume(struct device *dev)
  49. {
  50. struct tegra210_dmic *dmic = dev_get_drvdata(dev);
  51. int err;
  52. err = clk_prepare_enable(dmic->clk_dmic);
  53. if (err) {
  54. dev_err(dev, "failed to enable DMIC clock, err: %d\n", err);
  55. return err;
  56. }
  57. regcache_cache_only(dmic->regmap, false);
  58. regcache_sync(dmic->regmap);
  59. return 0;
  60. }
  61. static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
  62. struct snd_pcm_hw_params *params,
  63. struct snd_soc_dai *dai)
  64. {
  65. struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai);
  66. unsigned int srate, clk_rate, channels;
  67. struct tegra_cif_conf cif_conf;
  68. unsigned long long gain_q23 = DEFAULT_GAIN_Q23;
  69. int err;
  70. memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
  71. channels = params_channels(params);
  72. cif_conf.audio_ch = channels;
  73. switch (dmic->ch_select) {
  74. case DMIC_CH_SELECT_LEFT:
  75. case DMIC_CH_SELECT_RIGHT:
  76. cif_conf.client_ch = 1;
  77. break;
  78. case DMIC_CH_SELECT_STEREO:
  79. cif_conf.client_ch = 2;
  80. break;
  81. default:
  82. dev_err(dai->dev, "invalid DMIC client channels\n");
  83. return -EINVAL;
  84. }
  85. srate = params_rate(params);
  86. /*
  87. * DMIC clock rate is a multiple of 'Over Sampling Ratio' and
  88. * 'Sample Rate'. The supported OSR values are 64, 128 and 256.
  89. */
  90. clk_rate = (DMIC_OSR_FACTOR << dmic->osr_val) * srate;
  91. err = clk_set_rate(dmic->clk_dmic, clk_rate);
  92. if (err) {
  93. dev_err(dai->dev, "can't set DMIC clock rate %u, err: %d\n",
  94. clk_rate, err);
  95. return err;
  96. }
  97. regmap_update_bits(dmic->regmap,
  98. /* Reg */
  99. TEGRA210_DMIC_CTRL,
  100. /* Mask */
  101. TEGRA210_DMIC_CTRL_LRSEL_POLARITY_MASK |
  102. TEGRA210_DMIC_CTRL_OSR_MASK |
  103. TEGRA210_DMIC_CTRL_CHANNEL_SELECT_MASK,
  104. /* Value */
  105. (dmic->lrsel << LRSEL_POL_SHIFT) |
  106. (dmic->osr_val << OSR_SHIFT) |
  107. ((dmic->ch_select + 1) << CH_SEL_SHIFT));
  108. /*
  109. * Use LP filter gain register to apply boost.
  110. * Boost Gain Volume control has 100x factor.
  111. */
  112. if (dmic->boost_gain)
  113. gain_q23 = div_u64(gain_q23 * dmic->boost_gain, 100);
  114. regmap_write(dmic->regmap, TEGRA210_DMIC_LP_FILTER_GAIN,
  115. (unsigned int)gain_q23);
  116. switch (params_format(params)) {
  117. case SNDRV_PCM_FORMAT_S16_LE:
  118. cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
  119. break;
  120. case SNDRV_PCM_FORMAT_S32_LE:
  121. cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
  122. break;
  123. default:
  124. dev_err(dai->dev, "unsupported format!\n");
  125. return -EOPNOTSUPP;
  126. }
  127. cif_conf.client_bits = TEGRA_ACIF_BITS_24;
  128. cif_conf.mono_conv = dmic->mono_to_stereo;
  129. cif_conf.stereo_conv = dmic->stereo_to_mono;
  130. tegra_set_cif(dmic->regmap, TEGRA210_DMIC_TX_CIF_CTRL, &cif_conf);
  131. return 0;
  132. }
  133. static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol,
  134. struct snd_ctl_elem_value *ucontrol)
  135. {
  136. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  137. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  138. ucontrol->value.integer.value[0] = dmic->boost_gain;
  139. return 0;
  140. }
  141. static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol,
  142. struct snd_ctl_elem_value *ucontrol)
  143. {
  144. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  145. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  146. int value = ucontrol->value.integer.value[0];
  147. if (value == dmic->boost_gain)
  148. return 0;
  149. dmic->boost_gain = value;
  150. return 1;
  151. }
  152. static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol,
  153. struct snd_ctl_elem_value *ucontrol)
  154. {
  155. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  156. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  157. ucontrol->value.enumerated.item[0] = dmic->ch_select;
  158. return 0;
  159. }
  160. static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol,
  161. struct snd_ctl_elem_value *ucontrol)
  162. {
  163. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  164. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  165. unsigned int value = ucontrol->value.enumerated.item[0];
  166. if (value == dmic->ch_select)
  167. return 0;
  168. dmic->ch_select = value;
  169. return 1;
  170. }
  171. static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
  172. struct snd_ctl_elem_value *ucontrol)
  173. {
  174. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  175. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  176. ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo;
  177. return 0;
  178. }
  179. static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
  180. struct snd_ctl_elem_value *ucontrol)
  181. {
  182. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  183. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  184. unsigned int value = ucontrol->value.enumerated.item[0];
  185. if (value == dmic->mono_to_stereo)
  186. return 0;
  187. dmic->mono_to_stereo = value;
  188. return 1;
  189. }
  190. static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
  191. struct snd_ctl_elem_value *ucontrol)
  192. {
  193. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  194. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  195. ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono;
  196. return 0;
  197. }
  198. static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
  199. struct snd_ctl_elem_value *ucontrol)
  200. {
  201. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  202. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  203. unsigned int value = ucontrol->value.enumerated.item[0];
  204. if (value == dmic->stereo_to_mono)
  205. return 0;
  206. dmic->stereo_to_mono = value;
  207. return 1;
  208. }
  209. static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol,
  210. struct snd_ctl_elem_value *ucontrol)
  211. {
  212. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  213. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  214. ucontrol->value.enumerated.item[0] = dmic->osr_val;
  215. return 0;
  216. }
  217. static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol,
  218. struct snd_ctl_elem_value *ucontrol)
  219. {
  220. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  221. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  222. unsigned int value = ucontrol->value.enumerated.item[0];
  223. if (value == dmic->osr_val)
  224. return 0;
  225. dmic->osr_val = value;
  226. return 1;
  227. }
  228. static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol,
  229. struct snd_ctl_elem_value *ucontrol)
  230. {
  231. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  232. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  233. ucontrol->value.enumerated.item[0] = dmic->lrsel;
  234. return 0;
  235. }
  236. static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol,
  237. struct snd_ctl_elem_value *ucontrol)
  238. {
  239. struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
  240. struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
  241. unsigned int value = ucontrol->value.enumerated.item[0];
  242. if (value == dmic->lrsel)
  243. return 0;
  244. dmic->lrsel = value;
  245. return 1;
  246. }
  247. static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = {
  248. .hw_params = tegra210_dmic_hw_params,
  249. };
  250. static struct snd_soc_dai_driver tegra210_dmic_dais[] = {
  251. {
  252. .name = "DMIC-CIF",
  253. .capture = {
  254. .stream_name = "CIF-Capture",
  255. .channels_min = 1,
  256. .channels_max = 2,
  257. .rates = SNDRV_PCM_RATE_8000_48000,
  258. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  259. SNDRV_PCM_FMTBIT_S32_LE,
  260. },
  261. },
  262. {
  263. .name = "DMIC-DAP",
  264. .capture = {
  265. .stream_name = "DAP-Capture",
  266. .channels_min = 1,
  267. .channels_max = 2,
  268. .rates = SNDRV_PCM_RATE_8000_48000,
  269. .formats = SNDRV_PCM_FMTBIT_S16_LE |
  270. SNDRV_PCM_FMTBIT_S32_LE,
  271. },
  272. .ops = &tegra210_dmic_dai_ops,
  273. .symmetric_rate = 1,
  274. },
  275. };
  276. static const struct snd_soc_dapm_widget tegra210_dmic_widgets[] = {
  277. SND_SOC_DAPM_AIF_OUT("TX", NULL, 0, TEGRA210_DMIC_ENABLE, 0, 0),
  278. SND_SOC_DAPM_MIC("MIC", NULL),
  279. };
  280. static const struct snd_soc_dapm_route tegra210_dmic_routes[] = {
  281. { "XBAR-RX", NULL, "XBAR-Capture" },
  282. { "XBAR-Capture", NULL, "CIF-Capture" },
  283. { "CIF-Capture", NULL, "TX" },
  284. { "TX", NULL, "DAP-Capture" },
  285. { "DAP-Capture", NULL, "MIC" },
  286. };
  287. static const char * const tegra210_dmic_ch_select[] = {
  288. "Left", "Right", "Stereo",
  289. };
  290. static const struct soc_enum tegra210_dmic_ch_enum =
  291. SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_ch_select),
  292. tegra210_dmic_ch_select);
  293. static const char * const tegra210_dmic_mono_conv_text[] = {
  294. "Zero", "Copy",
  295. };
  296. static const char * const tegra210_dmic_stereo_conv_text[] = {
  297. "CH0", "CH1", "AVG",
  298. };
  299. static const struct soc_enum tegra210_dmic_mono_conv_enum =
  300. SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_mono_conv_text),
  301. tegra210_dmic_mono_conv_text);
  302. static const struct soc_enum tegra210_dmic_stereo_conv_enum =
  303. SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_stereo_conv_text),
  304. tegra210_dmic_stereo_conv_text);
  305. static const char * const tegra210_dmic_osr_text[] = {
  306. "OSR_64", "OSR_128", "OSR_256",
  307. };
  308. static const struct soc_enum tegra210_dmic_osr_enum =
  309. SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_osr_text),
  310. tegra210_dmic_osr_text);
  311. static const char * const tegra210_dmic_lrsel_text[] = {
  312. "Left", "Right",
  313. };
  314. static const struct soc_enum tegra210_dmic_lrsel_enum =
  315. SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(tegra210_dmic_lrsel_text),
  316. tegra210_dmic_lrsel_text);
  317. static const struct snd_kcontrol_new tegra210_dmic_controls[] = {
  318. SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0,
  319. tegra210_dmic_get_boost_gain,
  320. tegra210_dmic_put_boost_gain),
  321. SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum,
  322. tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select),
  323. SOC_ENUM_EXT("Mono To Stereo",
  324. tegra210_dmic_mono_conv_enum,
  325. tegra210_dmic_get_mono_to_stereo,
  326. tegra210_dmic_put_mono_to_stereo),
  327. SOC_ENUM_EXT("Stereo To Mono",
  328. tegra210_dmic_stereo_conv_enum,
  329. tegra210_dmic_get_stereo_to_mono,
  330. tegra210_dmic_put_stereo_to_mono),
  331. SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum,
  332. tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val),
  333. SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum,
  334. tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel),
  335. };
  336. static const struct snd_soc_component_driver tegra210_dmic_compnt = {
  337. .dapm_widgets = tegra210_dmic_widgets,
  338. .num_dapm_widgets = ARRAY_SIZE(tegra210_dmic_widgets),
  339. .dapm_routes = tegra210_dmic_routes,
  340. .num_dapm_routes = ARRAY_SIZE(tegra210_dmic_routes),
  341. .controls = tegra210_dmic_controls,
  342. .num_controls = ARRAY_SIZE(tegra210_dmic_controls),
  343. };
  344. static bool tegra210_dmic_wr_reg(struct device *dev, unsigned int reg)
  345. {
  346. switch (reg) {
  347. case TEGRA210_DMIC_TX_INT_MASK ... TEGRA210_DMIC_TX_CIF_CTRL:
  348. case TEGRA210_DMIC_ENABLE ... TEGRA210_DMIC_CG:
  349. case TEGRA210_DMIC_CTRL:
  350. case TEGRA210_DMIC_DBG_CTRL:
  351. case TEGRA210_DMIC_DCR_BIQUAD_0_COEF_4 ... TEGRA210_DMIC_LP_BIQUAD_1_COEF_4:
  352. return true;
  353. default:
  354. return false;
  355. }
  356. }
  357. static bool tegra210_dmic_rd_reg(struct device *dev, unsigned int reg)
  358. {
  359. if (tegra210_dmic_wr_reg(dev, reg))
  360. return true;
  361. switch (reg) {
  362. case TEGRA210_DMIC_TX_STATUS:
  363. case TEGRA210_DMIC_TX_INT_STATUS:
  364. case TEGRA210_DMIC_STATUS:
  365. case TEGRA210_DMIC_INT_STATUS:
  366. return true;
  367. default:
  368. return false;
  369. }
  370. }
  371. static bool tegra210_dmic_volatile_reg(struct device *dev, unsigned int reg)
  372. {
  373. switch (reg) {
  374. case TEGRA210_DMIC_TX_STATUS:
  375. case TEGRA210_DMIC_TX_INT_STATUS:
  376. case TEGRA210_DMIC_TX_INT_SET:
  377. case TEGRA210_DMIC_SOFT_RESET:
  378. case TEGRA210_DMIC_STATUS:
  379. case TEGRA210_DMIC_INT_STATUS:
  380. return true;
  381. default:
  382. return false;
  383. }
  384. }
  385. static const struct regmap_config tegra210_dmic_regmap_config = {
  386. .reg_bits = 32,
  387. .reg_stride = 4,
  388. .val_bits = 32,
  389. .max_register = TEGRA210_DMIC_LP_BIQUAD_1_COEF_4,
  390. .writeable_reg = tegra210_dmic_wr_reg,
  391. .readable_reg = tegra210_dmic_rd_reg,
  392. .volatile_reg = tegra210_dmic_volatile_reg,
  393. .reg_defaults = tegra210_dmic_reg_defaults,
  394. .num_reg_defaults = ARRAY_SIZE(tegra210_dmic_reg_defaults),
  395. .cache_type = REGCACHE_FLAT,
  396. };
  397. static int tegra210_dmic_probe(struct platform_device *pdev)
  398. {
  399. struct device *dev = &pdev->dev;
  400. struct tegra210_dmic *dmic;
  401. void __iomem *regs;
  402. int err;
  403. dmic = devm_kzalloc(dev, sizeof(*dmic), GFP_KERNEL);
  404. if (!dmic)
  405. return -ENOMEM;
  406. dmic->osr_val = DMIC_OSR_64;
  407. dmic->ch_select = DMIC_CH_SELECT_STEREO;
  408. dmic->lrsel = DMIC_LRSEL_LEFT;
  409. dmic->boost_gain = 0;
  410. dmic->stereo_to_mono = 0; /* "CH0" */
  411. dev_set_drvdata(dev, dmic);
  412. dmic->clk_dmic = devm_clk_get(dev, "dmic");
  413. if (IS_ERR(dmic->clk_dmic)) {
  414. dev_err(dev, "can't retrieve DMIC clock\n");
  415. return PTR_ERR(dmic->clk_dmic);
  416. }
  417. regs = devm_platform_ioremap_resource(pdev, 0);
  418. if (IS_ERR(regs))
  419. return PTR_ERR(regs);
  420. dmic->regmap = devm_regmap_init_mmio(dev, regs,
  421. &tegra210_dmic_regmap_config);
  422. if (IS_ERR(dmic->regmap)) {
  423. dev_err(dev, "regmap init failed\n");
  424. return PTR_ERR(dmic->regmap);
  425. }
  426. regcache_cache_only(dmic->regmap, true);
  427. err = devm_snd_soc_register_component(dev, &tegra210_dmic_compnt,
  428. tegra210_dmic_dais,
  429. ARRAY_SIZE(tegra210_dmic_dais));
  430. if (err) {
  431. dev_err(dev, "can't register DMIC component, err: %d\n", err);
  432. return err;
  433. }
  434. pm_runtime_enable(dev);
  435. return 0;
  436. }
  437. static int tegra210_dmic_remove(struct platform_device *pdev)
  438. {
  439. pm_runtime_disable(&pdev->dev);
  440. return 0;
  441. }
  442. static const struct dev_pm_ops tegra210_dmic_pm_ops = {
  443. SET_RUNTIME_PM_OPS(tegra210_dmic_runtime_suspend,
  444. tegra210_dmic_runtime_resume, NULL)
  445. SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
  446. pm_runtime_force_resume)
  447. };
  448. static const struct of_device_id tegra210_dmic_of_match[] = {
  449. { .compatible = "nvidia,tegra210-dmic" },
  450. {},
  451. };
  452. MODULE_DEVICE_TABLE(of, tegra210_dmic_of_match);
  453. static struct platform_driver tegra210_dmic_driver = {
  454. .driver = {
  455. .name = "tegra210-dmic",
  456. .of_match_table = tegra210_dmic_of_match,
  457. .pm = &tegra210_dmic_pm_ops,
  458. },
  459. .probe = tegra210_dmic_probe,
  460. .remove = tegra210_dmic_remove,
  461. };
  462. module_platform_driver(tegra210_dmic_driver)
  463. MODULE_AUTHOR("Rahul Mittal <[email protected]>");
  464. MODULE_DESCRIPTION("Tegra210 ASoC DMIC driver");
  465. MODULE_LICENSE("GPL v2");