1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> 4 */ 5 6 #include <linux/delay.h> 7 #include <linux/of_address.h> 8 9 #include "sun8i_dw_hdmi.h" 10 11 /* 12 * Address can be actually any value. Here is set to same value as 13 * it is set in BSP driver. 14 */ 15 #define I2C_ADDR 0x69 16 17 static const struct dw_hdmi_mpll_config sun50i_h6_mpll_cfg[] = { 18 { 19 30666000, { 20 { 0x00b3, 0x0000 }, 21 { 0x2153, 0x0000 }, 22 { 0x40f3, 0x0000 }, 23 }, 24 }, { 25 36800000, { 26 { 0x00b3, 0x0000 }, 27 { 0x2153, 0x0000 }, 28 { 0x40a2, 0x0001 }, 29 }, 30 }, { 31 46000000, { 32 { 0x00b3, 0x0000 }, 33 { 0x2142, 0x0001 }, 34 { 0x40a2, 0x0001 }, 35 }, 36 }, { 37 61333000, { 38 { 0x0072, 0x0001 }, 39 { 0x2142, 0x0001 }, 40 { 0x40a2, 0x0001 }, 41 }, 42 }, { 43 73600000, { 44 { 0x0072, 0x0001 }, 45 { 0x2142, 0x0001 }, 46 { 0x4061, 0x0002 }, 47 }, 48 }, { 49 92000000, { 50 { 0x0072, 0x0001 }, 51 { 0x2145, 0x0002 }, 52 { 0x4061, 0x0002 }, 53 }, 54 }, { 55 122666000, { 56 { 0x0051, 0x0002 }, 57 { 0x2145, 0x0002 }, 58 { 0x4061, 0x0002 }, 59 }, 60 }, { 61 147200000, { 62 { 0x0051, 0x0002 }, 63 { 0x2145, 0x0002 }, 64 { 0x4064, 0x0003 }, 65 }, 66 }, { 67 184000000, { 68 { 0x0051, 0x0002 }, 69 { 0x214c, 0x0003 }, 70 { 0x4064, 0x0003 }, 71 }, 72 }, { 73 226666000, { 74 { 0x0040, 0x0003 }, 75 { 0x214c, 0x0003 }, 76 { 0x4064, 0x0003 }, 77 }, 78 }, { 79 272000000, { 80 { 0x0040, 0x0003 }, 81 { 0x214c, 0x0003 }, 82 { 0x5a64, 0x0003 }, 83 }, 84 }, { 85 340000000, { 86 { 0x0040, 0x0003 }, 87 { 0x3b4c, 0x0003 }, 88 { 0x5a64, 0x0003 }, 89 }, 90 }, { 91 594000000, { 92 { 0x1a40, 0x0003 }, 93 { 0x3b4c, 0x0003 }, 94 { 0x5a64, 0x0003 }, 95 }, 96 }, { 97 ~0UL, { 98 { 0x0000, 0x0000 }, 99 { 0x0000, 0x0000 }, 100 { 0x0000, 0x0000 }, 101 }, 102 } 103 }; 104 105 static const struct dw_hdmi_curr_ctrl sun50i_h6_cur_ctr[] = { 106 /* pixelclk bpp8 bpp10 bpp12 */ 107 { 25175000, { 0x0000, 0x0000, 0x0000 }, }, 108 { 27000000, { 0x0012, 0x0000, 0x0000 }, }, 109 { 59400000, { 0x0008, 0x0008, 0x0008 }, }, 110 { 72000000, { 0x0008, 0x0008, 0x001b }, }, 111 { 74250000, { 0x0013, 0x0013, 0x0013 }, }, 112 { 90000000, { 0x0008, 0x001a, 0x001b }, }, 113 { 118800000, { 0x001b, 0x001a, 0x001b }, }, 114 { 144000000, { 0x001b, 0x001a, 0x0034 }, }, 115 { 180000000, { 0x001b, 0x0033, 0x0034 }, }, 116 { 216000000, { 0x0036, 0x0033, 0x0034 }, }, 117 { 237600000, { 0x0036, 0x0033, 0x001b }, }, 118 { 288000000, { 0x0036, 0x001b, 0x001b }, }, 119 { 297000000, { 0x0019, 0x001b, 0x0019 }, }, 120 { 330000000, { 0x0036, 0x001b, 0x001b }, }, 121 { 594000000, { 0x003f, 0x001b, 0x001b }, }, 122 { ~0UL, { 0x0000, 0x0000, 0x0000 }, } 123 }; 124 125 static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = { 126 /*pixelclk symbol term vlev*/ 127 { 74250000, 0x8009, 0x0004, 0x0232}, 128 { 148500000, 0x8029, 0x0004, 0x0273}, 129 { 594000000, 0x8039, 0x0004, 0x014a}, 130 { ~0UL, 0x0000, 0x0000, 0x0000} 131 }; 132 133 static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi, 134 struct sun8i_hdmi_phy *phy, 135 unsigned int clk_rate) 136 { 137 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, 138 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 139 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN); 140 141 /* power down */ 142 dw_hdmi_phy_gen2_txpwron(hdmi, 0); 143 dw_hdmi_phy_gen2_pddq(hdmi, 1); 144 145 dw_hdmi_phy_reset(hdmi); 146 147 dw_hdmi_phy_gen2_pddq(hdmi, 0); 148 149 dw_hdmi_phy_i2c_set_addr(hdmi, I2C_ADDR); 150 151 /* 152 * Values are taken from BSP HDMI driver. Although AW didn't 153 * release any documentation, explanation of this values can 154 * be found in i.MX 6Dual/6Quad Reference Manual. 155 */ 156 if (clk_rate <= 27000000) { 157 dw_hdmi_phy_i2c_write(hdmi, 0x01e0, 0x06); 158 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x15); 159 dw_hdmi_phy_i2c_write(hdmi, 0x08da, 0x10); 160 dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); 161 dw_hdmi_phy_i2c_write(hdmi, 0x0318, 0x0e); 162 dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); 163 } else if (clk_rate <= 74250000) { 164 dw_hdmi_phy_i2c_write(hdmi, 0x0540, 0x06); 165 dw_hdmi_phy_i2c_write(hdmi, 0x0005, 0x15); 166 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); 167 dw_hdmi_phy_i2c_write(hdmi, 0x0007, 0x19); 168 dw_hdmi_phy_i2c_write(hdmi, 0x02b5, 0x0e); 169 dw_hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); 170 } else if (clk_rate <= 148500000) { 171 dw_hdmi_phy_i2c_write(hdmi, 0x04a0, 0x06); 172 dw_hdmi_phy_i2c_write(hdmi, 0x000a, 0x15); 173 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); 174 dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19); 175 dw_hdmi_phy_i2c_write(hdmi, 0x0021, 0x0e); 176 dw_hdmi_phy_i2c_write(hdmi, 0x8029, 0x09); 177 } else { 178 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x06); 179 dw_hdmi_phy_i2c_write(hdmi, 0x000f, 0x15); 180 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x10); 181 dw_hdmi_phy_i2c_write(hdmi, 0x0002, 0x19); 182 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x0e); 183 dw_hdmi_phy_i2c_write(hdmi, 0x802b, 0x09); 184 } 185 186 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x1e); 187 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); 188 dw_hdmi_phy_i2c_write(hdmi, 0x0000, 0x17); 189 190 dw_hdmi_phy_gen2_txpwron(hdmi, 1); 191 192 return 0; 193 } 194 195 static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi, 196 struct sun8i_hdmi_phy *phy, 197 unsigned int clk_rate) 198 { 199 u32 pll_cfg1_init; 200 u32 pll_cfg2_init; 201 u32 ana_cfg1_end; 202 u32 ana_cfg2_init; 203 u32 ana_cfg3_init; 204 u32 b_offset = 0; 205 u32 val; 206 207 /* bandwidth / frequency independent settings */ 208 209 pll_cfg1_init = SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN | 210 SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN | 211 SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(7) | 212 SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(1) | 213 SUN8I_HDMI_PHY_PLL_CFG1_PLLDBEN | 214 SUN8I_HDMI_PHY_PLL_CFG1_CS | 215 SUN8I_HDMI_PHY_PLL_CFG1_CP_S(2) | 216 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63) | 217 SUN8I_HDMI_PHY_PLL_CFG1_BWS; 218 219 pll_cfg2_init = SUN8I_HDMI_PHY_PLL_CFG2_SV_H | 220 SUN8I_HDMI_PHY_PLL_CFG2_VCOGAIN_EN | 221 SUN8I_HDMI_PHY_PLL_CFG2_SDIV2; 222 223 ana_cfg1_end = SUN8I_HDMI_PHY_ANA_CFG1_REG_SVBH(1) | 224 SUN8I_HDMI_PHY_ANA_CFG1_AMP_OPT | 225 SUN8I_HDMI_PHY_ANA_CFG1_EMP_OPT | 226 SUN8I_HDMI_PHY_ANA_CFG1_AMPCK_OPT | 227 SUN8I_HDMI_PHY_ANA_CFG1_EMPCK_OPT | 228 SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL | 229 SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG | 230 SUN8I_HDMI_PHY_ANA_CFG1_REG_SCKTMDS | 231 SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN | 232 SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK | 233 SUN8I_HDMI_PHY_ANA_CFG1_TXEN_ALL | 234 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK | 235 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 | 236 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 | 237 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 | 238 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2 | 239 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 | 240 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 | 241 SUN8I_HDMI_PHY_ANA_CFG1_CKEN | 242 SUN8I_HDMI_PHY_ANA_CFG1_LDOEN | 243 SUN8I_HDMI_PHY_ANA_CFG1_ENVBS | 244 SUN8I_HDMI_PHY_ANA_CFG1_ENBI; 245 246 ana_cfg2_init = SUN8I_HDMI_PHY_ANA_CFG2_M_EN | 247 SUN8I_HDMI_PHY_ANA_CFG2_REG_DENCK | 248 SUN8I_HDMI_PHY_ANA_CFG2_REG_DEN | 249 SUN8I_HDMI_PHY_ANA_CFG2_REG_CKSS(1) | 250 SUN8I_HDMI_PHY_ANA_CFG2_REG_CSMPS(1); 251 252 ana_cfg3_init = SUN8I_HDMI_PHY_ANA_CFG3_REG_WIRE(0x3e0) | 253 SUN8I_HDMI_PHY_ANA_CFG3_SDAEN | 254 SUN8I_HDMI_PHY_ANA_CFG3_SCLEN; 255 256 /* bandwidth / frequency dependent settings */ 257 if (clk_rate <= 27000000) { 258 pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 | 259 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32); 260 pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) | 261 SUN8I_HDMI_PHY_PLL_CFG2_S(4); 262 ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW; 263 ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) | 264 SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal); 265 ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(3) | 266 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(5); 267 } else if (clk_rate <= 74250000) { 268 pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 | 269 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32); 270 pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) | 271 SUN8I_HDMI_PHY_PLL_CFG2_S(5); 272 ana_cfg1_end |= SUN8I_HDMI_PHY_ANA_CFG1_REG_CALSW; 273 ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4) | 274 SUN8I_HDMI_PHY_ANA_CFG2_REG_RESDI(phy->rcal); 275 ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(5) | 276 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(7); 277 } else if (clk_rate <= 148500000) { 278 pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 | 279 SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(32); 280 pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(4) | 281 SUN8I_HDMI_PHY_PLL_CFG2_S(6); 282 ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK | 283 SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW | 284 SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(2); 285 ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(7) | 286 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(9); 287 } else { 288 b_offset = 2; 289 pll_cfg1_init |= SUN8I_HDMI_PHY_PLL_CFG1_CNT_INT(63); 290 pll_cfg2_init |= SUN8I_HDMI_PHY_PLL_CFG2_VCO_S(6) | 291 SUN8I_HDMI_PHY_PLL_CFG2_S(7); 292 ana_cfg2_init |= SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSWCK | 293 SUN8I_HDMI_PHY_ANA_CFG2_REG_BIGSW | 294 SUN8I_HDMI_PHY_ANA_CFG2_REG_SLV(4); 295 ana_cfg3_init |= SUN8I_HDMI_PHY_ANA_CFG3_REG_AMPCK(9) | 296 SUN8I_HDMI_PHY_ANA_CFG3_REG_AMP(13) | 297 SUN8I_HDMI_PHY_ANA_CFG3_REG_EMP(3); 298 } 299 300 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 301 SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0); 302 303 /* 304 * NOTE: We have to be careful not to overwrite PHY parent 305 * clock selection bit and clock divider. 306 */ 307 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 308 (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 309 pll_cfg1_init); 310 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, 311 (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK, 312 pll_cfg2_init); 313 usleep_range(10000, 15000); 314 regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG3_REG, 315 SUN8I_HDMI_PHY_PLL_CFG3_SOUT_DIV2); 316 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 317 SUN8I_HDMI_PHY_PLL_CFG1_PLLEN, 318 SUN8I_HDMI_PHY_PLL_CFG1_PLLEN); 319 msleep(100); 320 321 /* get B value */ 322 regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); 323 val = (val & SUN8I_HDMI_PHY_ANA_STS_B_OUT_MSK) >> 324 SUN8I_HDMI_PHY_ANA_STS_B_OUT_SHIFT; 325 val = min(val + b_offset, (u32)0x3f); 326 327 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 328 SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 | 329 SUN8I_HDMI_PHY_PLL_CFG1_REG_OD, 330 SUN8I_HDMI_PHY_PLL_CFG1_REG_OD1 | 331 SUN8I_HDMI_PHY_PLL_CFG1_REG_OD); 332 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 333 SUN8I_HDMI_PHY_PLL_CFG1_B_IN_MSK, 334 val << SUN8I_HDMI_PHY_PLL_CFG1_B_IN_SHIFT); 335 msleep(100); 336 regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, ana_cfg1_end); 337 regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG2_REG, ana_cfg2_init); 338 regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG, ana_cfg3_init); 339 340 return 0; 341 } 342 343 static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data, 344 struct drm_display_mode *mode) 345 { 346 struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; 347 u32 val = 0; 348 349 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 350 val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC; 351 352 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 353 val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC; 354 355 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, 356 SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val); 357 358 if (phy->variant->has_phy_clk) 359 clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000); 360 361 return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000); 362 }; 363 364 static void sun8i_hdmi_phy_disable_a83t(struct dw_hdmi *hdmi, 365 struct sun8i_hdmi_phy *phy) 366 { 367 dw_hdmi_phy_gen2_txpwron(hdmi, 0); 368 dw_hdmi_phy_gen2_pddq(hdmi, 1); 369 370 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, 371 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0); 372 } 373 374 static void sun8i_hdmi_phy_disable_h3(struct dw_hdmi *hdmi, 375 struct sun8i_hdmi_phy *phy) 376 { 377 regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 378 SUN8I_HDMI_PHY_ANA_CFG1_LDOEN | 379 SUN8I_HDMI_PHY_ANA_CFG1_ENVBS | 380 SUN8I_HDMI_PHY_ANA_CFG1_ENBI); 381 regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0); 382 } 383 384 static void sun8i_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) 385 { 386 struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data; 387 388 phy->variant->phy_disable(hdmi, phy); 389 } 390 391 static const struct dw_hdmi_phy_ops sun8i_hdmi_phy_ops = { 392 .init = &sun8i_hdmi_phy_config, 393 .disable = &sun8i_hdmi_phy_disable, 394 .read_hpd = &dw_hdmi_phy_read_hpd, 395 .update_hpd = &dw_hdmi_phy_update_hpd, 396 .setup_hpd = &dw_hdmi_phy_setup_hpd, 397 }; 398 399 static void sun8i_hdmi_phy_unlock(struct sun8i_hdmi_phy *phy) 400 { 401 /* enable read access to HDMI controller */ 402 regmap_write(phy->regs, SUN8I_HDMI_PHY_READ_EN_REG, 403 SUN8I_HDMI_PHY_READ_EN_MAGIC); 404 405 /* unscramble register offsets */ 406 regmap_write(phy->regs, SUN8I_HDMI_PHY_UNSCRAMBLE_REG, 407 SUN8I_HDMI_PHY_UNSCRAMBLE_MAGIC); 408 } 409 410 static void sun50i_hdmi_phy_init_h6(struct sun8i_hdmi_phy *phy) 411 { 412 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, 413 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 414 SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN); 415 416 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG, 417 0xffff0000, 0x80c00000); 418 } 419 420 static void sun8i_hdmi_phy_init_a83t(struct sun8i_hdmi_phy *phy) 421 { 422 sun8i_hdmi_phy_unlock(phy); 423 424 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, 425 SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK, 426 SUN8I_HDMI_PHY_DBG_CTRL_PX_LOCK); 427 428 /* 429 * Set PHY I2C address. It must match to the address set by 430 * dw_hdmi_phy_set_slave_addr(). 431 */ 432 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, 433 SUN8I_HDMI_PHY_DBG_CTRL_ADDR_MASK, 434 SUN8I_HDMI_PHY_DBG_CTRL_ADDR(I2C_ADDR)); 435 } 436 437 static void sun8i_hdmi_phy_init_h3(struct sun8i_hdmi_phy *phy) 438 { 439 unsigned int val; 440 441 sun8i_hdmi_phy_unlock(phy); 442 443 regmap_write(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 0); 444 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 445 SUN8I_HDMI_PHY_ANA_CFG1_ENBI, 446 SUN8I_HDMI_PHY_ANA_CFG1_ENBI); 447 udelay(5); 448 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 449 SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN, 450 SUN8I_HDMI_PHY_ANA_CFG1_TMDSCLK_EN); 451 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 452 SUN8I_HDMI_PHY_ANA_CFG1_ENVBS, 453 SUN8I_HDMI_PHY_ANA_CFG1_ENVBS); 454 usleep_range(10, 20); 455 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 456 SUN8I_HDMI_PHY_ANA_CFG1_LDOEN, 457 SUN8I_HDMI_PHY_ANA_CFG1_LDOEN); 458 udelay(5); 459 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 460 SUN8I_HDMI_PHY_ANA_CFG1_CKEN, 461 SUN8I_HDMI_PHY_ANA_CFG1_CKEN); 462 usleep_range(40, 100); 463 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 464 SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL, 465 SUN8I_HDMI_PHY_ANA_CFG1_ENRCAL); 466 usleep_range(100, 200); 467 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 468 SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG, 469 SUN8I_HDMI_PHY_ANA_CFG1_ENCALOG); 470 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 471 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 | 472 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 | 473 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2, 474 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS0 | 475 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS1 | 476 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDS2); 477 478 /* wait for calibration to finish */ 479 regmap_read_poll_timeout(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, val, 480 (val & SUN8I_HDMI_PHY_ANA_STS_RCALEND2D), 481 100, 2000); 482 483 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 484 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK, 485 SUN8I_HDMI_PHY_ANA_CFG1_ENP2S_TMDSCLK); 486 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, 487 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 | 488 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 | 489 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 | 490 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK, 491 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS0 | 492 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS1 | 493 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDS2 | 494 SUN8I_HDMI_PHY_ANA_CFG1_BIASEN_TMDSCLK); 495 496 /* enable DDC communication */ 497 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG3_REG, 498 SUN8I_HDMI_PHY_ANA_CFG3_SCLEN | 499 SUN8I_HDMI_PHY_ANA_CFG3_SDAEN, 500 SUN8I_HDMI_PHY_ANA_CFG3_SCLEN | 501 SUN8I_HDMI_PHY_ANA_CFG3_SDAEN); 502 503 /* reset PHY PLL clock parent */ 504 regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 505 SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, 0); 506 507 /* set HW control of CEC pins */ 508 regmap_write(phy->regs, SUN8I_HDMI_PHY_CEC_REG, 0); 509 510 /* read calibration data */ 511 regmap_read(phy->regs, SUN8I_HDMI_PHY_ANA_STS_REG, &val); 512 phy->rcal = (val & SUN8I_HDMI_PHY_ANA_STS_RCAL_MASK) >> 2; 513 } 514 515 void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy) 516 { 517 phy->variant->phy_init(phy); 518 } 519 520 void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy, 521 struct dw_hdmi_plat_data *plat_data) 522 { 523 struct sun8i_hdmi_phy_variant *variant = phy->variant; 524 525 if (variant->is_custom_phy) { 526 plat_data->phy_ops = &sun8i_hdmi_phy_ops; 527 plat_data->phy_name = "sun8i_dw_hdmi_phy"; 528 plat_data->phy_data = phy; 529 } else { 530 plat_data->mpll_cfg = variant->mpll_cfg; 531 plat_data->cur_ctr = variant->cur_ctr; 532 plat_data->phy_config = variant->phy_cfg; 533 } 534 } 535 536 static struct regmap_config sun8i_hdmi_phy_regmap_config = { 537 .reg_bits = 32, 538 .val_bits = 32, 539 .reg_stride = 4, 540 .max_register = SUN8I_HDMI_PHY_CEC_REG, 541 .name = "phy" 542 }; 543 544 static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = { 545 .is_custom_phy = true, 546 .phy_init = &sun8i_hdmi_phy_init_a83t, 547 .phy_disable = &sun8i_hdmi_phy_disable_a83t, 548 .phy_config = &sun8i_hdmi_phy_config_a83t, 549 }; 550 551 static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = { 552 .has_phy_clk = true, 553 .is_custom_phy = true, 554 .phy_init = &sun8i_hdmi_phy_init_h3, 555 .phy_disable = &sun8i_hdmi_phy_disable_h3, 556 .phy_config = &sun8i_hdmi_phy_config_h3, 557 }; 558 559 static const struct sun8i_hdmi_phy_variant sun8i_r40_hdmi_phy = { 560 .has_phy_clk = true, 561 .has_second_pll = true, 562 .is_custom_phy = true, 563 .phy_init = &sun8i_hdmi_phy_init_h3, 564 .phy_disable = &sun8i_hdmi_phy_disable_h3, 565 .phy_config = &sun8i_hdmi_phy_config_h3, 566 }; 567 568 static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = { 569 .has_phy_clk = true, 570 .is_custom_phy = true, 571 .phy_init = &sun8i_hdmi_phy_init_h3, 572 .phy_disable = &sun8i_hdmi_phy_disable_h3, 573 .phy_config = &sun8i_hdmi_phy_config_h3, 574 }; 575 576 static const struct sun8i_hdmi_phy_variant sun50i_h6_hdmi_phy = { 577 .cur_ctr = sun50i_h6_cur_ctr, 578 .mpll_cfg = sun50i_h6_mpll_cfg, 579 .phy_cfg = sun50i_h6_phy_config, 580 .phy_init = &sun50i_hdmi_phy_init_h6, 581 }; 582 583 static const struct of_device_id sun8i_hdmi_phy_of_table[] = { 584 { 585 .compatible = "allwinner,sun8i-a83t-hdmi-phy", 586 .data = &sun8i_a83t_hdmi_phy, 587 }, 588 { 589 .compatible = "allwinner,sun8i-h3-hdmi-phy", 590 .data = &sun8i_h3_hdmi_phy, 591 }, 592 { 593 .compatible = "allwinner,sun8i-r40-hdmi-phy", 594 .data = &sun8i_r40_hdmi_phy, 595 }, 596 { 597 .compatible = "allwinner,sun50i-a64-hdmi-phy", 598 .data = &sun50i_a64_hdmi_phy, 599 }, 600 { 601 .compatible = "allwinner,sun50i-h6-hdmi-phy", 602 .data = &sun50i_h6_hdmi_phy, 603 }, 604 { /* sentinel */ } 605 }; 606 607 int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node) 608 { 609 const struct of_device_id *match; 610 struct device *dev = hdmi->dev; 611 struct sun8i_hdmi_phy *phy; 612 struct resource res; 613 void __iomem *regs; 614 int ret; 615 616 match = of_match_node(sun8i_hdmi_phy_of_table, node); 617 if (!match) { 618 dev_err(dev, "Incompatible HDMI PHY\n"); 619 return -EINVAL; 620 } 621 622 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); 623 if (!phy) 624 return -ENOMEM; 625 626 phy->variant = (struct sun8i_hdmi_phy_variant *)match->data; 627 628 ret = of_address_to_resource(node, 0, &res); 629 if (ret) { 630 dev_err(dev, "phy: Couldn't get our resources\n"); 631 return ret; 632 } 633 634 regs = devm_ioremap_resource(dev, &res); 635 if (IS_ERR(regs)) { 636 dev_err(dev, "Couldn't map the HDMI PHY registers\n"); 637 return PTR_ERR(regs); 638 } 639 640 phy->regs = devm_regmap_init_mmio(dev, regs, 641 &sun8i_hdmi_phy_regmap_config); 642 if (IS_ERR(phy->regs)) { 643 dev_err(dev, "Couldn't create the HDMI PHY regmap\n"); 644 return PTR_ERR(phy->regs); 645 } 646 647 phy->clk_bus = of_clk_get_by_name(node, "bus"); 648 if (IS_ERR(phy->clk_bus)) { 649 dev_err(dev, "Could not get bus clock\n"); 650 return PTR_ERR(phy->clk_bus); 651 } 652 653 phy->clk_mod = of_clk_get_by_name(node, "mod"); 654 if (IS_ERR(phy->clk_mod)) { 655 dev_err(dev, "Could not get mod clock\n"); 656 ret = PTR_ERR(phy->clk_mod); 657 goto err_put_clk_bus; 658 } 659 660 if (phy->variant->has_phy_clk) { 661 phy->clk_pll0 = of_clk_get_by_name(node, "pll-0"); 662 if (IS_ERR(phy->clk_pll0)) { 663 dev_err(dev, "Could not get pll-0 clock\n"); 664 ret = PTR_ERR(phy->clk_pll0); 665 goto err_put_clk_mod; 666 } 667 668 if (phy->variant->has_second_pll) { 669 phy->clk_pll1 = of_clk_get_by_name(node, "pll-1"); 670 if (IS_ERR(phy->clk_pll1)) { 671 dev_err(dev, "Could not get pll-1 clock\n"); 672 ret = PTR_ERR(phy->clk_pll1); 673 goto err_put_clk_pll0; 674 } 675 } 676 } 677 678 phy->rst_phy = of_reset_control_get_shared(node, "phy"); 679 if (IS_ERR(phy->rst_phy)) { 680 dev_err(dev, "Could not get phy reset control\n"); 681 ret = PTR_ERR(phy->rst_phy); 682 goto err_put_clk_pll1; 683 } 684 685 ret = reset_control_deassert(phy->rst_phy); 686 if (ret) { 687 dev_err(dev, "Cannot deassert phy reset control: %d\n", ret); 688 goto err_put_rst_phy; 689 } 690 691 ret = clk_prepare_enable(phy->clk_bus); 692 if (ret) { 693 dev_err(dev, "Cannot enable bus clock: %d\n", ret); 694 goto err_deassert_rst_phy; 695 } 696 697 ret = clk_prepare_enable(phy->clk_mod); 698 if (ret) { 699 dev_err(dev, "Cannot enable mod clock: %d\n", ret); 700 goto err_disable_clk_bus; 701 } 702 703 if (phy->variant->has_phy_clk) { 704 ret = sun8i_phy_clk_create(phy, dev, 705 phy->variant->has_second_pll); 706 if (ret) { 707 dev_err(dev, "Couldn't create the PHY clock\n"); 708 goto err_disable_clk_mod; 709 } 710 711 clk_prepare_enable(phy->clk_phy); 712 } 713 714 hdmi->phy = phy; 715 716 return 0; 717 718 err_disable_clk_mod: 719 clk_disable_unprepare(phy->clk_mod); 720 err_disable_clk_bus: 721 clk_disable_unprepare(phy->clk_bus); 722 err_deassert_rst_phy: 723 reset_control_assert(phy->rst_phy); 724 err_put_rst_phy: 725 reset_control_put(phy->rst_phy); 726 err_put_clk_pll1: 727 clk_put(phy->clk_pll1); 728 err_put_clk_pll0: 729 clk_put(phy->clk_pll0); 730 err_put_clk_mod: 731 clk_put(phy->clk_mod); 732 err_put_clk_bus: 733 clk_put(phy->clk_bus); 734 735 return ret; 736 } 737 738 void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi) 739 { 740 struct sun8i_hdmi_phy *phy = hdmi->phy; 741 742 clk_disable_unprepare(phy->clk_mod); 743 clk_disable_unprepare(phy->clk_bus); 744 clk_disable_unprepare(phy->clk_phy); 745 746 reset_control_assert(phy->rst_phy); 747 748 reset_control_put(phy->rst_phy); 749 750 clk_put(phy->clk_pll0); 751 clk_put(phy->clk_pll1); 752 clk_put(phy->clk_mod); 753 clk_put(phy->clk_bus); 754 } 755