Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
c1577c1e AT |
2 | /* |
3 | * HDMI PLL | |
4 | * | |
1b409fda | 5 | * Copyright (C) 2013 Texas Instruments Incorporated - https://www.ti.com/ |
c1577c1e AT |
6 | */ |
7 | ||
ac9f2421 TV |
8 | #define DSS_SUBSYS_NAME "HDMIPLL" |
9 | ||
c1577c1e AT |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> | |
c1577c1e AT |
12 | #include <linux/err.h> |
13 | #include <linux/io.h> | |
14 | #include <linux/platform_device.h> | |
c84c3a5b | 15 | #include <linux/clk.h> |
2d802453 | 16 | #include <linux/seq_file.h> |
86c9305c | 17 | #include <linux/pm_runtime.h> |
c84c3a5b | 18 | |
32043da7 | 19 | #include "omapdss.h" |
c1577c1e | 20 | #include "dss.h" |
ef26958a | 21 | #include "hdmi.h" |
c1577c1e | 22 | |
c1577c1e AT |
23 | void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) |
24 | { | |
25 | #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ | |
26 | hdmi_read_reg(pll->base, r)) | |
27 | ||
28 | DUMPPLL(PLLCTRL_PLL_CONTROL); | |
29 | DUMPPLL(PLLCTRL_PLL_STATUS); | |
30 | DUMPPLL(PLLCTRL_PLL_GO); | |
31 | DUMPPLL(PLLCTRL_CFG1); | |
32 | DUMPPLL(PLLCTRL_CFG2); | |
33 | DUMPPLL(PLLCTRL_CFG3); | |
34 | DUMPPLL(PLLCTRL_SSC_CFG1); | |
35 | DUMPPLL(PLLCTRL_SSC_CFG2); | |
36 | DUMPPLL(PLLCTRL_CFG4); | |
37 | } | |
38 | ||
c84c3a5b | 39 | static int hdmi_pll_enable(struct dss_pll *dsspll) |
c1577c1e | 40 | { |
c84c3a5b | 41 | struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll); |
03aafa2c | 42 | struct hdmi_wp_data *wp = pll->wp; |
f7dd8f52 | 43 | int r; |
c1577c1e | 44 | |
86c9305c TV |
45 | r = pm_runtime_get_sync(&pll->pdev->dev); |
46 | WARN_ON(r < 0); | |
c1577c1e | 47 | |
27260999 | 48 | dss_ctrl_pll_enable(dsspll, true); |
adb5ff83 | 49 | |
c1577c1e AT |
50 | r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); |
51 | if (r) | |
52 | return r; | |
53 | ||
c1577c1e AT |
54 | return 0; |
55 | } | |
56 | ||
c84c3a5b | 57 | static void hdmi_pll_disable(struct dss_pll *dsspll) |
c1577c1e | 58 | { |
c84c3a5b | 59 | struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll); |
03aafa2c | 60 | struct hdmi_wp_data *wp = pll->wp; |
86c9305c | 61 | int r; |
03aafa2c | 62 | |
c1577c1e | 63 | hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); |
adb5ff83 | 64 | |
27260999 | 65 | dss_ctrl_pll_enable(dsspll, false); |
86c9305c TV |
66 | |
67 | r = pm_runtime_put_sync(&pll->pdev->dev); | |
68 | WARN_ON(r < 0 && r != -ENOSYS); | |
c1577c1e AT |
69 | } |
70 | ||
1fdf9041 | 71 | static const struct dss_pll_ops hdmi_pll_ops = { |
c84c3a5b TV |
72 | .enable = hdmi_pll_enable, |
73 | .disable = hdmi_pll_disable, | |
74 | .set_config = dss_pll_write_config_type_b, | |
75 | }; | |
76 | ||
77 | static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = { | |
06ede3dd TV |
78 | .type = DSS_PLL_TYPE_B, |
79 | ||
c84c3a5b TV |
80 | .n_max = 255, |
81 | .m_min = 20, | |
82 | .m_max = 4095, | |
83 | .mX_max = 127, | |
84 | .fint_min = 500000, | |
85 | .fint_max = 2500000, | |
c84c3a5b TV |
86 | |
87 | .clkdco_min = 500000000, | |
88 | .clkdco_low = 1000000000, | |
89 | .clkdco_max = 2000000000, | |
90 | ||
91 | .n_msb = 8, | |
92 | .n_lsb = 1, | |
93 | .m_msb = 20, | |
94 | .m_lsb = 9, | |
95 | ||
96 | .mX_msb[0] = 24, | |
97 | .mX_lsb[0] = 18, | |
98 | ||
99 | .has_selfreqdco = true, | |
2d64b1b3 AT |
100 | }; |
101 | ||
c84c3a5b | 102 | static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = { |
06ede3dd TV |
103 | .type = DSS_PLL_TYPE_B, |
104 | ||
c84c3a5b TV |
105 | .n_max = 255, |
106 | .m_min = 20, | |
107 | .m_max = 2045, | |
108 | .mX_max = 127, | |
109 | .fint_min = 620000, | |
110 | .fint_max = 2500000, | |
c84c3a5b TV |
111 | |
112 | .clkdco_min = 750000000, | |
113 | .clkdco_low = 1500000000, | |
114 | .clkdco_max = 2500000000UL, | |
115 | ||
116 | .n_msb = 8, | |
117 | .n_lsb = 1, | |
118 | .m_msb = 20, | |
119 | .m_lsb = 9, | |
120 | ||
121 | .mX_msb[0] = 24, | |
122 | .mX_lsb[0] = 18, | |
123 | ||
124 | .has_selfreqdco = true, | |
125 | .has_refsel = true, | |
2d64b1b3 AT |
126 | }; |
127 | ||
7b295257 LP |
128 | static int hdmi_init_pll_data(struct dss_device *dss, |
129 | struct platform_device *pdev, | |
1fdf9041 | 130 | struct hdmi_pll_data *hpll) |
2d64b1b3 | 131 | { |
c84c3a5b TV |
132 | struct dss_pll *pll = &hpll->pll; |
133 | struct clk *clk; | |
134 | int r; | |
2d64b1b3 | 135 | |
c84c3a5b TV |
136 | clk = devm_clk_get(&pdev->dev, "sys_clk"); |
137 | if (IS_ERR(clk)) { | |
138 | DSSERR("can't get sys_clk\n"); | |
139 | return PTR_ERR(clk); | |
2d64b1b3 AT |
140 | } |
141 | ||
c84c3a5b | 142 | pll->name = "hdmi"; |
64e22ffd | 143 | pll->id = DSS_PLL_HDMI; |
c84c3a5b TV |
144 | pll->base = hpll->base; |
145 | pll->clkin = clk; | |
146 | ||
ba63b635 | 147 | if (hpll->wp->version == 4) |
c84c3a5b | 148 | pll->hw = &dss_omap4_hdmi_pll_hw; |
ba63b635 | 149 | else |
c84c3a5b | 150 | pll->hw = &dss_omap5_hdmi_pll_hw; |
2d64b1b3 | 151 | |
1fdf9041 | 152 | pll->ops = &hdmi_pll_ops; |
c84c3a5b | 153 | |
798957ae | 154 | r = dss_pll_register(dss, pll); |
c84c3a5b TV |
155 | if (r) |
156 | return r; | |
2d64b1b3 AT |
157 | |
158 | return 0; | |
159 | } | |
160 | ||
7b295257 LP |
161 | int hdmi_pll_init(struct dss_device *dss, struct platform_device *pdev, |
162 | struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) | |
c1577c1e | 163 | { |
2d64b1b3 | 164 | int r; |
c1577c1e | 165 | |
86c9305c | 166 | pll->pdev = pdev; |
03aafa2c TV |
167 | pll->wp = wp; |
168 | ||
ed8414ab | 169 | pll->base = devm_platform_ioremap_resource_byname(pdev, "pll"); |
b22622f0 | 170 | if (IS_ERR(pll->base)) |
2b22df83 | 171 | return PTR_ERR(pll->base); |
c1577c1e | 172 | |
7b295257 | 173 | r = hdmi_init_pll_data(dss, pdev, pll); |
c84c3a5b TV |
174 | if (r) { |
175 | DSSERR("failed to init HDMI PLL\n"); | |
176 | return r; | |
177 | } | |
178 | ||
c1577c1e AT |
179 | return 0; |
180 | } | |
c84c3a5b TV |
181 | |
182 | void hdmi_pll_uninit(struct hdmi_pll_data *hpll) | |
183 | { | |
184 | struct dss_pll *pll = &hpll->pll; | |
185 | ||
186 | dss_pll_unregister(pll); | |
187 | } |