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