jz4725b.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // JZ4725B CODEC driver
  4. //
  5. // Copyright (C) 2019, Paul Cercueil <[email protected]>
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/slab.h>
  10. #include <linux/io.h>
  11. #include <linux/iopoll.h>
  12. #include <linux/regmap.h>
  13. #include <linux/clk.h>
  14. #include <linux/delay.h>
  15. #include <sound/core.h>
  16. #include <sound/pcm.h>
  17. #include <sound/pcm_params.h>
  18. #include <sound/initval.h>
  19. #include <sound/soc.h>
  20. #include <sound/tlv.h>
  21. #define ICDC_RGADW_OFFSET 0x00
  22. #define ICDC_RGDATA_OFFSET 0x04
  23. /* ICDC internal register access control register(RGADW) */
  24. #define ICDC_RGADW_RGWR BIT(16)
  25. #define ICDC_RGADW_RGADDR_OFFSET 8
  26. #define ICDC_RGADW_RGADDR_MASK GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
  27. #define ICDC_RGADW_RGDIN_OFFSET 0
  28. #define ICDC_RGADW_RGDIN_MASK GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
  29. /* ICDC internal register data output register (RGDATA)*/
  30. #define ICDC_RGDATA_IRQ BIT(8)
  31. #define ICDC_RGDATA_RGDOUT_OFFSET 0
  32. #define ICDC_RGDATA_RGDOUT_MASK GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
  33. /* JZ internal register space */
  34. enum {
  35. JZ4725B_CODEC_REG_AICR,
  36. JZ4725B_CODEC_REG_CR1,
  37. JZ4725B_CODEC_REG_CR2,
  38. JZ4725B_CODEC_REG_CCR1,
  39. JZ4725B_CODEC_REG_CCR2,
  40. JZ4725B_CODEC_REG_PMR1,
  41. JZ4725B_CODEC_REG_PMR2,
  42. JZ4725B_CODEC_REG_CRR,
  43. JZ4725B_CODEC_REG_ICR,
  44. JZ4725B_CODEC_REG_IFR,
  45. JZ4725B_CODEC_REG_CGR1,
  46. JZ4725B_CODEC_REG_CGR2,
  47. JZ4725B_CODEC_REG_CGR3,
  48. JZ4725B_CODEC_REG_CGR4,
  49. JZ4725B_CODEC_REG_CGR5,
  50. JZ4725B_CODEC_REG_CGR6,
  51. JZ4725B_CODEC_REG_CGR7,
  52. JZ4725B_CODEC_REG_CGR8,
  53. JZ4725B_CODEC_REG_CGR9,
  54. JZ4725B_CODEC_REG_CGR10,
  55. JZ4725B_CODEC_REG_TR1,
  56. JZ4725B_CODEC_REG_TR2,
  57. JZ4725B_CODEC_REG_CR3,
  58. JZ4725B_CODEC_REG_AGC1,
  59. JZ4725B_CODEC_REG_AGC2,
  60. JZ4725B_CODEC_REG_AGC3,
  61. JZ4725B_CODEC_REG_AGC4,
  62. JZ4725B_CODEC_REG_AGC5,
  63. };
  64. #define REG_AICR_CONFIG1_OFFSET 0
  65. #define REG_AICR_CONFIG1_MASK (0xf << REG_AICR_CONFIG1_OFFSET)
  66. #define REG_CR1_SB_MICBIAS_OFFSET 7
  67. #define REG_CR1_MONO_OFFSET 6
  68. #define REG_CR1_DAC_MUTE_OFFSET 5
  69. #define REG_CR1_HP_DIS_OFFSET 4
  70. #define REG_CR1_DACSEL_OFFSET 3
  71. #define REG_CR1_BYPASS_OFFSET 2
  72. #define REG_CR2_DAC_DEEMP_OFFSET 7
  73. #define REG_CR2_DAC_ADWL_OFFSET 5
  74. #define REG_CR2_DAC_ADWL_MASK (0x3 << REG_CR2_DAC_ADWL_OFFSET)
  75. #define REG_CR2_ADC_ADWL_OFFSET 3
  76. #define REG_CR2_ADC_ADWL_MASK (0x3 << REG_CR2_ADC_ADWL_OFFSET)
  77. #define REG_CR2_ADC_HPF_OFFSET 2
  78. #define REG_CR3_SB_MIC1_OFFSET 7
  79. #define REG_CR3_SB_MIC2_OFFSET 6
  80. #define REG_CR3_SIDETONE1_OFFSET 5
  81. #define REG_CR3_SIDETONE2_OFFSET 4
  82. #define REG_CR3_MICDIFF_OFFSET 3
  83. #define REG_CR3_MICSTEREO_OFFSET 2
  84. #define REG_CR3_INSEL_OFFSET 0
  85. #define REG_CR3_INSEL_MASK (0x3 << REG_CR3_INSEL_OFFSET)
  86. #define REG_CCR1_CONFIG4_OFFSET 0
  87. #define REG_CCR1_CONFIG4_MASK (0xf << REG_CCR1_CONFIG4_OFFSET)
  88. #define REG_CCR2_DFREQ_OFFSET 4
  89. #define REG_CCR2_DFREQ_MASK (0xf << REG_CCR2_DFREQ_OFFSET)
  90. #define REG_CCR2_AFREQ_OFFSET 0
  91. #define REG_CCR2_AFREQ_MASK (0xf << REG_CCR2_AFREQ_OFFSET)
  92. #define REG_PMR1_SB_DAC_OFFSET 7
  93. #define REG_PMR1_SB_OUT_OFFSET 6
  94. #define REG_PMR1_SB_MIX_OFFSET 5
  95. #define REG_PMR1_SB_ADC_OFFSET 4
  96. #define REG_PMR1_SB_LIN_OFFSET 3
  97. #define REG_PMR1_SB_IND_OFFSET 0
  98. #define REG_PMR2_LRGI_OFFSET 7
  99. #define REG_PMR2_RLGI_OFFSET 6
  100. #define REG_PMR2_LRGOD_OFFSET 5
  101. #define REG_PMR2_RLGOD_OFFSET 4
  102. #define REG_PMR2_GIM_OFFSET 3
  103. #define REG_PMR2_SB_MC_OFFSET 2
  104. #define REG_PMR2_SB_OFFSET 1
  105. #define REG_PMR2_SB_SLEEP_OFFSET 0
  106. #define REG_IFR_RAMP_UP_DONE_OFFSET 3
  107. #define REG_IFR_RAMP_DOWN_DONE_OFFSET 2
  108. #define REG_CGR1_GODL_OFFSET 4
  109. #define REG_CGR1_GODL_MASK (0xf << REG_CGR1_GODL_OFFSET)
  110. #define REG_CGR1_GODR_OFFSET 0
  111. #define REG_CGR1_GODR_MASK (0xf << REG_CGR1_GODR_OFFSET)
  112. #define REG_CGR2_GO1R_OFFSET 0
  113. #define REG_CGR2_GO1R_MASK (0x1f << REG_CGR2_GO1R_OFFSET)
  114. #define REG_CGR3_GO1L_OFFSET 0
  115. #define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET)
  116. #define REG_CGR10_GIL_OFFSET 0
  117. #define REG_CGR10_GIR_OFFSET 4
  118. struct jz_icdc {
  119. struct regmap *regmap;
  120. void __iomem *base;
  121. struct clk *clk;
  122. };
  123. static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv, 0, 150, 0);
  124. static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0);
  125. static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
  126. SOC_DOUBLE_TLV("Master Playback Volume",
  127. JZ4725B_CODEC_REG_CGR1,
  128. REG_CGR1_GODL_OFFSET,
  129. REG_CGR1_GODR_OFFSET,
  130. 0xf, 1, jz4725b_dac_tlv),
  131. SOC_DOUBLE_TLV("Master Capture Volume",
  132. JZ4725B_CODEC_REG_CGR10,
  133. REG_CGR10_GIL_OFFSET,
  134. REG_CGR10_GIR_OFFSET,
  135. 0xf, 0, jz4725b_adc_tlv),
  136. SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
  137. REG_CR1_DAC_MUTE_OFFSET, 1, 1),
  138. SOC_SINGLE("Deemphasize Filter Playback Switch",
  139. JZ4725B_CODEC_REG_CR2,
  140. REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
  141. SOC_SINGLE("High-Pass Filter Capture Switch",
  142. JZ4725B_CODEC_REG_CR2,
  143. REG_CR2_ADC_HPF_OFFSET, 1, 0),
  144. };
  145. static const char * const jz4725b_codec_adc_src_texts[] = {
  146. "Mic 1", "Mic 2", "Line In", "Mixer",
  147. };
  148. static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
  149. static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
  150. JZ4725B_CODEC_REG_CR3,
  151. REG_CR3_INSEL_OFFSET,
  152. REG_CR3_INSEL_MASK,
  153. jz4725b_codec_adc_src_texts,
  154. jz4725b_codec_adc_src_values);
  155. static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
  156. SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum);
  157. static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
  158. SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
  159. REG_CR1_BYPASS_OFFSET, 1, 0),
  160. };
  161. static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
  162. struct snd_kcontrol *kcontrol,
  163. int event)
  164. {
  165. struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
  166. struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
  167. struct regmap *map = icdc->regmap;
  168. unsigned int val;
  169. switch (event) {
  170. case SND_SOC_DAPM_PRE_PMU:
  171. return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
  172. BIT(REG_IFR_RAMP_UP_DONE_OFFSET));
  173. case SND_SOC_DAPM_POST_PMU:
  174. return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
  175. val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
  176. 100000, 500000);
  177. case SND_SOC_DAPM_PRE_PMD:
  178. return regmap_clear_bits(map, JZ4725B_CODEC_REG_IFR,
  179. BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET));
  180. case SND_SOC_DAPM_POST_PMD:
  181. return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
  182. val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
  183. 100000, 500000);
  184. default:
  185. return -EINVAL;
  186. }
  187. }
  188. static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
  189. /* DAC */
  190. SND_SOC_DAPM_DAC("DAC", "Playback",
  191. JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
  192. /* ADC */
  193. SND_SOC_DAPM_ADC("ADC", "Capture",
  194. JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
  195. SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
  196. &jz4725b_codec_adc_src_ctrl),
  197. /* Mixer */
  198. SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
  199. REG_PMR1_SB_MIX_OFFSET, 1,
  200. jz4725b_codec_mixer_controls,
  201. ARRAY_SIZE(jz4725b_codec_mixer_controls)),
  202. SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
  203. REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
  204. SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1,
  205. REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0),
  206. SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
  207. REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
  208. SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
  209. REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
  210. SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
  211. REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
  212. SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
  213. REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
  214. jz4725b_out_stage_enable,
  215. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  216. SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  217. SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
  218. REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
  219. SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
  220. REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
  221. /* Pins */
  222. SND_SOC_DAPM_INPUT("MIC1P"),
  223. SND_SOC_DAPM_INPUT("MIC1N"),
  224. SND_SOC_DAPM_INPUT("MIC2P"),
  225. SND_SOC_DAPM_INPUT("MIC2N"),
  226. SND_SOC_DAPM_INPUT("LLINEIN"),
  227. SND_SOC_DAPM_INPUT("RLINEIN"),
  228. SND_SOC_DAPM_OUTPUT("LHPOUT"),
  229. SND_SOC_DAPM_OUTPUT("RHPOUT"),
  230. };
  231. static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
  232. {"Mic 1", NULL, "MIC1P"},
  233. {"Mic 1", NULL, "MIC1N"},
  234. {"Mic 2", NULL, "MIC2P"},
  235. {"Mic 2", NULL, "MIC2N"},
  236. {"Line In", NULL, "LLINEIN"},
  237. {"Line In", NULL, "RLINEIN"},
  238. {"Mixer", "Line In Bypass", "Line In"},
  239. {"DAC to Mixer", NULL, "DAC"},
  240. {"Mixer", NULL, "DAC to Mixer"},
  241. {"Mixer to ADC", NULL, "Mixer"},
  242. {"ADC Source Capture Route", "Mixer", "Mixer to ADC"},
  243. {"ADC Source Capture Route", "Line In", "Line In"},
  244. {"ADC Source Capture Route", "Mic 1", "Mic 1"},
  245. {"ADC Source Capture Route", "Mic 2", "Mic 2"},
  246. {"ADC", NULL, "ADC Source Capture Route"},
  247. {"Out Stage", NULL, "Mixer"},
  248. {"HP Out", NULL, "Out Stage"},
  249. {"LHPOUT", NULL, "HP Out"},
  250. {"RHPOUT", NULL, "HP Out"},
  251. };
  252. static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
  253. enum snd_soc_bias_level level)
  254. {
  255. struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
  256. struct regmap *map = icdc->regmap;
  257. switch (level) {
  258. case SND_SOC_BIAS_ON:
  259. regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
  260. BIT(REG_PMR2_SB_SLEEP_OFFSET));
  261. break;
  262. case SND_SOC_BIAS_PREPARE:
  263. /* Enable sound hardware */
  264. regmap_clear_bits(map, JZ4725B_CODEC_REG_PMR2,
  265. BIT(REG_PMR2_SB_OFFSET));
  266. msleep(224);
  267. break;
  268. case SND_SOC_BIAS_STANDBY:
  269. regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
  270. BIT(REG_PMR2_SB_SLEEP_OFFSET));
  271. break;
  272. case SND_SOC_BIAS_OFF:
  273. regmap_set_bits(map, JZ4725B_CODEC_REG_PMR2,
  274. BIT(REG_PMR2_SB_OFFSET));
  275. break;
  276. }
  277. return 0;
  278. }
  279. static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
  280. {
  281. struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
  282. struct regmap *map = icdc->regmap;
  283. clk_prepare_enable(icdc->clk);
  284. /* Write CONFIGn (n=1 to 8) bits.
  285. * The value 0x0f is specified in the datasheet as a requirement.
  286. */
  287. regmap_write(map, JZ4725B_CODEC_REG_AICR,
  288. 0xf << REG_AICR_CONFIG1_OFFSET);
  289. regmap_write(map, JZ4725B_CODEC_REG_CCR1,
  290. 0x0 << REG_CCR1_CONFIG4_OFFSET);
  291. return 0;
  292. }
  293. static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
  294. {
  295. struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
  296. clk_disable_unprepare(icdc->clk);
  297. }
  298. static const struct snd_soc_component_driver jz4725b_codec = {
  299. .probe = jz4725b_codec_dev_probe,
  300. .remove = jz4725b_codec_dev_remove,
  301. .set_bias_level = jz4725b_codec_set_bias_level,
  302. .controls = jz4725b_codec_controls,
  303. .num_controls = ARRAY_SIZE(jz4725b_codec_controls),
  304. .dapm_widgets = jz4725b_codec_dapm_widgets,
  305. .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
  306. .dapm_routes = jz4725b_codec_dapm_routes,
  307. .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes),
  308. .suspend_bias_off = 1,
  309. .use_pmdown_time = 1,
  310. };
  311. static const unsigned int jz4725b_codec_sample_rates[] = {
  312. 96000, 48000, 44100, 32000,
  313. 24000, 22050, 16000, 12000,
  314. 11025, 9600, 8000,
  315. };
  316. static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
  317. struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  318. {
  319. struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
  320. unsigned int rate, bit_width;
  321. switch (params_format(params)) {
  322. case SNDRV_PCM_FORMAT_S16_LE:
  323. bit_width = 0;
  324. break;
  325. case SNDRV_PCM_FORMAT_S18_3LE:
  326. bit_width = 1;
  327. break;
  328. case SNDRV_PCM_FORMAT_S20_3LE:
  329. bit_width = 2;
  330. break;
  331. case SNDRV_PCM_FORMAT_S24_3LE:
  332. bit_width = 3;
  333. break;
  334. default:
  335. return -EINVAL;
  336. }
  337. for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
  338. if (jz4725b_codec_sample_rates[rate] == params_rate(params))
  339. break;
  340. }
  341. if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
  342. return -EINVAL;
  343. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  344. regmap_update_bits(icdc->regmap,
  345. JZ4725B_CODEC_REG_CR2,
  346. REG_CR2_DAC_ADWL_MASK,
  347. bit_width << REG_CR2_DAC_ADWL_OFFSET);
  348. regmap_update_bits(icdc->regmap,
  349. JZ4725B_CODEC_REG_CCR2,
  350. REG_CCR2_DFREQ_MASK,
  351. rate << REG_CCR2_DFREQ_OFFSET);
  352. } else {
  353. regmap_update_bits(icdc->regmap,
  354. JZ4725B_CODEC_REG_CR2,
  355. REG_CR2_ADC_ADWL_MASK,
  356. bit_width << REG_CR2_ADC_ADWL_OFFSET);
  357. regmap_update_bits(icdc->regmap,
  358. JZ4725B_CODEC_REG_CCR2,
  359. REG_CCR2_AFREQ_MASK,
  360. rate << REG_CCR2_AFREQ_OFFSET);
  361. }
  362. return 0;
  363. }
  364. static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
  365. .hw_params = jz4725b_codec_hw_params,
  366. };
  367. #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
  368. SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
  369. static struct snd_soc_dai_driver jz4725b_codec_dai = {
  370. .name = "jz4725b-hifi",
  371. .playback = {
  372. .stream_name = "Playback",
  373. .channels_min = 2,
  374. .channels_max = 2,
  375. .rates = SNDRV_PCM_RATE_8000_96000,
  376. .formats = JZ_ICDC_FORMATS,
  377. },
  378. .capture = {
  379. .stream_name = "Capture",
  380. .channels_min = 2,
  381. .channels_max = 2,
  382. .rates = SNDRV_PCM_RATE_8000_96000,
  383. .formats = JZ_ICDC_FORMATS,
  384. },
  385. .ops = &jz4725b_codec_dai_ops,
  386. };
  387. static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
  388. {
  389. return reg == JZ4725B_CODEC_REG_IFR;
  390. }
  391. static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
  392. {
  393. return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
  394. }
  395. static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
  396. {
  397. u32 reg;
  398. return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
  399. !(reg & ICDC_RGADW_RGWR), 1000, 10000);
  400. }
  401. static int jz4725b_codec_reg_read(void *context, unsigned int reg,
  402. unsigned int *val)
  403. {
  404. struct jz_icdc *icdc = context;
  405. unsigned int i;
  406. u32 tmp;
  407. int ret;
  408. ret = jz4725b_codec_io_wait(icdc);
  409. if (ret)
  410. return ret;
  411. tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
  412. tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
  413. | (reg << ICDC_RGADW_RGADDR_OFFSET);
  414. writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
  415. /* wait 6+ cycles */
  416. for (i = 0; i < 6; i++)
  417. *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
  418. ICDC_RGDATA_RGDOUT_MASK;
  419. return 0;
  420. }
  421. static int jz4725b_codec_reg_write(void *context, unsigned int reg,
  422. unsigned int val)
  423. {
  424. struct jz_icdc *icdc = context;
  425. int ret;
  426. ret = jz4725b_codec_io_wait(icdc);
  427. if (ret)
  428. return ret;
  429. writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
  430. icdc->base + ICDC_RGADW_OFFSET);
  431. ret = jz4725b_codec_io_wait(icdc);
  432. if (ret)
  433. return ret;
  434. return 0;
  435. }
  436. static const u8 jz4725b_codec_reg_defaults[] = {
  437. 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
  438. 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
  439. 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
  440. 0x07, 0x44, 0x1f, 0x00,
  441. };
  442. static const struct regmap_config jz4725b_codec_regmap_config = {
  443. .reg_bits = 7,
  444. .val_bits = 8,
  445. .max_register = JZ4725B_CODEC_REG_AGC5,
  446. .volatile_reg = jz4725b_codec_volatile,
  447. .readable_reg = jz4725b_codec_can_access_reg,
  448. .writeable_reg = jz4725b_codec_can_access_reg,
  449. .reg_read = jz4725b_codec_reg_read,
  450. .reg_write = jz4725b_codec_reg_write,
  451. .reg_defaults_raw = jz4725b_codec_reg_defaults,
  452. .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
  453. .cache_type = REGCACHE_FLAT,
  454. };
  455. static int jz4725b_codec_probe(struct platform_device *pdev)
  456. {
  457. struct device *dev = &pdev->dev;
  458. struct jz_icdc *icdc;
  459. int ret;
  460. icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
  461. if (!icdc)
  462. return -ENOMEM;
  463. icdc->base = devm_platform_ioremap_resource(pdev, 0);
  464. if (IS_ERR(icdc->base))
  465. return PTR_ERR(icdc->base);
  466. icdc->regmap = devm_regmap_init(dev, NULL, icdc,
  467. &jz4725b_codec_regmap_config);
  468. if (IS_ERR(icdc->regmap))
  469. return PTR_ERR(icdc->regmap);
  470. icdc->clk = devm_clk_get(&pdev->dev, "aic");
  471. if (IS_ERR(icdc->clk))
  472. return PTR_ERR(icdc->clk);
  473. platform_set_drvdata(pdev, icdc);
  474. ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
  475. &jz4725b_codec_dai, 1);
  476. if (ret)
  477. dev_err(dev, "Failed to register codec\n");
  478. return ret;
  479. }
  480. static const struct of_device_id jz4725b_codec_of_matches[] = {
  481. { .compatible = "ingenic,jz4725b-codec", },
  482. { }
  483. };
  484. MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
  485. static struct platform_driver jz4725b_codec_driver = {
  486. .probe = jz4725b_codec_probe,
  487. .driver = {
  488. .name = "jz4725b-codec",
  489. .of_match_table = jz4725b_codec_of_matches,
  490. },
  491. };
  492. module_platform_driver(jz4725b_codec_driver);
  493. MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
  494. MODULE_AUTHOR("Paul Cercueil <[email protected]>");
  495. MODULE_LICENSE("GPL v2");