diff options
Diffstat (limited to 'drivers/video/fbdev/omap2/dss/hdmi_pll.c')
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi_pll.c | 107 |
1 files changed, 83 insertions, 24 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c index 5fc71215c303..54df12a8d744 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) |
@@ -194,38 +210,81 @@ void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) | |||
194 | hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); | 210 | hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); |
195 | } | 211 | } |
196 | 212 | ||
197 | #define PLL_OFFSET 0x200 | 213 | static const struct hdmi_pll_features omap44xx_pll_feats = { |
198 | #define PLL_SIZE 0x100 | 214 | .sys_reset = false, |
215 | .bound_dcofreq = false, | ||
216 | .fint_min = 500000, | ||
217 | .fint_max = 2500000, | ||
218 | .regm_max = 4095, | ||
219 | .dcofreq_low_min = 500000000, | ||
220 | .dcofreq_low_max = 1000000000, | ||
221 | .dcofreq_high_min = 1000000000, | ||
222 | .dcofreq_high_max = 2000000000, | ||
223 | }; | ||
224 | |||
225 | static const struct hdmi_pll_features omap54xx_pll_feats = { | ||
226 | .sys_reset = true, | ||
227 | .bound_dcofreq = true, | ||
228 | .fint_min = 620000, | ||
229 | .fint_max = 2500000, | ||
230 | .regm_max = 2046, | ||
231 | .dcofreq_low_min = 750000000, | ||
232 | .dcofreq_low_max = 1500000000, | ||
233 | .dcofreq_high_min = 1250000000, | ||
234 | .dcofreq_high_max = 2500000000UL, | ||
235 | }; | ||
236 | |||
237 | static int hdmi_pll_init_features(struct platform_device *pdev) | ||
238 | { | ||
239 | struct hdmi_pll_features *dst; | ||
240 | const struct hdmi_pll_features *src; | ||
241 | |||
242 | dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); | ||
243 | if (!dst) { | ||
244 | dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n"); | ||
245 | return -ENOMEM; | ||
246 | } | ||
247 | |||
248 | switch (omapdss_get_version()) { | ||
249 | case OMAPDSS_VER_OMAP4430_ES1: | ||
250 | case OMAPDSS_VER_OMAP4430_ES2: | ||
251 | case OMAPDSS_VER_OMAP4: | ||
252 | src = &omap44xx_pll_feats; | ||
253 | break; | ||
254 | |||
255 | case OMAPDSS_VER_OMAP5: | ||
256 | src = &omap54xx_pll_feats; | ||
257 | break; | ||
258 | |||
259 | default: | ||
260 | return -ENODEV; | ||
261 | } | ||
262 | |||
263 | memcpy(dst, src, sizeof(*dst)); | ||
264 | pll_feat = dst; | ||
265 | |||
266 | return 0; | ||
267 | } | ||
199 | 268 | ||
200 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) | 269 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) |
201 | { | 270 | { |
271 | int r; | ||
202 | struct resource *res; | 272 | struct resource *res; |
203 | struct resource temp_res; | 273 | |
274 | r = hdmi_pll_init_features(pdev); | ||
275 | if (r) | ||
276 | return r; | ||
204 | 277 | ||
205 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); | 278 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); |
206 | if (!res) { | 279 | if (!res) { |
207 | DSSDBG("can't get PLL mem resource by name\n"); | 280 | DSSERR("can't get PLL mem resource\n"); |
208 | /* | 281 | return -EINVAL; |
209 | * if hwmod/DT doesn't have the memory resource information | ||
210 | * split into HDMI sub blocks by name, we try again by getting | ||
211 | * the platform's first resource. this code will be removed when | ||
212 | * the driver can get the mem resources by name | ||
213 | */ | ||
214 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
215 | if (!res) { | ||
216 | DSSERR("can't get PLL mem resource\n"); | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | |||
220 | temp_res.start = res->start + PLL_OFFSET; | ||
221 | temp_res.end = temp_res.start + PLL_SIZE - 1; | ||
222 | res = &temp_res; | ||
223 | } | 282 | } |
224 | 283 | ||
225 | pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | 284 | pll->base = devm_ioremap_resource(&pdev->dev, res); |
226 | if (!pll->base) { | 285 | if (IS_ERR(pll->base)) { |
227 | DSSERR("can't ioremap PLLCTRL\n"); | 286 | DSSERR("can't ioremap PLLCTRL\n"); |
228 | return -ENOMEM; | 287 | return PTR_ERR(pll->base); |
229 | } | 288 | } |
230 | 289 | ||
231 | return 0; | 290 | return 0; |