1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 4 */ 5 6 #include <linux/clk.h> 7 #include <linux/mfd/syscon.h> 8 #include <linux/module.h> 9 #include <linux/platform_device.h> 10 #include <linux/phy/phy.h> 11 #include <linux/regmap.h> 12 #include <linux/regulator/consumer.h> 13 14 #include <drm/bridge/dw_hdmi.h> 15 #include <drm/drm_edid.h> 16 #include <drm/drm_of.h> 17 #include <drm/drm_probe_helper.h> 18 #include <drm/drm_simple_kms_helper.h> 19 20 #include "rockchip_drm_drv.h" 21 #include "rockchip_drm_vop.h" 22 23 #define RK3228_GRF_SOC_CON2 0x0408 24 #define RK3228_HDMI_SDAIN_MSK BIT(14) 25 #define RK3228_HDMI_SCLIN_MSK BIT(13) 26 #define RK3228_GRF_SOC_CON6 0x0418 27 #define RK3228_HDMI_HPD_VSEL BIT(6) 28 #define RK3228_HDMI_SDA_VSEL BIT(5) 29 #define RK3228_HDMI_SCL_VSEL BIT(4) 30 31 #define RK3288_GRF_SOC_CON6 0x025C 32 #define RK3288_HDMI_LCDC_SEL BIT(4) 33 #define RK3328_GRF_SOC_CON2 0x0408 34 35 #define RK3328_HDMI_SDAIN_MSK BIT(11) 36 #define RK3328_HDMI_SCLIN_MSK BIT(10) 37 #define RK3328_HDMI_HPD_IOE BIT(2) 38 #define RK3328_GRF_SOC_CON3 0x040c 39 /* need to be unset if hdmi or i2c should control voltage */ 40 #define RK3328_HDMI_SDA5V_GRF BIT(15) 41 #define RK3328_HDMI_SCL5V_GRF BIT(14) 42 #define RK3328_HDMI_HPD5V_GRF BIT(13) 43 #define RK3328_HDMI_CEC5V_GRF BIT(12) 44 #define RK3328_GRF_SOC_CON4 0x0410 45 #define RK3328_HDMI_HPD_SARADC BIT(13) 46 #define RK3328_HDMI_CEC_5V BIT(11) 47 #define RK3328_HDMI_SDA_5V BIT(10) 48 #define RK3328_HDMI_SCL_5V BIT(9) 49 #define RK3328_HDMI_HPD_5V BIT(8) 50 51 #define RK3399_GRF_SOC_CON20 0x6250 52 #define RK3399_HDMI_LCDC_SEL BIT(6) 53 54 #define RK3568_GRF_VO_CON1 0x0364 55 #define RK3568_HDMI_SDAIN_MSK BIT(15) 56 #define RK3568_HDMI_SCLIN_MSK BIT(14) 57 58 #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 59 60 /** 61 * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips 62 * @lcdsel_grf_reg: grf register offset of lcdc select 63 * @lcdsel_big: reg value of selecting vop big for HDMI 64 * @lcdsel_lit: reg value of selecting vop little for HDMI 65 */ 66 struct rockchip_hdmi_chip_data { 67 int lcdsel_grf_reg; 68 u32 lcdsel_big; 69 u32 lcdsel_lit; 70 }; 71 72 struct rockchip_hdmi { 73 struct device *dev; 74 struct regmap *regmap; 75 struct rockchip_encoder encoder; 76 const struct rockchip_hdmi_chip_data *chip_data; 77 const struct dw_hdmi_plat_data *plat_data; 78 struct clk *ref_clk; 79 struct clk *grf_clk; 80 struct dw_hdmi *hdmi; 81 struct regulator *avdd_0v9; 82 struct regulator *avdd_1v8; 83 struct phy *phy; 84 }; 85 86 static struct rockchip_hdmi *to_rockchip_hdmi(struct drm_encoder *encoder) 87 { 88 struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); 89 90 return container_of(rkencoder, struct rockchip_hdmi, encoder); 91 } 92 93 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { 94 { 95 27000000, { 96 { 0x00b3, 0x0000}, 97 { 0x2153, 0x0000}, 98 { 0x40f3, 0x0000} 99 }, 100 }, { 101 36000000, { 102 { 0x00b3, 0x0000}, 103 { 0x2153, 0x0000}, 104 { 0x40f3, 0x0000} 105 }, 106 }, { 107 40000000, { 108 { 0x00b3, 0x0000}, 109 { 0x2153, 0x0000}, 110 { 0x40f3, 0x0000} 111 }, 112 }, { 113 54000000, { 114 { 0x0072, 0x0001}, 115 { 0x2142, 0x0001}, 116 { 0x40a2, 0x0001}, 117 }, 118 }, { 119 65000000, { 120 { 0x0072, 0x0001}, 121 { 0x2142, 0x0001}, 122 { 0x40a2, 0x0001}, 123 }, 124 }, { 125 66000000, { 126 { 0x013e, 0x0003}, 127 { 0x217e, 0x0002}, 128 { 0x4061, 0x0002} 129 }, 130 }, { 131 74250000, { 132 { 0x0072, 0x0001}, 133 { 0x2145, 0x0002}, 134 { 0x4061, 0x0002} 135 }, 136 }, { 137 83500000, { 138 { 0x0072, 0x0001}, 139 }, 140 }, { 141 108000000, { 142 { 0x0051, 0x0002}, 143 { 0x2145, 0x0002}, 144 { 0x4061, 0x0002} 145 }, 146 }, { 147 106500000, { 148 { 0x0051, 0x0002}, 149 { 0x2145, 0x0002}, 150 { 0x4061, 0x0002} 151 }, 152 }, { 153 146250000, { 154 { 0x0051, 0x0002}, 155 { 0x2145, 0x0002}, 156 { 0x4061, 0x0002} 157 }, 158 }, { 159 148500000, { 160 { 0x0051, 0x0003}, 161 { 0x214c, 0x0003}, 162 { 0x4064, 0x0003} 163 }, 164 }, { 165 340000000, { 166 { 0x0040, 0x0003 }, 167 { 0x3b4c, 0x0003 }, 168 { 0x5a64, 0x0003 }, 169 }, 170 }, { 171 ~0UL, { 172 { 0x00a0, 0x000a }, 173 { 0x2001, 0x000f }, 174 { 0x4002, 0x000f }, 175 }, 176 } 177 }; 178 179 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { 180 /* pixelclk bpp8 bpp10 bpp12 */ 181 { 182 40000000, { 0x0018, 0x0018, 0x0018 }, 183 }, { 184 65000000, { 0x0028, 0x0028, 0x0028 }, 185 }, { 186 66000000, { 0x0038, 0x0038, 0x0038 }, 187 }, { 188 74250000, { 0x0028, 0x0038, 0x0038 }, 189 }, { 190 83500000, { 0x0028, 0x0038, 0x0038 }, 191 }, { 192 146250000, { 0x0038, 0x0038, 0x0038 }, 193 }, { 194 148500000, { 0x0000, 0x0038, 0x0038 }, 195 }, { 196 600000000, { 0x0000, 0x0000, 0x0000 }, 197 }, { 198 ~0UL, { 0x0000, 0x0000, 0x0000}, 199 } 200 }; 201 202 static const struct dw_hdmi_phy_config rockchip_phy_config[] = { 203 /*pixelclk symbol term vlev*/ 204 { 74250000, 0x8009, 0x0004, 0x0272}, 205 { 148500000, 0x802b, 0x0004, 0x028d}, 206 { 297000000, 0x8039, 0x0005, 0x028d}, 207 { ~0UL, 0x0000, 0x0000, 0x0000} 208 }; 209 210 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) 211 { 212 struct device_node *np = hdmi->dev->of_node; 213 214 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 215 if (IS_ERR(hdmi->regmap)) { 216 DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n"); 217 return PTR_ERR(hdmi->regmap); 218 } 219 220 hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "ref"); 221 if (!hdmi->ref_clk) 222 hdmi->ref_clk = devm_clk_get_optional(hdmi->dev, "vpll"); 223 224 if (PTR_ERR(hdmi->ref_clk) == -EPROBE_DEFER) { 225 return -EPROBE_DEFER; 226 } else if (IS_ERR(hdmi->ref_clk)) { 227 DRM_DEV_ERROR(hdmi->dev, "failed to get reference clock\n"); 228 return PTR_ERR(hdmi->ref_clk); 229 } 230 231 hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); 232 if (PTR_ERR(hdmi->grf_clk) == -ENOENT) { 233 hdmi->grf_clk = NULL; 234 } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { 235 return -EPROBE_DEFER; 236 } else if (IS_ERR(hdmi->grf_clk)) { 237 DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); 238 return PTR_ERR(hdmi->grf_clk); 239 } 240 241 hdmi->avdd_0v9 = devm_regulator_get(hdmi->dev, "avdd-0v9"); 242 if (IS_ERR(hdmi->avdd_0v9)) 243 return PTR_ERR(hdmi->avdd_0v9); 244 245 hdmi->avdd_1v8 = devm_regulator_get(hdmi->dev, "avdd-1v8"); 246 if (IS_ERR(hdmi->avdd_1v8)) 247 return PTR_ERR(hdmi->avdd_1v8); 248 249 return 0; 250 } 251 252 static enum drm_mode_status 253 dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, 254 const struct drm_display_info *info, 255 const struct drm_display_mode *mode) 256 { 257 struct rockchip_hdmi *hdmi = data; 258 const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; 259 int pclk = mode->clock * 1000; 260 bool exact_match = hdmi->plat_data->phy_force_vendor; 261 int i; 262 263 if (hdmi->ref_clk) { 264 int rpclk = clk_round_rate(hdmi->ref_clk, pclk); 265 266 if (abs(rpclk - pclk) > pclk / 1000) 267 return MODE_NOCLOCK; 268 } 269 270 for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { 271 /* 272 * For vendor specific phys force an exact match of the pixelclock 273 * to preserve the original behaviour of the driver. 274 */ 275 if (exact_match && pclk == mpll_cfg[i].mpixelclock) 276 return MODE_OK; 277 /* 278 * The Synopsys phy can work with pixelclocks up to the value given 279 * in the corresponding mpll_cfg entry. 280 */ 281 if (!exact_match && pclk <= mpll_cfg[i].mpixelclock) 282 return MODE_OK; 283 } 284 285 return MODE_BAD; 286 } 287 288 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) 289 { 290 } 291 292 static bool 293 dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, 294 const struct drm_display_mode *mode, 295 struct drm_display_mode *adj_mode) 296 { 297 return true; 298 } 299 300 static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, 301 struct drm_display_mode *mode, 302 struct drm_display_mode *adj_mode) 303 { 304 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); 305 306 clk_set_rate(hdmi->ref_clk, adj_mode->clock * 1000); 307 } 308 309 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) 310 { 311 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); 312 u32 val; 313 int ret; 314 315 if (hdmi->chip_data->lcdsel_grf_reg < 0) 316 return; 317 318 ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); 319 if (ret) 320 val = hdmi->chip_data->lcdsel_lit; 321 else 322 val = hdmi->chip_data->lcdsel_big; 323 324 ret = clk_prepare_enable(hdmi->grf_clk); 325 if (ret < 0) { 326 DRM_DEV_ERROR(hdmi->dev, "failed to enable grfclk %d\n", ret); 327 return; 328 } 329 330 ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); 331 if (ret != 0) 332 DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); 333 334 clk_disable_unprepare(hdmi->grf_clk); 335 DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", 336 ret ? "LIT" : "BIG"); 337 } 338 339 static int 340 dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, 341 struct drm_crtc_state *crtc_state, 342 struct drm_connector_state *conn_state) 343 { 344 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); 345 346 s->output_mode = ROCKCHIP_OUT_MODE_AAAA; 347 s->output_type = DRM_MODE_CONNECTOR_HDMIA; 348 349 return 0; 350 } 351 352 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { 353 .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, 354 .mode_set = dw_hdmi_rockchip_encoder_mode_set, 355 .enable = dw_hdmi_rockchip_encoder_enable, 356 .disable = dw_hdmi_rockchip_encoder_disable, 357 .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, 358 }; 359 360 static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, 361 const struct drm_display_info *display, 362 const struct drm_display_mode *mode) 363 { 364 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 365 366 return phy_power_on(hdmi->phy); 367 } 368 369 static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) 370 { 371 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 372 373 phy_power_off(hdmi->phy); 374 } 375 376 static void dw_hdmi_rk3228_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) 377 { 378 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 379 380 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 381 382 regmap_write(hdmi->regmap, 383 RK3228_GRF_SOC_CON6, 384 HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 385 RK3228_HDMI_SCL_VSEL, 386 RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 387 RK3228_HDMI_SCL_VSEL)); 388 389 regmap_write(hdmi->regmap, 390 RK3228_GRF_SOC_CON2, 391 HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK, 392 RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK)); 393 } 394 395 static enum drm_connector_status 396 dw_hdmi_rk3328_read_hpd(struct dw_hdmi *dw_hdmi, void *data) 397 { 398 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 399 enum drm_connector_status status; 400 401 status = dw_hdmi_phy_read_hpd(dw_hdmi, data); 402 403 if (status == connector_status_connected) 404 regmap_write(hdmi->regmap, 405 RK3328_GRF_SOC_CON4, 406 HIWORD_UPDATE(RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V, 407 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V)); 408 else 409 regmap_write(hdmi->regmap, 410 RK3328_GRF_SOC_CON4, 411 HIWORD_UPDATE(0, RK3328_HDMI_SDA_5V | 412 RK3328_HDMI_SCL_5V)); 413 return status; 414 } 415 416 static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) 417 { 418 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 419 420 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 421 422 /* Enable and map pins to 3V grf-controlled io-voltage */ 423 regmap_write(hdmi->regmap, 424 RK3328_GRF_SOC_CON4, 425 HIWORD_UPDATE(0, RK3328_HDMI_HPD_SARADC | RK3328_HDMI_CEC_5V | 426 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V | 427 RK3328_HDMI_HPD_5V)); 428 regmap_write(hdmi->regmap, 429 RK3328_GRF_SOC_CON3, 430 HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF | 431 RK3328_HDMI_HPD5V_GRF | 432 RK3328_HDMI_CEC5V_GRF)); 433 regmap_write(hdmi->regmap, 434 RK3328_GRF_SOC_CON2, 435 HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, 436 RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | 437 RK3328_HDMI_HPD_IOE)); 438 439 dw_hdmi_rk3328_read_hpd(dw_hdmi, data); 440 } 441 442 static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { 443 .init = dw_hdmi_rockchip_genphy_init, 444 .disable = dw_hdmi_rockchip_genphy_disable, 445 .read_hpd = dw_hdmi_phy_read_hpd, 446 .update_hpd = dw_hdmi_phy_update_hpd, 447 .setup_hpd = dw_hdmi_rk3228_setup_hpd, 448 }; 449 450 static struct rockchip_hdmi_chip_data rk3228_chip_data = { 451 .lcdsel_grf_reg = -1, 452 }; 453 454 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { 455 .mode_valid = dw_hdmi_rockchip_mode_valid, 456 .mpll_cfg = rockchip_mpll_cfg, 457 .cur_ctr = rockchip_cur_ctr, 458 .phy_config = rockchip_phy_config, 459 .phy_data = &rk3228_chip_data, 460 .phy_ops = &rk3228_hdmi_phy_ops, 461 .phy_name = "inno_dw_hdmi_phy2", 462 .phy_force_vendor = true, 463 }; 464 465 static struct rockchip_hdmi_chip_data rk3288_chip_data = { 466 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 467 .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), 468 .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), 469 }; 470 471 static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { 472 .mode_valid = dw_hdmi_rockchip_mode_valid, 473 .mpll_cfg = rockchip_mpll_cfg, 474 .cur_ctr = rockchip_cur_ctr, 475 .phy_config = rockchip_phy_config, 476 .phy_data = &rk3288_chip_data, 477 }; 478 479 static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { 480 .init = dw_hdmi_rockchip_genphy_init, 481 .disable = dw_hdmi_rockchip_genphy_disable, 482 .read_hpd = dw_hdmi_rk3328_read_hpd, 483 .update_hpd = dw_hdmi_phy_update_hpd, 484 .setup_hpd = dw_hdmi_rk3328_setup_hpd, 485 }; 486 487 static struct rockchip_hdmi_chip_data rk3328_chip_data = { 488 .lcdsel_grf_reg = -1, 489 }; 490 491 static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { 492 .mode_valid = dw_hdmi_rockchip_mode_valid, 493 .mpll_cfg = rockchip_mpll_cfg, 494 .cur_ctr = rockchip_cur_ctr, 495 .phy_config = rockchip_phy_config, 496 .phy_data = &rk3328_chip_data, 497 .phy_ops = &rk3328_hdmi_phy_ops, 498 .phy_name = "inno_dw_hdmi_phy2", 499 .phy_force_vendor = true, 500 .use_drm_infoframe = true, 501 }; 502 503 static struct rockchip_hdmi_chip_data rk3399_chip_data = { 504 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 505 .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), 506 .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), 507 }; 508 509 static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { 510 .mode_valid = dw_hdmi_rockchip_mode_valid, 511 .mpll_cfg = rockchip_mpll_cfg, 512 .cur_ctr = rockchip_cur_ctr, 513 .phy_config = rockchip_phy_config, 514 .phy_data = &rk3399_chip_data, 515 .use_drm_infoframe = true, 516 }; 517 518 static struct rockchip_hdmi_chip_data rk3568_chip_data = { 519 .lcdsel_grf_reg = -1, 520 }; 521 522 static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { 523 .mode_valid = dw_hdmi_rockchip_mode_valid, 524 .mpll_cfg = rockchip_mpll_cfg, 525 .cur_ctr = rockchip_cur_ctr, 526 .phy_config = rockchip_phy_config, 527 .phy_data = &rk3568_chip_data, 528 .use_drm_infoframe = true, 529 }; 530 531 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { 532 { .compatible = "rockchip,rk3228-dw-hdmi", 533 .data = &rk3228_hdmi_drv_data 534 }, 535 { .compatible = "rockchip,rk3288-dw-hdmi", 536 .data = &rk3288_hdmi_drv_data 537 }, 538 { .compatible = "rockchip,rk3328-dw-hdmi", 539 .data = &rk3328_hdmi_drv_data 540 }, 541 { .compatible = "rockchip,rk3399-dw-hdmi", 542 .data = &rk3399_hdmi_drv_data 543 }, 544 { .compatible = "rockchip,rk3568-dw-hdmi", 545 .data = &rk3568_hdmi_drv_data 546 }, 547 {}, 548 }; 549 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids); 550 551 static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, 552 void *data) 553 { 554 struct platform_device *pdev = to_platform_device(dev); 555 struct dw_hdmi_plat_data *plat_data; 556 const struct of_device_id *match; 557 struct drm_device *drm = data; 558 struct drm_encoder *encoder; 559 struct rockchip_hdmi *hdmi; 560 int ret; 561 562 if (!pdev->dev.of_node) 563 return -ENODEV; 564 565 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 566 if (!hdmi) 567 return -ENOMEM; 568 569 match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); 570 plat_data = devm_kmemdup(&pdev->dev, match->data, 571 sizeof(*plat_data), GFP_KERNEL); 572 if (!plat_data) 573 return -ENOMEM; 574 575 hdmi->dev = &pdev->dev; 576 hdmi->plat_data = plat_data; 577 hdmi->chip_data = plat_data->phy_data; 578 plat_data->phy_data = hdmi; 579 plat_data->priv_data = hdmi; 580 encoder = &hdmi->encoder.encoder; 581 582 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 583 rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, 584 dev->of_node, 0, 0); 585 586 /* 587 * If we failed to find the CRTC(s) which this encoder is 588 * supposed to be connected to, it's because the CRTC has 589 * not been registered yet. Defer probing, and hope that 590 * the required CRTC is added later. 591 */ 592 if (encoder->possible_crtcs == 0) 593 return -EPROBE_DEFER; 594 595 ret = rockchip_hdmi_parse_dt(hdmi); 596 if (ret) { 597 if (ret != -EPROBE_DEFER) 598 DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n"); 599 return ret; 600 } 601 602 hdmi->phy = devm_phy_optional_get(dev, "hdmi"); 603 if (IS_ERR(hdmi->phy)) { 604 ret = PTR_ERR(hdmi->phy); 605 if (ret != -EPROBE_DEFER) 606 DRM_DEV_ERROR(hdmi->dev, "failed to get phy\n"); 607 return ret; 608 } 609 610 ret = regulator_enable(hdmi->avdd_0v9); 611 if (ret) { 612 DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd0v9: %d\n", ret); 613 goto err_avdd_0v9; 614 } 615 616 ret = regulator_enable(hdmi->avdd_1v8); 617 if (ret) { 618 DRM_DEV_ERROR(hdmi->dev, "failed to enable avdd1v8: %d\n", ret); 619 goto err_avdd_1v8; 620 } 621 622 ret = clk_prepare_enable(hdmi->ref_clk); 623 if (ret) { 624 DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI reference clock: %d\n", 625 ret); 626 goto err_clk; 627 } 628 629 if (hdmi->chip_data == &rk3568_chip_data) { 630 regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, 631 HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | 632 RK3568_HDMI_SCLIN_MSK, 633 RK3568_HDMI_SDAIN_MSK | 634 RK3568_HDMI_SCLIN_MSK)); 635 } 636 637 drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); 638 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); 639 640 platform_set_drvdata(pdev, hdmi); 641 642 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); 643 644 /* 645 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), 646 * which would have called the encoder cleanup. Do it manually. 647 */ 648 if (IS_ERR(hdmi->hdmi)) { 649 ret = PTR_ERR(hdmi->hdmi); 650 goto err_bind; 651 } 652 653 return 0; 654 655 err_bind: 656 drm_encoder_cleanup(encoder); 657 clk_disable_unprepare(hdmi->ref_clk); 658 err_clk: 659 regulator_disable(hdmi->avdd_1v8); 660 err_avdd_1v8: 661 regulator_disable(hdmi->avdd_0v9); 662 err_avdd_0v9: 663 return ret; 664 } 665 666 static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, 667 void *data) 668 { 669 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); 670 671 dw_hdmi_unbind(hdmi->hdmi); 672 drm_encoder_cleanup(&hdmi->encoder.encoder); 673 clk_disable_unprepare(hdmi->ref_clk); 674 675 regulator_disable(hdmi->avdd_1v8); 676 regulator_disable(hdmi->avdd_0v9); 677 } 678 679 static const struct component_ops dw_hdmi_rockchip_ops = { 680 .bind = dw_hdmi_rockchip_bind, 681 .unbind = dw_hdmi_rockchip_unbind, 682 }; 683 684 static int dw_hdmi_rockchip_probe(struct platform_device *pdev) 685 { 686 return component_add(&pdev->dev, &dw_hdmi_rockchip_ops); 687 } 688 689 static void dw_hdmi_rockchip_remove(struct platform_device *pdev) 690 { 691 component_del(&pdev->dev, &dw_hdmi_rockchip_ops); 692 } 693 694 static int __maybe_unused dw_hdmi_rockchip_resume(struct device *dev) 695 { 696 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); 697 698 dw_hdmi_resume(hdmi->hdmi); 699 700 return 0; 701 } 702 703 static const struct dev_pm_ops dw_hdmi_rockchip_pm = { 704 SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_rockchip_resume) 705 }; 706 707 struct platform_driver dw_hdmi_rockchip_pltfm_driver = { 708 .probe = dw_hdmi_rockchip_probe, 709 .remove_new = dw_hdmi_rockchip_remove, 710 .driver = { 711 .name = "dwhdmi-rockchip", 712 .pm = &dw_hdmi_rockchip_pm, 713 .of_match_table = dw_hdmi_rockchip_dt_ids, 714 }, 715 }; 716