diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi_pll.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c index 5fc71215c303..2b910cb9eee4 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c +++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c | |||
@@ -23,6 +23,18 @@ | |||
23 | #define HDMI_DEFAULT_REGN 16 | 23 | #define HDMI_DEFAULT_REGN 16 |
24 | #define HDMI_DEFAULT_REGM2 1 | 24 | #define HDMI_DEFAULT_REGM2 1 |
25 | 25 | ||
26 | struct hdmi_pll_features { | ||
27 | bool sys_reset; | ||
28 | /* this is a hack, need to replace it with a better computation of M2 */ | ||
29 | bool bound_dcofreq; | ||
30 | unsigned long fint_min, fint_max; | ||
31 | u16 regm_max; | ||
32 | unsigned long dcofreq_low_min, dcofreq_low_max; | ||
33 | unsigned long dcofreq_high_min, dcofreq_high_max; | ||
34 | }; | ||
35 | |||
36 | static const struct hdmi_pll_features *pll_feat; | ||
37 | |||
26 | void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) | 38 | void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) |
27 | { | 39 | { |
28 | #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ | 40 | #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ |
@@ -57,7 +69,11 @@ void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy) | |||
57 | 69 | ||
58 | refclk = clkin / pi->regn; | 70 | refclk = clkin / pi->regn; |
59 | 71 | ||
60 | pi->regm2 = HDMI_DEFAULT_REGM2; | 72 | /* temorary hack to make sure DCO freq isn't calculated too low */ |
73 | if (pll_feat->bound_dcofreq && phy <= 65000) | ||
74 | pi->regm2 = 3; | ||
75 | else | ||
76 | pi->regm2 = HDMI_DEFAULT_REGM2; | ||
61 | 77 | ||
62 | /* | 78 | /* |
63 | * multiplier is pixel_clk/ref_clk | 79 | * multiplier is pixel_clk/ref_clk |
@@ -154,7 +170,7 @@ static int hdmi_pll_config(struct hdmi_pll_data *pll) | |||
154 | static int hdmi_pll_reset(struct hdmi_pll_data *pll) | 170 | static int hdmi_pll_reset(struct hdmi_pll_data *pll) |
155 | { | 171 | { |
156 | /* SYSRESET controlled by power FSM */ | 172 | /* SYSRESET controlled by power FSM */ |
157 | REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | 173 | REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, pll_feat->sys_reset, 3, 3); |
158 | 174 | ||
159 | /* READ 0x0 reset is in progress */ | 175 | /* READ 0x0 reset is in progress */ |
160 | if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1) | 176 | if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1) |
@@ -197,11 +213,72 @@ void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) | |||
197 | #define PLL_OFFSET 0x200 | 213 | #define PLL_OFFSET 0x200 |
198 | #define PLL_SIZE 0x100 | 214 | #define PLL_SIZE 0x100 |
199 | 215 | ||
216 | static const struct hdmi_pll_features omap44xx_pll_feats = { | ||
217 | .sys_reset = false, | ||
218 | .bound_dcofreq = false, | ||
219 | .fint_min = 500000, | ||
220 | .fint_max = 2500000, | ||
221 | .regm_max = 4095, | ||
222 | .dcofreq_low_min = 500000000, | ||
223 | .dcofreq_low_max = 1000000000, | ||
224 | .dcofreq_high_min = 1000000000, | ||
225 | .dcofreq_high_max = 2000000000, | ||
226 | }; | ||
227 | |||
228 | static const struct hdmi_pll_features omap54xx_pll_feats = { | ||
229 | .sys_reset = true, | ||
230 | .bound_dcofreq = true, | ||
231 | .fint_min = 620000, | ||
232 | .fint_max = 2500000, | ||
233 | .regm_max = 2046, | ||
234 | .dcofreq_low_min = 750000000, | ||
235 | .dcofreq_low_max = 1500000000, | ||
236 | .dcofreq_high_min = 1250000000, | ||
237 | .dcofreq_high_max = 2500000000UL, | ||
238 | }; | ||
239 | |||
240 | static int hdmi_pll_init_features(struct platform_device *pdev) | ||
241 | { | ||
242 | struct hdmi_pll_features *dst; | ||
243 | const struct hdmi_pll_features *src; | ||
244 | |||
245 | dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); | ||
246 | if (!dst) { | ||
247 | dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n"); | ||
248 | return -ENOMEM; | ||
249 | } | ||
250 | |||
251 | switch (omapdss_get_version()) { | ||
252 | case OMAPDSS_VER_OMAP4430_ES1: | ||
253 | case OMAPDSS_VER_OMAP4430_ES2: | ||
254 | case OMAPDSS_VER_OMAP4: | ||
255 | src = &omap44xx_pll_feats; | ||
256 | break; | ||
257 | |||
258 | case OMAPDSS_VER_OMAP5: | ||
259 | src = &omap54xx_pll_feats; | ||
260 | break; | ||
261 | |||
262 | default: | ||
263 | return -ENODEV; | ||
264 | } | ||
265 | |||
266 | memcpy(dst, src, sizeof(*dst)); | ||
267 | pll_feat = dst; | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
200 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) | 272 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) |
201 | { | 273 | { |
274 | int r; | ||
202 | struct resource *res; | 275 | struct resource *res; |
203 | struct resource temp_res; | 276 | struct resource temp_res; |
204 | 277 | ||
278 | r = hdmi_pll_init_features(pdev); | ||
279 | if (r) | ||
280 | return r; | ||
281 | |||
205 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); | 282 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); |
206 | if (!res) { | 283 | if (!res) { |
207 | DSSDBG("can't get PLL mem resource by name\n"); | 284 | DSSDBG("can't get PLL mem resource by name\n"); |