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