meson_vclk.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2016 BayLibre, SAS
  4. * Author: Neil Armstrong <narmstrong@baylibre.com>
  5. * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
  6. */
  7. #include <linux/export.h>
  8. #include <drm/drm_print.h>
  9. #include "meson_drv.h"
  10. #include "meson_vclk.h"
  11. /**
  12. * DOC: Video Clocks
  13. *
  14. * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
  15. * We handle the following encodings :
  16. *
  17. * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
  18. * - HDMI Pixel Clocks generation
  19. *
  20. * What is missing :
  21. *
  22. * - Genenate Pixel clocks for 2K/4K 10bit formats
  23. *
  24. * Clock generator scheme :
  25. *
  26. * .. code::
  27. *
  28. * __________ _________ _____
  29. * | | | | | |--ENCI
  30. * | HDMI PLL |-| PLL_DIV |--- VCLK--| |--ENCL
  31. * |__________| |_________| \ | MUX |--ENCP
  32. * --VCLK2-| |--VDAC
  33. * |_____|--HDMI-TX
  34. *
  35. * Final clocks can take input for either VCLK or VCLK2, but
  36. * VCLK is the preferred path for HDMI clocking and VCLK2 is the
  37. * preferred path for CVBS VDAC clocking.
  38. *
  39. * VCLK and VCLK2 have fixed divided clocks paths for /1, /2, /4, /6 or /12.
  40. *
  41. * The PLL_DIV can achieve an additional fractional dividing like
  42. * 1.5, 3.5, 3.75... to generate special 2K and 4K 10bit clocks.
  43. */
  44. /* HHI Registers */
  45. #define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
  46. #define VID_PLL_EN BIT(19)
  47. #define VID_PLL_BYPASS BIT(18)
  48. #define VID_PLL_PRESET BIT(15)
  49. #define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
  50. #define VCLK2_DIV_MASK 0xff
  51. #define VCLK2_DIV_EN BIT(16)
  52. #define VCLK2_DIV_RESET BIT(17)
  53. #define CTS_VDAC_SEL_MASK (0xf << 28)
  54. #define CTS_VDAC_SEL_SHIFT 28
  55. #define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
  56. #define VCLK2_EN BIT(19)
  57. #define VCLK2_SEL_MASK (0x7 << 16)
  58. #define VCLK2_SEL_SHIFT 16
  59. #define VCLK2_SOFT_RESET BIT(15)
  60. #define VCLK2_DIV1_EN BIT(0)
  61. #define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
  62. #define VCLK_DIV_MASK 0xff
  63. #define VCLK_DIV_EN BIT(16)
  64. #define VCLK_DIV_RESET BIT(17)
  65. #define CTS_ENCP_SEL_MASK (0xf << 24)
  66. #define CTS_ENCP_SEL_SHIFT 24
  67. #define CTS_ENCI_SEL_MASK (0xf << 28)
  68. #define CTS_ENCI_SEL_SHIFT 28
  69. #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
  70. #define VCLK_EN BIT(19)
  71. #define VCLK_SEL_MASK (0x7 << 16)
  72. #define VCLK_SEL_SHIFT 16
  73. #define VCLK_SOFT_RESET BIT(15)
  74. #define VCLK_DIV1_EN BIT(0)
  75. #define VCLK_DIV2_EN BIT(1)
  76. #define VCLK_DIV4_EN BIT(2)
  77. #define VCLK_DIV6_EN BIT(3)
  78. #define VCLK_DIV12_EN BIT(4)
  79. #define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
  80. #define CTS_ENCI_EN BIT(0)
  81. #define CTS_ENCP_EN BIT(2)
  82. #define CTS_VDAC_EN BIT(4)
  83. #define HDMI_TX_PIXEL_EN BIT(5)
  84. #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
  85. #define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
  86. #define HDMI_TX_PIXEL_SEL_SHIFT 16
  87. #define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
  88. #define CTS_HDMI_SYS_DIV_MASK (0x7f)
  89. #define CTS_HDMI_SYS_EN BIT(8)
  90. #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
  91. #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
  92. #define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
  93. #define HHI_HDMI_PLL_CNTL_EN BIT(30)
  94. #define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
  95. #define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
  96. #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
  97. #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
  98. #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
  99. #define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
  100. #define HDMI_PLL_RESET BIT(28)
  101. #define HDMI_PLL_RESET_G12A BIT(29)
  102. #define HDMI_PLL_LOCK BIT(31)
  103. #define HDMI_PLL_LOCK_G12A (3 << 30)
  104. #define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
  105. /* VID PLL Dividers */
  106. enum {
  107. VID_PLL_DIV_1 = 0,
  108. VID_PLL_DIV_2,
  109. VID_PLL_DIV_2p5,
  110. VID_PLL_DIV_3,
  111. VID_PLL_DIV_3p5,
  112. VID_PLL_DIV_3p75,
  113. VID_PLL_DIV_4,
  114. VID_PLL_DIV_5,
  115. VID_PLL_DIV_6,
  116. VID_PLL_DIV_6p25,
  117. VID_PLL_DIV_7,
  118. VID_PLL_DIV_7p5,
  119. VID_PLL_DIV_12,
  120. VID_PLL_DIV_14,
  121. VID_PLL_DIV_15,
  122. };
  123. void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
  124. {
  125. unsigned int shift_val = 0;
  126. unsigned int shift_sel = 0;
  127. /* Disable vid_pll output clock */
  128. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
  129. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
  130. switch (div) {
  131. case VID_PLL_DIV_2:
  132. shift_val = 0x0aaa;
  133. shift_sel = 0;
  134. break;
  135. case VID_PLL_DIV_2p5:
  136. shift_val = 0x5294;
  137. shift_sel = 2;
  138. break;
  139. case VID_PLL_DIV_3:
  140. shift_val = 0x0db6;
  141. shift_sel = 0;
  142. break;
  143. case VID_PLL_DIV_3p5:
  144. shift_val = 0x36cc;
  145. shift_sel = 1;
  146. break;
  147. case VID_PLL_DIV_3p75:
  148. shift_val = 0x6666;
  149. shift_sel = 2;
  150. break;
  151. case VID_PLL_DIV_4:
  152. shift_val = 0x0ccc;
  153. shift_sel = 0;
  154. break;
  155. case VID_PLL_DIV_5:
  156. shift_val = 0x739c;
  157. shift_sel = 2;
  158. break;
  159. case VID_PLL_DIV_6:
  160. shift_val = 0x0e38;
  161. shift_sel = 0;
  162. break;
  163. case VID_PLL_DIV_6p25:
  164. shift_val = 0x0000;
  165. shift_sel = 3;
  166. break;
  167. case VID_PLL_DIV_7:
  168. shift_val = 0x3c78;
  169. shift_sel = 1;
  170. break;
  171. case VID_PLL_DIV_7p5:
  172. shift_val = 0x78f0;
  173. shift_sel = 2;
  174. break;
  175. case VID_PLL_DIV_12:
  176. shift_val = 0x0fc0;
  177. shift_sel = 0;
  178. break;
  179. case VID_PLL_DIV_14:
  180. shift_val = 0x3f80;
  181. shift_sel = 1;
  182. break;
  183. case VID_PLL_DIV_15:
  184. shift_val = 0x7f80;
  185. shift_sel = 2;
  186. break;
  187. }
  188. if (div == VID_PLL_DIV_1)
  189. /* Enable vid_pll bypass to HDMI pll */
  190. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  191. VID_PLL_BYPASS, VID_PLL_BYPASS);
  192. else {
  193. /* Disable Bypass */
  194. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  195. VID_PLL_BYPASS, 0);
  196. /* Clear sel */
  197. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  198. 3 << 16, 0);
  199. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  200. VID_PLL_PRESET, 0);
  201. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  202. 0x7fff, 0);
  203. /* Setup sel and val */
  204. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  205. 3 << 16, shift_sel << 16);
  206. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  207. VID_PLL_PRESET, VID_PLL_PRESET);
  208. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  209. 0x7fff, shift_val);
  210. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  211. VID_PLL_PRESET, 0);
  212. }
  213. /* Enable the vid_pll output clock */
  214. regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
  215. VID_PLL_EN, VID_PLL_EN);
  216. }
  217. /*
  218. * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
  219. *
  220. * TOFIX: Refactor into table to also handle HDMI frequency and paths
  221. */
  222. static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
  223. {
  224. unsigned int val;
  225. /* Setup PLL to output 1.485GHz */
  226. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
  227. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
  228. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00404e00);
  229. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
  230. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
  231. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
  232. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
  233. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
  234. /* Poll for lock bit */
  235. regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
  236. (val & HDMI_PLL_LOCK), 10, 0);
  237. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  238. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
  239. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
  240. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
  241. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0xa6212844);
  242. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
  243. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
  244. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
  245. /* Reset PLL */
  246. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  247. HDMI_PLL_RESET, HDMI_PLL_RESET);
  248. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  249. HDMI_PLL_RESET, 0);
  250. /* Poll for lock bit */
  251. regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
  252. (val & HDMI_PLL_LOCK), 10, 0);
  253. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  254. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
  255. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
  256. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
  257. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
  258. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
  259. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
  260. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x56540000);
  261. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
  262. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
  263. /* Poll for lock bit */
  264. regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
  265. ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
  266. 10, 0);
  267. }
  268. /* Disable VCLK2 */
  269. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
  270. /* Setup vid_pll to /1 */
  271. meson_vid_pll_set(priv, VID_PLL_DIV_1);
  272. /* Setup the VCLK2 divider value to achieve 27MHz */
  273. regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
  274. VCLK2_DIV_MASK, (55 - 1));
  275. /* select vid_pll for vclk2 */
  276. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  277. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
  278. VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
  279. else
  280. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
  281. VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
  282. /* enable vclk2 gate */
  283. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
  284. /* select vclk_div1 for enci */
  285. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  286. CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
  287. /* select vclk_div1 for vdac */
  288. regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
  289. CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
  290. /* release vclk2_div_reset and enable vclk2_div */
  291. regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
  292. VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
  293. /* enable vclk2_div1 gate */
  294. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
  295. VCLK2_DIV1_EN, VCLK2_DIV1_EN);
  296. /* reset vclk2 */
  297. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
  298. VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
  299. regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
  300. VCLK2_SOFT_RESET, 0);
  301. /* enable enci_clk */
  302. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
  303. CTS_ENCI_EN, CTS_ENCI_EN);
  304. /* enable vdac_clk */
  305. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
  306. CTS_VDAC_EN, CTS_VDAC_EN);
  307. }
  308. enum {
  309. /* PLL O1 O2 O3 VP DV EN TX */
  310. /* 4320 /4 /4 /1 /5 /1 => /2 /2 */
  311. MESON_VCLK_HDMI_ENCI_54000 = 0,
  312. /* 4320 /4 /4 /1 /5 /1 => /1 /2 */
  313. MESON_VCLK_HDMI_DDR_54000,
  314. /* 2970 /4 /1 /1 /5 /1 => /1 /2 */
  315. MESON_VCLK_HDMI_DDR_148500,
  316. /* 2970 /2 /2 /2 /5 /1 => /1 /1 */
  317. MESON_VCLK_HDMI_74250,
  318. /* 2970 /1 /2 /2 /5 /1 => /1 /1 */
  319. MESON_VCLK_HDMI_148500,
  320. /* 2970 /1 /1 /1 /5 /2 => /1 /1 */
  321. MESON_VCLK_HDMI_297000,
  322. /* 5940 /1 /1 /2 /5 /1 => /1 /1 */
  323. MESON_VCLK_HDMI_594000,
  324. /* 2970 /1 /1 /1 /5 /1 => /1 /2 */
  325. MESON_VCLK_HDMI_594000_YUV420,
  326. };
  327. struct meson_vclk_params {
  328. unsigned int pll_freq;
  329. unsigned int phy_freq;
  330. unsigned int vclk_freq;
  331. unsigned int venc_freq;
  332. unsigned int pixel_freq;
  333. unsigned int pll_od1;
  334. unsigned int pll_od2;
  335. unsigned int pll_od3;
  336. unsigned int vid_pll_div;
  337. unsigned int vclk_div;
  338. } params[] = {
  339. [MESON_VCLK_HDMI_ENCI_54000] = {
  340. .pll_freq = 4320000,
  341. .phy_freq = 270000,
  342. .vclk_freq = 54000,
  343. .venc_freq = 54000,
  344. .pixel_freq = 54000,
  345. .pll_od1 = 4,
  346. .pll_od2 = 4,
  347. .pll_od3 = 1,
  348. .vid_pll_div = VID_PLL_DIV_5,
  349. .vclk_div = 1,
  350. },
  351. [MESON_VCLK_HDMI_DDR_54000] = {
  352. .pll_freq = 4320000,
  353. .phy_freq = 270000,
  354. .vclk_freq = 54000,
  355. .venc_freq = 54000,
  356. .pixel_freq = 27000,
  357. .pll_od1 = 4,
  358. .pll_od2 = 4,
  359. .pll_od3 = 1,
  360. .vid_pll_div = VID_PLL_DIV_5,
  361. .vclk_div = 1,
  362. },
  363. [MESON_VCLK_HDMI_DDR_148500] = {
  364. .pll_freq = 2970000,
  365. .phy_freq = 742500,
  366. .vclk_freq = 148500,
  367. .venc_freq = 148500,
  368. .pixel_freq = 74250,
  369. .pll_od1 = 4,
  370. .pll_od2 = 1,
  371. .pll_od3 = 1,
  372. .vid_pll_div = VID_PLL_DIV_5,
  373. .vclk_div = 1,
  374. },
  375. [MESON_VCLK_HDMI_74250] = {
  376. .pll_freq = 2970000,
  377. .phy_freq = 742500,
  378. .vclk_freq = 74250,
  379. .venc_freq = 74250,
  380. .pixel_freq = 74250,
  381. .pll_od1 = 2,
  382. .pll_od2 = 2,
  383. .pll_od3 = 2,
  384. .vid_pll_div = VID_PLL_DIV_5,
  385. .vclk_div = 1,
  386. },
  387. [MESON_VCLK_HDMI_148500] = {
  388. .pll_freq = 2970000,
  389. .phy_freq = 1485000,
  390. .vclk_freq = 148500,
  391. .venc_freq = 148500,
  392. .pixel_freq = 148500,
  393. .pll_od1 = 1,
  394. .pll_od2 = 2,
  395. .pll_od3 = 2,
  396. .vid_pll_div = VID_PLL_DIV_5,
  397. .vclk_div = 1,
  398. },
  399. [MESON_VCLK_HDMI_297000] = {
  400. .pll_freq = 5940000,
  401. .phy_freq = 2970000,
  402. .venc_freq = 297000,
  403. .vclk_freq = 297000,
  404. .pixel_freq = 297000,
  405. .pll_od1 = 2,
  406. .pll_od2 = 1,
  407. .pll_od3 = 1,
  408. .vid_pll_div = VID_PLL_DIV_5,
  409. .vclk_div = 2,
  410. },
  411. [MESON_VCLK_HDMI_594000] = {
  412. .pll_freq = 5940000,
  413. .phy_freq = 5940000,
  414. .venc_freq = 594000,
  415. .vclk_freq = 594000,
  416. .pixel_freq = 594000,
  417. .pll_od1 = 1,
  418. .pll_od2 = 1,
  419. .pll_od3 = 2,
  420. .vid_pll_div = VID_PLL_DIV_5,
  421. .vclk_div = 1,
  422. },
  423. [MESON_VCLK_HDMI_594000_YUV420] = {
  424. .pll_freq = 5940000,
  425. .phy_freq = 2970000,
  426. .venc_freq = 594000,
  427. .vclk_freq = 594000,
  428. .pixel_freq = 297000,
  429. .pll_od1 = 2,
  430. .pll_od2 = 1,
  431. .pll_od3 = 1,
  432. .vid_pll_div = VID_PLL_DIV_5,
  433. .vclk_div = 1,
  434. },
  435. { /* sentinel */ },
  436. };
  437. static inline unsigned int pll_od_to_reg(unsigned int od)
  438. {
  439. switch (od) {
  440. case 1:
  441. return 0;
  442. case 2:
  443. return 1;
  444. case 4:
  445. return 2;
  446. case 8:
  447. return 3;
  448. }
  449. /* Invalid */
  450. return 0;
  451. }
  452. void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
  453. unsigned int frac, unsigned int od1,
  454. unsigned int od2, unsigned int od3)
  455. {
  456. unsigned int val;
  457. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
  458. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000200 | m);
  459. if (frac)
  460. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
  461. 0x00004000 | frac);
  462. else
  463. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
  464. 0x00000000);
  465. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
  466. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
  467. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
  468. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
  469. /* Enable and unreset */
  470. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  471. 0x7 << 28, HHI_HDMI_PLL_CNTL_EN);
  472. /* Poll for lock bit */
  473. regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
  474. val, (val & HDMI_PLL_LOCK), 10, 0);
  475. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  476. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
  477. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000200 | m);
  478. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
  479. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
  480. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
  481. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
  482. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
  483. /* Reset PLL */
  484. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  485. HDMI_PLL_RESET, HDMI_PLL_RESET);
  486. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  487. HDMI_PLL_RESET, 0);
  488. /* Poll for lock bit */
  489. regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
  490. (val & HDMI_PLL_LOCK), 10, 0);
  491. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  492. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
  493. /* Enable and reset */
  494. /* TODO: add specific macro for g12a here */
  495. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  496. 0x3 << 28, 0x3 << 28);
  497. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
  498. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
  499. /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
  500. if (m >= 0xf7) {
  501. if (frac < 0x10000) {
  502. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
  503. 0x6a685c00);
  504. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
  505. 0x11551293);
  506. } else {
  507. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
  508. 0xea68dc00);
  509. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
  510. 0x65771290);
  511. }
  512. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
  513. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
  514. } else {
  515. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
  516. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
  517. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
  518. regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
  519. }
  520. do {
  521. /* Reset PLL */
  522. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  523. HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
  524. /* UN-Reset PLL */
  525. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  526. HDMI_PLL_RESET_G12A, 0);
  527. /* Poll for lock bits */
  528. if (!regmap_read_poll_timeout(priv->hhi,
  529. HHI_HDMI_PLL_CNTL, val,
  530. ((val & HDMI_PLL_LOCK_G12A)
  531. == HDMI_PLL_LOCK_G12A),
  532. 10, 100))
  533. break;
  534. } while(1);
  535. }
  536. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
  537. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
  538. 3 << 16, pll_od_to_reg(od1) << 16);
  539. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  540. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
  541. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
  542. 3 << 21, pll_od_to_reg(od1) << 21);
  543. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  544. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  545. 3 << 16, pll_od_to_reg(od1) << 16);
  546. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
  547. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
  548. 3 << 22, pll_od_to_reg(od2) << 22);
  549. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  550. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
  551. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
  552. 3 << 23, pll_od_to_reg(od2) << 23);
  553. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  554. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  555. 3 << 18, pll_od_to_reg(od2) << 18);
  556. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
  557. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
  558. 3 << 18, pll_od_to_reg(od3) << 18);
  559. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  560. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
  561. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
  562. 3 << 19, pll_od_to_reg(od3) << 19);
  563. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  564. regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
  565. 3 << 20, pll_od_to_reg(od3) << 20);
  566. }
  567. #define XTAL_FREQ 24000
  568. static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
  569. unsigned int pll_freq)
  570. {
  571. /* The GXBB PLL has a /2 pre-multiplier */
  572. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
  573. pll_freq /= 2;
  574. return pll_freq / XTAL_FREQ;
  575. }
  576. #define HDMI_FRAC_MAX_GXBB 4096
  577. #define HDMI_FRAC_MAX_GXL 1024
  578. #define HDMI_FRAC_MAX_G12A 131072
  579. static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
  580. unsigned int m,
  581. unsigned int pll_freq)
  582. {
  583. unsigned int parent_freq = XTAL_FREQ;
  584. unsigned int frac_max = HDMI_FRAC_MAX_GXL;
  585. unsigned int frac_m;
  586. unsigned int frac;
  587. /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
  588. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
  589. frac_max = HDMI_FRAC_MAX_GXBB;
  590. parent_freq *= 2;
  591. }
  592. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  593. frac_max = HDMI_FRAC_MAX_G12A;
  594. /* We can have a perfect match !*/
  595. if (pll_freq / m == parent_freq &&
  596. pll_freq % m == 0)
  597. return 0;
  598. frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
  599. frac_m = m * frac_max;
  600. if (frac_m > frac)
  601. return frac_max;
  602. frac -= frac_m;
  603. return min((u16)frac, (u16)(frac_max - 1));
  604. }
  605. static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
  606. unsigned int m,
  607. unsigned int frac)
  608. {
  609. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
  610. /* Empiric supported min/max dividers */
  611. if (m < 53 || m > 123)
  612. return false;
  613. if (frac >= HDMI_FRAC_MAX_GXBB)
  614. return false;
  615. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  616. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
  617. /* Empiric supported min/max dividers */
  618. if (m < 106 || m > 247)
  619. return false;
  620. if (frac >= HDMI_FRAC_MAX_GXL)
  621. return false;
  622. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  623. /* Empiric supported min/max dividers */
  624. if (m < 106 || m > 247)
  625. return false;
  626. if (frac >= HDMI_FRAC_MAX_G12A)
  627. return false;
  628. }
  629. return true;
  630. }
  631. static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
  632. unsigned int freq,
  633. unsigned int *m,
  634. unsigned int *frac,
  635. unsigned int *od)
  636. {
  637. /* Cycle from /16 to /2 */
  638. for (*od = 16 ; *od > 1 ; *od >>= 1) {
  639. *m = meson_hdmi_pll_get_m(priv, freq * *od);
  640. if (!*m)
  641. continue;
  642. *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
  643. DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d\n",
  644. freq, *m, *frac, *od);
  645. if (meson_hdmi_pll_validate_params(priv, *m, *frac))
  646. return true;
  647. }
  648. return false;
  649. }
  650. /* pll_freq is the frequency after the OD dividers */
  651. enum drm_mode_status
  652. meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
  653. {
  654. unsigned int od, m, frac;
  655. /* In DMT mode, path after PLL is always /10 */
  656. freq *= 10;
  657. /* Check against soc revision/package limits */
  658. if (priv->limits) {
  659. if (priv->limits->max_hdmi_phy_freq &&
  660. freq > priv->limits->max_hdmi_phy_freq)
  661. return MODE_CLOCK_HIGH;
  662. }
  663. if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
  664. return MODE_OK;
  665. return MODE_CLOCK_RANGE;
  666. }
  667. EXPORT_SYMBOL_GPL(meson_vclk_dmt_supported_freq);
  668. /* pll_freq is the frequency after the OD dividers */
  669. static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
  670. unsigned int pll_freq)
  671. {
  672. unsigned int od, m, frac, od1, od2, od3;
  673. if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
  674. /* OD2 goes to the PHY, and needs to be *10, so keep OD3=1 */
  675. od3 = 1;
  676. if (od < 4) {
  677. od1 = 2;
  678. od2 = 1;
  679. } else {
  680. od2 = od / 4;
  681. od1 = od / od2;
  682. }
  683. DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
  684. pll_freq, m, frac, od1, od2, od3);
  685. meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
  686. return;
  687. }
  688. DRM_ERROR("Fatal, unable to find parameters for PLL freq %d\n",
  689. pll_freq);
  690. }
  691. enum drm_mode_status
  692. meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
  693. unsigned int vclk_freq)
  694. {
  695. int i;
  696. DRM_DEBUG_DRIVER("phy_freq = %d vclk_freq = %d\n",
  697. phy_freq, vclk_freq);
  698. /* Check against soc revision/package limits */
  699. if (priv->limits) {
  700. if (priv->limits->max_hdmi_phy_freq &&
  701. phy_freq > priv->limits->max_hdmi_phy_freq)
  702. return MODE_CLOCK_HIGH;
  703. }
  704. for (i = 0 ; params[i].pixel_freq ; ++i) {
  705. DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
  706. i, params[i].pixel_freq,
  707. FREQ_1000_1001(params[i].pixel_freq));
  708. DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n",
  709. i, params[i].phy_freq,
  710. FREQ_1000_1001(params[i].phy_freq/10)*10);
  711. /* Match strict frequency */
  712. if (phy_freq == params[i].phy_freq &&
  713. vclk_freq == params[i].vclk_freq)
  714. return MODE_OK;
  715. /* Match 1000/1001 variant */
  716. if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) &&
  717. vclk_freq == FREQ_1000_1001(params[i].vclk_freq))
  718. return MODE_OK;
  719. }
  720. return MODE_CLOCK_RANGE;
  721. }
  722. EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
  723. static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
  724. unsigned int od1, unsigned int od2, unsigned int od3,
  725. unsigned int vid_pll_div, unsigned int vclk_div,
  726. unsigned int hdmi_tx_div, unsigned int venc_div,
  727. bool hdmi_use_enci, bool vic_alternate_clock)
  728. {
  729. unsigned int m = 0, frac = 0;
  730. /* Set HDMI-TX sys clock */
  731. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  732. CTS_HDMI_SYS_SEL_MASK, 0);
  733. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  734. CTS_HDMI_SYS_DIV_MASK, 0);
  735. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  736. CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
  737. /* Set HDMI PLL rate */
  738. if (!od1 && !od2 && !od3) {
  739. meson_hdmi_pll_generic_set(priv, pll_base_freq);
  740. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
  741. switch (pll_base_freq) {
  742. case 2970000:
  743. m = 0x3d;
  744. frac = vic_alternate_clock ? 0xd02 : 0xe00;
  745. break;
  746. case 4320000:
  747. m = vic_alternate_clock ? 0x59 : 0x5a;
  748. frac = vic_alternate_clock ? 0xe8f : 0;
  749. break;
  750. case 5940000:
  751. m = 0x7b;
  752. frac = vic_alternate_clock ? 0xa05 : 0xc00;
  753. break;
  754. }
  755. meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
  756. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  757. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
  758. switch (pll_base_freq) {
  759. case 2970000:
  760. m = 0x7b;
  761. frac = vic_alternate_clock ? 0x281 : 0x300;
  762. break;
  763. case 4320000:
  764. m = vic_alternate_clock ? 0xb3 : 0xb4;
  765. frac = vic_alternate_clock ? 0x347 : 0;
  766. break;
  767. case 5940000:
  768. m = 0xf7;
  769. frac = vic_alternate_clock ? 0x102 : 0x200;
  770. break;
  771. }
  772. meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
  773. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  774. switch (pll_base_freq) {
  775. case 2970000:
  776. m = 0x7b;
  777. frac = vic_alternate_clock ? 0x140b4 : 0x18000;
  778. break;
  779. case 4320000:
  780. m = vic_alternate_clock ? 0xb3 : 0xb4;
  781. frac = vic_alternate_clock ? 0x1a3ee : 0;
  782. break;
  783. case 5940000:
  784. m = 0xf7;
  785. frac = vic_alternate_clock ? 0x8148 : 0x10000;
  786. break;
  787. }
  788. meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
  789. }
  790. /* Setup vid_pll divider */
  791. meson_vid_pll_set(priv, vid_pll_div);
  792. /* Set VCLK div */
  793. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  794. VCLK_SEL_MASK, 0);
  795. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  796. VCLK_DIV_MASK, vclk_div - 1);
  797. /* Set HDMI-TX source */
  798. switch (hdmi_tx_div) {
  799. case 1:
  800. /* enable vclk_div1 gate */
  801. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  802. VCLK_DIV1_EN, VCLK_DIV1_EN);
  803. /* select vclk_div1 for HDMI-TX */
  804. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  805. HDMI_TX_PIXEL_SEL_MASK, 0);
  806. break;
  807. case 2:
  808. /* enable vclk_div2 gate */
  809. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  810. VCLK_DIV2_EN, VCLK_DIV2_EN);
  811. /* select vclk_div2 for HDMI-TX */
  812. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  813. HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
  814. break;
  815. case 4:
  816. /* enable vclk_div4 gate */
  817. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  818. VCLK_DIV4_EN, VCLK_DIV4_EN);
  819. /* select vclk_div4 for HDMI-TX */
  820. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  821. HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
  822. break;
  823. case 6:
  824. /* enable vclk_div6 gate */
  825. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  826. VCLK_DIV6_EN, VCLK_DIV6_EN);
  827. /* select vclk_div6 for HDMI-TX */
  828. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  829. HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
  830. break;
  831. case 12:
  832. /* enable vclk_div12 gate */
  833. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  834. VCLK_DIV12_EN, VCLK_DIV12_EN);
  835. /* select vclk_div12 for HDMI-TX */
  836. regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
  837. HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
  838. break;
  839. }
  840. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
  841. HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
  842. /* Set ENCI/ENCP Source */
  843. switch (venc_div) {
  844. case 1:
  845. /* enable vclk_div1 gate */
  846. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  847. VCLK_DIV1_EN, VCLK_DIV1_EN);
  848. if (hdmi_use_enci)
  849. /* select vclk_div1 for enci */
  850. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  851. CTS_ENCI_SEL_MASK, 0);
  852. else
  853. /* select vclk_div1 for encp */
  854. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  855. CTS_ENCP_SEL_MASK, 0);
  856. break;
  857. case 2:
  858. /* enable vclk_div2 gate */
  859. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  860. VCLK_DIV2_EN, VCLK_DIV2_EN);
  861. if (hdmi_use_enci)
  862. /* select vclk_div2 for enci */
  863. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  864. CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
  865. else
  866. /* select vclk_div2 for encp */
  867. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  868. CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
  869. break;
  870. case 4:
  871. /* enable vclk_div4 gate */
  872. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  873. VCLK_DIV4_EN, VCLK_DIV4_EN);
  874. if (hdmi_use_enci)
  875. /* select vclk_div4 for enci */
  876. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  877. CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
  878. else
  879. /* select vclk_div4 for encp */
  880. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  881. CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
  882. break;
  883. case 6:
  884. /* enable vclk_div6 gate */
  885. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  886. VCLK_DIV6_EN, VCLK_DIV6_EN);
  887. if (hdmi_use_enci)
  888. /* select vclk_div6 for enci */
  889. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  890. CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
  891. else
  892. /* select vclk_div6 for encp */
  893. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  894. CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
  895. break;
  896. case 12:
  897. /* enable vclk_div12 gate */
  898. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
  899. VCLK_DIV12_EN, VCLK_DIV12_EN);
  900. if (hdmi_use_enci)
  901. /* select vclk_div12 for enci */
  902. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  903. CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
  904. else
  905. /* select vclk_div12 for encp */
  906. regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
  907. CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
  908. break;
  909. }
  910. if (hdmi_use_enci)
  911. /* Enable ENCI clock gate */
  912. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
  913. CTS_ENCI_EN, CTS_ENCI_EN);
  914. else
  915. /* Enable ENCP clock gate */
  916. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
  917. CTS_ENCP_EN, CTS_ENCP_EN);
  918. regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
  919. }
  920. void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
  921. unsigned int phy_freq, unsigned int vclk_freq,
  922. unsigned int venc_freq, unsigned int dac_freq,
  923. bool hdmi_use_enci)
  924. {
  925. bool vic_alternate_clock = false;
  926. unsigned int freq;
  927. unsigned int hdmi_tx_div;
  928. unsigned int venc_div;
  929. if (target == MESON_VCLK_TARGET_CVBS) {
  930. meson_venci_cvbs_clock_config(priv);
  931. return;
  932. } else if (target == MESON_VCLK_TARGET_DMT) {
  933. /*
  934. * The DMT clock path is fixed after the PLL:
  935. * - automatic PLL freq + OD management
  936. * - vid_pll_div = VID_PLL_DIV_5
  937. * - vclk_div = 2
  938. * - hdmi_tx_div = 1
  939. * - venc_div = 1
  940. * - encp encoder
  941. */
  942. meson_vclk_set(priv, phy_freq, 0, 0, 0,
  943. VID_PLL_DIV_5, 2, 1, 1, false, false);
  944. return;
  945. }
  946. hdmi_tx_div = vclk_freq / dac_freq;
  947. if (hdmi_tx_div == 0) {
  948. pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
  949. dac_freq);
  950. return;
  951. }
  952. venc_div = vclk_freq / venc_freq;
  953. if (venc_div == 0) {
  954. pr_err("Fatal Error, invalid HDMI venc freq %d\n",
  955. venc_freq);
  956. return;
  957. }
  958. for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
  959. if ((phy_freq == params[freq].phy_freq ||
  960. phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) &&
  961. (vclk_freq == params[freq].vclk_freq ||
  962. vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) {
  963. if (vclk_freq != params[freq].vclk_freq)
  964. vic_alternate_clock = true;
  965. else
  966. vic_alternate_clock = false;
  967. if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
  968. !hdmi_use_enci)
  969. continue;
  970. if (freq == MESON_VCLK_HDMI_DDR_54000 &&
  971. hdmi_use_enci)
  972. continue;
  973. if (freq == MESON_VCLK_HDMI_DDR_148500 &&
  974. dac_freq == vclk_freq)
  975. continue;
  976. if (freq == MESON_VCLK_HDMI_148500 &&
  977. dac_freq != vclk_freq)
  978. continue;
  979. break;
  980. }
  981. }
  982. if (!params[freq].pixel_freq) {
  983. pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
  984. return;
  985. }
  986. meson_vclk_set(priv, params[freq].pll_freq,
  987. params[freq].pll_od1, params[freq].pll_od2,
  988. params[freq].pll_od3, params[freq].vid_pll_div,
  989. params[freq].vclk_div, hdmi_tx_div, venc_div,
  990. hdmi_use_enci, vic_alternate_clock);
  991. }
  992. EXPORT_SYMBOL_GPL(meson_vclk_setup);