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 22 #define RK3228_GRF_SOC_CON2 0x0408 23 #define RK3228_HDMI_SDAIN_MSK BIT(14) 24 #define RK3228_HDMI_SCLIN_MSK BIT(13) 25 #define RK3228_GRF_SOC_CON6 0x0418 26 #define RK3228_HDMI_HPD_VSEL BIT(6) 27 #define RK3228_HDMI_SDA_VSEL BIT(5) 28 #define RK3228_HDMI_SCL_VSEL BIT(4) 29 30 #define RK3288_GRF_SOC_CON6 0x025C 31 #define RK3288_HDMI_LCDC_SEL BIT(4) 32 #define RK3328_GRF_SOC_CON2 0x0408 33 34 #define RK3328_HDMI_SDAIN_MSK BIT(11) 35 #define RK3328_HDMI_SCLIN_MSK BIT(10) 36 #define RK3328_HDMI_HPD_IOE BIT(2) 37 #define RK3328_GRF_SOC_CON3 0x040c 38 /* need to be unset if hdmi or i2c should control voltage */ 39 #define RK3328_HDMI_SDA5V_GRF BIT(15) 40 #define RK3328_HDMI_SCL5V_GRF BIT(14) 41 #define RK3328_HDMI_HPD5V_GRF BIT(13) 42 #define RK3328_HDMI_CEC5V_GRF BIT(12) 43 #define RK3328_GRF_SOC_CON4 0x0410 44 #define RK3328_HDMI_HPD_SARADC BIT(13) 45 #define RK3328_HDMI_CEC_5V BIT(11) 46 #define RK3328_HDMI_SDA_5V BIT(10) 47 #define RK3328_HDMI_SCL_5V BIT(9) 48 #define RK3328_HDMI_HPD_5V BIT(8) 49 50 #define RK3399_GRF_SOC_CON20 0x6250 51 #define RK3399_HDMI_LCDC_SEL BIT(6) 52 53 #define RK3568_GRF_VO_CON1 0x0364 54 #define RK3568_HDMI_SDAIN_MSK BIT(15) 55 #define RK3568_HDMI_SCLIN_MSK BIT(14) 56 57 #define HIWORD_UPDATE(val, mask) (val | (mask) << 16) 58 59 /** 60 * struct rockchip_hdmi_chip_data - splite the grf setting of kind of chips 61 * @lcdsel_grf_reg: grf register offset of lcdc select 62 * @lcdsel_big: reg value of selecting vop big for HDMI 63 * @lcdsel_lit: reg value of selecting vop little for HDMI 64 * @max_tmds_clock: maximum TMDS clock rate supported 65 */ 66 struct rockchip_hdmi_chip_data { 67 int lcdsel_grf_reg; 68 u32 lcdsel_big; 69 u32 lcdsel_lit; 70 int max_tmds_clock; 71 }; 72 73 struct rockchip_hdmi { 74 struct device *dev; 75 struct regmap *regmap; 76 struct rockchip_encoder encoder; 77 const struct rockchip_hdmi_chip_data *chip_data; 78 const struct dw_hdmi_plat_data *plat_data; 79 struct clk *ref_clk; 80 struct clk *grf_clk; 81 struct dw_hdmi *hdmi; 82 struct phy *phy; 83 }; 84 85 static struct rockchip_hdmi *to_rockchip_hdmi(struct drm_encoder *encoder) 86 { 87 struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); 88 89 return container_of(rkencoder, struct rockchip_hdmi, encoder); 90 } 91 92 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { 93 { 94 27000000, { 95 { 0x00b3, 0x0000}, 96 { 0x2153, 0x0000}, 97 { 0x40f3, 0x0000} 98 }, 99 }, { 100 36000000, { 101 { 0x00b3, 0x0000}, 102 { 0x2153, 0x0000}, 103 { 0x40f3, 0x0000} 104 }, 105 }, { 106 40000000, { 107 { 0x00b3, 0x0000}, 108 { 0x2153, 0x0000}, 109 { 0x40f3, 0x0000} 110 }, 111 }, { 112 54000000, { 113 { 0x0072, 0x0001}, 114 { 0x2142, 0x0001}, 115 { 0x40a2, 0x0001}, 116 }, 117 }, { 118 65000000, { 119 { 0x0072, 0x0001}, 120 { 0x2142, 0x0001}, 121 { 0x40a2, 0x0001}, 122 }, 123 }, { 124 66000000, { 125 { 0x013e, 0x0003}, 126 { 0x217e, 0x0002}, 127 { 0x4061, 0x0002} 128 }, 129 }, { 130 74250000, { 131 { 0x0072, 0x0001}, 132 { 0x2145, 0x0002}, 133 { 0x4061, 0x0002} 134 }, 135 }, { 136 83500000, { 137 { 0x0072, 0x0001}, 138 }, 139 }, { 140 108000000, { 141 { 0x0051, 0x0002}, 142 { 0x2145, 0x0002}, 143 { 0x4061, 0x0002} 144 }, 145 }, { 146 106500000, { 147 { 0x0051, 0x0002}, 148 { 0x2145, 0x0002}, 149 { 0x4061, 0x0002} 150 }, 151 }, { 152 146250000, { 153 { 0x0051, 0x0002}, 154 { 0x2145, 0x0002}, 155 { 0x4061, 0x0002} 156 }, 157 }, { 158 148500000, { 159 { 0x0051, 0x0003}, 160 { 0x214c, 0x0003}, 161 { 0x4064, 0x0003} 162 }, 163 }, { 164 340000000, { 165 { 0x0040, 0x0003 }, 166 { 0x3b4c, 0x0003 }, 167 { 0x5a64, 0x0003 }, 168 }, 169 }, { 170 ~0UL, { 171 { 0x00a0, 0x000a }, 172 { 0x2001, 0x000f }, 173 { 0x4002, 0x000f }, 174 }, 175 } 176 }; 177 178 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { 179 /* pixelclk bpp8 bpp10 bpp12 */ 180 { 181 40000000, { 0x0018, 0x0018, 0x0018 }, 182 }, { 183 65000000, { 0x0028, 0x0028, 0x0028 }, 184 }, { 185 66000000, { 0x0038, 0x0038, 0x0038 }, 186 }, { 187 74250000, { 0x0028, 0x0038, 0x0038 }, 188 }, { 189 83500000, { 0x0028, 0x0038, 0x0038 }, 190 }, { 191 146250000, { 0x0038, 0x0038, 0x0038 }, 192 }, { 193 148500000, { 0x0000, 0x0038, 0x0038 }, 194 }, { 195 600000000, { 0x0000, 0x0000, 0x0000 }, 196 }, { 197 ~0UL, { 0x0000, 0x0000, 0x0000}, 198 } 199 }; 200 201 static const struct dw_hdmi_phy_config rockchip_phy_config[] = { 202 /*pixelclk symbol term vlev*/ 203 { 74250000, 0x8009, 0x0004, 0x0272}, 204 { 148500000, 0x802b, 0x0004, 0x028d}, 205 { 297000000, 0x8039, 0x0005, 0x028d}, 206 { ~0UL, 0x0000, 0x0000, 0x0000} 207 }; 208 209 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) 210 { 211 struct device_node *np = hdmi->dev->of_node; 212 int ret; 213 214 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 215 if (IS_ERR(hdmi->regmap)) { 216 drm_err(hdmi, "Unable to get rockchip,grf\n"); 217 return PTR_ERR(hdmi->regmap); 218 } 219 220 hdmi->ref_clk = devm_clk_get_optional_enabled(hdmi->dev, "ref"); 221 if (!hdmi->ref_clk) 222 hdmi->ref_clk = devm_clk_get_optional_enabled(hdmi->dev, "vpll"); 223 224 if (IS_ERR(hdmi->ref_clk)) { 225 ret = PTR_ERR(hdmi->ref_clk); 226 if (ret != -EPROBE_DEFER) 227 drm_err(hdmi, "failed to get reference clock\n"); 228 return ret; 229 } 230 231 hdmi->grf_clk = devm_clk_get_optional(hdmi->dev, "grf"); 232 if (IS_ERR(hdmi->grf_clk)) { 233 ret = PTR_ERR(hdmi->grf_clk); 234 if (ret != -EPROBE_DEFER) 235 drm_err(hdmi, "failed to get grf clock\n"); 236 return ret; 237 } 238 239 ret = devm_regulator_get_enable(hdmi->dev, "avdd-0v9"); 240 if (ret) 241 return ret; 242 243 ret = devm_regulator_get_enable(hdmi->dev, "avdd-1v8"); 244 245 return ret; 246 } 247 248 static enum drm_mode_status 249 dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, 250 const struct drm_display_info *info, 251 const struct drm_display_mode *mode) 252 { 253 struct rockchip_hdmi *hdmi = data; 254 const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; 255 int pclk = mode->clock * 1000; 256 bool exact_match = hdmi->plat_data->phy_force_vendor; 257 int i; 258 259 if (hdmi->chip_data->max_tmds_clock && 260 mode->clock > hdmi->chip_data->max_tmds_clock) 261 return MODE_CLOCK_HIGH; 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_err(hdmi, "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_err(hdmi, "Could not write to GRF: %d\n", ret); 333 334 clk_disable_unprepare(hdmi->grf_clk); 335 drm_dbg(hdmi, "vop %s output to hdmi\n", ret ? "LIT" : "BIG"); 336 } 337 338 static int 339 dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, 340 struct drm_crtc_state *crtc_state, 341 struct drm_connector_state *conn_state) 342 { 343 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); 344 345 s->output_mode = ROCKCHIP_OUT_MODE_AAAA; 346 s->output_type = DRM_MODE_CONNECTOR_HDMIA; 347 348 return 0; 349 } 350 351 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { 352 .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, 353 .mode_set = dw_hdmi_rockchip_encoder_mode_set, 354 .enable = dw_hdmi_rockchip_encoder_enable, 355 .disable = dw_hdmi_rockchip_encoder_disable, 356 .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, 357 }; 358 359 static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, 360 const struct drm_display_info *display, 361 const struct drm_display_mode *mode) 362 { 363 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 364 365 dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); 366 367 return phy_power_on(hdmi->phy); 368 } 369 370 static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) 371 { 372 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 373 374 phy_power_off(hdmi->phy); 375 } 376 377 static void dw_hdmi_rk3228_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) 378 { 379 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 380 381 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 382 383 regmap_write(hdmi->regmap, 384 RK3228_GRF_SOC_CON6, 385 HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 386 RK3228_HDMI_SCL_VSEL, 387 RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 388 RK3228_HDMI_SCL_VSEL)); 389 390 regmap_write(hdmi->regmap, 391 RK3228_GRF_SOC_CON2, 392 HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK, 393 RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK)); 394 } 395 396 static enum drm_connector_status 397 dw_hdmi_rk3328_read_hpd(struct dw_hdmi *dw_hdmi, void *data) 398 { 399 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 400 enum drm_connector_status status; 401 402 status = dw_hdmi_phy_read_hpd(dw_hdmi, data); 403 404 if (status == connector_status_connected) 405 regmap_write(hdmi->regmap, 406 RK3328_GRF_SOC_CON4, 407 HIWORD_UPDATE(RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V, 408 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V)); 409 else 410 regmap_write(hdmi->regmap, 411 RK3328_GRF_SOC_CON4, 412 HIWORD_UPDATE(0, RK3328_HDMI_SDA_5V | 413 RK3328_HDMI_SCL_5V)); 414 return status; 415 } 416 417 static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) 418 { 419 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 420 421 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 422 423 /* Enable and map pins to 3V grf-controlled io-voltage */ 424 regmap_write(hdmi->regmap, 425 RK3328_GRF_SOC_CON4, 426 HIWORD_UPDATE(0, RK3328_HDMI_HPD_SARADC | RK3328_HDMI_CEC_5V | 427 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V | 428 RK3328_HDMI_HPD_5V)); 429 regmap_write(hdmi->regmap, 430 RK3328_GRF_SOC_CON3, 431 HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF | 432 RK3328_HDMI_HPD5V_GRF | 433 RK3328_HDMI_CEC5V_GRF)); 434 regmap_write(hdmi->regmap, 435 RK3328_GRF_SOC_CON2, 436 HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, 437 RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | 438 RK3328_HDMI_HPD_IOE)); 439 440 dw_hdmi_rk3328_read_hpd(dw_hdmi, data); 441 } 442 443 static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { 444 .init = dw_hdmi_rockchip_genphy_init, 445 .disable = dw_hdmi_rockchip_genphy_disable, 446 .read_hpd = dw_hdmi_phy_read_hpd, 447 .update_hpd = dw_hdmi_phy_update_hpd, 448 .setup_hpd = dw_hdmi_rk3228_setup_hpd, 449 }; 450 451 static struct rockchip_hdmi_chip_data rk3228_chip_data = { 452 .lcdsel_grf_reg = -1, 453 .max_tmds_clock = 594000, 454 }; 455 456 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { 457 .mode_valid = dw_hdmi_rockchip_mode_valid, 458 .phy_data = &rk3228_chip_data, 459 .phy_ops = &rk3228_hdmi_phy_ops, 460 .phy_name = "inno_dw_hdmi_phy2", 461 .phy_force_vendor = true, 462 }; 463 464 static struct rockchip_hdmi_chip_data rk3288_chip_data = { 465 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 466 .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), 467 .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), 468 .max_tmds_clock = 340000, 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 .max_tmds_clock = 594000, 490 }; 491 492 static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { 493 .mode_valid = dw_hdmi_rockchip_mode_valid, 494 .phy_data = &rk3328_chip_data, 495 .phy_ops = &rk3328_hdmi_phy_ops, 496 .phy_name = "inno_dw_hdmi_phy2", 497 .phy_force_vendor = true, 498 .use_drm_infoframe = true, 499 }; 500 501 static struct rockchip_hdmi_chip_data rk3399_chip_data = { 502 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 503 .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), 504 .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), 505 .max_tmds_clock = 340000, 506 }; 507 508 static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { 509 .mode_valid = dw_hdmi_rockchip_mode_valid, 510 .mpll_cfg = rockchip_mpll_cfg, 511 .cur_ctr = rockchip_cur_ctr, 512 .phy_config = rockchip_phy_config, 513 .phy_data = &rk3399_chip_data, 514 .use_drm_infoframe = true, 515 }; 516 517 static struct rockchip_hdmi_chip_data rk3568_chip_data = { 518 .lcdsel_grf_reg = -1, 519 .max_tmds_clock = 340000, 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_err(hdmi, "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_err(hdmi, "failed to get phy\n"); 607 return ret; 608 } 609 610 if (hdmi->chip_data == &rk3568_chip_data) { 611 regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, 612 HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | 613 RK3568_HDMI_SCLIN_MSK, 614 RK3568_HDMI_SDAIN_MSK | 615 RK3568_HDMI_SCLIN_MSK)); 616 } 617 618 drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); 619 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); 620 621 platform_set_drvdata(pdev, hdmi); 622 623 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); 624 625 /* 626 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), 627 * which would have called the encoder cleanup. Do it manually. 628 */ 629 if (IS_ERR(hdmi->hdmi)) { 630 ret = PTR_ERR(hdmi->hdmi); 631 goto err_bind; 632 } 633 634 return 0; 635 636 err_bind: 637 drm_encoder_cleanup(encoder); 638 639 return ret; 640 } 641 642 static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, 643 void *data) 644 { 645 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); 646 647 dw_hdmi_unbind(hdmi->hdmi); 648 drm_encoder_cleanup(&hdmi->encoder.encoder); 649 } 650 651 static const struct component_ops dw_hdmi_rockchip_ops = { 652 .bind = dw_hdmi_rockchip_bind, 653 .unbind = dw_hdmi_rockchip_unbind, 654 }; 655 656 static int dw_hdmi_rockchip_probe(struct platform_device *pdev) 657 { 658 return component_add(&pdev->dev, &dw_hdmi_rockchip_ops); 659 } 660 661 static void dw_hdmi_rockchip_remove(struct platform_device *pdev) 662 { 663 component_del(&pdev->dev, &dw_hdmi_rockchip_ops); 664 } 665 666 static int __maybe_unused dw_hdmi_rockchip_resume(struct device *dev) 667 { 668 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); 669 670 dw_hdmi_resume(hdmi->hdmi); 671 672 return 0; 673 } 674 675 static const struct dev_pm_ops dw_hdmi_rockchip_pm = { 676 SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_rockchip_resume) 677 }; 678 679 struct platform_driver dw_hdmi_rockchip_pltfm_driver = { 680 .probe = dw_hdmi_rockchip_probe, 681 .remove_new = dw_hdmi_rockchip_remove, 682 .driver = { 683 .name = "dwhdmi-rockchip", 684 .pm = &dw_hdmi_rockchip_pm, 685 .of_match_table = dw_hdmi_rockchip_dt_ids, 686 }, 687 }; 688