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 *hdmiphy_clk; 80 struct clk *ref_clk; 81 struct clk *grf_clk; 82 struct dw_hdmi *hdmi; 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 30666000, { 96 { 0x00b3, 0x0000 }, 97 { 0x2153, 0x0000 }, 98 { 0x40f3, 0x0000 }, 99 }, 100 }, { 101 36800000, { 102 { 0x00b3, 0x0000 }, 103 { 0x2153, 0x0000 }, 104 { 0x40a2, 0x0001 }, 105 }, 106 }, { 107 46000000, { 108 { 0x00b3, 0x0000 }, 109 { 0x2142, 0x0001 }, 110 { 0x40a2, 0x0001 }, 111 }, 112 }, { 113 61333000, { 114 { 0x0072, 0x0001 }, 115 { 0x2142, 0x0001 }, 116 { 0x40a2, 0x0001 }, 117 }, 118 }, { 119 73600000, { 120 { 0x0072, 0x0001 }, 121 { 0x2142, 0x0001 }, 122 { 0x4061, 0x0002 }, 123 }, 124 }, { 125 92000000, { 126 { 0x0072, 0x0001 }, 127 { 0x2145, 0x0002 }, 128 { 0x4061, 0x0002 }, 129 }, 130 }, { 131 122666000, { 132 { 0x0051, 0x0002 }, 133 { 0x2145, 0x0002 }, 134 { 0x4061, 0x0002 }, 135 }, 136 }, { 137 147200000, { 138 { 0x0051, 0x0002 }, 139 { 0x2145, 0x0002 }, 140 { 0x4064, 0x0003 }, 141 }, 142 }, { 143 184000000, { 144 { 0x0051, 0x0002 }, 145 { 0x214c, 0x0003 }, 146 { 0x4064, 0x0003 }, 147 }, 148 }, { 149 226666000, { 150 { 0x0040, 0x0003 }, 151 { 0x214c, 0x0003 }, 152 { 0x4064, 0x0003 }, 153 }, 154 }, { 155 272000000, { 156 { 0x0040, 0x0003 }, 157 { 0x214c, 0x0003 }, 158 { 0x5a64, 0x0003 }, 159 }, 160 }, { 161 340000000, { 162 { 0x0040, 0x0003 }, 163 { 0x3b4c, 0x0003 }, 164 { 0x5a64, 0x0003 }, 165 }, 166 }, { 167 600000000, { 168 { 0x1a40, 0x0003 }, 169 { 0x3b4c, 0x0003 }, 170 { 0x5a64, 0x0003 }, 171 }, 172 }, { 173 ~0UL, { 174 { 0x0000, 0x0000 }, 175 { 0x0000, 0x0000 }, 176 { 0x0000, 0x0000 }, 177 }, 178 } 179 }; 180 181 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = { 182 /* pixelclk bpp8 bpp10 bpp12 */ 183 { 184 600000000, { 0x0000, 0x0000, 0x0000 }, 185 }, { 186 ~0UL, { 0x0000, 0x0000, 0x0000 }, 187 } 188 }; 189 190 static const struct dw_hdmi_phy_config rockchip_phy_config[] = { 191 /*pixelclk symbol term vlev*/ 192 { 74250000, 0x8009, 0x0004, 0x0272}, 193 { 165000000, 0x802b, 0x0004, 0x0209}, 194 { 297000000, 0x8039, 0x0005, 0x028d}, 195 { 594000000, 0x8039, 0x0000, 0x019d}, 196 { ~0UL, 0x0000, 0x0000, 0x0000} 197 }; 198 199 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) 200 { 201 struct device_node *np = hdmi->dev->of_node; 202 int ret; 203 204 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 205 if (IS_ERR(hdmi->regmap)) { 206 drm_err(hdmi, "Unable to get rockchip,grf\n"); 207 return PTR_ERR(hdmi->regmap); 208 } 209 210 hdmi->ref_clk = devm_clk_get_optional_enabled(hdmi->dev, "ref"); 211 if (!hdmi->ref_clk) 212 hdmi->ref_clk = devm_clk_get_optional_enabled(hdmi->dev, "vpll"); 213 214 if (IS_ERR(hdmi->ref_clk)) { 215 ret = PTR_ERR(hdmi->ref_clk); 216 if (ret != -EPROBE_DEFER) 217 drm_err(hdmi, "failed to get reference clock\n"); 218 return ret; 219 } 220 221 hdmi->grf_clk = devm_clk_get_optional(hdmi->dev, "grf"); 222 if (IS_ERR(hdmi->grf_clk)) { 223 ret = PTR_ERR(hdmi->grf_clk); 224 if (ret != -EPROBE_DEFER) 225 drm_err(hdmi, "failed to get grf clock\n"); 226 return ret; 227 } 228 229 ret = devm_regulator_get_enable(hdmi->dev, "avdd-0v9"); 230 if (ret) 231 return ret; 232 233 ret = devm_regulator_get_enable(hdmi->dev, "avdd-1v8"); 234 235 return ret; 236 } 237 238 static enum drm_mode_status 239 dw_hdmi_rockchip_mode_valid(struct dw_hdmi *dw_hdmi, void *data, 240 const struct drm_display_info *info, 241 const struct drm_display_mode *mode) 242 { 243 struct rockchip_hdmi *hdmi = data; 244 int pclk = mode->clock * 1000; 245 246 if (hdmi->chip_data->max_tmds_clock && 247 mode->clock > hdmi->chip_data->max_tmds_clock) 248 return MODE_CLOCK_HIGH; 249 250 if (hdmi->ref_clk) { 251 int rpclk = clk_round_rate(hdmi->ref_clk, pclk); 252 253 if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000) 254 return MODE_NOCLOCK; 255 } 256 257 if (hdmi->hdmiphy_clk) { 258 int rpclk = clk_round_rate(hdmi->hdmiphy_clk, pclk); 259 260 if (rpclk < 0 || abs(rpclk - pclk) > pclk / 1000) 261 return MODE_NOCLOCK; 262 } 263 264 return MODE_OK; 265 } 266 267 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder) 268 { 269 } 270 271 static bool 272 dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder, 273 const struct drm_display_mode *mode, 274 struct drm_display_mode *adj_mode) 275 { 276 return true; 277 } 278 279 static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder, 280 struct drm_display_mode *mode, 281 struct drm_display_mode *adj_mode) 282 { 283 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); 284 285 clk_set_rate(hdmi->ref_clk, adj_mode->clock * 1000); 286 } 287 288 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) 289 { 290 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); 291 u32 val; 292 int ret; 293 294 if (hdmi->chip_data->lcdsel_grf_reg < 0) 295 return; 296 297 ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); 298 if (ret) 299 val = hdmi->chip_data->lcdsel_lit; 300 else 301 val = hdmi->chip_data->lcdsel_big; 302 303 ret = clk_prepare_enable(hdmi->grf_clk); 304 if (ret < 0) { 305 drm_err(hdmi, "failed to enable grfclk %d\n", ret); 306 return; 307 } 308 309 ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); 310 if (ret != 0) 311 drm_err(hdmi, "Could not write to GRF: %d\n", ret); 312 313 clk_disable_unprepare(hdmi->grf_clk); 314 drm_dbg(hdmi, "vop %s output to hdmi\n", ret ? "LIT" : "BIG"); 315 } 316 317 static int 318 dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder, 319 struct drm_crtc_state *crtc_state, 320 struct drm_connector_state *conn_state) 321 { 322 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); 323 324 s->output_mode = ROCKCHIP_OUT_MODE_AAAA; 325 s->output_type = DRM_MODE_CONNECTOR_HDMIA; 326 327 return 0; 328 } 329 330 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = { 331 .mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup, 332 .mode_set = dw_hdmi_rockchip_encoder_mode_set, 333 .enable = dw_hdmi_rockchip_encoder_enable, 334 .disable = dw_hdmi_rockchip_encoder_disable, 335 .atomic_check = dw_hdmi_rockchip_encoder_atomic_check, 336 }; 337 338 static int dw_hdmi_rockchip_genphy_init(struct dw_hdmi *dw_hdmi, void *data, 339 const struct drm_display_info *display, 340 const struct drm_display_mode *mode) 341 { 342 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 343 344 dw_hdmi_set_high_tmds_clock_ratio(dw_hdmi, display); 345 346 return phy_power_on(hdmi->phy); 347 } 348 349 static void dw_hdmi_rockchip_genphy_disable(struct dw_hdmi *dw_hdmi, void *data) 350 { 351 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 352 353 phy_power_off(hdmi->phy); 354 } 355 356 static void dw_hdmi_rk3228_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) 357 { 358 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 359 360 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 361 362 regmap_write(hdmi->regmap, 363 RK3228_GRF_SOC_CON6, 364 HIWORD_UPDATE(RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 365 RK3228_HDMI_SCL_VSEL, 366 RK3228_HDMI_HPD_VSEL | RK3228_HDMI_SDA_VSEL | 367 RK3228_HDMI_SCL_VSEL)); 368 369 regmap_write(hdmi->regmap, 370 RK3228_GRF_SOC_CON2, 371 HIWORD_UPDATE(RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK, 372 RK3228_HDMI_SDAIN_MSK | RK3228_HDMI_SCLIN_MSK)); 373 } 374 375 static enum drm_connector_status 376 dw_hdmi_rk3328_read_hpd(struct dw_hdmi *dw_hdmi, void *data) 377 { 378 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 379 enum drm_connector_status status; 380 381 status = dw_hdmi_phy_read_hpd(dw_hdmi, data); 382 383 if (status == connector_status_connected) 384 regmap_write(hdmi->regmap, 385 RK3328_GRF_SOC_CON4, 386 HIWORD_UPDATE(RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V, 387 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V)); 388 else 389 regmap_write(hdmi->regmap, 390 RK3328_GRF_SOC_CON4, 391 HIWORD_UPDATE(0, RK3328_HDMI_SDA_5V | 392 RK3328_HDMI_SCL_5V)); 393 return status; 394 } 395 396 static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) 397 { 398 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; 399 400 dw_hdmi_phy_setup_hpd(dw_hdmi, data); 401 402 /* Enable and map pins to 3V grf-controlled io-voltage */ 403 regmap_write(hdmi->regmap, 404 RK3328_GRF_SOC_CON4, 405 HIWORD_UPDATE(0, RK3328_HDMI_HPD_SARADC | RK3328_HDMI_CEC_5V | 406 RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V | 407 RK3328_HDMI_HPD_5V)); 408 regmap_write(hdmi->regmap, 409 RK3328_GRF_SOC_CON3, 410 HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF | 411 RK3328_HDMI_HPD5V_GRF | 412 RK3328_HDMI_CEC5V_GRF)); 413 regmap_write(hdmi->regmap, 414 RK3328_GRF_SOC_CON2, 415 HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, 416 RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | 417 RK3328_HDMI_HPD_IOE)); 418 419 dw_hdmi_rk3328_read_hpd(dw_hdmi, data); 420 } 421 422 static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = { 423 .init = dw_hdmi_rockchip_genphy_init, 424 .disable = dw_hdmi_rockchip_genphy_disable, 425 .read_hpd = dw_hdmi_phy_read_hpd, 426 .update_hpd = dw_hdmi_phy_update_hpd, 427 .setup_hpd = dw_hdmi_rk3228_setup_hpd, 428 }; 429 430 static struct rockchip_hdmi_chip_data rk3228_chip_data = { 431 .lcdsel_grf_reg = -1, 432 .max_tmds_clock = 594000, 433 }; 434 435 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = { 436 .mode_valid = dw_hdmi_rockchip_mode_valid, 437 .phy_data = &rk3228_chip_data, 438 .phy_ops = &rk3228_hdmi_phy_ops, 439 .phy_name = "inno_dw_hdmi_phy2", 440 .phy_force_vendor = true, 441 }; 442 443 static struct rockchip_hdmi_chip_data rk3288_chip_data = { 444 .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, 445 .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), 446 .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), 447 .max_tmds_clock = 340000, 448 }; 449 450 static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { 451 .mode_valid = dw_hdmi_rockchip_mode_valid, 452 .mpll_cfg = rockchip_mpll_cfg, 453 .cur_ctr = rockchip_cur_ctr, 454 .phy_config = rockchip_phy_config, 455 .phy_data = &rk3288_chip_data, 456 }; 457 458 static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { 459 .init = dw_hdmi_rockchip_genphy_init, 460 .disable = dw_hdmi_rockchip_genphy_disable, 461 .read_hpd = dw_hdmi_rk3328_read_hpd, 462 .update_hpd = dw_hdmi_phy_update_hpd, 463 .setup_hpd = dw_hdmi_rk3328_setup_hpd, 464 }; 465 466 static struct rockchip_hdmi_chip_data rk3328_chip_data = { 467 .lcdsel_grf_reg = -1, 468 .max_tmds_clock = 594000, 469 }; 470 471 static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = { 472 .mode_valid = dw_hdmi_rockchip_mode_valid, 473 .phy_data = &rk3328_chip_data, 474 .phy_ops = &rk3328_hdmi_phy_ops, 475 .phy_name = "inno_dw_hdmi_phy2", 476 .phy_force_vendor = true, 477 .use_drm_infoframe = true, 478 }; 479 480 static struct rockchip_hdmi_chip_data rk3399_chip_data = { 481 .lcdsel_grf_reg = RK3399_GRF_SOC_CON20, 482 .lcdsel_big = HIWORD_UPDATE(0, RK3399_HDMI_LCDC_SEL), 483 .lcdsel_lit = HIWORD_UPDATE(RK3399_HDMI_LCDC_SEL, RK3399_HDMI_LCDC_SEL), 484 .max_tmds_clock = 594000, 485 }; 486 487 static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = { 488 .mode_valid = dw_hdmi_rockchip_mode_valid, 489 .mpll_cfg = rockchip_mpll_cfg, 490 .cur_ctr = rockchip_cur_ctr, 491 .phy_config = rockchip_phy_config, 492 .phy_data = &rk3399_chip_data, 493 .use_drm_infoframe = true, 494 }; 495 496 static struct rockchip_hdmi_chip_data rk3568_chip_data = { 497 .lcdsel_grf_reg = -1, 498 .max_tmds_clock = 594000, 499 }; 500 501 static const struct dw_hdmi_plat_data rk3568_hdmi_drv_data = { 502 .mode_valid = dw_hdmi_rockchip_mode_valid, 503 .mpll_cfg = rockchip_mpll_cfg, 504 .cur_ctr = rockchip_cur_ctr, 505 .phy_config = rockchip_phy_config, 506 .phy_data = &rk3568_chip_data, 507 .use_drm_infoframe = true, 508 }; 509 510 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = { 511 { .compatible = "rockchip,rk3228-dw-hdmi", 512 .data = &rk3228_hdmi_drv_data 513 }, 514 { .compatible = "rockchip,rk3288-dw-hdmi", 515 .data = &rk3288_hdmi_drv_data 516 }, 517 { .compatible = "rockchip,rk3328-dw-hdmi", 518 .data = &rk3328_hdmi_drv_data 519 }, 520 { .compatible = "rockchip,rk3399-dw-hdmi", 521 .data = &rk3399_hdmi_drv_data 522 }, 523 { .compatible = "rockchip,rk3568-dw-hdmi", 524 .data = &rk3568_hdmi_drv_data 525 }, 526 {}, 527 }; 528 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids); 529 530 static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, 531 void *data) 532 { 533 struct platform_device *pdev = to_platform_device(dev); 534 struct dw_hdmi_plat_data *plat_data; 535 const struct of_device_id *match; 536 struct drm_device *drm = data; 537 struct drm_encoder *encoder; 538 struct rockchip_hdmi *hdmi; 539 int ret; 540 541 if (!pdev->dev.of_node) 542 return -ENODEV; 543 544 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 545 if (!hdmi) 546 return -ENOMEM; 547 548 match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node); 549 plat_data = devm_kmemdup(&pdev->dev, match->data, 550 sizeof(*plat_data), GFP_KERNEL); 551 if (!plat_data) 552 return -ENOMEM; 553 554 hdmi->dev = &pdev->dev; 555 hdmi->plat_data = plat_data; 556 hdmi->chip_data = plat_data->phy_data; 557 plat_data->phy_data = hdmi; 558 plat_data->priv_data = hdmi; 559 encoder = &hdmi->encoder.encoder; 560 561 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 562 rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, 563 dev->of_node, 0, 0); 564 565 /* 566 * If we failed to find the CRTC(s) which this encoder is 567 * supposed to be connected to, it's because the CRTC has 568 * not been registered yet. Defer probing, and hope that 569 * the required CRTC is added later. 570 */ 571 if (encoder->possible_crtcs == 0) 572 return -EPROBE_DEFER; 573 574 ret = rockchip_hdmi_parse_dt(hdmi); 575 if (ret) { 576 if (ret != -EPROBE_DEFER) 577 drm_err(hdmi, "Unable to parse OF data\n"); 578 return ret; 579 } 580 581 hdmi->phy = devm_phy_optional_get(dev, "hdmi"); 582 if (IS_ERR(hdmi->phy)) { 583 ret = PTR_ERR(hdmi->phy); 584 if (ret != -EPROBE_DEFER) 585 drm_err(hdmi, "failed to get phy\n"); 586 return ret; 587 } 588 589 if (hdmi->phy) { 590 struct of_phandle_args clkspec; 591 592 clkspec.np = hdmi->phy->dev.of_node; 593 hdmi->hdmiphy_clk = of_clk_get_from_provider(&clkspec); 594 if (IS_ERR(hdmi->hdmiphy_clk)) 595 hdmi->hdmiphy_clk = NULL; 596 } 597 598 if (hdmi->chip_data == &rk3568_chip_data) { 599 regmap_write(hdmi->regmap, RK3568_GRF_VO_CON1, 600 HIWORD_UPDATE(RK3568_HDMI_SDAIN_MSK | 601 RK3568_HDMI_SCLIN_MSK, 602 RK3568_HDMI_SDAIN_MSK | 603 RK3568_HDMI_SCLIN_MSK)); 604 } 605 606 drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs); 607 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); 608 609 platform_set_drvdata(pdev, hdmi); 610 611 hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data); 612 613 /* 614 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), 615 * which would have called the encoder cleanup. Do it manually. 616 */ 617 if (IS_ERR(hdmi->hdmi)) { 618 ret = PTR_ERR(hdmi->hdmi); 619 goto err_bind; 620 } 621 622 return 0; 623 624 err_bind: 625 drm_encoder_cleanup(encoder); 626 627 return ret; 628 } 629 630 static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, 631 void *data) 632 { 633 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); 634 635 dw_hdmi_unbind(hdmi->hdmi); 636 drm_encoder_cleanup(&hdmi->encoder.encoder); 637 } 638 639 static const struct component_ops dw_hdmi_rockchip_ops = { 640 .bind = dw_hdmi_rockchip_bind, 641 .unbind = dw_hdmi_rockchip_unbind, 642 }; 643 644 static int dw_hdmi_rockchip_probe(struct platform_device *pdev) 645 { 646 return component_add(&pdev->dev, &dw_hdmi_rockchip_ops); 647 } 648 649 static void dw_hdmi_rockchip_remove(struct platform_device *pdev) 650 { 651 component_del(&pdev->dev, &dw_hdmi_rockchip_ops); 652 } 653 654 static int __maybe_unused dw_hdmi_rockchip_resume(struct device *dev) 655 { 656 struct rockchip_hdmi *hdmi = dev_get_drvdata(dev); 657 658 dw_hdmi_resume(hdmi->hdmi); 659 660 return 0; 661 } 662 663 static const struct dev_pm_ops dw_hdmi_rockchip_pm = { 664 SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_rockchip_resume) 665 }; 666 667 struct platform_driver dw_hdmi_rockchip_pltfm_driver = { 668 .probe = dw_hdmi_rockchip_probe, 669 .remove = dw_hdmi_rockchip_remove, 670 .driver = { 671 .name = "dwhdmi-rockchip", 672 .pm = &dw_hdmi_rockchip_pm, 673 .of_match_table = dw_hdmi_rockchip_dt_ids, 674 }, 675 }; 676