1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd. 4 * Copyright (c) 2024 Collabora Ltd. 5 * 6 * Author: Algea Cao <algea.cao@rock-chips.com> 7 * Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> 8 */ 9 10 #include <linux/clk.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/hw_bitfield.h> 13 #include <linux/mfd/syscon.h> 14 #include <linux/module.h> 15 #include <linux/platform_device.h> 16 #include <linux/phy/phy.h> 17 #include <linux/phy/phy-hdmi.h> 18 #include <linux/regmap.h> 19 #include <linux/workqueue.h> 20 21 #include <drm/bridge/dw_hdmi_qp.h> 22 #include <drm/display/drm_hdmi_helper.h> 23 #include <drm/drm_bridge_connector.h> 24 #include <drm/drm_of.h> 25 #include <drm/drm_probe_helper.h> 26 #include <drm/drm_simple_kms_helper.h> 27 28 #include "rockchip_drm_drv.h" 29 30 #define RK3576_IOC_MISC_CON0 0xa400 31 #define RK3576_HDMI_HPD_INT_MSK BIT(2) 32 #define RK3576_HDMI_HPD_INT_CLR BIT(1) 33 34 #define RK3576_IOC_HDMI_HPD_STATUS 0xa440 35 #define RK3576_HDMI_LEVEL_INT BIT(3) 36 37 #define RK3576_VO0_GRF_SOC_CON1 0x0004 38 #define RK3576_HDMI_FRL_MOD BIT(0) 39 #define RK3576_HDMI_HDCP14_MEM_EN BIT(15) 40 41 #define RK3576_VO0_GRF_SOC_CON8 0x0020 42 #define RK3576_COLOR_DEPTH_MASK GENMASK(11, 8) 43 #define RK3576_8BPC 0x0 44 #define RK3576_10BPC 0x6 45 #define RK3576_COLOR_FORMAT_MASK GENMASK(7, 4) 46 #define RK3576_RGB 0x9 47 #define RK3576_YUV422 0x1 48 #define RK3576_YUV444 0x2 49 #define RK3576_YUV420 0x3 50 #define RK3576_CECIN_MASK BIT(3) 51 52 #define RK3576_VO0_GRF_SOC_CON14 0x0038 53 #define RK3576_I2S_SEL_MASK BIT(0) 54 #define RK3576_SPDIF_SEL_MASK BIT(1) 55 #define HDCP0_P1_GPIO_IN BIT(2) 56 #define RK3576_SCLIN_MASK BIT(4) 57 #define RK3576_SDAIN_MASK BIT(5) 58 #define RK3576_HDMI_GRANT_SEL BIT(6) 59 60 #define RK3588_GRF_SOC_CON2 0x0308 61 #define RK3588_HDMI0_HPD_INT_MSK BIT(13) 62 #define RK3588_HDMI0_HPD_INT_CLR BIT(12) 63 #define RK3588_HDMI1_HPD_INT_MSK BIT(15) 64 #define RK3588_HDMI1_HPD_INT_CLR BIT(14) 65 #define RK3588_GRF_SOC_CON7 0x031c 66 #define RK3588_HPD_HDMI0_IO_EN_MASK BIT(12) 67 #define RK3588_HPD_HDMI1_IO_EN_MASK BIT(13) 68 #define RK3588_GRF_SOC_STATUS1 0x0384 69 #define RK3588_HDMI0_LEVEL_INT BIT(16) 70 #define RK3588_HDMI1_LEVEL_INT BIT(24) 71 #define RK3588_GRF_VO1_CON3 0x000c 72 #define RK3588_GRF_VO1_CON6 0x0018 73 #define RK3588_COLOR_DEPTH_MASK GENMASK(7, 4) 74 #define RK3588_8BPC 0x0 75 #define RK3588_10BPC 0x6 76 #define RK3588_COLOR_FORMAT_MASK GENMASK(3, 0) 77 #define RK3588_RGB 0x0 78 #define RK3588_YUV420 0x3 79 #define RK3588_SCLIN_MASK BIT(9) 80 #define RK3588_SDAIN_MASK BIT(10) 81 #define RK3588_MODE_MASK BIT(11) 82 #define RK3588_I2S_SEL_MASK BIT(13) 83 #define RK3588_GRF_VO1_CON9 0x0024 84 #define RK3588_HDMI0_GRANT_SEL BIT(10) 85 #define RK3588_HDMI1_GRANT_SEL BIT(12) 86 87 #define HOTPLUG_DEBOUNCE_MS 150 88 #define MAX_HDMI_PORT_NUM 2 89 90 struct rockchip_hdmi_qp { 91 struct device *dev; 92 struct regmap *regmap; 93 struct regmap *vo_regmap; 94 struct rockchip_encoder encoder; 95 struct dw_hdmi_qp *hdmi; 96 struct phy *phy; 97 struct gpio_desc *frl_enable_gpio; 98 struct delayed_work hpd_work; 99 int port_id; 100 const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops; 101 unsigned long long tmds_char_rate; 102 }; 103 104 struct rockchip_hdmi_qp_ctrl_ops { 105 void (*io_init)(struct rockchip_hdmi_qp *hdmi); 106 void (*enc_init)(struct rockchip_hdmi_qp *hdmi, struct rockchip_crtc_state *state); 107 irqreturn_t (*irq_callback)(int irq, void *dev_id); 108 irqreturn_t (*hardirq_callback)(int irq, void *dev_id); 109 }; 110 111 static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder) 112 { 113 struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder); 114 115 return container_of(rkencoder, struct rockchip_hdmi_qp, encoder); 116 } 117 118 static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder) 119 { 120 struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder); 121 struct drm_crtc *crtc = encoder->crtc; 122 123 /* Unconditionally switch to TMDS as FRL is not yet supported */ 124 gpiod_set_value_cansleep(hdmi->frl_enable_gpio, 0); 125 126 if (!crtc || !crtc->state) 127 return; 128 129 if (hdmi->ctrl_ops->enc_init) 130 hdmi->ctrl_ops->enc_init(hdmi, to_rockchip_crtc_state(crtc->state)); 131 } 132 133 static int 134 dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder, 135 struct drm_crtc_state *crtc_state, 136 struct drm_connector_state *conn_state) 137 { 138 struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder); 139 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); 140 union phy_configure_opts phy_cfg = {}; 141 int ret; 142 143 if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate && 144 s->output_bpc == conn_state->hdmi.output_bpc) 145 return 0; 146 147 phy_cfg.hdmi.tmds_char_rate = conn_state->hdmi.tmds_char_rate; 148 phy_cfg.hdmi.bpc = conn_state->hdmi.output_bpc; 149 150 ret = phy_configure(hdmi->phy, &phy_cfg); 151 if (!ret) { 152 hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate; 153 s->output_mode = ROCKCHIP_OUT_MODE_AAAA; 154 s->output_type = DRM_MODE_CONNECTOR_HDMIA; 155 s->output_bpc = conn_state->hdmi.output_bpc; 156 } else { 157 dev_err(hdmi->dev, "Failed to configure phy: %d\n", ret); 158 } 159 160 return ret; 161 } 162 163 static const struct 164 drm_encoder_helper_funcs dw_hdmi_qp_rockchip_encoder_helper_funcs = { 165 .enable = dw_hdmi_qp_rockchip_encoder_enable, 166 .atomic_check = dw_hdmi_qp_rockchip_encoder_atomic_check, 167 }; 168 169 static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data) 170 { 171 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 172 173 return phy_power_on(hdmi->phy); 174 } 175 176 static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi, 177 void *data) 178 { 179 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 180 181 phy_power_off(hdmi->phy); 182 } 183 184 static enum drm_connector_status 185 dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) 186 { 187 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 188 u32 val; 189 190 regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val); 191 val &= hdmi->port_id ? RK3588_HDMI1_LEVEL_INT : RK3588_HDMI0_LEVEL_INT; 192 193 return val ? connector_status_connected : connector_status_disconnected; 194 } 195 196 static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) 197 { 198 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 199 u32 val; 200 201 if (hdmi->port_id) 202 val = (FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_CLR, 1) | 203 FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 0)); 204 else 205 val = (FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_CLR, 1) | 206 FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 0)); 207 208 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 209 } 210 211 static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = { 212 .init = dw_hdmi_qp_rk3588_phy_init, 213 .disable = dw_hdmi_qp_rk3588_phy_disable, 214 .read_hpd = dw_hdmi_qp_rk3588_read_hpd, 215 .setup_hpd = dw_hdmi_qp_rk3588_setup_hpd, 216 }; 217 218 static enum drm_connector_status 219 dw_hdmi_qp_rk3576_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) 220 { 221 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 222 u32 val; 223 224 regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &val); 225 226 return val & RK3576_HDMI_LEVEL_INT ? 227 connector_status_connected : connector_status_disconnected; 228 } 229 230 static void dw_hdmi_qp_rk3576_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data) 231 { 232 struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data; 233 u32 val; 234 235 val = (FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_CLR, 1) | 236 FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0)); 237 238 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 239 regmap_write(hdmi->regmap, 0xa404, 0xffff0102); 240 } 241 242 static const struct dw_hdmi_qp_phy_ops rk3576_hdmi_phy_ops = { 243 .init = dw_hdmi_qp_rk3588_phy_init, 244 .disable = dw_hdmi_qp_rk3588_phy_disable, 245 .read_hpd = dw_hdmi_qp_rk3576_read_hpd, 246 .setup_hpd = dw_hdmi_qp_rk3576_setup_hpd, 247 }; 248 249 static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work) 250 { 251 struct rockchip_hdmi_qp *hdmi = container_of(work, 252 struct rockchip_hdmi_qp, 253 hpd_work.work); 254 struct drm_device *drm = hdmi->encoder.encoder.dev; 255 bool changed; 256 257 if (drm) { 258 changed = drm_helper_hpd_irq_event(drm); 259 if (changed) 260 dev_dbg(hdmi->dev, "connector status changed\n"); 261 } 262 } 263 264 static irqreturn_t dw_hdmi_qp_rk3576_hardirq(int irq, void *dev_id) 265 { 266 struct rockchip_hdmi_qp *hdmi = dev_id; 267 u32 intr_stat, val; 268 269 regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat); 270 if (intr_stat) { 271 val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 1); 272 273 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 274 return IRQ_WAKE_THREAD; 275 } 276 277 return IRQ_NONE; 278 } 279 280 static irqreturn_t dw_hdmi_qp_rk3576_irq(int irq, void *dev_id) 281 { 282 struct rockchip_hdmi_qp *hdmi = dev_id; 283 u32 intr_stat, val; 284 285 regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat); 286 287 if (!intr_stat) 288 return IRQ_NONE; 289 290 val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_CLR, 1); 291 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 292 mod_delayed_work(system_wq, &hdmi->hpd_work, 293 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); 294 295 val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0); 296 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 297 298 return IRQ_HANDLED; 299 } 300 301 static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id) 302 { 303 struct rockchip_hdmi_qp *hdmi = dev_id; 304 u32 intr_stat, val; 305 306 regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); 307 308 if (intr_stat) { 309 if (hdmi->port_id) 310 val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 1); 311 else 312 val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 1); 313 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 314 return IRQ_WAKE_THREAD; 315 } 316 317 return IRQ_NONE; 318 } 319 320 static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id) 321 { 322 struct rockchip_hdmi_qp *hdmi = dev_id; 323 u32 intr_stat, val; 324 325 regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat); 326 if (!intr_stat) 327 return IRQ_NONE; 328 329 if (hdmi->port_id) 330 val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_CLR, 1); 331 else 332 val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_CLR, 1); 333 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 334 335 mod_delayed_work(system_wq, &hdmi->hpd_work, 336 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS)); 337 338 if (hdmi->port_id) 339 val |= FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 0); 340 else 341 val |= FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 0); 342 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 343 344 return IRQ_HANDLED; 345 } 346 347 static void dw_hdmi_qp_rk3576_io_init(struct rockchip_hdmi_qp *hdmi) 348 { 349 u32 val; 350 351 val = FIELD_PREP_WM16(RK3576_SCLIN_MASK, 1) | 352 FIELD_PREP_WM16(RK3576_SDAIN_MASK, 1) | 353 FIELD_PREP_WM16(RK3576_HDMI_GRANT_SEL, 1) | 354 FIELD_PREP_WM16(RK3576_I2S_SEL_MASK, 1); 355 356 regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON14, val); 357 358 val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0); 359 regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val); 360 } 361 362 static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi) 363 { 364 u32 val; 365 366 val = FIELD_PREP_WM16(RK3588_SCLIN_MASK, 1) | 367 FIELD_PREP_WM16(RK3588_SDAIN_MASK, 1) | 368 FIELD_PREP_WM16(RK3588_MODE_MASK, 1) | 369 FIELD_PREP_WM16(RK3588_I2S_SEL_MASK, 1); 370 regmap_write(hdmi->vo_regmap, 371 hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3, 372 val); 373 374 val = FIELD_PREP_WM16(RK3588_HPD_HDMI0_IO_EN_MASK, 1) | 375 FIELD_PREP_WM16(RK3588_HPD_HDMI1_IO_EN_MASK, 1); 376 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val); 377 378 if (hdmi->port_id) 379 val = FIELD_PREP_WM16(RK3588_HDMI1_GRANT_SEL, 1); 380 else 381 val = FIELD_PREP_WM16(RK3588_HDMI0_GRANT_SEL, 1); 382 regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val); 383 384 if (hdmi->port_id) 385 val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 1); 386 else 387 val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 1); 388 regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val); 389 } 390 391 static void dw_hdmi_qp_rk3576_enc_init(struct rockchip_hdmi_qp *hdmi, 392 struct rockchip_crtc_state *state) 393 { 394 u32 val; 395 396 if (state->output_bpc == 10) 397 val = FIELD_PREP_WM16(RK3576_COLOR_DEPTH_MASK, RK3576_10BPC); 398 else 399 val = FIELD_PREP_WM16(RK3576_COLOR_DEPTH_MASK, RK3576_8BPC); 400 401 regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON8, val); 402 } 403 404 static void dw_hdmi_qp_rk3588_enc_init(struct rockchip_hdmi_qp *hdmi, 405 struct rockchip_crtc_state *state) 406 { 407 u32 val; 408 409 if (state->output_bpc == 10) 410 val = FIELD_PREP_WM16(RK3588_COLOR_DEPTH_MASK, RK3588_10BPC); 411 else 412 val = FIELD_PREP_WM16(RK3588_COLOR_DEPTH_MASK, RK3588_8BPC); 413 414 regmap_write(hdmi->vo_regmap, 415 hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3, 416 val); 417 } 418 419 static const struct rockchip_hdmi_qp_ctrl_ops rk3576_hdmi_ctrl_ops = { 420 .io_init = dw_hdmi_qp_rk3576_io_init, 421 .enc_init = dw_hdmi_qp_rk3576_enc_init, 422 .irq_callback = dw_hdmi_qp_rk3576_irq, 423 .hardirq_callback = dw_hdmi_qp_rk3576_hardirq, 424 }; 425 426 static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = { 427 .io_init = dw_hdmi_qp_rk3588_io_init, 428 .enc_init = dw_hdmi_qp_rk3588_enc_init, 429 .irq_callback = dw_hdmi_qp_rk3588_irq, 430 .hardirq_callback = dw_hdmi_qp_rk3588_hardirq, 431 }; 432 433 struct rockchip_hdmi_qp_cfg { 434 unsigned int num_ports; 435 unsigned int port_ids[MAX_HDMI_PORT_NUM]; 436 const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops; 437 const struct dw_hdmi_qp_phy_ops *phy_ops; 438 }; 439 440 static const struct rockchip_hdmi_qp_cfg rk3576_hdmi_cfg = { 441 .num_ports = 1, 442 .port_ids = { 443 0x27da0000, 444 }, 445 .ctrl_ops = &rk3576_hdmi_ctrl_ops, 446 .phy_ops = &rk3576_hdmi_phy_ops, 447 }; 448 449 static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = { 450 .num_ports = 2, 451 .port_ids = { 452 0xfde80000, 453 0xfdea0000, 454 }, 455 .ctrl_ops = &rk3588_hdmi_ctrl_ops, 456 .phy_ops = &rk3588_hdmi_phy_ops, 457 }; 458 459 static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = { 460 { 461 .compatible = "rockchip,rk3576-dw-hdmi-qp", 462 .data = &rk3576_hdmi_cfg 463 }, { 464 .compatible = "rockchip,rk3588-dw-hdmi-qp", 465 .data = &rk3588_hdmi_cfg 466 }, 467 {}, 468 }; 469 MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids); 470 471 static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master, 472 void *data) 473 { 474 struct platform_device *pdev = to_platform_device(dev); 475 struct dw_hdmi_qp_plat_data plat_data = {}; 476 const struct rockchip_hdmi_qp_cfg *cfg; 477 struct drm_device *drm = data; 478 struct drm_connector *connector; 479 struct drm_encoder *encoder; 480 struct rockchip_hdmi_qp *hdmi; 481 struct resource *res; 482 struct clk_bulk_data *clks; 483 struct clk *ref_clk; 484 int ret, irq, i; 485 486 if (!pdev->dev.of_node) 487 return -ENODEV; 488 489 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 490 if (!hdmi) 491 return -ENOMEM; 492 493 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 494 if (!res) 495 return -ENODEV; 496 497 cfg = of_device_get_match_data(dev); 498 if (!cfg) 499 return -ENODEV; 500 501 if (!cfg->ctrl_ops || !cfg->ctrl_ops->io_init || 502 !cfg->ctrl_ops->irq_callback || !cfg->ctrl_ops->hardirq_callback) 503 return dev_err_probe(dev, -ENODEV, "Missing platform ctrl ops\n"); 504 505 hdmi->ctrl_ops = cfg->ctrl_ops; 506 hdmi->dev = &pdev->dev; 507 hdmi->port_id = -ENODEV; 508 509 /* Identify port ID by matching base IO address */ 510 for (i = 0; i < cfg->num_ports; i++) { 511 if (res->start == cfg->port_ids[i]) { 512 hdmi->port_id = i; 513 break; 514 } 515 } 516 if (hdmi->port_id < 0) 517 return dev_err_probe(hdmi->dev, hdmi->port_id, 518 "Failed to match HDMI port ID\n"); 519 520 plat_data.phy_ops = cfg->phy_ops; 521 plat_data.phy_data = hdmi; 522 plat_data.max_bpc = 10; 523 524 encoder = &hdmi->encoder.encoder; 525 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); 526 527 rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder, 528 dev->of_node, 0, 0); 529 /* 530 * If we failed to find the CRTC(s) which this encoder is 531 * supposed to be connected to, it's because the CRTC has 532 * not been registered yet. Defer probing, and hope that 533 * the required CRTC is added later. 534 */ 535 if (encoder->possible_crtcs == 0) 536 return -EPROBE_DEFER; 537 538 hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, 539 "rockchip,grf"); 540 if (IS_ERR(hdmi->regmap)) 541 return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->regmap), 542 "Unable to get rockchip,grf\n"); 543 544 hdmi->vo_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, 545 "rockchip,vo-grf"); 546 if (IS_ERR(hdmi->vo_regmap)) 547 return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->vo_regmap), 548 "Unable to get rockchip,vo-grf\n"); 549 550 ret = devm_clk_bulk_get_all_enabled(hdmi->dev, &clks); 551 if (ret < 0) 552 return dev_err_probe(hdmi->dev, ret, "Failed to get clocks\n"); 553 554 ref_clk = clk_get(hdmi->dev, "ref"); 555 if (IS_ERR(ref_clk)) 556 return dev_err_probe(hdmi->dev, PTR_ERR(ref_clk), 557 "Failed to get ref clock\n"); 558 559 plat_data.ref_clk_rate = clk_get_rate(ref_clk); 560 clk_put(ref_clk); 561 562 hdmi->frl_enable_gpio = devm_gpiod_get_optional(hdmi->dev, "frl-enable", 563 GPIOD_OUT_LOW); 564 if (IS_ERR(hdmi->frl_enable_gpio)) 565 return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->frl_enable_gpio), 566 "Failed to request FRL enable GPIO\n"); 567 568 hdmi->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0); 569 if (IS_ERR(hdmi->phy)) 570 return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->phy), 571 "Failed to get phy\n"); 572 573 cfg->ctrl_ops->io_init(hdmi); 574 575 INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work); 576 577 plat_data.main_irq = platform_get_irq_byname(pdev, "main"); 578 if (plat_data.main_irq < 0) 579 return plat_data.main_irq; 580 581 plat_data.cec_irq = platform_get_irq_byname(pdev, "cec"); 582 if (plat_data.cec_irq < 0) 583 return plat_data.cec_irq; 584 585 irq = platform_get_irq_byname(pdev, "hpd"); 586 if (irq < 0) 587 return irq; 588 589 ret = devm_request_threaded_irq(hdmi->dev, irq, 590 cfg->ctrl_ops->hardirq_callback, 591 cfg->ctrl_ops->irq_callback, 592 IRQF_SHARED, "dw-hdmi-qp-hpd", 593 hdmi); 594 if (ret) 595 return ret; 596 597 drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs); 598 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); 599 600 platform_set_drvdata(pdev, hdmi); 601 602 hdmi->hdmi = dw_hdmi_qp_bind(pdev, encoder, &plat_data); 603 if (IS_ERR(hdmi->hdmi)) { 604 drm_encoder_cleanup(encoder); 605 return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hdmi), 606 "Failed to bind dw-hdmi-qp"); 607 } 608 609 connector = drm_bridge_connector_init(drm, encoder); 610 if (IS_ERR(connector)) 611 return dev_err_probe(hdmi->dev, PTR_ERR(connector), 612 "Failed to init bridge connector\n"); 613 614 return drm_connector_attach_encoder(connector, encoder); 615 } 616 617 static void dw_hdmi_qp_rockchip_unbind(struct device *dev, 618 struct device *master, 619 void *data) 620 { 621 struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); 622 623 cancel_delayed_work_sync(&hdmi->hpd_work); 624 625 drm_encoder_cleanup(&hdmi->encoder.encoder); 626 } 627 628 static const struct component_ops dw_hdmi_qp_rockchip_ops = { 629 .bind = dw_hdmi_qp_rockchip_bind, 630 .unbind = dw_hdmi_qp_rockchip_unbind, 631 }; 632 633 static int dw_hdmi_qp_rockchip_probe(struct platform_device *pdev) 634 { 635 return component_add(&pdev->dev, &dw_hdmi_qp_rockchip_ops); 636 } 637 638 static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev) 639 { 640 component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops); 641 } 642 643 static int __maybe_unused dw_hdmi_qp_rockchip_suspend(struct device *dev) 644 { 645 struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); 646 647 dw_hdmi_qp_suspend(dev, hdmi->hdmi); 648 649 return 0; 650 } 651 652 static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev) 653 { 654 struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev); 655 656 hdmi->ctrl_ops->io_init(hdmi); 657 658 dw_hdmi_qp_resume(dev, hdmi->hdmi); 659 660 if (hdmi->encoder.encoder.dev) 661 drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev); 662 663 return 0; 664 } 665 666 static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = { 667 SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_qp_rockchip_suspend, 668 dw_hdmi_qp_rockchip_resume) 669 }; 670 671 struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = { 672 .probe = dw_hdmi_qp_rockchip_probe, 673 .remove = dw_hdmi_qp_rockchip_remove, 674 .driver = { 675 .name = "dwhdmiqp-rockchip", 676 .pm = &dw_hdmi_qp_rockchip_pm, 677 .of_match_table = dw_hdmi_qp_rockchip_dt_ids, 678 }, 679 }; 680