uda134x.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /*
  2. * uda134x.c -- UDA134X ALSA SoC Codec driver
  3. *
  4. * Modifications by Christian Pellegrin <chripell@evolware.org>
  5. *
  6. * Copyright 2007 Dension Audio Systems Ltd.
  7. * Author: Zoltan Devai
  8. *
  9. * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/delay.h>
  17. #include <linux/slab.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/uda134x.h>
  23. #include <sound/l3.h>
  24. #include "uda134x.h"
  25. #define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
  26. #define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
  27. SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
  28. struct uda134x_priv {
  29. int sysclk;
  30. int dai_fmt;
  31. struct snd_pcm_substream *master_substream;
  32. struct snd_pcm_substream *slave_substream;
  33. struct regmap *regmap;
  34. struct uda134x_platform_data *pd;
  35. };
  36. static const struct reg_default uda134x_reg_defaults[] = {
  37. { UDA134X_EA000, 0x04 },
  38. { UDA134X_EA001, 0x04 },
  39. { UDA134X_EA010, 0x04 },
  40. { UDA134X_EA011, 0x00 },
  41. { UDA134X_EA100, 0x00 },
  42. { UDA134X_EA101, 0x00 },
  43. { UDA134X_EA110, 0x00 },
  44. { UDA134X_EA111, 0x00 },
  45. { UDA134X_STATUS0, 0x00 },
  46. { UDA134X_STATUS1, 0x03 },
  47. { UDA134X_DATA000, 0x00 },
  48. { UDA134X_DATA001, 0x00 },
  49. { UDA134X_DATA010, 0x00 },
  50. { UDA134X_DATA011, 0x00 },
  51. { UDA134X_DATA1, 0x00 },
  52. };
  53. /*
  54. * Write to the uda134x registers
  55. *
  56. */
  57. static int uda134x_regmap_write(void *context, unsigned int reg,
  58. unsigned int value)
  59. {
  60. struct uda134x_platform_data *pd = context;
  61. int ret;
  62. u8 addr;
  63. u8 data = value;
  64. switch (reg) {
  65. case UDA134X_STATUS0:
  66. case UDA134X_STATUS1:
  67. addr = UDA134X_STATUS_ADDR;
  68. data |= (reg - UDA134X_STATUS0) << 7;
  69. break;
  70. case UDA134X_DATA000:
  71. case UDA134X_DATA001:
  72. case UDA134X_DATA010:
  73. case UDA134X_DATA011:
  74. addr = UDA134X_DATA0_ADDR;
  75. data |= (reg - UDA134X_DATA000) << 6;
  76. break;
  77. case UDA134X_DATA1:
  78. addr = UDA134X_DATA1_ADDR;
  79. break;
  80. default:
  81. /* It's an extended address register */
  82. addr = (reg | UDA134X_EXTADDR_PREFIX);
  83. ret = l3_write(&pd->l3,
  84. UDA134X_DATA0_ADDR, &addr, 1);
  85. if (ret != 1)
  86. return -EIO;
  87. addr = UDA134X_DATA0_ADDR;
  88. data = (value | UDA134X_EXTDATA_PREFIX);
  89. break;
  90. }
  91. ret = l3_write(&pd->l3,
  92. addr, &data, 1);
  93. if (ret != 1)
  94. return -EIO;
  95. return 0;
  96. }
  97. static inline void uda134x_reset(struct snd_soc_codec *codec)
  98. {
  99. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  100. unsigned int mask = 1<<6;
  101. regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, mask);
  102. msleep(1);
  103. regmap_update_bits(uda134x->regmap, UDA134X_STATUS0, mask, 0);
  104. }
  105. static int uda134x_mute(struct snd_soc_dai *dai, int mute)
  106. {
  107. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(dai->codec);
  108. unsigned int mask = 1<<2;
  109. unsigned int val;
  110. pr_debug("%s mute: %d\n", __func__, mute);
  111. if (mute)
  112. val = mask;
  113. else
  114. val = 0;
  115. return regmap_update_bits(uda134x->regmap, UDA134X_DATA010, mask, val);
  116. }
  117. static int uda134x_startup(struct snd_pcm_substream *substream,
  118. struct snd_soc_dai *dai)
  119. {
  120. struct snd_soc_codec *codec = dai->codec;
  121. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  122. struct snd_pcm_runtime *master_runtime;
  123. if (uda134x->master_substream) {
  124. master_runtime = uda134x->master_substream->runtime;
  125. pr_debug("%s constraining to %d bits at %d\n", __func__,
  126. master_runtime->sample_bits,
  127. master_runtime->rate);
  128. snd_pcm_hw_constraint_single(substream->runtime,
  129. SNDRV_PCM_HW_PARAM_RATE,
  130. master_runtime->rate);
  131. snd_pcm_hw_constraint_single(substream->runtime,
  132. SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
  133. master_runtime->sample_bits);
  134. uda134x->slave_substream = substream;
  135. } else
  136. uda134x->master_substream = substream;
  137. return 0;
  138. }
  139. static void uda134x_shutdown(struct snd_pcm_substream *substream,
  140. struct snd_soc_dai *dai)
  141. {
  142. struct snd_soc_codec *codec = dai->codec;
  143. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  144. if (uda134x->master_substream == substream)
  145. uda134x->master_substream = uda134x->slave_substream;
  146. uda134x->slave_substream = NULL;
  147. }
  148. static int uda134x_hw_params(struct snd_pcm_substream *substream,
  149. struct snd_pcm_hw_params *params,
  150. struct snd_soc_dai *dai)
  151. {
  152. struct snd_soc_codec *codec = dai->codec;
  153. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  154. unsigned int hw_params = 0;
  155. if (substream == uda134x->slave_substream) {
  156. pr_debug("%s ignoring hw_params for slave substream\n",
  157. __func__);
  158. return 0;
  159. }
  160. pr_debug("%s sysclk: %d, rate:%d\n", __func__,
  161. uda134x->sysclk, params_rate(params));
  162. /* set SYSCLK / fs ratio */
  163. switch (uda134x->sysclk / params_rate(params)) {
  164. case 512:
  165. break;
  166. case 384:
  167. hw_params |= (1<<4);
  168. break;
  169. case 256:
  170. hw_params |= (1<<5);
  171. break;
  172. default:
  173. printk(KERN_ERR "%s unsupported fs\n", __func__);
  174. return -EINVAL;
  175. }
  176. pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
  177. uda134x->dai_fmt, params_format(params));
  178. /* set DAI format and word length */
  179. switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  180. case SND_SOC_DAIFMT_I2S:
  181. break;
  182. case SND_SOC_DAIFMT_RIGHT_J:
  183. switch (params_width(params)) {
  184. case 16:
  185. hw_params |= (1<<1);
  186. break;
  187. case 18:
  188. hw_params |= (1<<2);
  189. break;
  190. case 20:
  191. hw_params |= ((1<<2) | (1<<1));
  192. break;
  193. default:
  194. printk(KERN_ERR "%s unsupported format (right)\n",
  195. __func__);
  196. return -EINVAL;
  197. }
  198. break;
  199. case SND_SOC_DAIFMT_LEFT_J:
  200. hw_params |= (1<<3);
  201. break;
  202. default:
  203. printk(KERN_ERR "%s unsupported format\n", __func__);
  204. return -EINVAL;
  205. }
  206. return regmap_update_bits(uda134x->regmap, UDA134X_STATUS0,
  207. STATUS0_SYSCLK_MASK | STATUS0_DAIFMT_MASK, hw_params);
  208. }
  209. static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
  210. int clk_id, unsigned int freq, int dir)
  211. {
  212. struct snd_soc_codec *codec = codec_dai->codec;
  213. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  214. pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
  215. clk_id, freq, dir);
  216. /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
  217. because the codec is slave. Of course limitations of the clock
  218. master (the IIS controller) apply.
  219. We'll error out on set_hw_params if it's not OK */
  220. if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
  221. uda134x->sysclk = freq;
  222. return 0;
  223. }
  224. printk(KERN_ERR "%s unsupported sysclk\n", __func__);
  225. return -EINVAL;
  226. }
  227. static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
  228. unsigned int fmt)
  229. {
  230. struct snd_soc_codec *codec = codec_dai->codec;
  231. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  232. pr_debug("%s fmt: %08X\n", __func__, fmt);
  233. /* codec supports only full slave mode */
  234. if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
  235. printk(KERN_ERR "%s unsupported slave mode\n", __func__);
  236. return -EINVAL;
  237. }
  238. /* no support for clock inversion */
  239. if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
  240. printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
  241. return -EINVAL;
  242. }
  243. /* We can't setup DAI format here as it depends on the word bit num */
  244. /* so let's just store the value for later */
  245. uda134x->dai_fmt = fmt;
  246. return 0;
  247. }
  248. static int uda134x_set_bias_level(struct snd_soc_codec *codec,
  249. enum snd_soc_bias_level level)
  250. {
  251. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  252. struct uda134x_platform_data *pd = uda134x->pd;
  253. pr_debug("%s bias level %d\n", __func__, level);
  254. switch (level) {
  255. case SND_SOC_BIAS_ON:
  256. break;
  257. case SND_SOC_BIAS_PREPARE:
  258. /* power on */
  259. if (pd->power) {
  260. pd->power(1);
  261. regcache_sync(uda134x->regmap);
  262. }
  263. break;
  264. case SND_SOC_BIAS_STANDBY:
  265. break;
  266. case SND_SOC_BIAS_OFF:
  267. /* power off */
  268. if (pd->power) {
  269. pd->power(0);
  270. regcache_mark_dirty(uda134x->regmap);
  271. }
  272. break;
  273. }
  274. return 0;
  275. }
  276. static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
  277. "Minimum2", "Maximum"};
  278. static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
  279. static const char *uda134x_mixmode[] = {"Differential", "Analog1",
  280. "Analog2", "Both"};
  281. static const struct soc_enum uda134x_mixer_enum[] = {
  282. SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
  283. SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
  284. SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
  285. };
  286. static const struct snd_kcontrol_new uda1341_snd_controls[] = {
  287. SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
  288. SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
  289. SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
  290. SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
  291. SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
  292. SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
  293. SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
  294. SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
  295. SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
  296. SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
  297. SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
  298. SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
  299. SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
  300. SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
  301. SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
  302. SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
  303. SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
  304. SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
  305. SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
  306. SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
  307. };
  308. static const struct snd_kcontrol_new uda1340_snd_controls[] = {
  309. SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
  310. SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
  311. SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
  312. SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
  313. SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
  314. SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
  315. };
  316. static const struct snd_kcontrol_new uda1345_snd_controls[] = {
  317. SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
  318. SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
  319. SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
  320. };
  321. /* UDA1341 has the DAC/ADC power down in STATUS1 */
  322. static const struct snd_soc_dapm_widget uda1341_dapm_widgets[] = {
  323. SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_STATUS1, 0, 0),
  324. SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_STATUS1, 1, 0),
  325. };
  326. /* UDA1340/4/5 has the DAC/ADC pwoer down in DATA0 11 */
  327. static const struct snd_soc_dapm_widget uda1340_dapm_widgets[] = {
  328. SND_SOC_DAPM_DAC("DAC", "Playback", UDA134X_DATA011, 0, 0),
  329. SND_SOC_DAPM_ADC("ADC", "Capture", UDA134X_DATA011, 1, 0),
  330. };
  331. /* Common DAPM widgets */
  332. static const struct snd_soc_dapm_widget uda134x_dapm_widgets[] = {
  333. SND_SOC_DAPM_INPUT("VINL1"),
  334. SND_SOC_DAPM_INPUT("VINR1"),
  335. SND_SOC_DAPM_INPUT("VINL2"),
  336. SND_SOC_DAPM_INPUT("VINR2"),
  337. SND_SOC_DAPM_OUTPUT("VOUTL"),
  338. SND_SOC_DAPM_OUTPUT("VOUTR"),
  339. };
  340. static const struct snd_soc_dapm_route uda134x_dapm_routes[] = {
  341. { "ADC", NULL, "VINL1" },
  342. { "ADC", NULL, "VINR1" },
  343. { "ADC", NULL, "VINL2" },
  344. { "ADC", NULL, "VINR2" },
  345. { "VOUTL", NULL, "DAC" },
  346. { "VOUTR", NULL, "DAC" },
  347. };
  348. static const struct snd_soc_dai_ops uda134x_dai_ops = {
  349. .startup = uda134x_startup,
  350. .shutdown = uda134x_shutdown,
  351. .hw_params = uda134x_hw_params,
  352. .digital_mute = uda134x_mute,
  353. .set_sysclk = uda134x_set_dai_sysclk,
  354. .set_fmt = uda134x_set_dai_fmt,
  355. };
  356. static struct snd_soc_dai_driver uda134x_dai = {
  357. .name = "uda134x-hifi",
  358. /* playback capabilities */
  359. .playback = {
  360. .stream_name = "Playback",
  361. .channels_min = 1,
  362. .channels_max = 2,
  363. .rates = UDA134X_RATES,
  364. .formats = UDA134X_FORMATS,
  365. },
  366. /* capture capabilities */
  367. .capture = {
  368. .stream_name = "Capture",
  369. .channels_min = 1,
  370. .channels_max = 2,
  371. .rates = UDA134X_RATES,
  372. .formats = UDA134X_FORMATS,
  373. },
  374. /* pcm operations */
  375. .ops = &uda134x_dai_ops,
  376. };
  377. static int uda134x_soc_probe(struct snd_soc_codec *codec)
  378. {
  379. struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
  380. struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
  381. struct uda134x_platform_data *pd = uda134x->pd;
  382. const struct snd_soc_dapm_widget *widgets;
  383. unsigned num_widgets;
  384. int ret;
  385. printk(KERN_INFO "UDA134X SoC Audio Codec\n");
  386. switch (pd->model) {
  387. case UDA134X_UDA1340:
  388. case UDA134X_UDA1341:
  389. case UDA134X_UDA1344:
  390. case UDA134X_UDA1345:
  391. break;
  392. default:
  393. printk(KERN_ERR "UDA134X SoC codec: "
  394. "unsupported model %d\n",
  395. pd->model);
  396. return -EINVAL;
  397. }
  398. if (pd->power)
  399. pd->power(1);
  400. uda134x_reset(codec);
  401. if (pd->model == UDA134X_UDA1341) {
  402. widgets = uda1341_dapm_widgets;
  403. num_widgets = ARRAY_SIZE(uda1341_dapm_widgets);
  404. } else {
  405. widgets = uda1340_dapm_widgets;
  406. num_widgets = ARRAY_SIZE(uda1340_dapm_widgets);
  407. }
  408. ret = snd_soc_dapm_new_controls(dapm, widgets, num_widgets);
  409. if (ret) {
  410. printk(KERN_ERR "%s failed to register dapm controls: %d",
  411. __func__, ret);
  412. return ret;
  413. }
  414. switch (pd->model) {
  415. case UDA134X_UDA1340:
  416. case UDA134X_UDA1344:
  417. ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
  418. ARRAY_SIZE(uda1340_snd_controls));
  419. break;
  420. case UDA134X_UDA1341:
  421. ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
  422. ARRAY_SIZE(uda1341_snd_controls));
  423. break;
  424. case UDA134X_UDA1345:
  425. ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
  426. ARRAY_SIZE(uda1345_snd_controls));
  427. break;
  428. default:
  429. printk(KERN_ERR "%s unknown codec type: %d",
  430. __func__, pd->model);
  431. return -EINVAL;
  432. }
  433. if (ret < 0) {
  434. printk(KERN_ERR "UDA134X: failed to register controls\n");
  435. return ret;
  436. }
  437. return 0;
  438. }
  439. static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
  440. .probe = uda134x_soc_probe,
  441. .set_bias_level = uda134x_set_bias_level,
  442. .suspend_bias_off = true,
  443. .dapm_widgets = uda134x_dapm_widgets,
  444. .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
  445. .dapm_routes = uda134x_dapm_routes,
  446. .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
  447. };
  448. static const struct regmap_config uda134x_regmap_config = {
  449. .reg_bits = 8,
  450. .val_bits = 8,
  451. .max_register = UDA134X_DATA1,
  452. .reg_defaults = uda134x_reg_defaults,
  453. .num_reg_defaults = ARRAY_SIZE(uda134x_reg_defaults),
  454. .cache_type = REGCACHE_RBTREE,
  455. .reg_write = uda134x_regmap_write,
  456. };
  457. static int uda134x_codec_probe(struct platform_device *pdev)
  458. {
  459. struct uda134x_platform_data *pd = pdev->dev.platform_data;
  460. struct uda134x_priv *uda134x;
  461. if (!pd) {
  462. dev_err(&pdev->dev, "Missing L3 bitbang function\n");
  463. return -ENODEV;
  464. }
  465. uda134x = devm_kzalloc(&pdev->dev, sizeof(*uda134x), GFP_KERNEL);
  466. if (!uda134x)
  467. return -ENOMEM;
  468. uda134x->pd = pd;
  469. platform_set_drvdata(pdev, uda134x);
  470. uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd,
  471. &uda134x_regmap_config);
  472. if (IS_ERR(uda134x->regmap))
  473. return PTR_ERR(uda134x->regmap);
  474. return snd_soc_register_codec(&pdev->dev,
  475. &soc_codec_dev_uda134x, &uda134x_dai, 1);
  476. }
  477. static int uda134x_codec_remove(struct platform_device *pdev)
  478. {
  479. snd_soc_unregister_codec(&pdev->dev);
  480. return 0;
  481. }
  482. static struct platform_driver uda134x_codec_driver = {
  483. .driver = {
  484. .name = "uda134x-codec",
  485. },
  486. .probe = uda134x_codec_probe,
  487. .remove = uda134x_codec_remove,
  488. };
  489. module_platform_driver(uda134x_codec_driver);
  490. MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
  491. MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
  492. MODULE_LICENSE("GPL");