jz4725b.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // JZ4725B CODEC driver
  4. //
  5. // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
  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. struct jz_icdc {
  117. struct regmap *regmap;
  118. void __iomem *base;
  119. struct clk *clk;
  120. };
  121. static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0);
  122. static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600);
  123. static const struct snd_kcontrol_new jz4725b_codec_controls[] = {
  124. SOC_DOUBLE_TLV("Master Playback Volume",
  125. JZ4725B_CODEC_REG_CGR1,
  126. REG_CGR1_GODL_OFFSET,
  127. REG_CGR1_GODR_OFFSET,
  128. 0xf, 1, jz4725b_dac_tlv),
  129. SOC_DOUBLE_R_TLV("Master Capture Volume",
  130. JZ4725B_CODEC_REG_CGR3,
  131. JZ4725B_CODEC_REG_CGR2,
  132. REG_CGR2_GO1R_OFFSET,
  133. 0x1f, 1, jz4725b_line_tlv),
  134. SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1,
  135. REG_CR1_DAC_MUTE_OFFSET, 1, 1),
  136. SOC_SINGLE("Deemphasize Filter Playback Switch",
  137. JZ4725B_CODEC_REG_CR2,
  138. REG_CR2_DAC_DEEMP_OFFSET, 1, 0),
  139. SOC_SINGLE("High-Pass Filter Capture Switch",
  140. JZ4725B_CODEC_REG_CR2,
  141. REG_CR2_ADC_HPF_OFFSET, 1, 0),
  142. };
  143. static const char * const jz4725b_codec_adc_src_texts[] = {
  144. "Mic 1", "Mic 2", "Line In", "Mixer",
  145. };
  146. static const unsigned int jz4725b_codec_adc_src_values[] = { 0, 1, 2, 3, };
  147. static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum,
  148. JZ4725B_CODEC_REG_CR3,
  149. REG_CR3_INSEL_OFFSET,
  150. REG_CR3_INSEL_MASK,
  151. jz4725b_codec_adc_src_texts,
  152. jz4725b_codec_adc_src_values);
  153. static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl =
  154. SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum);
  155. static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = {
  156. SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1,
  157. REG_CR1_BYPASS_OFFSET, 1, 0),
  158. };
  159. static int jz4725b_out_stage_enable(struct snd_soc_dapm_widget *w,
  160. struct snd_kcontrol *kcontrol,
  161. int event)
  162. {
  163. struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
  164. struct jz_icdc *icdc = snd_soc_component_get_drvdata(codec);
  165. struct regmap *map = icdc->regmap;
  166. unsigned int val;
  167. switch (event) {
  168. case SND_SOC_DAPM_PRE_PMU:
  169. return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
  170. BIT(REG_IFR_RAMP_UP_DONE_OFFSET), 0);
  171. case SND_SOC_DAPM_POST_PMU:
  172. return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
  173. val, val & BIT(REG_IFR_RAMP_UP_DONE_OFFSET),
  174. 100000, 500000);
  175. case SND_SOC_DAPM_PRE_PMD:
  176. return regmap_update_bits(map, JZ4725B_CODEC_REG_IFR,
  177. BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET), 0);
  178. case SND_SOC_DAPM_POST_PMD:
  179. return regmap_read_poll_timeout(map, JZ4725B_CODEC_REG_IFR,
  180. val, val & BIT(REG_IFR_RAMP_DOWN_DONE_OFFSET),
  181. 100000, 500000);
  182. default:
  183. return -EINVAL;
  184. }
  185. }
  186. static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = {
  187. /* DAC */
  188. SND_SOC_DAPM_DAC("DAC", "Playback",
  189. JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_DAC_OFFSET, 1),
  190. /* ADC */
  191. SND_SOC_DAPM_ADC("ADC", "Capture",
  192. JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1),
  193. SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0,
  194. &jz4725b_codec_adc_src_ctrl),
  195. /* Mixer */
  196. SND_SOC_DAPM_MIXER("Mixer", JZ4725B_CODEC_REG_PMR1,
  197. REG_PMR1_SB_MIX_OFFSET, 1,
  198. jz4725b_codec_mixer_controls,
  199. ARRAY_SIZE(jz4725b_codec_mixer_controls)),
  200. SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1,
  201. REG_CR1_DACSEL_OFFSET, 0, NULL, 0),
  202. SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0),
  203. SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1,
  204. REG_CR1_HP_DIS_OFFSET, 1, NULL, 0),
  205. SND_SOC_DAPM_MIXER("Mic 1", JZ4725B_CODEC_REG_CR3,
  206. REG_CR3_SB_MIC1_OFFSET, 1, NULL, 0),
  207. SND_SOC_DAPM_MIXER("Mic 2", JZ4725B_CODEC_REG_CR3,
  208. REG_CR3_SB_MIC2_OFFSET, 1, NULL, 0),
  209. SND_SOC_DAPM_MIXER_E("Out Stage", JZ4725B_CODEC_REG_PMR1,
  210. REG_PMR1_SB_OUT_OFFSET, 1, NULL, 0,
  211. jz4725b_out_stage_enable,
  212. SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
  213. SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
  214. SND_SOC_DAPM_MIXER("Mixer to ADC", JZ4725B_CODEC_REG_PMR1,
  215. REG_PMR1_SB_IND_OFFSET, 1, NULL, 0),
  216. SND_SOC_DAPM_SUPPLY("Mic Bias", JZ4725B_CODEC_REG_CR1,
  217. REG_CR1_SB_MICBIAS_OFFSET, 1, NULL, 0),
  218. /* Pins */
  219. SND_SOC_DAPM_INPUT("MIC1P"),
  220. SND_SOC_DAPM_INPUT("MIC1N"),
  221. SND_SOC_DAPM_INPUT("MIC2P"),
  222. SND_SOC_DAPM_INPUT("MIC2N"),
  223. SND_SOC_DAPM_INPUT("LLINEIN"),
  224. SND_SOC_DAPM_INPUT("RLINEIN"),
  225. SND_SOC_DAPM_OUTPUT("LHPOUT"),
  226. SND_SOC_DAPM_OUTPUT("RHPOUT"),
  227. };
  228. static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = {
  229. {"Mic 1", NULL, "MIC1P"},
  230. {"Mic 1", NULL, "MIC1N"},
  231. {"Mic 2", NULL, "MIC2P"},
  232. {"Mic 2", NULL, "MIC2N"},
  233. {"Line In", NULL, "LLINEIN"},
  234. {"Line In", NULL, "RLINEIN"},
  235. {"Mixer", "Line In Bypass", "Line In"},
  236. {"DAC to Mixer", NULL, "DAC"},
  237. {"Mixer", NULL, "DAC to Mixer"},
  238. {"Mixer to ADC", NULL, "Mixer"},
  239. {"ADC Source", "Mixer", "Mixer to ADC"},
  240. {"ADC Source", "Line In", "Line In"},
  241. {"ADC Source", "Mic 1", "Mic 1"},
  242. {"ADC Source", "Mic 2", "Mic 2"},
  243. {"ADC", NULL, "ADC Source"},
  244. {"Out Stage", NULL, "Mixer"},
  245. {"HP Out", NULL, "Out Stage"},
  246. {"LHPOUT", NULL, "HP Out"},
  247. {"RHPOUT", NULL, "HP Out"},
  248. };
  249. static int jz4725b_codec_set_bias_level(struct snd_soc_component *component,
  250. enum snd_soc_bias_level level)
  251. {
  252. struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
  253. struct regmap *map = icdc->regmap;
  254. switch (level) {
  255. case SND_SOC_BIAS_ON:
  256. regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
  257. BIT(REG_PMR2_SB_SLEEP_OFFSET), 0);
  258. break;
  259. case SND_SOC_BIAS_PREPARE:
  260. /* Enable sound hardware */
  261. regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
  262. BIT(REG_PMR2_SB_OFFSET), 0);
  263. msleep(224);
  264. break;
  265. case SND_SOC_BIAS_STANDBY:
  266. regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
  267. BIT(REG_PMR2_SB_SLEEP_OFFSET),
  268. BIT(REG_PMR2_SB_SLEEP_OFFSET));
  269. break;
  270. case SND_SOC_BIAS_OFF:
  271. regmap_update_bits(map, JZ4725B_CODEC_REG_PMR2,
  272. BIT(REG_PMR2_SB_OFFSET),
  273. BIT(REG_PMR2_SB_OFFSET));
  274. break;
  275. }
  276. return 0;
  277. }
  278. static int jz4725b_codec_dev_probe(struct snd_soc_component *component)
  279. {
  280. struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
  281. struct regmap *map = icdc->regmap;
  282. clk_prepare_enable(icdc->clk);
  283. /* Write CONFIGn (n=1 to 8) bits.
  284. * The value 0x0f is specified in the datasheet as a requirement.
  285. */
  286. regmap_write(map, JZ4725B_CODEC_REG_AICR,
  287. 0xf << REG_AICR_CONFIG1_OFFSET);
  288. regmap_write(map, JZ4725B_CODEC_REG_CCR1,
  289. 0x0 << REG_CCR1_CONFIG4_OFFSET);
  290. return 0;
  291. }
  292. static void jz4725b_codec_dev_remove(struct snd_soc_component *component)
  293. {
  294. struct jz_icdc *icdc = snd_soc_component_get_drvdata(component);
  295. clk_disable_unprepare(icdc->clk);
  296. }
  297. static const struct snd_soc_component_driver jz4725b_codec = {
  298. .probe = jz4725b_codec_dev_probe,
  299. .remove = jz4725b_codec_dev_remove,
  300. .set_bias_level = jz4725b_codec_set_bias_level,
  301. .controls = jz4725b_codec_controls,
  302. .num_controls = ARRAY_SIZE(jz4725b_codec_controls),
  303. .dapm_widgets = jz4725b_codec_dapm_widgets,
  304. .num_dapm_widgets = ARRAY_SIZE(jz4725b_codec_dapm_widgets),
  305. .dapm_routes = jz4725b_codec_dapm_routes,
  306. .num_dapm_routes = ARRAY_SIZE(jz4725b_codec_dapm_routes),
  307. .suspend_bias_off = 1,
  308. .use_pmdown_time = 1,
  309. };
  310. static const unsigned int jz4725b_codec_sample_rates[] = {
  311. 96000, 48000, 44100, 32000,
  312. 24000, 22050, 16000, 12000,
  313. 11025, 9600, 8000,
  314. };
  315. static int jz4725b_codec_hw_params(struct snd_pcm_substream *substream,
  316. struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
  317. {
  318. struct jz_icdc *icdc = snd_soc_component_get_drvdata(dai->component);
  319. unsigned int rate, bit_width;
  320. switch (params_format(params)) {
  321. case SNDRV_PCM_FORMAT_S16_LE:
  322. bit_width = 0;
  323. break;
  324. case SNDRV_PCM_FORMAT_S18_3LE:
  325. bit_width = 1;
  326. break;
  327. case SNDRV_PCM_FORMAT_S20_3LE:
  328. bit_width = 2;
  329. break;
  330. case SNDRV_PCM_FORMAT_S24_3LE:
  331. bit_width = 3;
  332. break;
  333. default:
  334. return -EINVAL;
  335. }
  336. for (rate = 0; rate < ARRAY_SIZE(jz4725b_codec_sample_rates); rate++) {
  337. if (jz4725b_codec_sample_rates[rate] == params_rate(params))
  338. break;
  339. }
  340. if (rate == ARRAY_SIZE(jz4725b_codec_sample_rates))
  341. return -EINVAL;
  342. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  343. regmap_update_bits(icdc->regmap,
  344. JZ4725B_CODEC_REG_CR2,
  345. REG_CR2_DAC_ADWL_MASK,
  346. bit_width << REG_CR2_DAC_ADWL_OFFSET);
  347. regmap_update_bits(icdc->regmap,
  348. JZ4725B_CODEC_REG_CCR2,
  349. REG_CCR2_DFREQ_MASK,
  350. rate << REG_CCR2_DFREQ_OFFSET);
  351. } else {
  352. regmap_update_bits(icdc->regmap,
  353. JZ4725B_CODEC_REG_CR2,
  354. REG_CR2_ADC_ADWL_MASK,
  355. bit_width << REG_CR2_ADC_ADWL_OFFSET);
  356. regmap_update_bits(icdc->regmap,
  357. JZ4725B_CODEC_REG_CCR2,
  358. REG_CCR2_AFREQ_MASK,
  359. rate << REG_CCR2_AFREQ_OFFSET);
  360. }
  361. return 0;
  362. }
  363. static const struct snd_soc_dai_ops jz4725b_codec_dai_ops = {
  364. .hw_params = jz4725b_codec_hw_params,
  365. };
  366. #define JZ_ICDC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \
  367. SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_3LE)
  368. static struct snd_soc_dai_driver jz4725b_codec_dai = {
  369. .name = "jz4725b-hifi",
  370. .playback = {
  371. .stream_name = "Playback",
  372. .channels_min = 2,
  373. .channels_max = 2,
  374. .rates = SNDRV_PCM_RATE_8000_96000,
  375. .formats = JZ_ICDC_FORMATS,
  376. },
  377. .capture = {
  378. .stream_name = "Capture",
  379. .channels_min = 2,
  380. .channels_max = 2,
  381. .rates = SNDRV_PCM_RATE_8000_96000,
  382. .formats = JZ_ICDC_FORMATS,
  383. },
  384. .ops = &jz4725b_codec_dai_ops,
  385. };
  386. static bool jz4725b_codec_volatile(struct device *dev, unsigned int reg)
  387. {
  388. return reg == JZ4725B_CODEC_REG_IFR;
  389. }
  390. static bool jz4725b_codec_can_access_reg(struct device *dev, unsigned int reg)
  391. {
  392. return (reg != JZ4725B_CODEC_REG_TR1) && (reg != JZ4725B_CODEC_REG_TR2);
  393. }
  394. static int jz4725b_codec_io_wait(struct jz_icdc *icdc)
  395. {
  396. u32 reg;
  397. return readl_poll_timeout(icdc->base + ICDC_RGADW_OFFSET, reg,
  398. !(reg & ICDC_RGADW_RGWR), 1000, 10000);
  399. }
  400. static int jz4725b_codec_reg_read(void *context, unsigned int reg,
  401. unsigned int *val)
  402. {
  403. struct jz_icdc *icdc = context;
  404. unsigned int i;
  405. u32 tmp;
  406. int ret;
  407. ret = jz4725b_codec_io_wait(icdc);
  408. if (ret)
  409. return ret;
  410. tmp = readl(icdc->base + ICDC_RGADW_OFFSET);
  411. tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
  412. | (reg << ICDC_RGADW_RGADDR_OFFSET);
  413. writel(tmp, icdc->base + ICDC_RGADW_OFFSET);
  414. /* wait 6+ cycles */
  415. for (i = 0; i < 6; i++)
  416. *val = readl(icdc->base + ICDC_RGDATA_OFFSET) &
  417. ICDC_RGDATA_RGDOUT_MASK;
  418. return 0;
  419. }
  420. static int jz4725b_codec_reg_write(void *context, unsigned int reg,
  421. unsigned int val)
  422. {
  423. struct jz_icdc *icdc = context;
  424. int ret;
  425. ret = jz4725b_codec_io_wait(icdc);
  426. if (ret)
  427. return ret;
  428. writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
  429. icdc->base + ICDC_RGADW_OFFSET);
  430. ret = jz4725b_codec_io_wait(icdc);
  431. if (ret)
  432. return ret;
  433. return 0;
  434. }
  435. static const u8 jz4725b_codec_reg_defaults[] = {
  436. 0x0c, 0xaa, 0x78, 0x00, 0x00, 0xff, 0x03, 0x51,
  437. 0x3f, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
  438. 0x04, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0x34,
  439. 0x07, 0x44, 0x1f, 0x00,
  440. };
  441. static const struct regmap_config jz4725b_codec_regmap_config = {
  442. .reg_bits = 7,
  443. .val_bits = 8,
  444. .max_register = JZ4725B_CODEC_REG_AGC5,
  445. .volatile_reg = jz4725b_codec_volatile,
  446. .readable_reg = jz4725b_codec_can_access_reg,
  447. .writeable_reg = jz4725b_codec_can_access_reg,
  448. .reg_read = jz4725b_codec_reg_read,
  449. .reg_write = jz4725b_codec_reg_write,
  450. .reg_defaults_raw = jz4725b_codec_reg_defaults,
  451. .num_reg_defaults_raw = ARRAY_SIZE(jz4725b_codec_reg_defaults),
  452. .cache_type = REGCACHE_FLAT,
  453. };
  454. static int jz4725b_codec_probe(struct platform_device *pdev)
  455. {
  456. struct device *dev = &pdev->dev;
  457. struct jz_icdc *icdc;
  458. int ret;
  459. icdc = devm_kzalloc(dev, sizeof(*icdc), GFP_KERNEL);
  460. if (!icdc)
  461. return -ENOMEM;
  462. icdc->base = devm_platform_ioremap_resource(pdev, 0);
  463. if (IS_ERR(icdc->base))
  464. return PTR_ERR(icdc->base);
  465. icdc->regmap = devm_regmap_init(dev, NULL, icdc,
  466. &jz4725b_codec_regmap_config);
  467. if (IS_ERR(icdc->regmap))
  468. return PTR_ERR(icdc->regmap);
  469. icdc->clk = devm_clk_get(&pdev->dev, "aic");
  470. if (IS_ERR(icdc->clk))
  471. return PTR_ERR(icdc->clk);
  472. platform_set_drvdata(pdev, icdc);
  473. ret = devm_snd_soc_register_component(dev, &jz4725b_codec,
  474. &jz4725b_codec_dai, 1);
  475. if (ret)
  476. dev_err(dev, "Failed to register codec\n");
  477. return ret;
  478. }
  479. static const struct of_device_id jz4725b_codec_of_matches[] = {
  480. { .compatible = "ingenic,jz4725b-codec", },
  481. { }
  482. };
  483. MODULE_DEVICE_TABLE(of, jz4725b_codec_of_matches);
  484. static struct platform_driver jz4725b_codec_driver = {
  485. .probe = jz4725b_codec_probe,
  486. .driver = {
  487. .name = "jz4725b-codec",
  488. .of_match_table = jz4725b_codec_of_matches,
  489. },
  490. };
  491. module_platform_driver(jz4725b_codec_driver);
  492. MODULE_DESCRIPTION("JZ4725B SoC internal codec driver");
  493. MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
  494. MODULE_LICENSE("GPL v2");