Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/vc4: hdmi: Support the BCM2711 HDMI controllers

Now that the driver is ready for it, let's bring in the HDMI controllers
variants for the BCM2711.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Tested-by: Chanwoo Choi <cw00.choi@samsung.com>
Tested-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
Tested-by: Stefan Wahren <stefan.wahren@i2se.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://patchwork.freedesktop.org/patch/msgid/b540c7a9ebb7ad51da39271a8388b69c7e27e582.1599120059.git-series.maxime@cerno.tech

+1004
+284
drivers/gpu/drm/vc4/vc4_hdmi.c
··· 43 43 #include <linux/of_platform.h> 44 44 #include <linux/pm_runtime.h> 45 45 #include <linux/rational.h> 46 + #include <linux/reset.h> 46 47 #include <sound/dmaengine_pcm.h> 47 48 #include <sound/pcm_drm_eld.h> 48 49 #include <sound/pcm_params.h> ··· 53 52 #include "vc4_hdmi.h" 54 53 #include "vc4_hdmi_regs.h" 55 54 #include "vc4_regs.h" 55 + 56 + #define VC5_HDMI_HORZA_HFP_SHIFT 16 57 + #define VC5_HDMI_HORZA_HFP_MASK VC4_MASK(28, 16) 58 + #define VC5_HDMI_HORZA_VPOS BIT(15) 59 + #define VC5_HDMI_HORZA_HPOS BIT(14) 60 + #define VC5_HDMI_HORZA_HAP_SHIFT 0 61 + #define VC5_HDMI_HORZA_HAP_MASK VC4_MASK(13, 0) 62 + 63 + #define VC5_HDMI_HORZB_HBP_SHIFT 16 64 + #define VC5_HDMI_HORZB_HBP_MASK VC4_MASK(26, 16) 65 + #define VC5_HDMI_HORZB_HSP_SHIFT 0 66 + #define VC5_HDMI_HORZB_HSP_MASK VC4_MASK(10, 0) 67 + 68 + #define VC5_HDMI_VERTA_VSP_SHIFT 24 69 + #define VC5_HDMI_VERTA_VSP_MASK VC4_MASK(28, 24) 70 + #define VC5_HDMI_VERTA_VFP_SHIFT 16 71 + #define VC5_HDMI_VERTA_VFP_MASK VC4_MASK(22, 16) 72 + #define VC5_HDMI_VERTA_VAL_SHIFT 0 73 + #define VC5_HDMI_VERTA_VAL_MASK VC4_MASK(12, 0) 74 + 75 + #define VC5_HDMI_VERTB_VSPO_SHIFT 16 76 + #define VC5_HDMI_VERTB_VSPO_MASK VC4_MASK(29, 16) 77 + 78 + # define VC4_HD_M_SW_RST BIT(2) 79 + # define VC4_HD_M_ENABLE BIT(0) 56 80 57 81 #define CEC_CLOCK_FREQ 40000 58 82 #define VC4_HSM_MID_CLOCK 149985000 ··· 107 81 VC4_HDMI_SW_RESET_FORMAT_DETECT); 108 82 109 83 HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0); 84 + } 85 + 86 + static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi) 87 + { 88 + reset_control_reset(vc4_hdmi->reset); 89 + 90 + HDMI_WRITE(HDMI_DVP_CTL, 0); 91 + 92 + HDMI_WRITE(HDMI_CLOCK_STOP, 93 + HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL); 110 94 } 111 95 112 96 static enum drm_connector_status ··· 429 393 HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); 430 394 } 431 395 396 + static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) 397 + { 398 + u32 csc_ctl; 399 + 400 + csc_ctl = 0x07; /* RGB_CONVERT_MODE = custom matrix, || USE_RGB_TO_YCBCR */ 401 + 402 + if (enable) { 403 + /* CEA VICs other than #1 requre limited range RGB 404 + * output unless overridden by an AVI infoframe. 405 + * Apply a colorspace conversion to squash 0-255 down 406 + * to 16-235. The matrix here is: 407 + * 408 + * [ 0.8594 0 0 16] 409 + * [ 0 0.8594 0 16] 410 + * [ 0 0 0.8594 16] 411 + * [ 0 0 0 1] 412 + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets 413 + */ 414 + HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x1b80); 415 + HDMI_WRITE(HDMI_CSC_14_13, (0x0400 << 16) | 0x0000); 416 + HDMI_WRITE(HDMI_CSC_22_21, (0x1b80 << 16) | 0x0000); 417 + HDMI_WRITE(HDMI_CSC_24_23, (0x0400 << 16) | 0x0000); 418 + HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); 419 + HDMI_WRITE(HDMI_CSC_34_33, (0x0400 << 16) | 0x1b80); 420 + } else { 421 + /* Still use the matrix for full range, but make it unity. 422 + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets 423 + */ 424 + HDMI_WRITE(HDMI_CSC_12_11, (0x0000 << 16) | 0x2000); 425 + HDMI_WRITE(HDMI_CSC_14_13, (0x0000 << 16) | 0x0000); 426 + HDMI_WRITE(HDMI_CSC_22_21, (0x2000 << 16) | 0x0000); 427 + HDMI_WRITE(HDMI_CSC_24_23, (0x0000 << 16) | 0x0000); 428 + HDMI_WRITE(HDMI_CSC_32_31, (0x0000 << 16) | 0x0000); 429 + HDMI_WRITE(HDMI_CSC_34_33, (0x0000 << 16) | 0x2000); 430 + } 431 + 432 + HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); 433 + } 434 + 432 435 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, 433 436 struct drm_display_mode *mode) 434 437 { ··· 511 436 512 437 HDMI_WRITE(HDMI_VERTB0, vertb_even); 513 438 HDMI_WRITE(HDMI_VERTB1, vertb); 439 + } 440 + static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, 441 + struct drm_display_mode *mode) 442 + { 443 + bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; 444 + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; 445 + bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; 446 + u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; 447 + u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, 448 + VC5_HDMI_VERTA_VSP) | 449 + VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, 450 + VC5_HDMI_VERTA_VFP) | 451 + VC4_SET_FIELD(mode->crtc_vdisplay, VC5_HDMI_VERTA_VAL)); 452 + u32 vertb = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | 453 + VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, 454 + VC4_HDMI_VERTB_VBP)); 455 + u32 vertb_even = (VC4_SET_FIELD(0, VC5_HDMI_VERTB_VSPO) | 456 + VC4_SET_FIELD(mode->crtc_vtotal - 457 + mode->crtc_vsync_end - 458 + interlaced, 459 + VC4_HDMI_VERTB_VBP)); 460 + 461 + HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); 462 + HDMI_WRITE(HDMI_HORZA, 463 + (vsync_pos ? VC5_HDMI_HORZA_VPOS : 0) | 464 + (hsync_pos ? VC5_HDMI_HORZA_HPOS : 0) | 465 + VC4_SET_FIELD(mode->hdisplay * pixel_rep, 466 + VC5_HDMI_HORZA_HAP) | 467 + VC4_SET_FIELD((mode->hsync_start - 468 + mode->hdisplay) * pixel_rep, 469 + VC5_HDMI_HORZA_HFP)); 470 + 471 + HDMI_WRITE(HDMI_HORZB, 472 + VC4_SET_FIELD((mode->htotal - 473 + mode->hsync_end) * pixel_rep, 474 + VC5_HDMI_HORZB_HBP) | 475 + VC4_SET_FIELD((mode->hsync_end - 476 + mode->hsync_start) * pixel_rep, 477 + VC5_HDMI_HORZB_HSP)); 478 + 479 + HDMI_WRITE(HDMI_VERTA0, verta); 480 + HDMI_WRITE(HDMI_VERTA1, verta); 481 + 482 + HDMI_WRITE(HDMI_VERTB0, vertb_even); 483 + HDMI_WRITE(HDMI_VERTB1, vertb); 484 + 485 + HDMI_WRITE(HDMI_CLOCK_STOP, 0); 514 486 } 515 487 516 488 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) ··· 786 664 for (i = 0; i < 8; i++) { 787 665 if (channel_mask & BIT(i)) 788 666 channel_map |= i << (3 * i); 667 + } 668 + return channel_map; 669 + } 670 + 671 + static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) 672 + { 673 + int i; 674 + u32 channel_map = 0; 675 + 676 + for (i = 0; i < 8; i++) { 677 + if (channel_mask & BIT(i)) 678 + channel_map |= i << (4 * i); 789 679 } 790 680 return channel_map; 791 681 } ··· 1533 1399 return 0; 1534 1400 } 1535 1401 1402 + static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) 1403 + { 1404 + struct platform_device *pdev = vc4_hdmi->pdev; 1405 + struct device *dev = &pdev->dev; 1406 + struct resource *res; 1407 + 1408 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi"); 1409 + if (!res) 1410 + return -ENODEV; 1411 + 1412 + vc4_hdmi->hdmicore_regs = devm_ioremap(dev, res->start, 1413 + resource_size(res)); 1414 + if (IS_ERR(vc4_hdmi->hdmicore_regs)) 1415 + return PTR_ERR(vc4_hdmi->hdmicore_regs); 1416 + 1417 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hd"); 1418 + if (!res) 1419 + return -ENODEV; 1420 + 1421 + vc4_hdmi->hd_regs = devm_ioremap(dev, res->start, resource_size(res)); 1422 + if (IS_ERR(vc4_hdmi->hd_regs)) 1423 + return PTR_ERR(vc4_hdmi->hd_regs); 1424 + 1425 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cec"); 1426 + if (!res) 1427 + return -ENODEV; 1428 + 1429 + vc4_hdmi->cec_regs = devm_ioremap(dev, res->start, resource_size(res)); 1430 + if (IS_ERR(vc4_hdmi->cec_regs)) 1431 + return PTR_ERR(vc4_hdmi->cec_regs); 1432 + 1433 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csc"); 1434 + if (!res) 1435 + return -ENODEV; 1436 + 1437 + vc4_hdmi->csc_regs = devm_ioremap(dev, res->start, resource_size(res)); 1438 + if (IS_ERR(vc4_hdmi->csc_regs)) 1439 + return PTR_ERR(vc4_hdmi->csc_regs); 1440 + 1441 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dvp"); 1442 + if (!res) 1443 + return -ENODEV; 1444 + 1445 + vc4_hdmi->dvp_regs = devm_ioremap(dev, res->start, resource_size(res)); 1446 + if (IS_ERR(vc4_hdmi->dvp_regs)) 1447 + return PTR_ERR(vc4_hdmi->dvp_regs); 1448 + 1449 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); 1450 + if (!res) 1451 + return -ENODEV; 1452 + 1453 + vc4_hdmi->phy_regs = devm_ioremap(dev, res->start, resource_size(res)); 1454 + if (IS_ERR(vc4_hdmi->phy_regs)) 1455 + return PTR_ERR(vc4_hdmi->phy_regs); 1456 + 1457 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "packet"); 1458 + if (!res) 1459 + return -ENODEV; 1460 + 1461 + vc4_hdmi->ram_regs = devm_ioremap(dev, res->start, resource_size(res)); 1462 + if (IS_ERR(vc4_hdmi->ram_regs)) 1463 + return PTR_ERR(vc4_hdmi->ram_regs); 1464 + 1465 + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rm"); 1466 + if (!res) 1467 + return -ENODEV; 1468 + 1469 + vc4_hdmi->rm_regs = devm_ioremap(dev, res->start, resource_size(res)); 1470 + if (IS_ERR(vc4_hdmi->rm_regs)) 1471 + return PTR_ERR(vc4_hdmi->rm_regs); 1472 + 1473 + vc4_hdmi->hsm_clock = devm_clk_get(dev, "hdmi"); 1474 + if (IS_ERR(vc4_hdmi->hsm_clock)) { 1475 + DRM_ERROR("Failed to get HDMI state machine clock\n"); 1476 + return PTR_ERR(vc4_hdmi->hsm_clock); 1477 + } 1478 + 1479 + vc4_hdmi->pixel_bvb_clock = devm_clk_get(dev, "bvb"); 1480 + if (IS_ERR(vc4_hdmi->pixel_bvb_clock)) { 1481 + DRM_ERROR("Failed to get pixel bvb clock\n"); 1482 + return PTR_ERR(vc4_hdmi->pixel_bvb_clock); 1483 + } 1484 + 1485 + vc4_hdmi->audio_clock = devm_clk_get(dev, "audio"); 1486 + if (IS_ERR(vc4_hdmi->audio_clock)) { 1487 + DRM_ERROR("Failed to get audio clock\n"); 1488 + return PTR_ERR(vc4_hdmi->audio_clock); 1489 + } 1490 + 1491 + vc4_hdmi->reset = devm_reset_control_get(dev, NULL); 1492 + if (IS_ERR(vc4_hdmi->reset)) { 1493 + DRM_ERROR("Failed to get HDMI reset line\n"); 1494 + return PTR_ERR(vc4_hdmi->reset); 1495 + } 1496 + 1497 + return 0; 1498 + } 1499 + 1536 1500 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) 1537 1501 { 1538 1502 const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); ··· 1801 1569 .channel_map = vc4_hdmi_channel_map, 1802 1570 }; 1803 1571 1572 + static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = { 1573 + .encoder_type = VC4_ENCODER_TYPE_HDMI0, 1574 + .debugfs_name = "hdmi0_regs", 1575 + .card_name = "vc4-hdmi-0", 1576 + .max_pixel_clock = 297000000, 1577 + .registers = vc5_hdmi_hdmi0_fields, 1578 + .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi0_fields), 1579 + .phy_lane_mapping = { 1580 + PHY_LANE_0, 1581 + PHY_LANE_1, 1582 + PHY_LANE_2, 1583 + PHY_LANE_CK, 1584 + }, 1585 + 1586 + .init_resources = vc5_hdmi_init_resources, 1587 + .csc_setup = vc5_hdmi_csc_setup, 1588 + .reset = vc5_hdmi_reset, 1589 + .set_timings = vc5_hdmi_set_timings, 1590 + .phy_init = vc5_hdmi_phy_init, 1591 + .phy_disable = vc5_hdmi_phy_disable, 1592 + .phy_rng_enable = vc5_hdmi_phy_rng_enable, 1593 + .phy_rng_disable = vc5_hdmi_phy_rng_disable, 1594 + .channel_map = vc5_hdmi_channel_map, 1595 + }; 1596 + 1597 + static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = { 1598 + .encoder_type = VC4_ENCODER_TYPE_HDMI1, 1599 + .debugfs_name = "hdmi1_regs", 1600 + .card_name = "vc4-hdmi-1", 1601 + .max_pixel_clock = 297000000, 1602 + .registers = vc5_hdmi_hdmi1_fields, 1603 + .num_registers = ARRAY_SIZE(vc5_hdmi_hdmi1_fields), 1604 + .phy_lane_mapping = { 1605 + PHY_LANE_1, 1606 + PHY_LANE_0, 1607 + PHY_LANE_CK, 1608 + PHY_LANE_2, 1609 + }, 1610 + 1611 + .init_resources = vc5_hdmi_init_resources, 1612 + .csc_setup = vc5_hdmi_csc_setup, 1613 + .reset = vc5_hdmi_reset, 1614 + .set_timings = vc5_hdmi_set_timings, 1615 + .phy_init = vc5_hdmi_phy_init, 1616 + .phy_disable = vc5_hdmi_phy_disable, 1617 + .phy_rng_enable = vc5_hdmi_phy_rng_enable, 1618 + .phy_rng_disable = vc5_hdmi_phy_rng_disable, 1619 + .channel_map = vc5_hdmi_channel_map, 1620 + }; 1621 + 1804 1622 static const struct of_device_id vc4_hdmi_dt_match[] = { 1805 1623 { .compatible = "brcm,bcm2835-hdmi", .data = &bcm2835_variant }, 1624 + { .compatible = "brcm,bcm2711-hdmi0", .data = &bcm2711_hdmi0_variant }, 1625 + { .compatible = "brcm,bcm2711-hdmi1", .data = &bcm2711_hdmi1_variant }, 1806 1626 {} 1807 1627 }; 1808 1628
+36
drivers/gpu/drm/vc4/vc4_hdmi.h
··· 26 26 struct vc4_hdmi; 27 27 struct vc4_hdmi_register; 28 28 29 + enum vc4_hdmi_phy_channel { 30 + PHY_LANE_0 = 0, 31 + PHY_LANE_1, 32 + PHY_LANE_2, 33 + PHY_LANE_CK, 34 + }; 35 + 29 36 struct vc4_hdmi_variant { 30 37 /* Encoder Type for that controller */ 31 38 enum vc4_encoder_type encoder_type; ··· 54 47 55 48 /* Number of registers on that variant */ 56 49 unsigned int num_registers; 50 + 51 + /* BCM2711 Only. 52 + * The variants don't map the lane in the same order in the 53 + * PHY, so this is an array mapping the HDMI channel (index) 54 + * to the PHY lane (value). 55 + */ 56 + enum vc4_hdmi_phy_channel phy_lane_mapping[4]; 57 57 58 58 /* Callback to get the resources (memory region, interrupts, 59 59 * clocks, etc) for that variant. ··· 122 108 struct i2c_adapter *ddc; 123 109 void __iomem *hdmicore_regs; 124 110 void __iomem *hd_regs; 111 + 112 + /* VC5 Only */ 113 + void __iomem *cec_regs; 114 + /* VC5 Only */ 115 + void __iomem *csc_regs; 116 + /* VC5 Only */ 117 + void __iomem *dvp_regs; 118 + /* VC5 Only */ 119 + void __iomem *phy_regs; 120 + /* VC5 Only */ 121 + void __iomem *ram_regs; 122 + /* VC5 Only */ 123 + void __iomem *rm_regs; 124 + 125 125 int hpd_gpio; 126 126 bool hpd_active_low; 127 127 ··· 148 120 struct clk *hsm_clock; 149 121 struct clk *audio_clock; 150 122 struct clk *pixel_bvb_clock; 123 + 124 + struct reset_control *reset; 151 125 152 126 struct debugfs_regset32 hdmi_regset; 153 127 struct debugfs_regset32 hd_regset; ··· 174 144 void vc4_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); 175 145 void vc4_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); 176 146 void vc4_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); 147 + 148 + void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, 149 + struct drm_display_mode *mode); 150 + void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi); 151 + void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi); 152 + void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi); 177 153 178 154 #endif /* _VC4_HDMI_H_ */
+481
drivers/gpu/drm/vc4/vc4_hdmi_phy.c
··· 10 10 #include "vc4_regs.h" 11 11 #include "vc4_hdmi_regs.h" 12 12 13 + #define VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB BIT(5) 14 + #define VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB BIT(4) 15 + #define VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET BIT(3) 16 + #define VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET BIT(2) 17 + #define VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET BIT(1) 18 + #define VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET BIT(0) 19 + 20 + #define VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN BIT(4) 21 + 22 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_SHIFT 29 23 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP_MASK VC4_MASK(31, 29) 24 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_SHIFT 24 25 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV_MASK VC4_MASK(28, 24) 26 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_SHIFT 21 27 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP_MASK VC4_MASK(23, 21) 28 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_SHIFT 16 29 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV_MASK VC4_MASK(20, 16) 30 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_SHIFT 13 31 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP_MASK VC4_MASK(15, 13) 32 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_SHIFT 8 33 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV_MASK VC4_MASK(12, 8) 34 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_SHIFT 5 35 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP_MASK VC4_MASK(7, 5) 36 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_SHIFT 0 37 + #define VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV_MASK VC4_MASK(4, 0) 38 + 39 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_SHIFT 15 40 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2_MASK VC4_MASK(19, 15) 41 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_SHIFT 10 42 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1_MASK VC4_MASK(14, 10) 43 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_SHIFT 5 44 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0_MASK VC4_MASK(9, 5) 45 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_SHIFT 0 46 + #define VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK_MASK VC4_MASK(4, 0) 47 + 48 + #define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_SHIFT 16 49 + #define VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN_MASK VC4_MASK(19, 16) 50 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_SHIFT 12 51 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2_MASK VC4_MASK(15, 12) 52 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_SHIFT 8 53 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1_MASK VC4_MASK(11, 8) 54 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_SHIFT 4 55 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0_MASK VC4_MASK(7, 4) 56 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_SHIFT 0 57 + #define VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK_MASK VC4_MASK(3, 0) 58 + 59 + #define VC4_HDMI_TX_PHY_CTL_3_RP_SHIFT 17 60 + #define VC4_HDMI_TX_PHY_CTL_3_RP_MASK VC4_MASK(19, 17) 61 + #define VC4_HDMI_TX_PHY_CTL_3_RZ_SHIFT 12 62 + #define VC4_HDMI_TX_PHY_CTL_3_RZ_MASK VC4_MASK(16, 12) 63 + #define VC4_HDMI_TX_PHY_CTL_3_CP1_SHIFT 10 64 + #define VC4_HDMI_TX_PHY_CTL_3_CP1_MASK VC4_MASK(11, 10) 65 + #define VC4_HDMI_TX_PHY_CTL_3_CP_SHIFT 8 66 + #define VC4_HDMI_TX_PHY_CTL_3_CP_MASK VC4_MASK(9, 8) 67 + #define VC4_HDMI_TX_PHY_CTL_3_CZ_SHIFT 6 68 + #define VC4_HDMI_TX_PHY_CTL_3_CZ_MASK VC4_MASK(7, 6) 69 + #define VC4_HDMI_TX_PHY_CTL_3_ICP_SHIFT 0 70 + #define VC4_HDMI_TX_PHY_CTL_3_ICP_MASK VC4_MASK(5, 0) 71 + 72 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE BIT(13) 73 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_VC_RANGE_EN BIT(12) 74 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_LOW BIT(11) 75 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_EMULATE_VC_HIGH BIT(10) 76 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_SHIFT 9 77 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL_MASK VC4_MASK(9, 9) 78 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_FB_DIV2 BIT(8) 79 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_POST_DIV2 BIT(7) 80 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN BIT(6) 81 + #define VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK BIT(5) 82 + 83 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_SHIFT 16 84 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_CPP_MASK VC4_MASK(27, 16) 85 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_SHIFT 14 86 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY_MASK VC4_MASK(15, 14) 87 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE BIT(13) 88 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_SHIFT 11 89 + #define VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL_MASK VC4_MASK(12, 11) 90 + 91 + #define VC4_HDMI_TX_PHY_CLK_DIV_VCO_SHIFT 8 92 + #define VC4_HDMI_TX_PHY_CLK_DIV_VCO_MASK VC4_MASK(15, 8) 93 + 94 + #define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_SHIFT 0 95 + #define VC4_HDMI_TX_PHY_PLL_CFG_PDIV_MASK VC4_MASK(3, 0) 96 + 97 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_MASK VC4_MASK(13, 12) 98 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL_SHIFT 12 99 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_MASK VC4_MASK(9, 8) 100 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL_SHIFT 8 101 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_MASK VC4_MASK(5, 4) 102 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL_SHIFT 4 103 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_MASK VC4_MASK(1, 0) 104 + #define VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL_SHIFT 0 105 + 106 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK VC4_MASK(27, 0) 107 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_SHIFT 0 108 + 109 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK VC4_MASK(27, 0) 110 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_SHIFT 0 111 + 112 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_MASK VC4_MASK(31, 16) 113 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD_SHIFT 16 114 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_MASK VC4_MASK(15, 0) 115 + #define VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD_SHIFT 0 116 + 117 + #define VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS BIT(19) 118 + #define VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR BIT(17) 119 + #define VC4_HDMI_RM_CONTROL_FREE_RUN BIT(4) 120 + 121 + #define VC4_HDMI_RM_OFFSET_ONLY BIT(31) 122 + #define VC4_HDMI_RM_OFFSET_OFFSET_SHIFT 0 123 + #define VC4_HDMI_RM_OFFSET_OFFSET_MASK VC4_MASK(30, 0) 124 + 125 + #define VC4_HDMI_RM_FORMAT_SHIFT_SHIFT 24 126 + #define VC4_HDMI_RM_FORMAT_SHIFT_MASK VC4_MASK(25, 24) 127 + 128 + #define OSCILLATOR_FREQUENCY 54000000 129 + 13 130 void vc4_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) 14 131 { 15 132 /* PHY should be in reset, like ··· 154 37 HDMI_WRITE(HDMI_TX_PHY_CTL_0, 155 38 HDMI_READ(HDMI_TX_PHY_CTL_0) | 156 39 VC4_HDMI_TX_PHY_RNG_PWRDN); 40 + } 41 + 42 + static unsigned long long 43 + phy_get_vco_freq(unsigned long long clock, u8 *vco_sel, u8 *vco_div) 44 + { 45 + unsigned long long vco_freq = clock; 46 + unsigned int _vco_div = 0; 47 + unsigned int _vco_sel = 0; 48 + 49 + while (vco_freq < 3000000000ULL) { 50 + _vco_div++; 51 + vco_freq = clock * _vco_div * 10; 52 + } 53 + 54 + if (vco_freq > 4500000000ULL) 55 + _vco_sel = 1; 56 + 57 + *vco_sel = _vco_sel; 58 + *vco_div = _vco_div; 59 + 60 + return vco_freq; 61 + } 62 + 63 + static u8 phy_get_cp_current(unsigned long vco_freq) 64 + { 65 + if (vco_freq < 3700000000ULL) 66 + return 0x1c; 67 + 68 + return 0x18; 69 + } 70 + 71 + static u32 phy_get_rm_offset(unsigned long long vco_freq) 72 + { 73 + unsigned long long fref = OSCILLATOR_FREQUENCY; 74 + u64 offset = 0; 75 + 76 + /* RM offset is stored as 9.22 format */ 77 + offset = vco_freq * 2; 78 + offset = offset << 22; 79 + do_div(offset, fref); 80 + offset >>= 2; 81 + 82 + return offset; 83 + } 84 + 85 + static u8 phy_get_vco_gain(unsigned long long vco_freq) 86 + { 87 + if (vco_freq < 3350000000ULL) 88 + return 0xf; 89 + 90 + if (vco_freq < 3700000000ULL) 91 + return 0xc; 92 + 93 + if (vco_freq < 4050000000ULL) 94 + return 0x6; 95 + 96 + if (vco_freq < 4800000000ULL) 97 + return 0x5; 98 + 99 + if (vco_freq < 5200000000ULL) 100 + return 0x7; 101 + 102 + return 0x2; 103 + } 104 + 105 + struct phy_lane_settings { 106 + struct { 107 + u8 preemphasis; 108 + u8 main_driver; 109 + } amplitude; 110 + 111 + u8 res_sel_data; 112 + u8 term_res_sel_data; 113 + }; 114 + 115 + struct phy_settings { 116 + unsigned long long min_rate; 117 + unsigned long long max_rate; 118 + struct phy_lane_settings channel[3]; 119 + struct phy_lane_settings clock; 120 + }; 121 + 122 + static const struct phy_settings vc5_hdmi_phy_settings[] = { 123 + { 124 + 0, 50000000, 125 + { 126 + {{0x0, 0x0A}, 0x12, 0x0}, 127 + {{0x0, 0x0A}, 0x12, 0x0}, 128 + {{0x0, 0x0A}, 0x12, 0x0} 129 + }, 130 + {{0x0, 0x0A}, 0x18, 0x0}, 131 + }, 132 + { 133 + 50000001, 75000000, 134 + { 135 + {{0x0, 0x09}, 0x12, 0x0}, 136 + {{0x0, 0x09}, 0x12, 0x0}, 137 + {{0x0, 0x09}, 0x12, 0x0} 138 + }, 139 + {{0x0, 0x0C}, 0x18, 0x3}, 140 + }, 141 + { 142 + 75000001, 165000000, 143 + { 144 + {{0x0, 0x09}, 0x12, 0x0}, 145 + {{0x0, 0x09}, 0x12, 0x0}, 146 + {{0x0, 0x09}, 0x12, 0x0} 147 + }, 148 + {{0x0, 0x0C}, 0x18, 0x3}, 149 + }, 150 + { 151 + 165000001, 250000000, 152 + { 153 + {{0x0, 0x0F}, 0x12, 0x1}, 154 + {{0x0, 0x0F}, 0x12, 0x1}, 155 + {{0x0, 0x0F}, 0x12, 0x1} 156 + }, 157 + {{0x0, 0x0C}, 0x18, 0x3}, 158 + }, 159 + { 160 + 250000001, 340000000, 161 + { 162 + {{0x2, 0x0D}, 0x12, 0x1}, 163 + {{0x2, 0x0D}, 0x12, 0x1}, 164 + {{0x2, 0x0D}, 0x12, 0x1} 165 + }, 166 + {{0x0, 0x0C}, 0x18, 0xF}, 167 + }, 168 + { 169 + 340000001, 450000000, 170 + { 171 + {{0x0, 0x1B}, 0x12, 0xF}, 172 + {{0x0, 0x1B}, 0x12, 0xF}, 173 + {{0x0, 0x1B}, 0x12, 0xF} 174 + }, 175 + {{0x0, 0x0A}, 0x12, 0xF}, 176 + }, 177 + { 178 + 450000001, 600000000, 179 + { 180 + {{0x0, 0x1C}, 0x12, 0xF}, 181 + {{0x0, 0x1C}, 0x12, 0xF}, 182 + {{0x0, 0x1C}, 0x12, 0xF} 183 + }, 184 + {{0x0, 0x0B}, 0x13, 0xF}, 185 + }, 186 + }; 187 + 188 + static const struct phy_settings *phy_get_settings(unsigned long long tmds_rate) 189 + { 190 + unsigned int count = ARRAY_SIZE(vc5_hdmi_phy_settings); 191 + unsigned int i; 192 + 193 + for (i = 0; i < count; i++) { 194 + const struct phy_settings *s = &vc5_hdmi_phy_settings[i]; 195 + 196 + if (tmds_rate >= s->min_rate && tmds_rate <= s->max_rate) 197 + return s; 198 + } 199 + 200 + /* 201 + * If the pixel clock exceeds our max setting, try the max 202 + * setting anyway. 203 + */ 204 + return &vc5_hdmi_phy_settings[count - 1]; 205 + } 206 + 207 + static const struct phy_lane_settings * 208 + phy_get_channel_settings(enum vc4_hdmi_phy_channel chan, 209 + unsigned long long tmds_rate) 210 + { 211 + const struct phy_settings *settings = phy_get_settings(tmds_rate); 212 + 213 + if (chan == PHY_LANE_CK) 214 + return &settings->clock; 215 + 216 + return &settings->channel[chan]; 217 + } 218 + 219 + static void vc5_hdmi_reset_phy(struct vc4_hdmi *vc4_hdmi) 220 + { 221 + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 0x0f); 222 + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, BIT(10)); 223 + } 224 + 225 + void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, struct drm_display_mode *mode) 226 + { 227 + const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings; 228 + const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; 229 + unsigned long long pixel_freq = mode->clock * 1000; 230 + unsigned long long vco_freq; 231 + unsigned char word_sel; 232 + u8 vco_sel, vco_div; 233 + 234 + vco_freq = phy_get_vco_freq(pixel_freq, &vco_sel, &vco_div); 235 + 236 + vc5_hdmi_reset_phy(vc4_hdmi); 237 + 238 + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, 239 + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); 240 + 241 + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 242 + HDMI_READ(HDMI_TX_PHY_RESET_CTL) & 243 + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_0_RESET & 244 + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_1_RESET & 245 + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_2_RESET & 246 + ~VC4_HDMI_TX_PHY_RESET_CTL_TX_CK_RESET); 247 + 248 + HDMI_WRITE(HDMI_RM_CONTROL, 249 + HDMI_READ(HDMI_RM_CONTROL) | 250 + VC4_HDMI_RM_CONTROL_EN_FREEZE_COUNTERS | 251 + VC4_HDMI_RM_CONTROL_EN_LOAD_INTEGRATOR | 252 + VC4_HDMI_RM_CONTROL_FREE_RUN); 253 + 254 + HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 255 + (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1) & 256 + ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT_MASK) | 257 + VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1_MIN_LIMIT)); 258 + 259 + HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 260 + (HDMI_READ(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2) & 261 + ~VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT_MASK) | 262 + VC4_SET_FIELD(0, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2_MAX_LIMIT)); 263 + 264 + HDMI_WRITE(HDMI_RM_OFFSET, 265 + VC4_SET_FIELD(phy_get_rm_offset(vco_freq), 266 + VC4_HDMI_RM_OFFSET_OFFSET) | 267 + VC4_HDMI_RM_OFFSET_ONLY); 268 + 269 + HDMI_WRITE(HDMI_TX_PHY_CLK_DIV, 270 + VC4_SET_FIELD(vco_div, VC4_HDMI_TX_PHY_CLK_DIV_VCO)); 271 + 272 + HDMI_WRITE(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 273 + VC4_SET_FIELD(0xe147, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_HOLD_THRESHOLD) | 274 + VC4_SET_FIELD(0xe14, VC4_HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4_STABLE_THRESHOLD)); 275 + 276 + HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_0, 277 + VC4_HDMI_TX_PHY_PLL_CTL_0_ENA_VCO_CLK | 278 + VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_CONT_EN | 279 + VC4_HDMI_TX_PHY_PLL_CTL_0_MASH11_MODE | 280 + VC4_SET_FIELD(vco_sel, VC4_HDMI_TX_PHY_PLL_CTL_0_VCO_SEL)); 281 + 282 + HDMI_WRITE(HDMI_TX_PHY_PLL_CTL_1, 283 + HDMI_READ(HDMI_TX_PHY_PLL_CTL_1) | 284 + VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_ENABLE | 285 + VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_PLL_CTL_1_POST_RST_SEL) | 286 + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CTL_1_FREQ_DOUBLER_DELAY) | 287 + VC4_SET_FIELD(0x8a, VC4_HDMI_TX_PHY_PLL_CTL_1_CPP)); 288 + 289 + HDMI_WRITE(HDMI_RM_FORMAT, 290 + HDMI_READ(HDMI_RM_FORMAT) | 291 + VC4_SET_FIELD(2, VC4_HDMI_RM_FORMAT_SHIFT)); 292 + 293 + HDMI_WRITE(HDMI_TX_PHY_PLL_CFG, 294 + HDMI_READ(HDMI_TX_PHY_PLL_CFG) | 295 + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_PLL_CFG_PDIV)); 296 + 297 + if (pixel_freq >= 340000000) 298 + word_sel = 3; 299 + else 300 + word_sel = 0; 301 + HDMI_WRITE(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, word_sel); 302 + 303 + HDMI_WRITE(HDMI_TX_PHY_CTL_3, 304 + VC4_SET_FIELD(phy_get_cp_current(vco_freq), 305 + VC4_HDMI_TX_PHY_CTL_3_ICP) | 306 + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP) | 307 + VC4_SET_FIELD(1, VC4_HDMI_TX_PHY_CTL_3_CP1) | 308 + VC4_SET_FIELD(3, VC4_HDMI_TX_PHY_CTL_3_CZ) | 309 + VC4_SET_FIELD(4, VC4_HDMI_TX_PHY_CTL_3_RP) | 310 + VC4_SET_FIELD(6, VC4_HDMI_TX_PHY_CTL_3_RZ)); 311 + 312 + chan0_settings = 313 + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_0], 314 + pixel_freq); 315 + chan1_settings = 316 + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_1], 317 + pixel_freq); 318 + chan2_settings = 319 + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_2], 320 + pixel_freq); 321 + clock_settings = 322 + phy_get_channel_settings(variant->phy_lane_mapping[PHY_LANE_CK], 323 + pixel_freq); 324 + 325 + HDMI_WRITE(HDMI_TX_PHY_CTL_0, 326 + VC4_SET_FIELD(chan0_settings->amplitude.preemphasis, 327 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_PREEMP) | 328 + VC4_SET_FIELD(chan0_settings->amplitude.main_driver, 329 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_0_MAINDRV) | 330 + VC4_SET_FIELD(chan1_settings->amplitude.preemphasis, 331 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_PREEMP) | 332 + VC4_SET_FIELD(chan1_settings->amplitude.main_driver, 333 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_1_MAINDRV) | 334 + VC4_SET_FIELD(chan2_settings->amplitude.preemphasis, 335 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_PREEMP) | 336 + VC4_SET_FIELD(chan2_settings->amplitude.main_driver, 337 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_2_MAINDRV) | 338 + VC4_SET_FIELD(clock_settings->amplitude.preemphasis, 339 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_PREEMP) | 340 + VC4_SET_FIELD(clock_settings->amplitude.main_driver, 341 + VC4_HDMI_TX_PHY_CTL_0_PREEMP_CK_MAINDRV)); 342 + 343 + HDMI_WRITE(HDMI_TX_PHY_CTL_1, 344 + HDMI_READ(HDMI_TX_PHY_CTL_1) | 345 + VC4_SET_FIELD(chan0_settings->res_sel_data, 346 + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA0) | 347 + VC4_SET_FIELD(chan1_settings->res_sel_data, 348 + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA1) | 349 + VC4_SET_FIELD(chan2_settings->res_sel_data, 350 + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_DATA2) | 351 + VC4_SET_FIELD(clock_settings->res_sel_data, 352 + VC4_HDMI_TX_PHY_CTL_1_RES_SEL_CK)); 353 + 354 + HDMI_WRITE(HDMI_TX_PHY_CTL_2, 355 + VC4_SET_FIELD(chan0_settings->term_res_sel_data, 356 + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA0) | 357 + VC4_SET_FIELD(chan1_settings->term_res_sel_data, 358 + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA1) | 359 + VC4_SET_FIELD(chan2_settings->term_res_sel_data, 360 + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELDATA2) | 361 + VC4_SET_FIELD(clock_settings->term_res_sel_data, 362 + VC4_HDMI_TX_PHY_CTL_2_TERM_RES_SELCK) | 363 + VC4_SET_FIELD(phy_get_vco_gain(vco_freq), 364 + VC4_HDMI_TX_PHY_CTL_2_VCO_GAIN)); 365 + 366 + HDMI_WRITE(HDMI_TX_PHY_CHANNEL_SWAP, 367 + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_0], 368 + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX0_OUT_SEL) | 369 + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_1], 370 + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX1_OUT_SEL) | 371 + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_2], 372 + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TX2_OUT_SEL) | 373 + VC4_SET_FIELD(variant->phy_lane_mapping[PHY_LANE_CK], 374 + VC4_HDMI_TX_PHY_CHANNEL_SWAP_TXCK_OUT_SEL)); 375 + 376 + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 377 + HDMI_READ(HDMI_TX_PHY_RESET_CTL) & 378 + ~(VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB | 379 + VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB)); 380 + 381 + HDMI_WRITE(HDMI_TX_PHY_RESET_CTL, 382 + HDMI_READ(HDMI_TX_PHY_RESET_CTL) | 383 + VC4_HDMI_TX_PHY_RESET_CTL_PLL_RESETB | 384 + VC4_HDMI_TX_PHY_RESET_CTL_PLLDIV_RESETB); 385 + } 386 + 387 + void vc5_hdmi_phy_disable(struct vc4_hdmi *vc4_hdmi) 388 + { 389 + vc5_hdmi_reset_phy(vc4_hdmi); 390 + } 391 + 392 + void vc5_hdmi_phy_rng_enable(struct vc4_hdmi *vc4_hdmi) 393 + { 394 + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, 395 + HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) & 396 + ~VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); 397 + } 398 + 399 + void vc5_hdmi_phy_rng_disable(struct vc4_hdmi *vc4_hdmi) 400 + { 401 + HDMI_WRITE(HDMI_TX_PHY_POWERDOWN_CTL, 402 + HDMI_READ(HDMI_TX_PHY_POWERDOWN_CTL) | 403 + VC4_HDMI_TX_PHY_POWERDOWN_CTL_RNDGEN_PWRDN); 157 404 }
+201
drivers/gpu/drm/vc4/vc4_hdmi_regs.h
··· 9 9 VC4_INVALID = 0, 10 10 VC4_HDMI, 11 11 VC4_HD, 12 + VC5_CEC, 13 + VC5_CSC, 14 + VC5_DVP, 15 + VC5_PHY, 16 + VC5_RAM, 17 + VC5_RM, 12 18 }; 13 19 14 20 enum vc4_hdmi_field { ··· 42 36 HDMI_CEC_TX_DATA_2, 43 37 HDMI_CEC_TX_DATA_3, 44 38 HDMI_CEC_TX_DATA_4, 39 + HDMI_CLOCK_STOP, 45 40 HDMI_CORE_REV, 46 41 HDMI_CRP_CFG, 47 42 HDMI_CSC_12_11, ··· 59 52 */ 60 53 HDMI_CTS_0, 61 54 HDMI_CTS_1, 55 + HDMI_DVP_CTL, 62 56 HDMI_FIFO_CTL, 63 57 HDMI_FRAME_COUNT, 64 58 HDMI_HORZA, ··· 92 84 HDMI_RAM_PACKET_CONFIG, 93 85 HDMI_RAM_PACKET_START, 94 86 HDMI_RAM_PACKET_STATUS, 87 + HDMI_RM_CONTROL, 88 + HDMI_RM_FORMAT, 89 + HDMI_RM_OFFSET, 95 90 HDMI_SCHEDULER_CONTROL, 96 91 HDMI_SW_RESET_CONTROL, 92 + HDMI_TX_PHY_CHANNEL_SWAP, 93 + HDMI_TX_PHY_CLK_DIV, 97 94 HDMI_TX_PHY_CTL_0, 95 + HDMI_TX_PHY_CTL_1, 96 + HDMI_TX_PHY_CTL_2, 97 + HDMI_TX_PHY_CTL_3, 98 + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 99 + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 100 + HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 101 + HDMI_TX_PHY_PLL_CFG, 102 + HDMI_TX_PHY_PLL_CTL_0, 103 + HDMI_TX_PHY_PLL_CTL_1, 104 + HDMI_TX_PHY_POWERDOWN_CTL, 98 105 HDMI_TX_PHY_RESET_CTL, 106 + HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 107 + HDMI_VEC_INTERFACE_XBAR, 99 108 HDMI_VERTA0, 100 109 HDMI_VERTA1, 101 110 HDMI_VERTB0, ··· 135 110 136 111 #define VC4_HD_REG(reg, offset) _VC4_REG(VC4_HD, reg, offset) 137 112 #define VC4_HDMI_REG(reg, offset) _VC4_REG(VC4_HDMI, reg, offset) 113 + #define VC5_CEC_REG(reg, offset) _VC4_REG(VC5_CEC, reg, offset) 114 + #define VC5_CSC_REG(reg, offset) _VC4_REG(VC5_CSC, reg, offset) 115 + #define VC5_DVP_REG(reg, offset) _VC4_REG(VC5_DVP, reg, offset) 116 + #define VC5_PHY_REG(reg, offset) _VC4_REG(VC5_PHY, reg, offset) 117 + #define VC5_RAM_REG(reg, offset) _VC4_REG(VC5_RAM, reg, offset) 118 + #define VC5_RM_REG(reg, offset) _VC4_REG(VC5_RM, reg, offset) 138 119 139 120 static const struct vc4_hdmi_register vc4_hdmi_fields[] = { 140 121 VC4_HD_REG(HDMI_M_CTL, 0x000c), ··· 203 172 VC4_HDMI_REG(HDMI_RAM_PACKET_START, 0x0400), 204 173 }; 205 174 175 + static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = { 176 + VC4_HD_REG(HDMI_DVP_CTL, 0x0000), 177 + VC4_HD_REG(HDMI_MAI_CTL, 0x0010), 178 + VC4_HD_REG(HDMI_MAI_THR, 0x0014), 179 + VC4_HD_REG(HDMI_MAI_FMT, 0x0018), 180 + VC4_HD_REG(HDMI_MAI_DATA, 0x001c), 181 + VC4_HD_REG(HDMI_MAI_SMP, 0x0020), 182 + VC4_HD_REG(HDMI_VID_CTL, 0x0044), 183 + VC4_HD_REG(HDMI_FRAME_COUNT, 0x0060), 184 + 185 + VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074), 186 + VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8), 187 + VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc), 188 + VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4), 189 + VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8), 190 + VC4_HDMI_REG(HDMI_CTS_0, 0x0cc), 191 + VC4_HDMI_REG(HDMI_CTS_1, 0x0d0), 192 + VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0), 193 + VC4_HDMI_REG(HDMI_HORZA, 0x0e4), 194 + VC4_HDMI_REG(HDMI_HORZB, 0x0e8), 195 + VC4_HDMI_REG(HDMI_VERTA0, 0x0ec), 196 + VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), 197 + VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), 198 + VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), 199 + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), 200 + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), 201 + VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8), 202 + 203 + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), 204 + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), 205 + 206 + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), 207 + VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004), 208 + VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), 209 + VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), 210 + VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), 211 + VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014), 212 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c), 213 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020), 214 + VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028), 215 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034), 216 + VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044), 217 + VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c), 218 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050), 219 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054), 220 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c), 221 + 222 + VC5_RM_REG(HDMI_RM_CONTROL, 0x000), 223 + VC5_RM_REG(HDMI_RM_OFFSET, 0x018), 224 + VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), 225 + 226 + VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), 227 + 228 + VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), 229 + VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), 230 + VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), 231 + VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), 232 + VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), 233 + VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), 234 + VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), 235 + VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), 236 + VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), 237 + VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), 238 + VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), 239 + VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), 240 + VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), 241 + 242 + VC5_CSC_REG(HDMI_CSC_CTL, 0x000), 243 + VC5_CSC_REG(HDMI_CSC_12_11, 0x004), 244 + VC5_CSC_REG(HDMI_CSC_14_13, 0x008), 245 + VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), 246 + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), 247 + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), 248 + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), 249 + }; 250 + 251 + static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = { 252 + VC4_HD_REG(HDMI_DVP_CTL, 0x0000), 253 + VC4_HD_REG(HDMI_MAI_CTL, 0x0030), 254 + VC4_HD_REG(HDMI_MAI_THR, 0x0034), 255 + VC4_HD_REG(HDMI_MAI_FMT, 0x0038), 256 + VC4_HD_REG(HDMI_MAI_DATA, 0x003c), 257 + VC4_HD_REG(HDMI_MAI_SMP, 0x0040), 258 + VC4_HD_REG(HDMI_VID_CTL, 0x0048), 259 + VC4_HD_REG(HDMI_FRAME_COUNT, 0x0064), 260 + 261 + VC4_HDMI_REG(HDMI_FIFO_CTL, 0x074), 262 + VC4_HDMI_REG(HDMI_AUDIO_PACKET_CONFIG, 0x0b8), 263 + VC4_HDMI_REG(HDMI_RAM_PACKET_CONFIG, 0x0bc), 264 + VC4_HDMI_REG(HDMI_RAM_PACKET_STATUS, 0x0c4), 265 + VC4_HDMI_REG(HDMI_CRP_CFG, 0x0c8), 266 + VC4_HDMI_REG(HDMI_CTS_0, 0x0cc), 267 + VC4_HDMI_REG(HDMI_CTS_1, 0x0d0), 268 + VC4_HDMI_REG(HDMI_SCHEDULER_CONTROL, 0x0e0), 269 + VC4_HDMI_REG(HDMI_HORZA, 0x0e4), 270 + VC4_HDMI_REG(HDMI_HORZB, 0x0e8), 271 + VC4_HDMI_REG(HDMI_VERTA0, 0x0ec), 272 + VC4_HDMI_REG(HDMI_VERTB0, 0x0f0), 273 + VC4_HDMI_REG(HDMI_VERTA1, 0x0f4), 274 + VC4_HDMI_REG(HDMI_VERTB1, 0x0f8), 275 + VC4_HDMI_REG(HDMI_MAI_CHANNEL_MAP, 0x09c), 276 + VC4_HDMI_REG(HDMI_MAI_CONFIG, 0x0a0), 277 + VC4_HDMI_REG(HDMI_HOTPLUG, 0x1a8), 278 + 279 + VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), 280 + VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), 281 + 282 + VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), 283 + VC5_PHY_REG(HDMI_TX_PHY_POWERDOWN_CTL, 0x004), 284 + VC5_PHY_REG(HDMI_TX_PHY_CTL_0, 0x008), 285 + VC5_PHY_REG(HDMI_TX_PHY_CTL_1, 0x00c), 286 + VC5_PHY_REG(HDMI_TX_PHY_CTL_2, 0x010), 287 + VC5_PHY_REG(HDMI_TX_PHY_CTL_3, 0x014), 288 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_0, 0x01c), 289 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CTL_1, 0x020), 290 + VC5_PHY_REG(HDMI_TX_PHY_CLK_DIV, 0x028), 291 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CFG, 0x034), 292 + VC5_PHY_REG(HDMI_TX_PHY_CHANNEL_SWAP, 0x04c), 293 + VC5_PHY_REG(HDMI_TX_PHY_TMDS_CLK_WORD_SEL, 0x044), 294 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_1, 0x050), 295 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_2, 0x054), 296 + VC5_PHY_REG(HDMI_TX_PHY_PLL_CALIBRATION_CONFIG_4, 0x05c), 297 + 298 + VC5_RM_REG(HDMI_RM_CONTROL, 0x000), 299 + VC5_RM_REG(HDMI_RM_OFFSET, 0x018), 300 + VC5_RM_REG(HDMI_RM_FORMAT, 0x01c), 301 + 302 + VC5_RAM_REG(HDMI_RAM_PACKET_START, 0x000), 303 + 304 + VC5_CEC_REG(HDMI_CEC_CNTRL_1, 0x010), 305 + VC5_CEC_REG(HDMI_CEC_CNTRL_2, 0x014), 306 + VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018), 307 + VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c), 308 + VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020), 309 + VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028), 310 + VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c), 311 + VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030), 312 + VC5_CEC_REG(HDMI_CEC_TX_DATA_4, 0x034), 313 + VC5_CEC_REG(HDMI_CEC_RX_DATA_1, 0x038), 314 + VC5_CEC_REG(HDMI_CEC_RX_DATA_2, 0x03c), 315 + VC5_CEC_REG(HDMI_CEC_RX_DATA_3, 0x040), 316 + VC5_CEC_REG(HDMI_CEC_RX_DATA_4, 0x044), 317 + 318 + VC5_CSC_REG(HDMI_CSC_CTL, 0x000), 319 + VC5_CSC_REG(HDMI_CSC_12_11, 0x004), 320 + VC5_CSC_REG(HDMI_CSC_14_13, 0x008), 321 + VC5_CSC_REG(HDMI_CSC_22_21, 0x00c), 322 + VC5_CSC_REG(HDMI_CSC_24_23, 0x010), 323 + VC5_CSC_REG(HDMI_CSC_32_31, 0x014), 324 + VC5_CSC_REG(HDMI_CSC_34_33, 0x018), 325 + }; 326 + 206 327 static inline 207 328 void __iomem *__vc4_hdmi_get_field_base(struct vc4_hdmi *hdmi, 208 329 enum vc4_hdmi_regs reg) ··· 365 182 366 183 case VC4_HDMI: 367 184 return hdmi->hdmicore_regs; 185 + 186 + case VC5_CSC: 187 + return hdmi->csc_regs; 188 + 189 + case VC5_CEC: 190 + return hdmi->cec_regs; 191 + 192 + case VC5_DVP: 193 + return hdmi->dvp_regs; 194 + 195 + case VC5_PHY: 196 + return hdmi->phy_regs; 197 + 198 + case VC5_RAM: 199 + return hdmi->ram_regs; 200 + 201 + case VC5_RM: 202 + return hdmi->rm_regs; 368 203 369 204 default: 370 205 return NULL;
+2
drivers/gpu/drm/vc4/vc4_regs.h
··· 744 744 # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) 745 745 # define VC4_HD_CSC_CTL_ENABLE BIT(0) 746 746 747 + # define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1) 748 + 747 749 /* HVS display list information. */ 748 750 #define HVS_BOOTLOADER_DLIST_END 32 749 751