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