1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2013 Red Hat |
4 | * Author: Rob Clark <robdclark@gmail.com> |
5 | */ |
6 | |
7 | #include <linux/delay.h> |
8 | |
9 | #include "hdmi.h" |
10 | |
11 | static void hdmi_phy_8x60_powerup(struct hdmi_phy *phy, |
12 | unsigned long int pixclock) |
13 | { |
14 | /* De-serializer delay D/C for non-lbk mode: */ |
15 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG0, |
16 | data: HDMI_8x60_PHY_REG0_DESER_DEL_CTRL(val: 3)); |
17 | |
18 | if (pixclock == 27000000) { |
19 | /* video_format == HDMI_VFRMT_720x480p60_16_9 */ |
20 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG1, |
21 | data: HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(val: 5) | |
22 | HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(val: 3)); |
23 | } else { |
24 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG1, |
25 | data: HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(val: 5) | |
26 | HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(val: 4)); |
27 | } |
28 | |
29 | /* No matter what, start from the power down mode: */ |
30 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
31 | HDMI_8x60_PHY_REG2_PD_PWRGEN | |
32 | HDMI_8x60_PHY_REG2_PD_PLL | |
33 | HDMI_8x60_PHY_REG2_PD_DRIVE_4 | |
34 | HDMI_8x60_PHY_REG2_PD_DRIVE_3 | |
35 | HDMI_8x60_PHY_REG2_PD_DRIVE_2 | |
36 | HDMI_8x60_PHY_REG2_PD_DRIVE_1 | |
37 | HDMI_8x60_PHY_REG2_PD_DESER); |
38 | |
39 | /* Turn PowerGen on: */ |
40 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
41 | HDMI_8x60_PHY_REG2_PD_PLL | |
42 | HDMI_8x60_PHY_REG2_PD_DRIVE_4 | |
43 | HDMI_8x60_PHY_REG2_PD_DRIVE_3 | |
44 | HDMI_8x60_PHY_REG2_PD_DRIVE_2 | |
45 | HDMI_8x60_PHY_REG2_PD_DRIVE_1 | |
46 | HDMI_8x60_PHY_REG2_PD_DESER); |
47 | |
48 | /* Turn PLL power on: */ |
49 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
50 | HDMI_8x60_PHY_REG2_PD_DRIVE_4 | |
51 | HDMI_8x60_PHY_REG2_PD_DRIVE_3 | |
52 | HDMI_8x60_PHY_REG2_PD_DRIVE_2 | |
53 | HDMI_8x60_PHY_REG2_PD_DRIVE_1 | |
54 | HDMI_8x60_PHY_REG2_PD_DESER); |
55 | |
56 | /* Write to HIGH after PLL power down de-assert: */ |
57 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG3, |
58 | HDMI_8x60_PHY_REG3_PLL_ENABLE); |
59 | |
60 | /* ASIC power on; PHY REG9 = 0 */ |
61 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG9, data: 0); |
62 | |
63 | /* Enable PLL lock detect, PLL lock det will go high after lock |
64 | * Enable the re-time logic |
65 | */ |
66 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG12, |
67 | HDMI_8x60_PHY_REG12_RETIMING_EN | |
68 | HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN); |
69 | |
70 | /* Drivers are on: */ |
71 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
72 | HDMI_8x60_PHY_REG2_PD_DESER); |
73 | |
74 | /* If the RX detector is needed: */ |
75 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
76 | HDMI_8x60_PHY_REG2_RCV_SENSE_EN | |
77 | HDMI_8x60_PHY_REG2_PD_DESER); |
78 | |
79 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG4, data: 0); |
80 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG5, data: 0); |
81 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG6, data: 0); |
82 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG7, data: 0); |
83 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG8, data: 0); |
84 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG9, data: 0); |
85 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG10, data: 0); |
86 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG11, data: 0); |
87 | |
88 | /* If we want to use lock enable based on counting: */ |
89 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG12, |
90 | HDMI_8x60_PHY_REG12_RETIMING_EN | |
91 | HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN | |
92 | HDMI_8x60_PHY_REG12_FORCE_LOCK); |
93 | } |
94 | |
95 | static void hdmi_phy_8x60_powerdown(struct hdmi_phy *phy) |
96 | { |
97 | /* Assert RESET PHY from controller */ |
98 | hdmi_phy_write(phy, REG_HDMI_PHY_CTRL, |
99 | HDMI_PHY_CTRL_SW_RESET); |
100 | udelay(10); |
101 | /* De-assert RESET PHY from controller */ |
102 | hdmi_phy_write(phy, REG_HDMI_PHY_CTRL, data: 0); |
103 | /* Turn off Driver */ |
104 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
105 | HDMI_8x60_PHY_REG2_PD_DRIVE_4 | |
106 | HDMI_8x60_PHY_REG2_PD_DRIVE_3 | |
107 | HDMI_8x60_PHY_REG2_PD_DRIVE_2 | |
108 | HDMI_8x60_PHY_REG2_PD_DRIVE_1 | |
109 | HDMI_8x60_PHY_REG2_PD_DESER); |
110 | udelay(10); |
111 | /* Disable PLL */ |
112 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG3, data: 0); |
113 | /* Power down PHY, but keep RX-sense: */ |
114 | hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, |
115 | HDMI_8x60_PHY_REG2_RCV_SENSE_EN | |
116 | HDMI_8x60_PHY_REG2_PD_PWRGEN | |
117 | HDMI_8x60_PHY_REG2_PD_PLL | |
118 | HDMI_8x60_PHY_REG2_PD_DRIVE_4 | |
119 | HDMI_8x60_PHY_REG2_PD_DRIVE_3 | |
120 | HDMI_8x60_PHY_REG2_PD_DRIVE_2 | |
121 | HDMI_8x60_PHY_REG2_PD_DRIVE_1 | |
122 | HDMI_8x60_PHY_REG2_PD_DESER); |
123 | } |
124 | |
125 | static const char * const hdmi_phy_8x60_reg_names[] = { |
126 | "core-vdda" , |
127 | }; |
128 | |
129 | static const char * const hdmi_phy_8x60_clk_names[] = { |
130 | "slave_iface" , |
131 | }; |
132 | |
133 | const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg = { |
134 | .type = MSM_HDMI_PHY_8x60, |
135 | .powerup = hdmi_phy_8x60_powerup, |
136 | .powerdown = hdmi_phy_8x60_powerdown, |
137 | .reg_names = hdmi_phy_8x60_reg_names, |
138 | .num_regs = ARRAY_SIZE(hdmi_phy_8x60_reg_names), |
139 | .clk_names = hdmi_phy_8x60_clk_names, |
140 | .num_clks = ARRAY_SIZE(hdmi_phy_8x60_clk_names), |
141 | }; |
142 | |