jz4770.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Ingenic JZ4770 CODEC driver
  4. //
  5. // Copyright (C) 2012, Maarten ter Huurne <[email protected]>
  6. // Copyright (C) 2019, Paul Cercueil <[email protected]>
  7. #include <linux/clk.h>
  8. #include <linux/delay.h>
  9. #include <linux/iopoll.h>
  10. #include <linux/module.h>
  11. #include <linux/regmap.h>
  12. #include <linux/time64.h>
  13. #include <sound/pcm_params.h>
  14. #include <sound/soc.h>
  15. #include <sound/soc-dai.h>
  16. #include <sound/soc-dapm.h>
  17. #include <sound/tlv.h>
  18. #define ICDC_RGADW_OFFSET 0x00
  19. #define ICDC_RGDATA_OFFSET 0x04
  20. /* ICDC internal register access control register(RGADW) */
  21. #define ICDC_RGADW_RGWR BIT(16)
  22. #define ICDC_RGADW_RGADDR_OFFSET 8
  23. #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
  24. #define ICDC_RGADW_RGDIN_OFFSET 0
  25. #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
  26. /* ICDC internal register data output register (RGDATA)*/
  27. #define ICDC_RGDATA_IRQ BIT(8)
  28. #define ICDC_RGDATA_RGDOUT_OFFSET 0
  29. #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
  30. /* Internal register space, accessed through regmap */
  31. enum {
  32. JZ4770_CODEC_REG_SR,
  33. JZ4770_CODEC_REG_AICR_DAC,
  34. JZ4770_CODEC_REG_AICR_ADC,
  35. JZ4770_CODEC_REG_CR_LO,
  36. JZ4770_CODEC_REG_CR_HP,
  37. JZ4770_CODEC_REG_MISSING_REG1,
  38. JZ4770_CODEC_REG_CR_DAC,
  39. JZ4770_CODEC_REG_CR_MIC,
  40. JZ4770_CODEC_REG_CR_LI,
  41. JZ4770_CODEC_REG_CR_ADC,
  42. JZ4770_CODEC_REG_CR_MIX,
  43. JZ4770_CODEC_REG_CR_VIC,
  44. JZ4770_CODEC_REG_CCR,
  45. JZ4770_CODEC_REG_FCR_DAC,
  46. JZ4770_CODEC_REG_FCR_ADC,
  47. JZ4770_CODEC_REG_ICR,
  48. JZ4770_CODEC_REG_IMR,
  49. JZ4770_CODEC_REG_IFR,
  50. JZ4770_CODEC_REG_GCR_HPL,
  51. JZ4770_CODEC_REG_GCR_HPR,
  52. JZ4770_CODEC_REG_GCR_LIBYL,
  53. JZ4770_CODEC_REG_GCR_LIBYR,
  54. JZ4770_CODEC_REG_GCR_DACL,
  55. JZ4770_CODEC_REG_GCR_DACR,
  56. JZ4770_CODEC_REG_GCR_MIC1,
  57. JZ4770_CODEC_REG_GCR_MIC2,
  58. JZ4770_CODEC_REG_GCR_ADCL,
  59. JZ4770_CODEC_REG_GCR_ADCR,
  60. JZ4770_CODEC_REG_MISSING_REG2,
  61. JZ4770_CODEC_REG_GCR_MIXADC,
  62. JZ4770_CODEC_REG_GCR_MIXDAC,
  63. JZ4770_CODEC_REG_AGC1,
  64. JZ4770_CODEC_REG_AGC2,
  65. JZ4770_CODEC_REG_AGC3,
  66. JZ4770_CODEC_REG_AGC4,
  67. JZ4770_CODEC_REG_AGC5,
  68. };
  69. #define REG_AICR_DAC_ADWL_OFFSET 6
  70. #define REG_AICR_DAC_ADWL_MASK (0x3 << REG_AICR_DAC_ADWL_OFFSET)
  71. #define REG_AICR_DAC_SERIAL BIT(1)
  72. #define REG_AICR_DAC_I2S BIT(0)
  73. #define REG_AICR_ADC_ADWL_OFFSET 6
  74. #define REG_AICR_ADC_ADWL_MASK (0x3 << REG_AICR_ADC_ADWL_OFFSET)
  75. #define REG_AICR_ADC_SERIAL BIT(1)
  76. #define REG_AICR_ADC_I2S BIT(0)
  77. #define REG_CR_LO_MUTE_OFFSET 7
  78. #define REG_CR_LO_SB_OFFSET 4
  79. #define REG_CR_LO_SEL_OFFSET 0
  80. #define REG_CR_LO_SEL_MASK (0x3 << REG_CR_LO_SEL_OFFSET)
  81. #define REG_CR_HP_MUTE BIT(7)
  82. #define REG_CR_HP_LOAD BIT(6)
  83. #define REG_CR_HP_SB_OFFSET 4
  84. #define REG_CR_HP_SB_HPCM_OFFSET 3
  85. #define REG_CR_HP_SEL_OFFSET 0
  86. #define REG_CR_HP_SEL_MASK (0x3 << REG_CR_HP_SEL_OFFSET)
  87. #define REG_CR_DAC_MUTE BIT(7)
  88. #define REG_CR_DAC_MONO BIT(6)
  89. #define REG_CR_DAC_LEFT_ONLY BIT(5)
  90. #define REG_CR_DAC_SB_OFFSET 4
  91. #define REG_CR_DAC_LRSWAP BIT(3)
  92. #define REG_CR_MIC_STEREO_OFFSET 7
  93. #define REG_CR_MIC_IDIFF_OFFSET 6
  94. #define REG_CR_MIC_SB_MIC2_OFFSET 5
  95. #define REG_CR_MIC_SB_MIC1_OFFSET 4
  96. #define REG_CR_MIC_BIAS_V0_OFFSET 1
  97. #define REG_CR_MIC_BIAS_SB_OFFSET 0
  98. #define REG_CR_LI_LIBY_OFFSET 4
  99. #define REG_CR_LI_SB_OFFSET 0
  100. #define REG_CR_ADC_DMIC_SEL BIT(7)
  101. #define REG_CR_ADC_MONO BIT(6)
  102. #define REG_CR_ADC_LEFT_ONLY BIT(5)
  103. #define REG_CR_ADC_SB_OFFSET 4
  104. #define REG_CR_ADC_LRSWAP BIT(3)
  105. #define REG_CR_ADC_IN_SEL_OFFSET 0
  106. #define REG_CR_ADC_IN_SEL_MASK (0x3 << REG_CR_ADC_IN_SEL_OFFSET)
  107. #define REG_CR_VIC_SB_SLEEP BIT(1)
  108. #define REG_CR_VIC_SB BIT(0)
  109. #define REG_CCR_CRYSTAL_OFFSET 0
  110. #define REG_CCR_CRYSTAL_MASK (0xf << REG_CCR_CRYSTAL_OFFSET)
  111. #define REG_FCR_DAC_FREQ_OFFSET 0
  112. #define REG_FCR_DAC_FREQ_MASK (0xf << REG_FCR_DAC_FREQ_OFFSET)
  113. #define REG_FCR_ADC_FREQ_OFFSET 0
  114. #define REG_FCR_ADC_FREQ_MASK (0xf << REG_FCR_ADC_FREQ_OFFSET)
  115. #define REG_ICR_INT_FORM_OFFSET 6
  116. #define REG_ICR_INT_FORM_MASK (0x3 << REG_ICR_INT_FORM_OFFSET)
  117. #define REG_IMR_ALL_MASK (0x7f)
  118. #define REG_IMR_SCLR_MASK BIT(6)
  119. #define REG_IMR_JACK_MASK BIT(5)
  120. #define REG_IMR_SCMC_MASK BIT(4)
  121. #define REG_IMR_RUP_MASK BIT(3)
  122. #define REG_IMR_RDO_MASK BIT(2)
  123. #define REG_IMR_GUP_MASK BIT(1)
  124. #define REG_IMR_GDO_MASK BIT(0)
  125. #define REG_IFR_ALL_MASK (0x7f)
  126. #define REG_IFR_SCLR BIT(6)
  127. #define REG_IFR_JACK BIT(5)
  128. #define REG_IFR_SCMC BIT(4)
  129. #define REG_IFR_RUP BIT(3)
  130. #define REG_IFR_RDO BIT(2)
  131. #define REG_IFR_GUP BIT(1)
  132. #define REG_IFR_GDO BIT(0)
  133. #define REG_GCR_HPL_LRGO BIT(7)
  134. #define REG_GCR_DACL_RLGOD BIT(7)
  135. #define REG_GCR_GAIN_OFFSET 0
  136. #define REG_GCR_GAIN_MAX 0x1f
  137. #define REG_GCR_MIC_GAIN_OFFSET 0
  138. #define REG_GCR_MIC_GAIN_MAX 5
  139. #define REG_GCR_ADC_GAIN_OFFSET 0
  140. #define REG_GCR_ADC_GAIN_MAX 23
  141. #define REG_AGC1_EN BIT(7)
  142. /* codec private data */
  143. struct jz_codec {
  144. struct device *dev;
  145. struct regmap *regmap;
  146. void __iomem *base;
  147. struct clk *clk;
  148. };
  149. static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
  150. enum snd_soc_bias_level level)
  151. {
  152. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  153. struct regmap *regmap = jz_codec->regmap;
  154. switch (level) {
  155. case SND_SOC_BIAS_PREPARE:
  156. /* Reset all interrupt flags. */
  157. regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
  158. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
  159. REG_CR_VIC_SB);
  160. msleep(250);
  161. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
  162. REG_CR_VIC_SB_SLEEP);
  163. msleep(400);
  164. break;
  165. case SND_SOC_BIAS_STANDBY:
  166. regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
  167. REG_CR_VIC_SB_SLEEP);
  168. regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
  169. REG_CR_VIC_SB);
  170. fallthrough;
  171. default:
  172. break;
  173. }
  174. return 0;
  175. }
  176. static int jz4770_codec_startup(struct snd_pcm_substream *substream,
  177. struct snd_soc_dai *dai)
  178. {
  179. struct snd_soc_component *codec = dai->component;
  180. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
  181. /*
  182. * SYSCLK output from the codec to the AIC is required to keep the
  183. * DMA transfer going during playback when all audible outputs have
  184. * been disabled.
  185. */
  186. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  187. snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
  188. return 0;
  189. }
  190. static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
  191. struct snd_soc_dai *dai)
  192. {
  193. struct snd_soc_component *codec = dai->component;
  194. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
  195. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  196. snd_soc_dapm_disable_pin(dapm, "SYSCLK");
  197. }
  198. static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
  199. int cmd, struct snd_soc_dai *dai)
  200. {
  201. struct snd_soc_component *codec = dai->component;
  202. int ret = 0;
  203. switch (cmd) {
  204. case SNDRV_PCM_TRIGGER_START:
  205. case SNDRV_PCM_TRIGGER_RESUME:
  206. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  207. if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
  208. snd_soc_component_force_bias_level(codec,
  209. SND_SOC_BIAS_ON);
  210. break;
  211. case SNDRV_PCM_TRIGGER_STOP:
  212. case SNDRV_PCM_TRIGGER_SUSPEND:
  213. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  214. /* do nothing */
  215. break;
  216. default:
  217. ret = -EINVAL;
  218. }
  219. return ret;
  220. }
  221. static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
  222. {
  223. struct snd_soc_component *codec = dai->component;
  224. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  225. unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
  226. unsigned int val;
  227. int change, err;
  228. change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
  229. REG_CR_DAC_MUTE,
  230. mute ? REG_CR_DAC_MUTE : 0);
  231. if (change == 1) {
  232. regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
  233. if (val & BIT(REG_CR_DAC_SB_OFFSET))
  234. return 1;
  235. err = regmap_read_poll_timeout(jz_codec->regmap,
  236. JZ4770_CODEC_REG_IFR,
  237. val, val & gain_bit,
  238. 1000, 1 * USEC_PER_SEC);
  239. if (err) {
  240. dev_err(jz_codec->dev,
  241. "Timeout while setting digital mute: %d", err);
  242. return err;
  243. }
  244. /* clear GUP/GDO flag */
  245. regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
  246. gain_bit);
  247. }
  248. return 0;
  249. }
  250. /* unit: 0.01dB */
  251. static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
  252. static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
  253. static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
  254. static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
  255. static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
  256. /* Unconditional controls. */
  257. static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
  258. /* record gain control */
  259. SOC_DOUBLE_R_TLV("PCM Capture Volume",
  260. JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
  261. REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
  262. 0, adc_tlv),
  263. SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
  264. JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
  265. REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
  266. SOC_SINGLE_TLV("Mixer Capture Volume",
  267. JZ4770_CODEC_REG_GCR_MIXADC,
  268. REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
  269. SOC_SINGLE_TLV("Mixer Playback Volume",
  270. JZ4770_CODEC_REG_GCR_MIXDAC,
  271. REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
  272. };
  273. static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
  274. {
  275. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  276. .name = "Volume",
  277. .info = snd_soc_info_volsw,
  278. .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
  279. | SNDRV_CTL_ELEM_ACCESS_READWRITE,
  280. .tlv.p = dac_tlv,
  281. .get = snd_soc_dapm_get_volsw,
  282. .put = snd_soc_dapm_put_volsw,
  283. /*
  284. * NOTE: DACR/DACL are inversed; the gain value written to DACR
  285. * seems to affect the left channel, and the gain value written
  286. * to DACL seems to affect the right channel.
  287. */
  288. .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
  289. JZ4770_CODEC_REG_GCR_DACL,
  290. REG_GCR_GAIN_OFFSET,
  291. REG_GCR_GAIN_MAX, 1),
  292. },
  293. };
  294. static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
  295. {
  296. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  297. .name = "Volume",
  298. .info = snd_soc_info_volsw,
  299. .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
  300. | SNDRV_CTL_ELEM_ACCESS_READWRITE,
  301. .tlv.p = out_tlv,
  302. .get = snd_soc_dapm_get_volsw,
  303. .put = snd_soc_dapm_put_volsw,
  304. /* HPR/HPL inversed for the same reason as above */
  305. .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
  306. JZ4770_CODEC_REG_GCR_HPL,
  307. REG_GCR_GAIN_OFFSET,
  308. REG_GCR_GAIN_MAX, 1),
  309. },
  310. };
  311. static int hpout_event(struct snd_soc_dapm_widget *w,
  312. struct snd_kcontrol *kcontrol, int event)
  313. {
  314. struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
  315. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  316. unsigned int val;
  317. int err;
  318. switch (event) {
  319. case SND_SOC_DAPM_PRE_PMU:
  320. /* unmute HP */
  321. regmap_clear_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
  322. REG_CR_HP_MUTE);
  323. break;
  324. case SND_SOC_DAPM_POST_PMU:
  325. /* wait for ramp-up complete (RUP) */
  326. err = regmap_read_poll_timeout(jz_codec->regmap,
  327. JZ4770_CODEC_REG_IFR,
  328. val, val & REG_IFR_RUP,
  329. 1000, 1 * USEC_PER_SEC);
  330. if (err) {
  331. dev_err(jz_codec->dev, "RUP timeout: %d", err);
  332. return err;
  333. }
  334. /* clear RUP flag */
  335. regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
  336. REG_IFR_RUP);
  337. break;
  338. case SND_SOC_DAPM_POST_PMD:
  339. /* mute HP */
  340. regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
  341. REG_CR_HP_MUTE);
  342. err = regmap_read_poll_timeout(jz_codec->regmap,
  343. JZ4770_CODEC_REG_IFR,
  344. val, val & REG_IFR_RDO,
  345. 1000, 1 * USEC_PER_SEC);
  346. if (err) {
  347. dev_err(jz_codec->dev, "RDO timeout: %d", err);
  348. return err;
  349. }
  350. /* clear RDO flag */
  351. regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
  352. REG_IFR_RDO);
  353. break;
  354. }
  355. return 0;
  356. }
  357. static int adc_poweron_event(struct snd_soc_dapm_widget *w,
  358. struct snd_kcontrol *kcontrol, int event)
  359. {
  360. if (event == SND_SOC_DAPM_POST_PMU)
  361. msleep(1000);
  362. return 0;
  363. }
  364. static const char * const jz4770_codec_hp_texts[] = {
  365. "PCM", "Line In", "Mic 1", "Mic 2"
  366. };
  367. static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
  368. static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
  369. JZ4770_CODEC_REG_CR_HP,
  370. REG_CR_HP_SEL_OFFSET,
  371. REG_CR_HP_SEL_MASK,
  372. jz4770_codec_hp_texts,
  373. jz4770_codec_hp_values);
  374. static const struct snd_kcontrol_new jz4770_codec_hp_source =
  375. SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
  376. static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
  377. JZ4770_CODEC_REG_CR_LO,
  378. REG_CR_LO_SEL_OFFSET,
  379. REG_CR_LO_SEL_MASK,
  380. jz4770_codec_hp_texts,
  381. jz4770_codec_hp_values);
  382. static const struct snd_kcontrol_new jz4770_codec_lo_source =
  383. SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
  384. static const char * const jz4770_codec_cap_texts[] = {
  385. "Line In", "Mic 1", "Mic 2"
  386. };
  387. static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
  388. static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
  389. JZ4770_CODEC_REG_CR_ADC,
  390. REG_CR_ADC_IN_SEL_OFFSET,
  391. REG_CR_ADC_IN_SEL_MASK,
  392. jz4770_codec_cap_texts,
  393. jz4770_codec_cap_values);
  394. static const struct snd_kcontrol_new jz4770_codec_cap_source =
  395. SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
  396. static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
  397. SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
  398. REG_CR_MIC_STEREO_OFFSET, 1, 0),
  399. };
  400. static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
  401. SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
  402. REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
  403. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  404. SND_SOC_DAPM_POST_PMD),
  405. SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
  406. REG_CR_LO_SB_OFFSET, 1, NULL, 0),
  407. SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
  408. REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
  409. SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
  410. REG_CR_LI_SB_OFFSET, 1, NULL, 0),
  411. SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
  412. &jz4770_codec_hp_source),
  413. SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
  414. &jz4770_codec_cap_source),
  415. SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
  416. &jz4770_codec_lo_source),
  417. SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
  418. REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
  419. SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
  420. REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
  421. SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
  422. REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
  423. SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
  424. jz4770_codec_mic_controls,
  425. ARRAY_SIZE(jz4770_codec_mic_controls)),
  426. SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
  427. REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
  428. SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
  429. REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
  430. SND_SOC_DAPM_POST_PMU),
  431. SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
  432. REG_CR_DAC_SB_OFFSET, 1),
  433. SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
  434. jz4770_codec_pcm_playback_controls,
  435. ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
  436. SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
  437. jz4770_codec_hp_playback_controls,
  438. ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
  439. SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
  440. REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
  441. SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
  442. REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
  443. SND_SOC_DAPM_INPUT("MIC1P"),
  444. SND_SOC_DAPM_INPUT("MIC1N"),
  445. SND_SOC_DAPM_INPUT("MIC2P"),
  446. SND_SOC_DAPM_INPUT("MIC2N"),
  447. SND_SOC_DAPM_OUTPUT("LOUT"),
  448. SND_SOC_DAPM_OUTPUT("ROUT"),
  449. SND_SOC_DAPM_OUTPUT("LHPOUT"),
  450. SND_SOC_DAPM_OUTPUT("RHPOUT"),
  451. SND_SOC_DAPM_INPUT("LLINEIN"),
  452. SND_SOC_DAPM_INPUT("RLINEIN"),
  453. SND_SOC_DAPM_OUTPUT("SYSCLK"),
  454. };
  455. /* Unconditional routes. */
  456. static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
  457. { "Mic 1", NULL, "MIC1P" },
  458. { "Mic Diff", NULL, "MIC1N" },
  459. { "Mic 1", NULL, "Mic Diff" },
  460. { "Mic 2", NULL, "MIC2P" },
  461. { "Mic Diff", NULL, "MIC2N" },
  462. { "Mic 2", NULL, "Mic Diff" },
  463. { "Line In", NULL, "LLINEIN" },
  464. { "Line In", NULL, "RLINEIN" },
  465. { "Mic", "Stereo Capture Switch", "Mic 1" },
  466. { "Mic", "Stereo Capture Switch", "Mic 2" },
  467. { "Headphones Source", "Mic 1", "Mic" },
  468. { "Headphones Source", "Mic 2", "Mic" },
  469. { "Capture Source", "Mic 1", "Mic" },
  470. { "Capture Source", "Mic 2", "Mic" },
  471. { "Headphones Source", "Mic 1", "Mic 1" },
  472. { "Headphones Source", "Mic 2", "Mic 2" },
  473. { "Headphones Source", "Line In", "Line In Bypass" },
  474. { "Headphones Source", "PCM", "Headphones Playback" },
  475. { "HP Out", NULL, "Headphones Source" },
  476. { "Capture Source", "Line In", "Line In" },
  477. { "Capture Source", "Mic 1", "Mic 1" },
  478. { "Capture Source", "Mic 2", "Mic 2" },
  479. { "ADC", NULL, "Capture Source" },
  480. { "Line In Bypass", NULL, "Line In" },
  481. { "Line Out Source", "Line In", "Line In Bypass" },
  482. { "Line Out Source", "PCM", "PCM Playback" },
  483. { "LHPOUT", NULL, "HP Out"},
  484. { "RHPOUT", NULL, "HP Out"},
  485. { "Line Out", NULL, "Line Out Source" },
  486. { "Line Out Switch 2", NULL, "Line Out" },
  487. { "LOUT", NULL, "Line Out Switch 2"},
  488. { "ROUT", NULL, "Line Out Switch 2"},
  489. { "PCM Playback", "Volume", "DAC" },
  490. { "Headphones Playback", "Volume", "PCM Playback" },
  491. { "SYSCLK", NULL, "DAC" },
  492. };
  493. static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
  494. {
  495. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  496. struct regmap *regmap = jz_codec->regmap;
  497. /* Collect updates for later sending. */
  498. regcache_cache_only(regmap, true);
  499. /* default HP output to PCM */
  500. regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
  501. /* default line output to PCM */
  502. regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
  503. /* Disable stereo mic */
  504. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
  505. BIT(REG_CR_MIC_STEREO_OFFSET));
  506. /* Set mic 1 as default source for ADC */
  507. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
  508. REG_CR_ADC_IN_SEL_MASK);
  509. /* ADC/DAC: serial + i2s */
  510. regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
  511. REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
  512. regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
  513. REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
  514. /* The generated IRQ is a high level */
  515. regmap_clear_bits(regmap, JZ4770_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
  516. regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
  517. REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
  518. REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
  519. REG_IMR_GDO_MASK);
  520. /* 12M oscillator */
  521. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
  522. /* 0: 16ohm/220uF, 1: 10kohm/1uF */
  523. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
  524. /* disable automatic gain */
  525. regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
  526. /* Disable DAC lrswap */
  527. regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
  528. /* Independent L/R DAC gain control */
  529. regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
  530. REG_GCR_DACL_RLGOD);
  531. /* Disable ADC lrswap */
  532. regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
  533. /* default to cap-less mode(0) */
  534. regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP,
  535. BIT(REG_CR_HP_SB_HPCM_OFFSET));
  536. /* Send collected updates. */
  537. regcache_cache_only(regmap, false);
  538. regcache_sync(regmap);
  539. }
  540. static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
  541. {
  542. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  543. clk_prepare_enable(jz_codec->clk);
  544. jz4770_codec_codec_init_regs(codec);
  545. return 0;
  546. }
  547. static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
  548. {
  549. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  550. clk_disable_unprepare(jz_codec->clk);
  551. }
  552. static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
  553. .probe = jz4770_codec_codec_probe,
  554. .remove = jz4770_codec_codec_remove,
  555. .set_bias_level = jz4770_codec_set_bias_level,
  556. .controls = jz4770_codec_snd_controls,
  557. .num_controls = ARRAY_SIZE(jz4770_codec_snd_controls),
  558. .dapm_widgets = jz4770_codec_dapm_widgets,
  559. .num_dapm_widgets = ARRAY_SIZE(jz4770_codec_dapm_widgets),
  560. .dapm_routes = jz4770_codec_dapm_routes,
  561. .num_dapm_routes = ARRAY_SIZE(jz4770_codec_dapm_routes),
  562. .suspend_bias_off = 1,
  563. .use_pmdown_time = 1,
  564. };
  565. static const unsigned int jz4770_codec_sample_rates[] = {
  566. 96000, 48000, 44100, 32000,
  567. 24000, 22050, 16000, 12000,
  568. 11025, 9600, 8000,
  569. };
  570. static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
  571. struct snd_pcm_hw_params *params,
  572. struct snd_soc_dai *dai)
  573. {
  574. struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
  575. unsigned int rate, bit_width;
  576. switch (params_format(params)) {
  577. case SNDRV_PCM_FORMAT_S16_LE:
  578. bit_width = 0;
  579. break;
  580. case SNDRV_PCM_FORMAT_S18_3LE:
  581. bit_width = 1;
  582. break;
  583. case SNDRV_PCM_FORMAT_S20_3LE:
  584. bit_width = 2;
  585. break;
  586. case SNDRV_PCM_FORMAT_S24_3LE:
  587. bit_width = 3;
  588. break;
  589. default:
  590. return -EINVAL;
  591. }
  592. for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
  593. if (jz4770_codec_sample_rates[rate] == params_rate(params))
  594. break;
  595. }
  596. if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
  597. return -EINVAL;
  598. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  599. regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
  600. REG_AICR_DAC_ADWL_MASK,
  601. bit_width << REG_AICR_DAC_ADWL_OFFSET);
  602. regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
  603. REG_FCR_DAC_FREQ_MASK,
  604. rate << REG_FCR_DAC_FREQ_OFFSET);
  605. } else {
  606. regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
  607. REG_AICR_ADC_ADWL_MASK,
  608. bit_width << REG_AICR_ADC_ADWL_OFFSET);
  609. regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
  610. REG_FCR_ADC_FREQ_MASK,
  611. rate << REG_FCR_ADC_FREQ_OFFSET);
  612. }
  613. return 0;
  614. }
  615. static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
  616. .startup = jz4770_codec_startup,
  617. .shutdown = jz4770_codec_shutdown,
  618. .hw_params = jz4770_codec_hw_params,
  619. .trigger = jz4770_codec_pcm_trigger,
  620. .mute_stream = jz4770_codec_mute_stream,
  621. .no_capture_mute = 1,
  622. };
  623. #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
  624. SNDRV_PCM_FMTBIT_S18_3LE | \
  625. SNDRV_PCM_FMTBIT_S20_3LE | \
  626. SNDRV_PCM_FMTBIT_S24_3LE)
  627. static struct snd_soc_dai_driver jz4770_codec_dai = {
  628. .name = "jz4770-hifi",
  629. .playback = {
  630. .stream_name = "Playback",
  631. .channels_min = 2,
  632. .channels_max = 2,
  633. .rates = SNDRV_PCM_RATE_8000_96000,
  634. .formats = JZ_CODEC_FORMATS,
  635. },
  636. .capture = {
  637. .stream_name = "Capture",
  638. .channels_min = 2,
  639. .channels_max = 2,
  640. .rates = SNDRV_PCM_RATE_8000_96000,
  641. .formats = JZ_CODEC_FORMATS,
  642. },
  643. .ops = &jz4770_codec_dai_ops,
  644. };
  645. static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
  646. {
  647. return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
  648. }
  649. static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
  650. {
  651. switch (reg) {
  652. case JZ4770_CODEC_REG_MISSING_REG1:
  653. case JZ4770_CODEC_REG_MISSING_REG2:
  654. return false;
  655. default:
  656. return true;
  657. }
  658. }
  659. static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
  660. {
  661. switch (reg) {
  662. case JZ4770_CODEC_REG_SR:
  663. case JZ4770_CODEC_REG_MISSING_REG1:
  664. case JZ4770_CODEC_REG_MISSING_REG2:
  665. return false;
  666. default:
  667. return true;
  668. }
  669. }
  670. static int jz4770_codec_io_wait(struct jz_codec *codec)
  671. {
  672. u32 reg;
  673. return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
  674. !(reg & ICDC_RGADW_RGWR),
  675. 1000, 1 * USEC_PER_SEC);
  676. }
  677. static int jz4770_codec_reg_read(void *context, unsigned int reg,
  678. unsigned int *val)
  679. {
  680. struct jz_codec *codec = context;
  681. unsigned int i;
  682. u32 tmp;
  683. int ret;
  684. ret = jz4770_codec_io_wait(codec);
  685. if (ret)
  686. return ret;
  687. tmp = readl(codec->base + ICDC_RGADW_OFFSET);
  688. tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
  689. | (reg << ICDC_RGADW_RGADDR_OFFSET);
  690. writel(tmp, codec->base + ICDC_RGADW_OFFSET);
  691. /* wait 6+ cycles */
  692. for (i = 0; i < 6; i++)
  693. *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
  694. ICDC_RGDATA_RGDOUT_MASK;
  695. return 0;
  696. }
  697. static int jz4770_codec_reg_write(void *context, unsigned int reg,
  698. unsigned int val)
  699. {
  700. struct jz_codec *codec = context;
  701. int ret;
  702. ret = jz4770_codec_io_wait(codec);
  703. if (ret)
  704. return ret;
  705. writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
  706. codec->base + ICDC_RGADW_OFFSET);
  707. ret = jz4770_codec_io_wait(codec);
  708. if (ret)
  709. return ret;
  710. return 0;
  711. }
  712. static const u8 jz4770_codec_reg_defaults[] = {
  713. 0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
  714. 0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
  715. 0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
  716. 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
  717. 0x07, 0x44, 0x1F, 0x00
  718. };
  719. static struct regmap_config jz4770_codec_regmap_config = {
  720. .reg_bits = 7,
  721. .val_bits = 8,
  722. .max_register = JZ4770_CODEC_REG_AGC5,
  723. .volatile_reg = jz4770_codec_volatile,
  724. .readable_reg = jz4770_codec_readable,
  725. .writeable_reg = jz4770_codec_writeable,
  726. .reg_read = jz4770_codec_reg_read,
  727. .reg_write = jz4770_codec_reg_write,
  728. .reg_defaults_raw = jz4770_codec_reg_defaults,
  729. .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
  730. .cache_type = REGCACHE_FLAT,
  731. };
  732. static int jz4770_codec_probe(struct platform_device *pdev)
  733. {
  734. struct device *dev = &pdev->dev;
  735. struct jz_codec *codec;
  736. int ret;
  737. codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
  738. if (!codec)
  739. return -ENOMEM;
  740. codec->dev = dev;
  741. codec->base = devm_platform_ioremap_resource(pdev, 0);
  742. if (IS_ERR(codec->base))
  743. return PTR_ERR(codec->base);
  744. codec->regmap = devm_regmap_init(dev, NULL, codec,
  745. &jz4770_codec_regmap_config);
  746. if (IS_ERR(codec->regmap))
  747. return PTR_ERR(codec->regmap);
  748. codec->clk = devm_clk_get(dev, "aic");
  749. if (IS_ERR(codec->clk))
  750. return PTR_ERR(codec->clk);
  751. platform_set_drvdata(pdev, codec);
  752. ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
  753. &jz4770_codec_dai, 1);
  754. if (ret) {
  755. dev_err(dev, "Failed to register codec: %d\n", ret);
  756. return ret;
  757. }
  758. return 0;
  759. }
  760. static const struct of_device_id jz4770_codec_of_matches[] = {
  761. { .compatible = "ingenic,jz4770-codec", },
  762. { /* sentinel */ }
  763. };
  764. MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
  765. static struct platform_driver jz4770_codec_driver = {
  766. .probe = jz4770_codec_probe,
  767. .driver = {
  768. .name = "jz4770-codec",
  769. .of_match_table = jz4770_codec_of_matches,
  770. },
  771. };
  772. module_platform_driver(jz4770_codec_driver);
  773. MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
  774. MODULE_AUTHOR("Maarten ter Huurne <[email protected]>");
  775. MODULE_AUTHOR("Paul Cercueil <[email protected]>");
  776. MODULE_LICENSE("GPL v2");