jz4760.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // Ingenic JZ4760 CODEC driver
  4. //
  5. // Copyright (C) 2021, Christophe Branchereau <[email protected]>
  6. // Copyright (C) 2021, Paul Cercueil <[email protected]>
  7. #include <linux/bitfield.h>
  8. #include <linux/clk.h>
  9. #include <linux/delay.h>
  10. #include <linux/iopoll.h>
  11. #include <linux/module.h>
  12. #include <linux/regmap.h>
  13. #include <linux/time64.h>
  14. #include <sound/pcm_params.h>
  15. #include <sound/soc.h>
  16. #include <sound/soc-dai.h>
  17. #include <sound/soc-dapm.h>
  18. #include <sound/tlv.h>
  19. #define ICDC_RGADW_OFFSET 0x00
  20. #define ICDC_RGDATA_OFFSET 0x04
  21. /* ICDC internal register access control register(RGADW) */
  22. #define ICDC_RGADW_RGWR BIT(16)
  23. #define ICDC_RGADW_RGADDR_MASK GENMASK(14, 8)
  24. #define ICDC_RGADW_RGDIN_MASK GENMASK(7, 0)
  25. /* ICDC internal register data output register (RGDATA)*/
  26. #define ICDC_RGDATA_IRQ BIT(8)
  27. #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, 0)
  28. /* Internal register space, accessed through regmap */
  29. enum {
  30. JZ4760_CODEC_REG_SR,
  31. JZ4760_CODEC_REG_AICR,
  32. JZ4760_CODEC_REG_CR1,
  33. JZ4760_CODEC_REG_CR2,
  34. JZ4760_CODEC_REG_CR3,
  35. JZ4760_CODEC_REG_CR4,
  36. JZ4760_CODEC_REG_CCR1,
  37. JZ4760_CODEC_REG_CCR2,
  38. JZ4760_CODEC_REG_PMR1,
  39. JZ4760_CODEC_REG_PMR2,
  40. JZ4760_CODEC_REG_ICR,
  41. JZ4760_CODEC_REG_IFR,
  42. JZ4760_CODEC_REG_GCR1,
  43. JZ4760_CODEC_REG_GCR2,
  44. JZ4760_CODEC_REG_GCR3,
  45. JZ4760_CODEC_REG_GCR4,
  46. JZ4760_CODEC_REG_GCR5,
  47. JZ4760_CODEC_REG_GCR6,
  48. JZ4760_CODEC_REG_GCR7,
  49. JZ4760_CODEC_REG_GCR8,
  50. JZ4760_CODEC_REG_GCR9,
  51. JZ4760_CODEC_REG_AGC1,
  52. JZ4760_CODEC_REG_AGC2,
  53. JZ4760_CODEC_REG_AGC3,
  54. JZ4760_CODEC_REG_AGC4,
  55. JZ4760_CODEC_REG_AGC5,
  56. JZ4760_CODEC_REG_MIX1,
  57. JZ4760_CODEC_REG_MIX2,
  58. };
  59. #define REG_AICR_DAC_ADWL_MASK GENMASK(7, 6)
  60. #define REG_AICR_DAC_SERIAL BIT(3)
  61. #define REG_AICR_DAC_I2S BIT(1)
  62. #define REG_AICR_ADC_ADWL_MASK GENMASK(5, 4)
  63. #define REG_AICR_ADC_SERIAL BIT(2)
  64. #define REG_AICR_ADC_I2S BIT(0)
  65. #define REG_CR1_HP_LOAD BIT(7)
  66. #define REG_CR1_HP_MUTE BIT(5)
  67. #define REG_CR1_LO_MUTE_OFFSET 4
  68. #define REG_CR1_BTL_MUTE_OFFSET 3
  69. #define REG_CR1_OUTSEL_OFFSET 0
  70. #define REG_CR1_OUTSEL_MASK GENMASK(1, REG_CR1_OUTSEL_OFFSET)
  71. #define REG_CR2_DAC_MONO BIT(7)
  72. #define REG_CR2_DAC_MUTE BIT(5)
  73. #define REG_CR2_DAC_NOMAD BIT(1)
  74. #define REG_CR2_DAC_RIGHT_ONLY BIT(0)
  75. #define REG_CR3_ADC_INSEL_OFFSET 2
  76. #define REG_CR3_ADC_INSEL_MASK GENMASK(3, REG_CR3_ADC_INSEL_OFFSET)
  77. #define REG_CR3_MICSTEREO_OFFSET 1
  78. #define REG_CR3_MICDIFF_OFFSET 0
  79. #define REG_CR4_ADC_HPF_OFFSET 7
  80. #define REG_CR4_ADC_RIGHT_ONLY BIT(0)
  81. #define REG_CCR1_CRYSTAL_MASK GENMASK(3, 0)
  82. #define REG_CCR2_DAC_FREQ_MASK GENMASK(7, 4)
  83. #define REG_CCR2_ADC_FREQ_MASK GENMASK(3, 0)
  84. #define REG_PMR1_SB BIT(7)
  85. #define REG_PMR1_SB_SLEEP BIT(6)
  86. #define REG_PMR1_SB_AIP_OFFSET 5
  87. #define REG_PMR1_SB_LINE_OFFSET 4
  88. #define REG_PMR1_SB_MIC1_OFFSET 3
  89. #define REG_PMR1_SB_MIC2_OFFSET 2
  90. #define REG_PMR1_SB_BYPASS_OFFSET 1
  91. #define REG_PMR1_SB_MICBIAS_OFFSET 0
  92. #define REG_PMR2_SB_ADC_OFFSET 4
  93. #define REG_PMR2_SB_HP_OFFSET 3
  94. #define REG_PMR2_SB_BTL_OFFSET 2
  95. #define REG_PMR2_SB_LOUT_OFFSET 1
  96. #define REG_PMR2_SB_DAC_OFFSET 0
  97. #define REG_ICR_INT_FORM_MASK GENMASK(7, 6)
  98. #define REG_ICR_ALL_MASK GENMASK(5, 0)
  99. #define REG_ICR_JACK_MASK BIT(5)
  100. #define REG_ICR_SCMC_MASK BIT(4)
  101. #define REG_ICR_RUP_MASK BIT(3)
  102. #define REG_ICR_RDO_MASK BIT(2)
  103. #define REG_ICR_GUP_MASK BIT(1)
  104. #define REG_ICR_GDO_MASK BIT(0)
  105. #define REG_IFR_ALL_MASK GENMASK(5, 0)
  106. #define REG_IFR_JACK BIT(6)
  107. #define REG_IFR_JACK_EVENT BIT(5)
  108. #define REG_IFR_SCMC BIT(4)
  109. #define REG_IFR_RUP BIT(3)
  110. #define REG_IFR_RDO BIT(2)
  111. #define REG_IFR_GUP BIT(1)
  112. #define REG_IFR_GDO BIT(0)
  113. #define REG_GCR_GAIN_OFFSET 0
  114. #define REG_GCR_GAIN_MAX 0x1f
  115. #define REG_GCR_RL BIT(7)
  116. #define REG_GCR_GIM1_MASK GENMASK(5, 3)
  117. #define REG_GCR_GIM2_MASK GENMASK(2, 0)
  118. #define REG_GCR_GIM_GAIN_MAX 7
  119. #define REG_AGC1_EN BIT(7)
  120. #define REG_AGC1_TARGET_MASK GENMASK(5, 2)
  121. #define REG_AGC2_NG_THR_MASK GENMASK(6, 4)
  122. #define REG_AGC2_HOLD_MASK GENMASK(3, 0)
  123. #define REG_AGC3_ATK_MASK GENMASK(7, 4)
  124. #define REG_AGC3_DCY_MASK GENMASK(3, 0)
  125. #define REG_AGC4_AGC_MAX_MASK GENMASK(4, 0)
  126. #define REG_AGC5_AGC_MIN_MASK GENMASK(4, 0)
  127. #define REG_MIX1_MIX_REC_MASK GENMASK(7, 6)
  128. #define REG_MIX1_GIMIX_MASK GENMASK(4, 0)
  129. #define REG_MIX2_DAC_MIX_MASK GENMASK(7, 6)
  130. #define REG_MIX2_GOMIX_MASK GENMASK(4, 0)
  131. /* codec private data */
  132. struct jz_codec {
  133. struct device *dev;
  134. struct regmap *regmap;
  135. void __iomem *base;
  136. struct clk *clk;
  137. };
  138. static int jz4760_codec_set_bias_level(struct snd_soc_component *codec,
  139. enum snd_soc_bias_level level)
  140. {
  141. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  142. struct regmap *regmap = jz_codec->regmap;
  143. switch (level) {
  144. case SND_SOC_BIAS_PREPARE:
  145. /* Reset all interrupt flags. */
  146. regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK);
  147. regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
  148. msleep(250);
  149. regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
  150. msleep(400);
  151. break;
  152. case SND_SOC_BIAS_STANDBY:
  153. regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);
  154. regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);
  155. break;
  156. default:
  157. break;
  158. }
  159. return 0;
  160. }
  161. static int jz4760_codec_startup(struct snd_pcm_substream *substream,
  162. struct snd_soc_dai *dai)
  163. {
  164. struct snd_soc_component *codec = dai->component;
  165. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
  166. int ret = 0;
  167. /*
  168. * SYSCLK output from the codec to the AIC is required to keep the
  169. * DMA transfer going during playback when all audible outputs have
  170. * been disabled.
  171. */
  172. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  173. ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
  174. return ret;
  175. }
  176. static void jz4760_codec_shutdown(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. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
  182. snd_soc_dapm_disable_pin(dapm, "SYSCLK");
  183. }
  184. static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream,
  185. int cmd, struct snd_soc_dai *dai)
  186. {
  187. struct snd_soc_component *codec = dai->component;
  188. int ret = 0;
  189. switch (cmd) {
  190. case SNDRV_PCM_TRIGGER_START:
  191. case SNDRV_PCM_TRIGGER_RESUME:
  192. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  193. if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
  194. snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON);
  195. break;
  196. case SNDRV_PCM_TRIGGER_STOP:
  197. case SNDRV_PCM_TRIGGER_SUSPEND:
  198. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  199. /* do nothing */
  200. break;
  201. default:
  202. ret = -EINVAL;
  203. }
  204. return ret;
  205. }
  206. static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
  207. {
  208. struct snd_soc_component *codec = dai->component;
  209. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  210. unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
  211. unsigned int val, reg;
  212. int change, err;
  213. change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2,
  214. REG_CR2_DAC_MUTE,
  215. mute ? REG_CR2_DAC_MUTE : 0);
  216. if (change == 1) {
  217. regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val);
  218. if (val & BIT(REG_PMR2_SB_DAC_OFFSET))
  219. return 1;
  220. err = regmap_read_poll_timeout(jz_codec->regmap,
  221. JZ4760_CODEC_REG_IFR,
  222. val, val & gain_bit,
  223. 1000, 1 * USEC_PER_SEC);
  224. if (err) {
  225. dev_err(jz_codec->dev,
  226. "Timeout while setting digital mute: %d", err);
  227. return err;
  228. }
  229. /* clear GUP/GDO flag */
  230. regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit);
  231. }
  232. regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, &reg);
  233. return 0;
  234. }
  235. /* unit: 0.01dB */
  236. static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100);
  237. static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
  238. static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100);
  239. static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
  240. /* Unconditional controls. */
  241. static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = {
  242. /* record gain control */
  243. SOC_DOUBLE_R_TLV("PCM Capture Volume",
  244. JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8,
  245. REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv),
  246. SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
  247. JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3,
  248. REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
  249. SOC_SINGLE("High-Pass Filter Capture Switch",
  250. JZ4760_CODEC_REG_CR4,
  251. REG_CR4_ADC_HPF_OFFSET, 1, 0),
  252. };
  253. static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = {
  254. {
  255. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  256. .name = "Volume",
  257. .info = snd_soc_info_volsw,
  258. .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
  259. | SNDRV_CTL_ELEM_ACCESS_READWRITE,
  260. .tlv.p = dac_tlv,
  261. .get = snd_soc_dapm_get_volsw,
  262. .put = snd_soc_dapm_put_volsw,
  263. .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6,
  264. JZ4760_CODEC_REG_GCR5,
  265. REG_GCR_GAIN_OFFSET,
  266. REG_GCR_GAIN_MAX, 1),
  267. },
  268. };
  269. static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = {
  270. {
  271. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  272. .name = "Volume",
  273. .info = snd_soc_info_volsw,
  274. .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
  275. | SNDRV_CTL_ELEM_ACCESS_READWRITE,
  276. .tlv.p = out_tlv,
  277. .get = snd_soc_dapm_get_volsw,
  278. .put = snd_soc_dapm_put_volsw,
  279. .private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2,
  280. JZ4760_CODEC_REG_GCR1,
  281. REG_GCR_GAIN_OFFSET,
  282. REG_GCR_GAIN_MAX, 1),
  283. },
  284. };
  285. static int hpout_event(struct snd_soc_dapm_widget *w,
  286. struct snd_kcontrol *kcontrol, int event)
  287. {
  288. struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
  289. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  290. unsigned int val;
  291. int err;
  292. switch (event) {
  293. case SND_SOC_DAPM_PRE_PMU:
  294. /* unmute HP */
  295. regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
  296. REG_CR1_HP_MUTE);
  297. break;
  298. case SND_SOC_DAPM_POST_PMU:
  299. /* wait for ramp-up complete (RUP) */
  300. err = regmap_read_poll_timeout(jz_codec->regmap,
  301. JZ4760_CODEC_REG_IFR,
  302. val, val & REG_IFR_RUP,
  303. 1000, 1 * USEC_PER_SEC);
  304. if (err) {
  305. dev_err(jz_codec->dev, "RUP timeout: %d", err);
  306. return err;
  307. }
  308. /* clear RUP flag */
  309. regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
  310. REG_IFR_RUP);
  311. break;
  312. case SND_SOC_DAPM_POST_PMD:
  313. /* mute HP */
  314. regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,
  315. REG_CR1_HP_MUTE);
  316. err = regmap_read_poll_timeout(jz_codec->regmap,
  317. JZ4760_CODEC_REG_IFR,
  318. val, val & REG_IFR_RDO,
  319. 1000, 1 * USEC_PER_SEC);
  320. if (err) {
  321. dev_err(jz_codec->dev, "RDO timeout: %d", err);
  322. return err;
  323. }
  324. /* clear RDO flag */
  325. regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,
  326. REG_IFR_RDO);
  327. break;
  328. }
  329. return 0;
  330. }
  331. static const char * const jz4760_codec_hp_texts[] = {
  332. "PCM", "Line In", "Mic 1", "Mic 2"
  333. };
  334. static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 };
  335. static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum,
  336. JZ4760_CODEC_REG_CR1,
  337. REG_CR1_OUTSEL_OFFSET,
  338. REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET,
  339. jz4760_codec_hp_texts,
  340. jz4760_codec_hp_values);
  341. static const struct snd_kcontrol_new jz4760_codec_hp_source =
  342. SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum);
  343. static const char * const jz4760_codec_cap_texts[] = {
  344. "Line In", "Mic 1", "Mic 2"
  345. };
  346. static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 };
  347. static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum,
  348. JZ4760_CODEC_REG_CR3,
  349. REG_CR3_ADC_INSEL_OFFSET,
  350. REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET,
  351. jz4760_codec_cap_texts,
  352. jz4760_codec_cap_values);
  353. static const struct snd_kcontrol_new jz4760_codec_cap_source =
  354. SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum);
  355. static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = {
  356. SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3,
  357. REG_CR3_MICSTEREO_OFFSET, 1, 0),
  358. };
  359. static const struct snd_kcontrol_new jz4760_codec_line_out_switch =
  360. SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
  361. REG_CR1_LO_MUTE_OFFSET, 0, 0);
  362. static const struct snd_kcontrol_new jz4760_codec_btl_out_switch =
  363. SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,
  364. REG_CR1_BTL_MUTE_OFFSET, 0, 0);
  365. static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = {
  366. SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2,
  367. REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event,
  368. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  369. SND_SOC_DAPM_POST_PMD),
  370. SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2,
  371. REG_PMR2_SB_LOUT_OFFSET, 1,
  372. &jz4760_codec_line_out_switch),
  373. SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2,
  374. REG_PMR2_SB_BTL_OFFSET, 1,
  375. &jz4760_codec_btl_out_switch),
  376. SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1,
  377. REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0),
  378. SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
  379. &jz4760_codec_hp_source),
  380. SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
  381. &jz4760_codec_cap_source),
  382. SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1,
  383. REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0),
  384. SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1,
  385. REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0),
  386. SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3,
  387. REG_CR3_MICDIFF_OFFSET, 0, NULL, 0),
  388. SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
  389. jz4760_codec_mic_controls,
  390. ARRAY_SIZE(jz4760_codec_mic_controls)),
  391. SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1,
  392. REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0),
  393. SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2,
  394. REG_PMR2_SB_ADC_OFFSET, 1),
  395. SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2,
  396. REG_PMR2_SB_DAC_OFFSET, 1),
  397. SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
  398. jz4760_codec_pcm_playback_controls,
  399. ARRAY_SIZE(jz4760_codec_pcm_playback_controls)),
  400. SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
  401. jz4760_codec_hp_playback_controls,
  402. ARRAY_SIZE(jz4760_codec_hp_playback_controls)),
  403. SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1,
  404. REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
  405. SND_SOC_DAPM_INPUT("MIC1P"),
  406. SND_SOC_DAPM_INPUT("MIC1N"),
  407. SND_SOC_DAPM_INPUT("MIC2P"),
  408. SND_SOC_DAPM_INPUT("MIC2N"),
  409. SND_SOC_DAPM_INPUT("LLINEIN"),
  410. SND_SOC_DAPM_INPUT("RLINEIN"),
  411. SND_SOC_DAPM_OUTPUT("LHPOUT"),
  412. SND_SOC_DAPM_OUTPUT("RHPOUT"),
  413. SND_SOC_DAPM_OUTPUT("LOUT"),
  414. SND_SOC_DAPM_OUTPUT("ROUT"),
  415. SND_SOC_DAPM_OUTPUT("BTLP"),
  416. SND_SOC_DAPM_OUTPUT("BTLN"),
  417. SND_SOC_DAPM_OUTPUT("SYSCLK"),
  418. };
  419. /* Unconditional routes. */
  420. static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = {
  421. { "Mic 1", NULL, "MIC1P" },
  422. { "Mic Diff", NULL, "MIC1N" },
  423. { "Mic 1", NULL, "Mic Diff" },
  424. { "Mic 2", NULL, "MIC2P" },
  425. { "Mic Diff", NULL, "MIC2N" },
  426. { "Mic 2", NULL, "Mic Diff" },
  427. { "Line In", NULL, "LLINEIN" },
  428. { "Line In", NULL, "RLINEIN" },
  429. { "Mic", "Stereo Capture Switch", "Mic 1" },
  430. { "Mic", "Stereo Capture Switch", "Mic 2" },
  431. { "Headphones Source", "Mic 1", "Mic" },
  432. { "Headphones Source", "Mic 2", "Mic" },
  433. { "Capture Source", "Mic 1", "Mic" },
  434. { "Capture Source", "Mic 2", "Mic" },
  435. { "Capture Source", "Line In", "Line In" },
  436. { "Capture Source", "Mic 1", "Mic 1" },
  437. { "Capture Source", "Mic 2", "Mic 2" },
  438. { "ADC", NULL, "Capture Source" },
  439. { "Line In Bypass", NULL, "Line In" },
  440. { "Headphones Source", "Mic 1", "Mic 1" },
  441. { "Headphones Source", "Mic 2", "Mic 2" },
  442. { "Headphones Source", "Line In", "Line In Bypass" },
  443. { "Headphones Source", "PCM", "Headphones Playback" },
  444. { "HP Out", NULL, "Headphones Source" },
  445. { "LHPOUT", NULL, "HP Out" },
  446. { "RHPOUT", NULL, "HP Out" },
  447. { "Line Out", "Switch", "HP Out" },
  448. { "LOUT", NULL, "Line Out" },
  449. { "ROUT", NULL, "Line Out" },
  450. { "BTL Out", "Switch", "Line Out" },
  451. { "BTLP", NULL, "BTL Out"},
  452. { "BTLN", NULL, "BTL Out"},
  453. { "PCM Playback", "Volume", "DAC" },
  454. { "Headphones Playback", "Volume", "PCM Playback" },
  455. { "SYSCLK", NULL, "DAC" },
  456. };
  457. static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec)
  458. {
  459. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  460. struct regmap *regmap = jz_codec->regmap;
  461. /* Collect updates for later sending. */
  462. regcache_cache_only(regmap, true);
  463. /* default Amp output to PCM */
  464. regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK);
  465. /* Disable stereo mic */
  466. regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
  467. BIT(REG_CR3_MICSTEREO_OFFSET));
  468. /* Set mic 1 as default source for ADC */
  469. regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,
  470. REG_CR3_ADC_INSEL_MASK);
  471. /* ADC/DAC: serial + i2s */
  472. regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR,
  473. REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S |
  474. REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
  475. /* The generated IRQ is a high level */
  476. regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
  477. regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK,
  478. REG_ICR_JACK_MASK | REG_ICR_RUP_MASK |
  479. REG_ICR_RDO_MASK | REG_ICR_GUP_MASK |
  480. REG_ICR_GDO_MASK);
  481. /* 12M oscillator */
  482. regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK);
  483. /* 0: 16ohm/220uF, 1: 10kohm/1uF */
  484. regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD);
  485. /* default to NOMAD */
  486. regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2,
  487. REG_CR2_DAC_NOMAD);
  488. /* disable automatic gain */
  489. regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN);
  490. /* Independent L/R DAC gain control */
  491. regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5,
  492. REG_GCR_RL);
  493. /* Send collected updates. */
  494. regcache_cache_only(regmap, false);
  495. regcache_sync(regmap);
  496. }
  497. static int jz4760_codec_codec_probe(struct snd_soc_component *codec)
  498. {
  499. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  500. clk_prepare_enable(jz_codec->clk);
  501. jz4760_codec_codec_init_regs(codec);
  502. return 0;
  503. }
  504. static void jz4760_codec_codec_remove(struct snd_soc_component *codec)
  505. {
  506. struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
  507. clk_disable_unprepare(jz_codec->clk);
  508. }
  509. static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = {
  510. .probe = jz4760_codec_codec_probe,
  511. .remove = jz4760_codec_codec_remove,
  512. .set_bias_level = jz4760_codec_set_bias_level,
  513. .controls = jz4760_codec_snd_controls,
  514. .num_controls = ARRAY_SIZE(jz4760_codec_snd_controls),
  515. .dapm_widgets = jz4760_codec_dapm_widgets,
  516. .num_dapm_widgets = ARRAY_SIZE(jz4760_codec_dapm_widgets),
  517. .dapm_routes = jz4760_codec_dapm_routes,
  518. .num_dapm_routes = ARRAY_SIZE(jz4760_codec_dapm_routes),
  519. .suspend_bias_off = 1,
  520. .use_pmdown_time = 1,
  521. };
  522. static const unsigned int jz4760_codec_sample_rates[] = {
  523. 96000, 48000, 44100, 32000,
  524. 24000, 22050, 16000, 12000,
  525. 11025, 9600, 8000,
  526. };
  527. static int jz4760_codec_hw_params(struct snd_pcm_substream *substream,
  528. struct snd_pcm_hw_params *params,
  529. struct snd_soc_dai *dai)
  530. {
  531. struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
  532. unsigned int rate, bit_width;
  533. switch (params_format(params)) {
  534. case SNDRV_PCM_FORMAT_S16_LE:
  535. bit_width = 0;
  536. break;
  537. case SNDRV_PCM_FORMAT_S18_3LE:
  538. bit_width = 1;
  539. break;
  540. case SNDRV_PCM_FORMAT_S20_3LE:
  541. bit_width = 2;
  542. break;
  543. case SNDRV_PCM_FORMAT_S24_3LE:
  544. bit_width = 3;
  545. break;
  546. default:
  547. return -EINVAL;
  548. }
  549. for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) {
  550. if (jz4760_codec_sample_rates[rate] == params_rate(params))
  551. break;
  552. }
  553. if (rate == ARRAY_SIZE(jz4760_codec_sample_rates))
  554. return -EINVAL;
  555. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  556. regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
  557. REG_AICR_DAC_ADWL_MASK,
  558. FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width));
  559. regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
  560. REG_CCR2_DAC_FREQ_MASK,
  561. FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate));
  562. } else {
  563. regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,
  564. REG_AICR_ADC_ADWL_MASK,
  565. FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width));
  566. regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,
  567. REG_CCR2_ADC_FREQ_MASK,
  568. FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate));
  569. }
  570. return 0;
  571. }
  572. static const struct snd_soc_dai_ops jz4760_codec_dai_ops = {
  573. .startup = jz4760_codec_startup,
  574. .shutdown = jz4760_codec_shutdown,
  575. .hw_params = jz4760_codec_hw_params,
  576. .trigger = jz4760_codec_pcm_trigger,
  577. .mute_stream = jz4760_codec_mute_stream,
  578. .no_capture_mute = 1,
  579. };
  580. #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
  581. SNDRV_PCM_FMTBIT_S18_3LE | \
  582. SNDRV_PCM_FMTBIT_S20_3LE | \
  583. SNDRV_PCM_FMTBIT_S24_3LE)
  584. static struct snd_soc_dai_driver jz4760_codec_dai = {
  585. .name = "jz4760-hifi",
  586. .playback = {
  587. .stream_name = "Playback",
  588. .channels_min = 2,
  589. .channels_max = 2,
  590. .rates = SNDRV_PCM_RATE_8000_96000,
  591. .formats = JZ_CODEC_FORMATS,
  592. },
  593. .capture = {
  594. .stream_name = "Capture",
  595. .channels_min = 2,
  596. .channels_max = 2,
  597. .rates = SNDRV_PCM_RATE_8000_96000,
  598. .formats = JZ_CODEC_FORMATS,
  599. },
  600. .ops = &jz4760_codec_dai_ops,
  601. };
  602. static bool jz4760_codec_volatile(struct device *dev, unsigned int reg)
  603. {
  604. return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR;
  605. }
  606. static bool jz4760_codec_writeable(struct device *dev, unsigned int reg)
  607. {
  608. switch (reg) {
  609. case JZ4760_CODEC_REG_SR:
  610. return false;
  611. default:
  612. return true;
  613. }
  614. }
  615. static int jz4760_codec_io_wait(struct jz_codec *codec)
  616. {
  617. u32 reg;
  618. return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
  619. !(reg & ICDC_RGADW_RGWR),
  620. 1000, 1 * USEC_PER_SEC);
  621. }
  622. static int jz4760_codec_reg_read(void *context, unsigned int reg,
  623. unsigned int *val)
  624. {
  625. struct jz_codec *codec = context;
  626. unsigned int i;
  627. u32 tmp;
  628. int ret;
  629. ret = jz4760_codec_io_wait(codec);
  630. if (ret)
  631. return ret;
  632. tmp = readl(codec->base + ICDC_RGADW_OFFSET);
  633. tmp &= ~ICDC_RGADW_RGADDR_MASK;
  634. tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg);
  635. writel(tmp, codec->base + ICDC_RGADW_OFFSET);
  636. /* wait 6+ cycles */
  637. for (i = 0; i < 6; i++)
  638. *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
  639. ICDC_RGDATA_RGDOUT_MASK;
  640. return 0;
  641. }
  642. static int jz4760_codec_reg_write(void *context, unsigned int reg,
  643. unsigned int val)
  644. {
  645. struct jz_codec *codec = context;
  646. int ret;
  647. ret = jz4760_codec_io_wait(codec);
  648. if (ret)
  649. return ret;
  650. writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val,
  651. codec->base + ICDC_RGADW_OFFSET);
  652. ret = jz4760_codec_io_wait(codec);
  653. if (ret)
  654. return ret;
  655. return 0;
  656. }
  657. static const u8 jz4760_codec_reg_defaults[] = {
  658. 0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00,
  659. 0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06,
  660. 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44,
  661. 0x1F, 0x00, 0x00, 0x00
  662. };
  663. static struct regmap_config jz4760_codec_regmap_config = {
  664. .reg_bits = 7,
  665. .val_bits = 8,
  666. .max_register = JZ4760_CODEC_REG_MIX2,
  667. .volatile_reg = jz4760_codec_volatile,
  668. .writeable_reg = jz4760_codec_writeable,
  669. .reg_read = jz4760_codec_reg_read,
  670. .reg_write = jz4760_codec_reg_write,
  671. .reg_defaults_raw = jz4760_codec_reg_defaults,
  672. .num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults),
  673. .cache_type = REGCACHE_FLAT,
  674. };
  675. static int jz4760_codec_probe(struct platform_device *pdev)
  676. {
  677. struct device *dev = &pdev->dev;
  678. struct jz_codec *codec;
  679. int ret;
  680. codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
  681. if (!codec)
  682. return -ENOMEM;
  683. codec->dev = dev;
  684. codec->base = devm_platform_ioremap_resource(pdev, 0);
  685. if (IS_ERR(codec->base))
  686. return PTR_ERR(codec->base);
  687. codec->regmap = devm_regmap_init(dev, NULL, codec,
  688. &jz4760_codec_regmap_config);
  689. if (IS_ERR(codec->regmap))
  690. return PTR_ERR(codec->regmap);
  691. codec->clk = devm_clk_get(dev, "aic");
  692. if (IS_ERR(codec->clk))
  693. return PTR_ERR(codec->clk);
  694. platform_set_drvdata(pdev, codec);
  695. ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev,
  696. &jz4760_codec_dai, 1);
  697. if (ret) {
  698. dev_err(dev, "Failed to register codec: %d\n", ret);
  699. return ret;
  700. }
  701. return 0;
  702. }
  703. static const struct of_device_id jz4760_codec_of_matches[] = {
  704. { .compatible = "ingenic,jz4760-codec", },
  705. { /* sentinel */ }
  706. };
  707. MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches);
  708. static struct platform_driver jz4760_codec_driver = {
  709. .probe = jz4760_codec_probe,
  710. .driver = {
  711. .name = "jz4760-codec",
  712. .of_match_table = jz4760_codec_of_matches,
  713. },
  714. };
  715. module_platform_driver(jz4760_codec_driver);
  716. MODULE_DESCRIPTION("JZ4760 SoC internal codec driver");
  717. MODULE_AUTHOR("Christophe Branchereau <[email protected]>");
  718. MODULE_AUTHOR("Paul Cercueil <[email protected]>");
  719. MODULE_LICENSE("GPL v2");