aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2016-06-06 03:16:51 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2016-06-06 03:16:51 -0400
commitecf140dfc3fe169aaff8f5561d345f6b96d7b476 (patch)
tree5e360dedcb193a4b321abf427f1629a7c35a5bf0 /drivers/gpu/drm/omapdrm
parent449c5e9c33fd03625e12e3ed32b84bbbb9243d99 (diff)
parent31dca077056afd0a6089b9eaca1e4e485acc1ddc (diff)
Merge branch '4.8/omapdrm-pll' (omapdrm PLL work)
Merge omapdrm PLL work, which makes it possible to use the DSS PLLs in a versatile manner, for example, HDMI PLL can be used for LCDs.
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c91
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dpi.c133
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c55
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c252
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.h45
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss_features.c43
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss_features.h1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi.h3
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4.c6
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5.c6
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi_pll.c75
-rw-r--r--drivers/gpu/drm/omapdrm/dss/pll.c126
-rw-r--r--drivers/gpu/drm/omapdrm/dss/video-pll.c6
13 files changed, 494 insertions, 348 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index f83608b69e68..7b78da6d51cf 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -3299,30 +3299,21 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
3299 3299
3300static unsigned long dispc_fclk_rate(void) 3300static unsigned long dispc_fclk_rate(void)
3301{ 3301{
3302 struct dss_pll *pll; 3302 unsigned long r;
3303 unsigned long r = 0; 3303 enum dss_clk_source src;
3304
3305 src = dss_get_dispc_clk_source();
3304 3306
3305 switch (dss_get_dispc_clk_source()) { 3307 if (src == DSS_CLK_SRC_FCK) {
3306 case OMAP_DSS_CLK_SRC_FCK:
3307 r = dss_get_dispc_clk_rate(); 3308 r = dss_get_dispc_clk_rate();
3308 break; 3309 } else {
3309 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 3310 struct dss_pll *pll;
3310 pll = dss_pll_find("dsi0"); 3311 unsigned clkout_idx;
3311 if (!pll)
3312 pll = dss_pll_find("video0");
3313 3312
3314 r = pll->cinfo.clkout[0]; 3313 pll = dss_pll_find_by_src(src);
3315 break; 3314 clkout_idx = dss_pll_get_clkout_idx_for_src(src);
3316 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3317 pll = dss_pll_find("dsi1");
3318 if (!pll)
3319 pll = dss_pll_find("video1");
3320 3315
3321 r = pll->cinfo.clkout[0]; 3316 r = pll->cinfo.clkout[clkout_idx];
3322 break;
3323 default:
3324 BUG();
3325 return 0;
3326 } 3317 }
3327 3318
3328 return r; 3319 return r;
@@ -3330,43 +3321,31 @@ static unsigned long dispc_fclk_rate(void)
3330 3321
3331static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) 3322static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
3332{ 3323{
3333 struct dss_pll *pll;
3334 int lcd; 3324 int lcd;
3335 unsigned long r; 3325 unsigned long r;
3336 u32 l; 3326 enum dss_clk_source src;
3337 3327
3338 if (dss_mgr_is_lcd(channel)) { 3328 /* for TV, LCLK rate is the FCLK rate */
3339 l = dispc_read_reg(DISPC_DIVISORo(channel)); 3329 if (!dss_mgr_is_lcd(channel))
3340 3330 return dispc_fclk_rate();
3341 lcd = FLD_GET(l, 23, 16);
3342 3331
3343 switch (dss_get_lcd_clk_source(channel)) { 3332 src = dss_get_lcd_clk_source(channel);
3344 case OMAP_DSS_CLK_SRC_FCK:
3345 r = dss_get_dispc_clk_rate();
3346 break;
3347 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3348 pll = dss_pll_find("dsi0");
3349 if (!pll)
3350 pll = dss_pll_find("video0");
3351 3333
3352 r = pll->cinfo.clkout[0]; 3334 if (src == DSS_CLK_SRC_FCK) {
3353 break; 3335 r = dss_get_dispc_clk_rate();
3354 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 3336 } else {
3355 pll = dss_pll_find("dsi1"); 3337 struct dss_pll *pll;
3356 if (!pll) 3338 unsigned clkout_idx;
3357 pll = dss_pll_find("video1");
3358 3339
3359 r = pll->cinfo.clkout[0]; 3340 pll = dss_pll_find_by_src(src);
3360 break; 3341 clkout_idx = dss_pll_get_clkout_idx_for_src(src);
3361 default:
3362 BUG();
3363 return 0;
3364 }
3365 3342
3366 return r / lcd; 3343 r = pll->cinfo.clkout[clkout_idx];
3367 } else {
3368 return dispc_fclk_rate();
3369 } 3344 }
3345
3346 lcd = REG_GET(DISPC_DIVISORo(channel), 23, 16);
3347
3348 return r / lcd;
3370} 3349}
3371 3350
3372static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) 3351static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
@@ -3426,15 +3405,14 @@ static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3426static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3405static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
3427{ 3406{
3428 int lcd, pcd; 3407 int lcd, pcd;
3429 enum omap_dss_clk_source lcd_clk_src; 3408 enum dss_clk_source lcd_clk_src;
3430 3409
3431 seq_printf(s, "- %s -\n", mgr_desc[channel].name); 3410 seq_printf(s, "- %s -\n", mgr_desc[channel].name);
3432 3411
3433 lcd_clk_src = dss_get_lcd_clk_source(channel); 3412 lcd_clk_src = dss_get_lcd_clk_source(channel);
3434 3413
3435 seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name, 3414 seq_printf(s, "%s clk source = %s\n", mgr_desc[channel].name,
3436 dss_get_generic_clk_source_name(lcd_clk_src), 3415 dss_get_clk_source_name(lcd_clk_src));
3437 dss_feat_get_clk_source_name(lcd_clk_src));
3438 3416
3439 dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd); 3417 dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd);
3440 3418
@@ -3448,16 +3426,15 @@ void dispc_dump_clocks(struct seq_file *s)
3448{ 3426{
3449 int lcd; 3427 int lcd;
3450 u32 l; 3428 u32 l;
3451 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); 3429 enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
3452 3430
3453 if (dispc_runtime_get()) 3431 if (dispc_runtime_get())
3454 return; 3432 return;
3455 3433
3456 seq_printf(s, "- DISPC -\n"); 3434 seq_printf(s, "- DISPC -\n");
3457 3435
3458 seq_printf(s, "dispc fclk source = %s (%s)\n", 3436 seq_printf(s, "dispc fclk source = %s\n",
3459 dss_get_generic_clk_source_name(dispc_clk_src), 3437 dss_get_clk_source_name(dispc_clk_src));
3460 dss_feat_get_clk_source_name(dispc_clk_src));
3461 3438
3462 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); 3439 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
3463 3440
diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c
index 97ea60257884..db72b507384b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dpi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dpi.c
@@ -39,12 +39,11 @@
39#include "dss.h" 39#include "dss.h"
40#include "dss_features.h" 40#include "dss_features.h"
41 41
42#define HSDIV_DISPC 0
43
44struct dpi_data { 42struct dpi_data {
45 struct platform_device *pdev; 43 struct platform_device *pdev;
46 44
47 struct regulator *vdds_dsi_reg; 45 struct regulator *vdds_dsi_reg;
46 enum dss_clk_source clk_src;
48 struct dss_pll *pll; 47 struct dss_pll *pll;
49 48
50 struct mutex lock; 49 struct mutex lock;
@@ -69,7 +68,7 @@ static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
69 return dev_get_drvdata(&pdev->dev); 68 return dev_get_drvdata(&pdev->dev);
70} 69}
71 70
72static struct dss_pll *dpi_get_pll(enum omap_channel channel) 71static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel)
73{ 72{
74 /* 73 /*
75 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL 74 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
@@ -83,64 +82,51 @@ static struct dss_pll *dpi_get_pll(enum omap_channel channel)
83 case OMAPDSS_VER_OMAP3630: 82 case OMAPDSS_VER_OMAP3630:
84 case OMAPDSS_VER_AM35xx: 83 case OMAPDSS_VER_AM35xx:
85 case OMAPDSS_VER_AM43xx: 84 case OMAPDSS_VER_AM43xx:
86 return NULL; 85 return DSS_CLK_SRC_FCK;
87 86
88 case OMAPDSS_VER_OMAP4430_ES1: 87 case OMAPDSS_VER_OMAP4430_ES1:
89 case OMAPDSS_VER_OMAP4430_ES2: 88 case OMAPDSS_VER_OMAP4430_ES2:
90 case OMAPDSS_VER_OMAP4: 89 case OMAPDSS_VER_OMAP4:
91 switch (channel) { 90 switch (channel) {
92 case OMAP_DSS_CHANNEL_LCD: 91 case OMAP_DSS_CHANNEL_LCD:
93 return dss_pll_find("dsi0"); 92 return DSS_CLK_SRC_PLL1_1;
94 case OMAP_DSS_CHANNEL_LCD2: 93 case OMAP_DSS_CHANNEL_LCD2:
95 return dss_pll_find("dsi1"); 94 return DSS_CLK_SRC_PLL2_1;
96 default: 95 default:
97 return NULL; 96 return DSS_CLK_SRC_FCK;
98 } 97 }
99 98
100 case OMAPDSS_VER_OMAP5: 99 case OMAPDSS_VER_OMAP5:
101 switch (channel) { 100 switch (channel) {
102 case OMAP_DSS_CHANNEL_LCD: 101 case OMAP_DSS_CHANNEL_LCD:
103 return dss_pll_find("dsi0"); 102 return DSS_CLK_SRC_PLL1_1;
104 case OMAP_DSS_CHANNEL_LCD3: 103 case OMAP_DSS_CHANNEL_LCD3:
105 return dss_pll_find("dsi1"); 104 return DSS_CLK_SRC_PLL2_1;
105 case OMAP_DSS_CHANNEL_LCD2:
106 default: 106 default:
107 return NULL; 107 return DSS_CLK_SRC_FCK;
108 } 108 }
109 109
110 case OMAPDSS_VER_DRA7xx: 110 case OMAPDSS_VER_DRA7xx:
111 switch (channel) { 111 switch (channel) {
112 case OMAP_DSS_CHANNEL_LCD: 112 case OMAP_DSS_CHANNEL_LCD:
113 return DSS_CLK_SRC_PLL1_1;
113 case OMAP_DSS_CHANNEL_LCD2: 114 case OMAP_DSS_CHANNEL_LCD2:
114 return dss_pll_find("video0"); 115 return DSS_CLK_SRC_PLL1_3;
115 case OMAP_DSS_CHANNEL_LCD3: 116 case OMAP_DSS_CHANNEL_LCD3:
116 return dss_pll_find("video1"); 117 return DSS_CLK_SRC_PLL2_1;
117 default: 118 default:
118 return NULL; 119 return DSS_CLK_SRC_FCK;
119 } 120 }
120 121
121 default: 122 default:
122 return NULL; 123 return DSS_CLK_SRC_FCK;
123 }
124}
125
126static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
127{
128 switch (channel) {
129 case OMAP_DSS_CHANNEL_LCD:
130 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
131 case OMAP_DSS_CHANNEL_LCD2:
132 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
133 case OMAP_DSS_CHANNEL_LCD3:
134 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
135 default:
136 /* this shouldn't happen */
137 WARN_ON(1);
138 return OMAP_DSS_CLK_SRC_FCK;
139 } 124 }
140} 125}
141 126
142struct dpi_clk_calc_ctx { 127struct dpi_clk_calc_ctx {
143 struct dss_pll *pll; 128 struct dss_pll *pll;
129 unsigned clkout_idx;
144 130
145 /* inputs */ 131 /* inputs */
146 132
@@ -148,7 +134,7 @@ struct dpi_clk_calc_ctx {
148 134
149 /* outputs */ 135 /* outputs */
150 136
151 struct dss_pll_clock_info dsi_cinfo; 137 struct dss_pll_clock_info pll_cinfo;
152 unsigned long fck; 138 unsigned long fck;
153 struct dispc_clock_info dispc_cinfo; 139 struct dispc_clock_info dispc_cinfo;
154}; 140};
@@ -193,8 +179,8 @@ static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
193 if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000) 179 if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000)
194 return false; 180 return false;
195 181
196 ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc; 182 ctx->pll_cinfo.mX[ctx->clkout_idx] = m_dispc;
197 ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc; 183 ctx->pll_cinfo.clkout[ctx->clkout_idx] = dispc;
198 184
199 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, 185 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
200 dpi_calc_dispc_cb, ctx); 186 dpi_calc_dispc_cb, ctx);
@@ -207,12 +193,12 @@ static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
207{ 193{
208 struct dpi_clk_calc_ctx *ctx = data; 194 struct dpi_clk_calc_ctx *ctx = data;
209 195
210 ctx->dsi_cinfo.n = n; 196 ctx->pll_cinfo.n = n;
211 ctx->dsi_cinfo.m = m; 197 ctx->pll_cinfo.m = m;
212 ctx->dsi_cinfo.fint = fint; 198 ctx->pll_cinfo.fint = fint;
213 ctx->dsi_cinfo.clkdco = clkdco; 199 ctx->pll_cinfo.clkdco = clkdco;
214 200
215 return dss_pll_hsdiv_calc(ctx->pll, clkdco, 201 return dss_pll_hsdiv_calc_a(ctx->pll, clkdco,
216 ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), 202 ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
217 dpi_calc_hsdiv_cb, ctx); 203 dpi_calc_hsdiv_cb, ctx);
218} 204}
@@ -227,25 +213,39 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
227 dpi_calc_dispc_cb, ctx); 213 dpi_calc_dispc_cb, ctx);
228} 214}
229 215
230static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck, 216static bool dpi_pll_clk_calc(struct dpi_data *dpi, unsigned long pck,
231 struct dpi_clk_calc_ctx *ctx) 217 struct dpi_clk_calc_ctx *ctx)
232{ 218{
233 unsigned long clkin; 219 unsigned long clkin;
234 unsigned long pll_min, pll_max;
235 220
236 memset(ctx, 0, sizeof(*ctx)); 221 memset(ctx, 0, sizeof(*ctx));
237 ctx->pll = dpi->pll; 222 ctx->pll = dpi->pll;
238 ctx->pck_min = pck - 1000; 223 ctx->clkout_idx = dss_pll_get_clkout_idx_for_src(dpi->clk_src);
239 ctx->pck_max = pck + 1000;
240 224
241 pll_min = 0; 225 clkin = clk_get_rate(dpi->pll->clkin);
242 pll_max = 0;
243 226
244 clkin = clk_get_rate(ctx->pll->clkin); 227 if (dpi->pll->hw->type == DSS_PLL_TYPE_A) {
228 unsigned long pll_min, pll_max;
245 229
246 return dss_pll_calc(ctx->pll, clkin, 230 ctx->pck_min = pck - 1000;
247 pll_min, pll_max, 231 ctx->pck_max = pck + 1000;
248 dpi_calc_pll_cb, ctx); 232
233 pll_min = 0;
234 pll_max = 0;
235
236 return dss_pll_calc_a(ctx->pll, clkin,
237 pll_min, pll_max,
238 dpi_calc_pll_cb, ctx);
239 } else { /* DSS_PLL_TYPE_B */
240 dss_pll_calc_b(dpi->pll, clkin, pck, &ctx->pll_cinfo);
241
242 ctx->dispc_cinfo.lck_div = 1;
243 ctx->dispc_cinfo.pck_div = 1;
244 ctx->dispc_cinfo.lck = ctx->pll_cinfo.clkout[0];
245 ctx->dispc_cinfo.pck = ctx->dispc_cinfo.lck;
246
247 return true;
248 }
249} 249}
250 250
251static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) 251static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
@@ -279,7 +279,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
279 279
280 280
281 281
282static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel, 282static int dpi_set_pll_clk(struct dpi_data *dpi, enum omap_channel channel,
283 unsigned long pck_req, unsigned long *fck, int *lck_div, 283 unsigned long pck_req, unsigned long *fck, int *lck_div,
284 int *pck_div) 284 int *pck_div)
285{ 285{
@@ -287,20 +287,19 @@ static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
287 int r; 287 int r;
288 bool ok; 288 bool ok;
289 289
290 ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx); 290 ok = dpi_pll_clk_calc(dpi, pck_req, &ctx);
291 if (!ok) 291 if (!ok)
292 return -EINVAL; 292 return -EINVAL;
293 293
294 r = dss_pll_set_config(dpi->pll, &ctx.dsi_cinfo); 294 r = dss_pll_set_config(dpi->pll, &ctx.pll_cinfo);
295 if (r) 295 if (r)
296 return r; 296 return r;
297 297
298 dss_select_lcd_clk_source(channel, 298 dss_select_lcd_clk_source(channel, dpi->clk_src);
299 dpi_get_alt_clk_src(channel));
300 299
301 dpi->mgr_config.clock_info = ctx.dispc_cinfo; 300 dpi->mgr_config.clock_info = ctx.dispc_cinfo;
302 301
303 *fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC]; 302 *fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
304 *lck_div = ctx.dispc_cinfo.lck_div; 303 *lck_div = ctx.dispc_cinfo.lck_div;
305 *pck_div = ctx.dispc_cinfo.pck_div; 304 *pck_div = ctx.dispc_cinfo.pck_div;
306 305
@@ -342,7 +341,7 @@ static int dpi_set_mode(struct dpi_data *dpi)
342 int r = 0; 341 int r = 0;
343 342
344 if (dpi->pll) 343 if (dpi->pll)
345 r = dpi_set_dsi_clk(dpi, channel, t->pixelclock, &fck, 344 r = dpi_set_pll_clk(dpi, channel, t->pixelclock, &fck,
346 &lck_div, &pck_div); 345 &lck_div, &pck_div);
347 else 346 else
348 r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck, 347 r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
@@ -419,7 +418,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
419 if (dpi->pll) { 418 if (dpi->pll) {
420 r = dss_pll_enable(dpi->pll); 419 r = dss_pll_enable(dpi->pll);
421 if (r) 420 if (r)
422 goto err_dsi_pll_init; 421 goto err_pll_init;
423 } 422 }
424 423
425 r = dpi_set_mode(dpi); 424 r = dpi_set_mode(dpi);
@@ -442,7 +441,7 @@ err_mgr_enable:
442err_set_mode: 441err_set_mode:
443 if (dpi->pll) 442 if (dpi->pll)
444 dss_pll_disable(dpi->pll); 443 dss_pll_disable(dpi->pll);
445err_dsi_pll_init: 444err_pll_init:
446err_src_sel: 445err_src_sel:
447 dispc_runtime_put(); 446 dispc_runtime_put();
448err_get_dispc: 447err_get_dispc:
@@ -465,7 +464,7 @@ static void dpi_display_disable(struct omap_dss_device *dssdev)
465 dss_mgr_disable(channel); 464 dss_mgr_disable(channel);
466 465
467 if (dpi->pll) { 466 if (dpi->pll) {
468 dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK); 467 dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
469 dss_pll_disable(dpi->pll); 468 dss_pll_disable(dpi->pll);
470 } 469 }
471 470
@@ -524,11 +523,11 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
524 return -EINVAL; 523 return -EINVAL;
525 524
526 if (dpi->pll) { 525 if (dpi->pll) {
527 ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx); 526 ok = dpi_pll_clk_calc(dpi, timings->pixelclock, &ctx);
528 if (!ok) 527 if (!ok)
529 return -EINVAL; 528 return -EINVAL;
530 529
531 fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC]; 530 fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
532 } else { 531 } else {
533 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx); 532 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
534 if (!ok) 533 if (!ok)
@@ -558,7 +557,7 @@ static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
558 mutex_unlock(&dpi->lock); 557 mutex_unlock(&dpi->lock);
559} 558}
560 559
561static int dpi_verify_dsi_pll(struct dss_pll *pll) 560static int dpi_verify_pll(struct dss_pll *pll)
562{ 561{
563 int r; 562 int r;
564 563
@@ -602,16 +601,14 @@ static void dpi_init_pll(struct dpi_data *dpi)
602 if (dpi->pll) 601 if (dpi->pll)
603 return; 602 return;
604 603
605 pll = dpi_get_pll(dpi->output.dispc_channel); 604 dpi->clk_src = dpi_get_clk_src(dpi->output.dispc_channel);
605
606 pll = dss_pll_find_by_src(dpi->clk_src);
606 if (!pll) 607 if (!pll)
607 return; 608 return;
608 609
609 /* On DRA7 we need to set a mux to use the PLL */ 610 if (dpi_verify_pll(pll)) {
610 if (omapdss_get_version() == OMAPDSS_VER_DRA7xx) 611 DSSWARN("PLL not operational\n");
611 dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel);
612
613 if (dpi_verify_dsi_pll(pll)) {
614 DSSWARN("DSI PLL not operational\n");
615 return; 612 return;
616 } 613 }
617 614
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 9ed8272e54ae..0a634438ba3b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -1262,7 +1262,7 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1262 unsigned long r; 1262 unsigned long r;
1263 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1263 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1264 1264
1265 if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) { 1265 if (dss_get_dsi_clk_source(dsi->module_id) == DSS_CLK_SRC_FCK) {
1266 /* DSI FCLK source is DSS_CLK_FCK */ 1266 /* DSI FCLK source is DSS_CLK_FCK */
1267 r = clk_get_rate(dsi->dss_clk); 1267 r = clk_get_rate(dsi->dss_clk);
1268 } else { 1268 } else {
@@ -1475,7 +1475,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1475{ 1475{
1476 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1476 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1477 struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo; 1477 struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
1478 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; 1478 enum dss_clk_source dispc_clk_src, dsi_clk_src;
1479 int dsi_module = dsi->module_id; 1479 int dsi_module = dsi->module_id;
1480 struct dss_pll *pll = &dsi->pll; 1480 struct dss_pll *pll = &dsi->pll;
1481 1481
@@ -1495,28 +1495,27 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1495 cinfo->clkdco, cinfo->m); 1495 cinfo->clkdco, cinfo->m);
1496 1496
1497 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16lum_dispc %u\t(%s)\n", 1497 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16lum_dispc %u\t(%s)\n",
1498 dss_feat_get_clk_source_name(dsi_module == 0 ? 1498 dss_get_clk_source_name(dsi_module == 0 ?
1499 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : 1499 DSS_CLK_SRC_PLL1_1 :
1500 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC), 1500 DSS_CLK_SRC_PLL2_1),
1501 cinfo->clkout[HSDIV_DISPC], 1501 cinfo->clkout[HSDIV_DISPC],
1502 cinfo->mX[HSDIV_DISPC], 1502 cinfo->mX[HSDIV_DISPC],
1503 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1503 dispc_clk_src == DSS_CLK_SRC_FCK ?
1504 "off" : "on"); 1504 "off" : "on");
1505 1505
1506 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16lum_dsi %u\t(%s)\n", 1506 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16lum_dsi %u\t(%s)\n",
1507 dss_feat_get_clk_source_name(dsi_module == 0 ? 1507 dss_get_clk_source_name(dsi_module == 0 ?
1508 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : 1508 DSS_CLK_SRC_PLL1_2 :
1509 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI), 1509 DSS_CLK_SRC_PLL2_2),
1510 cinfo->clkout[HSDIV_DSI], 1510 cinfo->clkout[HSDIV_DSI],
1511 cinfo->mX[HSDIV_DSI], 1511 cinfo->mX[HSDIV_DSI],
1512 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1512 dsi_clk_src == DSS_CLK_SRC_FCK ?
1513 "off" : "on"); 1513 "off" : "on");
1514 1514
1515 seq_printf(s, "- DSI%d -\n", dsi_module + 1); 1515 seq_printf(s, "- DSI%d -\n", dsi_module + 1);
1516 1516
1517 seq_printf(s, "dsi fclk source = %s (%s)\n", 1517 seq_printf(s, "dsi fclk source = %s\n",
1518 dss_get_generic_clk_source_name(dsi_clk_src), 1518 dss_get_clk_source_name(dsi_clk_src));
1519 dss_feat_get_clk_source_name(dsi_clk_src));
1520 1519
1521 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev)); 1520 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
1522 1521
@@ -4102,8 +4101,8 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
4102 int r; 4101 int r;
4103 4102
4104 dss_select_lcd_clk_source(channel, dsi->module_id == 0 ? 4103 dss_select_lcd_clk_source(channel, dsi->module_id == 0 ?
4105 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : 4104 DSS_CLK_SRC_PLL1_1 :
4106 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC); 4105 DSS_CLK_SRC_PLL2_1);
4107 4106
4108 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4107 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4109 r = dss_mgr_register_framedone_handler(channel, 4108 r = dss_mgr_register_framedone_handler(channel,
@@ -4150,7 +4149,7 @@ err1:
4150 dss_mgr_unregister_framedone_handler(channel, 4149 dss_mgr_unregister_framedone_handler(channel,
4151 dsi_framedone_irq_callback, dsidev); 4150 dsi_framedone_irq_callback, dsidev);
4152err: 4151err:
4153 dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK); 4152 dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
4154 return r; 4153 return r;
4155} 4154}
4156 4155
@@ -4163,7 +4162,7 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
4163 dss_mgr_unregister_framedone_handler(channel, 4162 dss_mgr_unregister_framedone_handler(channel,
4164 dsi_framedone_irq_callback, dsidev); 4163 dsi_framedone_irq_callback, dsidev);
4165 4164
4166 dss_select_lcd_clk_source(channel, OMAP_DSS_CLK_SRC_FCK); 4165 dss_select_lcd_clk_source(channel, DSS_CLK_SRC_FCK);
4167} 4166}
4168 4167
4169static int dsi_configure_dsi_clocks(struct platform_device *dsidev) 4168static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
@@ -4197,8 +4196,8 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
4197 goto err1; 4196 goto err1;
4198 4197
4199 dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ? 4198 dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ?
4200 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : 4199 DSS_CLK_SRC_PLL1_2 :
4201 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI); 4200 DSS_CLK_SRC_PLL2_2);
4202 4201
4203 DSSDBG("PLL OK\n"); 4202 DSSDBG("PLL OK\n");
4204 4203
@@ -4230,7 +4229,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
4230err3: 4229err3:
4231 dsi_cio_uninit(dsidev); 4230 dsi_cio_uninit(dsidev);
4232err2: 4231err2:
4233 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4232 dss_select_dsi_clk_source(dsi->module_id, DSS_CLK_SRC_FCK);
4234err1: 4233err1:
4235 dss_pll_disable(&dsi->pll); 4234 dss_pll_disable(&dsi->pll);
4236err0: 4235err0:
@@ -4252,7 +4251,7 @@ static void dsi_display_uninit_dsi(struct platform_device *dsidev,
4252 dsi_vc_enable(dsidev, 2, 0); 4251 dsi_vc_enable(dsidev, 2, 0);
4253 dsi_vc_enable(dsidev, 3, 0); 4252 dsi_vc_enable(dsidev, 3, 0);
4254 4253
4255 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4254 dss_select_dsi_clk_source(dsi->module_id, DSS_CLK_SRC_FCK);
4256 dsi_cio_uninit(dsidev); 4255 dsi_cio_uninit(dsidev);
4257 dsi_pll_uninit(dsidev, disconnect_lanes); 4256 dsi_pll_uninit(dsidev, disconnect_lanes);
4258} 4257}
@@ -4453,7 +4452,7 @@ static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
4453 ctx->dsi_cinfo.fint = fint; 4452 ctx->dsi_cinfo.fint = fint;
4454 ctx->dsi_cinfo.clkdco = clkdco; 4453 ctx->dsi_cinfo.clkdco = clkdco;
4455 4454
4456 return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min, 4455 return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
4457 dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), 4456 dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
4458 dsi_cm_calc_hsdiv_cb, ctx); 4457 dsi_cm_calc_hsdiv_cb, ctx);
4459} 4458}
@@ -4492,7 +4491,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
4492 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4); 4491 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
4493 pll_max = cfg->hs_clk_max * 4; 4492 pll_max = cfg->hs_clk_max * 4;
4494 4493
4495 return dss_pll_calc(ctx->pll, clkin, 4494 return dss_pll_calc_a(ctx->pll, clkin,
4496 pll_min, pll_max, 4495 pll_min, pll_max,
4497 dsi_cm_calc_pll_cb, ctx); 4496 dsi_cm_calc_pll_cb, ctx);
4498} 4497}
@@ -4751,7 +4750,7 @@ static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
4751 ctx->dsi_cinfo.fint = fint; 4750 ctx->dsi_cinfo.fint = fint;
4752 ctx->dsi_cinfo.clkdco = clkdco; 4751 ctx->dsi_cinfo.clkdco = clkdco;
4753 4752
4754 return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min, 4753 return dss_pll_hsdiv_calc_a(ctx->pll, clkdco, ctx->req_pck_min,
4755 dss_feat_get_param_max(FEAT_PARAM_DSS_FCK), 4754 dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
4756 dsi_vm_calc_hsdiv_cb, ctx); 4755 dsi_vm_calc_hsdiv_cb, ctx);
4757} 4756}
@@ -4793,7 +4792,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
4793 pll_max = byteclk_max * 4 * 4; 4792 pll_max = byteclk_max * 4 * 4;
4794 } 4793 }
4795 4794
4796 return dss_pll_calc(ctx->pll, clkin, 4795 return dss_pll_calc_a(ctx->pll, clkin,
4797 pll_min, pll_max, 4796 pll_min, pll_max,
4798 dsi_vm_calc_pll_cb, ctx); 4797 dsi_vm_calc_pll_cb, ctx);
4799} 4798}
@@ -5139,6 +5138,8 @@ static const struct dss_pll_ops dsi_pll_ops = {
5139}; 5138};
5140 5139
5141static const struct dss_pll_hw dss_omap3_dsi_pll_hw = { 5140static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
5141 .type = DSS_PLL_TYPE_A,
5142
5142 .n_max = (1 << 7) - 1, 5143 .n_max = (1 << 7) - 1,
5143 .m_max = (1 << 11) - 1, 5144 .m_max = (1 << 11) - 1,
5144 .mX_max = (1 << 4) - 1, 5145 .mX_max = (1 << 4) - 1,
@@ -5164,6 +5165,8 @@ static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
5164}; 5165};
5165 5166
5166static const struct dss_pll_hw dss_omap4_dsi_pll_hw = { 5167static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
5168 .type = DSS_PLL_TYPE_A,
5169
5167 .n_max = (1 << 8) - 1, 5170 .n_max = (1 << 8) - 1,
5168 .m_max = (1 << 12) - 1, 5171 .m_max = (1 << 12) - 1,
5169 .mX_max = (1 << 5) - 1, 5172 .mX_max = (1 << 5) - 1,
@@ -5189,6 +5192,8 @@ static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
5189}; 5192};
5190 5193
5191static const struct dss_pll_hw dss_omap5_dsi_pll_hw = { 5194static const struct dss_pll_hw dss_omap5_dsi_pll_hw = {
5195 .type = DSS_PLL_TYPE_A,
5196
5192 .n_max = (1 << 8) - 1, 5197 .n_max = (1 << 8) - 1,
5193 .m_max = (1 << 12) - 1, 5198 .m_max = (1 << 12) - 1,
5194 .mX_max = (1 << 5) - 1, 5199 .mX_max = (1 << 5) - 1,
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 3303cfad4838..6ac54c35227e 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -76,6 +76,8 @@ struct dss_features {
76 const enum omap_display_type *ports; 76 const enum omap_display_type *ports;
77 int num_ports; 77 int num_ports;
78 int (*dpi_select_source)(int port, enum omap_channel channel); 78 int (*dpi_select_source)(int port, enum omap_channel channel);
79 int (*select_lcd_source)(enum omap_channel channel,
80 enum dss_clk_source clk_src);
79}; 81};
80 82
81static struct { 83static struct {
@@ -92,9 +94,9 @@ static struct {
92 unsigned long cache_prate; 94 unsigned long cache_prate;
93 struct dispc_clock_info cache_dispc_cinfo; 95 struct dispc_clock_info cache_dispc_cinfo;
94 96
95 enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; 97 enum dss_clk_source dsi_clk_source[MAX_NUM_DSI];
96 enum omap_dss_clk_source dispc_clk_source; 98 enum dss_clk_source dispc_clk_source;
97 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; 99 enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
98 100
99 bool ctx_valid; 101 bool ctx_valid;
100 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 102 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
@@ -106,11 +108,14 @@ static struct {
106} dss; 108} dss;
107 109
108static const char * const dss_generic_clk_source_names[] = { 110static const char * const dss_generic_clk_source_names[] = {
109 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", 111 [DSS_CLK_SRC_FCK] = "FCK",
110 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", 112 [DSS_CLK_SRC_PLL1_1] = "PLL1:1",
111 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 113 [DSS_CLK_SRC_PLL1_2] = "PLL1:2",
112 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC", 114 [DSS_CLK_SRC_PLL1_3] = "PLL1:3",
113 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI", 115 [DSS_CLK_SRC_PLL2_1] = "PLL2:1",
116 [DSS_CLK_SRC_PLL2_2] = "PLL2:2",
117 [DSS_CLK_SRC_PLL2_3] = "PLL2:3",
118 [DSS_CLK_SRC_HDMI_PLL] = "HDMI PLL",
114}; 119};
115 120
116static bool dss_initialized; 121static bool dss_initialized;
@@ -203,68 +208,70 @@ void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable)
203 1 << shift, val << shift); 208 1 << shift, val << shift);
204} 209}
205 210
206void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, 211static int dss_ctrl_pll_set_control_mux(enum dss_clk_source clk_src,
207 enum omap_channel channel) 212 enum omap_channel channel)
208{ 213{
209 unsigned shift, val; 214 unsigned shift, val;
210 215
211 if (!dss.syscon_pll_ctrl) 216 if (!dss.syscon_pll_ctrl)
212 return; 217 return -EINVAL;
213 218
214 switch (channel) { 219 switch (channel) {
215 case OMAP_DSS_CHANNEL_LCD: 220 case OMAP_DSS_CHANNEL_LCD:
216 shift = 3; 221 shift = 3;
217 222
218 switch (pll_id) { 223 switch (clk_src) {
219 case DSS_PLL_VIDEO1: 224 case DSS_CLK_SRC_PLL1_1:
220 val = 0; break; 225 val = 0; break;
221 case DSS_PLL_HDMI: 226 case DSS_CLK_SRC_HDMI_PLL:
222 val = 1; break; 227 val = 1; break;
223 default: 228 default:
224 DSSERR("error in PLL mux config for LCD\n"); 229 DSSERR("error in PLL mux config for LCD\n");
225 return; 230 return -EINVAL;
226 } 231 }
227 232
228 break; 233 break;
229 case OMAP_DSS_CHANNEL_LCD2: 234 case OMAP_DSS_CHANNEL_LCD2:
230 shift = 5; 235 shift = 5;
231 236
232 switch (pll_id) { 237 switch (clk_src) {
233 case DSS_PLL_VIDEO1: 238 case DSS_CLK_SRC_PLL1_3:
234 val = 0; break; 239 val = 0; break;
235 case DSS_PLL_VIDEO2: 240 case DSS_CLK_SRC_PLL2_3:
236 val = 1; break; 241 val = 1; break;
237 case DSS_PLL_HDMI: 242 case DSS_CLK_SRC_HDMI_PLL:
238 val = 2; break; 243 val = 2; break;
239 default: 244 default:
240 DSSERR("error in PLL mux config for LCD2\n"); 245 DSSERR("error in PLL mux config for LCD2\n");
241 return; 246 return -EINVAL;
242 } 247 }
243 248
244 break; 249 break;
245 case OMAP_DSS_CHANNEL_LCD3: 250 case OMAP_DSS_CHANNEL_LCD3:
246 shift = 7; 251 shift = 7;
247 252
248 switch (pll_id) { 253 switch (clk_src) {
249 case DSS_PLL_VIDEO1: 254 case DSS_CLK_SRC_PLL2_1:
250 val = 1; break;
251 case DSS_PLL_VIDEO2:
252 val = 0; break; 255 val = 0; break;
253 case DSS_PLL_HDMI: 256 case DSS_CLK_SRC_PLL1_3:
257 val = 1; break;
258 case DSS_CLK_SRC_HDMI_PLL:
254 val = 2; break; 259 val = 2; break;
255 default: 260 default:
256 DSSERR("error in PLL mux config for LCD3\n"); 261 DSSERR("error in PLL mux config for LCD3\n");
257 return; 262 return -EINVAL;
258 } 263 }
259 264
260 break; 265 break;
261 default: 266 default:
262 DSSERR("error in PLL mux config\n"); 267 DSSERR("error in PLL mux config\n");
263 return; 268 return -EINVAL;
264 } 269 }
265 270
266 regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset, 271 regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset,
267 0x3 << shift, val << shift); 272 0x3 << shift, val << shift);
273
274 return 0;
268} 275}
269 276
270void dss_sdi_init(int datapairs) 277void dss_sdi_init(int datapairs)
@@ -354,14 +361,14 @@ void dss_sdi_disable(void)
354 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ 361 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
355} 362}
356 363
357const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) 364const char *dss_get_clk_source_name(enum dss_clk_source clk_src)
358{ 365{
359 return dss_generic_clk_source_names[clk_src]; 366 return dss_generic_clk_source_names[clk_src];
360} 367}
361 368
362void dss_dump_clocks(struct seq_file *s) 369void dss_dump_clocks(struct seq_file *s)
363{ 370{
364 const char *fclk_name, *fclk_real_name; 371 const char *fclk_name;
365 unsigned long fclk_rate; 372 unsigned long fclk_rate;
366 373
367 if (dss_runtime_get()) 374 if (dss_runtime_get())
@@ -369,12 +376,11 @@ void dss_dump_clocks(struct seq_file *s)
369 376
370 seq_printf(s, "- DSS -\n"); 377 seq_printf(s, "- DSS -\n");
371 378
372 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 379 fclk_name = dss_get_clk_source_name(DSS_CLK_SRC_FCK);
373 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
374 fclk_rate = clk_get_rate(dss.dss_clk); 380 fclk_rate = clk_get_rate(dss.dss_clk);
375 381
376 seq_printf(s, "%s (%s) = %lu\n", 382 seq_printf(s, "%s = %lu\n",
377 fclk_name, fclk_real_name, 383 fclk_name,
378 fclk_rate); 384 fclk_rate);
379 385
380 dss_runtime_put(); 386 dss_runtime_put();
@@ -403,19 +409,42 @@ static void dss_dump_regs(struct seq_file *s)
403#undef DUMPREG 409#undef DUMPREG
404} 410}
405 411
406static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) 412static int dss_get_channel_index(enum omap_channel channel)
413{
414 switch (channel) {
415 case OMAP_DSS_CHANNEL_LCD:
416 return 0;
417 case OMAP_DSS_CHANNEL_LCD2:
418 return 1;
419 case OMAP_DSS_CHANNEL_LCD3:
420 return 2;
421 default:
422 WARN_ON(1);
423 return 0;
424 }
425}
426
427static void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
407{ 428{
408 int b; 429 int b;
409 u8 start, end; 430 u8 start, end;
410 431
432 /*
433 * We always use PRCM clock as the DISPC func clock, except on DSS3,
434 * where we don't have separate DISPC and LCD clock sources.
435 */
436 if (WARN_ON(dss_has_feature(FEAT_LCD_CLK_SRC) &&
437 clk_src != DSS_CLK_SRC_FCK))
438 return;
439
411 switch (clk_src) { 440 switch (clk_src) {
412 case OMAP_DSS_CLK_SRC_FCK: 441 case DSS_CLK_SRC_FCK:
413 b = 0; 442 b = 0;
414 break; 443 break;
415 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 444 case DSS_CLK_SRC_PLL1_1:
416 b = 1; 445 b = 1;
417 break; 446 break;
418 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 447 case DSS_CLK_SRC_PLL2_1:
419 b = 2; 448 b = 2;
420 break; 449 break;
421 default: 450 default:
@@ -431,19 +460,19 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
431} 460}
432 461
433void dss_select_dsi_clk_source(int dsi_module, 462void dss_select_dsi_clk_source(int dsi_module,
434 enum omap_dss_clk_source clk_src) 463 enum dss_clk_source clk_src)
435{ 464{
436 int b, pos; 465 int b, pos;
437 466
438 switch (clk_src) { 467 switch (clk_src) {
439 case OMAP_DSS_CLK_SRC_FCK: 468 case DSS_CLK_SRC_FCK:
440 b = 0; 469 b = 0;
441 break; 470 break;
442 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: 471 case DSS_CLK_SRC_PLL1_2:
443 BUG_ON(dsi_module != 0); 472 BUG_ON(dsi_module != 0);
444 b = 1; 473 b = 1;
445 break; 474 break;
446 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: 475 case DSS_CLK_SRC_PLL2_2:
447 BUG_ON(dsi_module != 1); 476 BUG_ON(dsi_module != 1);
448 b = 1; 477 b = 1;
449 break; 478 break;
@@ -458,59 +487,125 @@ void dss_select_dsi_clk_source(int dsi_module,
458 dss.dsi_clk_source[dsi_module] = clk_src; 487 dss.dsi_clk_source[dsi_module] = clk_src;
459} 488}
460 489
490static int dss_lcd_clk_mux_dra7(enum omap_channel channel,
491 enum dss_clk_source clk_src)
492{
493 const u8 ctrl_bits[] = {
494 [OMAP_DSS_CHANNEL_LCD] = 0,
495 [OMAP_DSS_CHANNEL_LCD2] = 12,
496 [OMAP_DSS_CHANNEL_LCD3] = 19,
497 };
498
499 u8 ctrl_bit = ctrl_bits[channel];
500 int r;
501
502 if (clk_src == DSS_CLK_SRC_FCK) {
503 /* LCDx_CLK_SWITCH */
504 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
505 return -EINVAL;
506 }
507
508 r = dss_ctrl_pll_set_control_mux(clk_src, channel);
509 if (r)
510 return r;
511
512 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
513
514 return 0;
515}
516
517static int dss_lcd_clk_mux_omap5(enum omap_channel channel,
518 enum dss_clk_source clk_src)
519{
520 const u8 ctrl_bits[] = {
521 [OMAP_DSS_CHANNEL_LCD] = 0,
522 [OMAP_DSS_CHANNEL_LCD2] = 12,
523 [OMAP_DSS_CHANNEL_LCD3] = 19,
524 };
525 const enum dss_clk_source allowed_plls[] = {
526 [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
527 [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_FCK,
528 [OMAP_DSS_CHANNEL_LCD3] = DSS_CLK_SRC_PLL2_1,
529 };
530
531 u8 ctrl_bit = ctrl_bits[channel];
532
533 if (clk_src == DSS_CLK_SRC_FCK) {
534 /* LCDx_CLK_SWITCH */
535 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
536 return -EINVAL;
537 }
538
539 if (WARN_ON(allowed_plls[channel] != clk_src))
540 return -EINVAL;
541
542 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
543
544 return 0;
545}
546
547static int dss_lcd_clk_mux_omap4(enum omap_channel channel,
548 enum dss_clk_source clk_src)
549{
550 const u8 ctrl_bits[] = {
551 [OMAP_DSS_CHANNEL_LCD] = 0,
552 [OMAP_DSS_CHANNEL_LCD2] = 12,
553 };
554 const enum dss_clk_source allowed_plls[] = {
555 [OMAP_DSS_CHANNEL_LCD] = DSS_CLK_SRC_PLL1_1,
556 [OMAP_DSS_CHANNEL_LCD2] = DSS_CLK_SRC_PLL2_1,
557 };
558
559 u8 ctrl_bit = ctrl_bits[channel];
560
561 if (clk_src == DSS_CLK_SRC_FCK) {
562 /* LCDx_CLK_SWITCH */
563 REG_FLD_MOD(DSS_CONTROL, 0, ctrl_bit, ctrl_bit);
564 return 0;
565 }
566
567 if (WARN_ON(allowed_plls[channel] != clk_src))
568 return -EINVAL;
569
570 REG_FLD_MOD(DSS_CONTROL, 1, ctrl_bit, ctrl_bit);
571
572 return 0;
573}
574
461void dss_select_lcd_clk_source(enum omap_channel channel, 575void dss_select_lcd_clk_source(enum omap_channel channel,
462 enum omap_dss_clk_source clk_src) 576 enum dss_clk_source clk_src)
463{ 577{
464 int b, ix, pos; 578 int idx = dss_get_channel_index(channel);
579 int r;
465 580
466 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { 581 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
467 dss_select_dispc_clk_source(clk_src); 582 dss_select_dispc_clk_source(clk_src);
583 dss.lcd_clk_source[idx] = clk_src;
468 return; 584 return;
469 } 585 }
470 586
471 switch (clk_src) { 587 r = dss.feat->select_lcd_source(channel, clk_src);
472 case OMAP_DSS_CLK_SRC_FCK: 588 if (r)
473 b = 0;
474 break;
475 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
476 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
477 b = 1;
478 break;
479 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
480 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
481 channel != OMAP_DSS_CHANNEL_LCD3);
482 b = 1;
483 break;
484 default:
485 BUG();
486 return; 589 return;
487 }
488
489 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 :
490 (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
491 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
492 590
493 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 591 dss.lcd_clk_source[idx] = clk_src;
494 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
495 dss.lcd_clk_source[ix] = clk_src;
496} 592}
497 593
498enum omap_dss_clk_source dss_get_dispc_clk_source(void) 594enum dss_clk_source dss_get_dispc_clk_source(void)
499{ 595{
500 return dss.dispc_clk_source; 596 return dss.dispc_clk_source;
501} 597}
502 598
503enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module) 599enum dss_clk_source dss_get_dsi_clk_source(int dsi_module)
504{ 600{
505 return dss.dsi_clk_source[dsi_module]; 601 return dss.dsi_clk_source[dsi_module];
506} 602}
507 603
508enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) 604enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
509{ 605{
510 if (dss_has_feature(FEAT_LCD_CLK_SRC)) { 606 if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
511 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 607 int idx = dss_get_channel_index(channel);
512 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); 608 return dss.lcd_clk_source[idx];
513 return dss.lcd_clk_source[ix];
514 } else { 609 } else {
515 /* LCD_CLK source is the same as DISPC_FCLK source for 610 /* LCD_CLK source is the same as DISPC_FCLK source for
516 * OMAP2 and OMAP3 */ 611 * OMAP2 and OMAP3 */
@@ -859,6 +954,7 @@ static const struct dss_features omap44xx_dss_feats = {
859 .dpi_select_source = &dss_dpi_select_source_omap4, 954 .dpi_select_source = &dss_dpi_select_source_omap4,
860 .ports = omap2plus_ports, 955 .ports = omap2plus_ports,
861 .num_ports = ARRAY_SIZE(omap2plus_ports), 956 .num_ports = ARRAY_SIZE(omap2plus_ports),
957 .select_lcd_source = &dss_lcd_clk_mux_omap4,
862}; 958};
863 959
864static const struct dss_features omap54xx_dss_feats = { 960static const struct dss_features omap54xx_dss_feats = {
@@ -868,6 +964,7 @@ static const struct dss_features omap54xx_dss_feats = {
868 .dpi_select_source = &dss_dpi_select_source_omap5, 964 .dpi_select_source = &dss_dpi_select_source_omap5,
869 .ports = omap2plus_ports, 965 .ports = omap2plus_ports,
870 .num_ports = ARRAY_SIZE(omap2plus_ports), 966 .num_ports = ARRAY_SIZE(omap2plus_ports),
967 .select_lcd_source = &dss_lcd_clk_mux_omap5,
871}; 968};
872 969
873static const struct dss_features am43xx_dss_feats = { 970static const struct dss_features am43xx_dss_feats = {
@@ -886,6 +983,7 @@ static const struct dss_features dra7xx_dss_feats = {
886 .dpi_select_source = &dss_dpi_select_source_dra7xx, 983 .dpi_select_source = &dss_dpi_select_source_dra7xx,
887 .ports = dra7xx_ports, 984 .ports = dra7xx_ports,
888 .num_ports = ARRAY_SIZE(dra7xx_ports), 985 .num_ports = ARRAY_SIZE(dra7xx_ports),
986 .select_lcd_source = &dss_lcd_clk_mux_dra7,
889}; 987};
890 988
891static int dss_init_features(struct platform_device *pdev) 989static int dss_init_features(struct platform_device *pdev)
@@ -1143,18 +1241,18 @@ static int dss_bind(struct device *dev)
1143 /* Select DPLL */ 1241 /* Select DPLL */
1144 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); 1242 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
1145 1243
1146 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 1244 dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
1147 1245
1148#ifdef CONFIG_OMAP2_DSS_VENC 1246#ifdef CONFIG_OMAP2_DSS_VENC
1149 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ 1247 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
1150 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ 1248 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
1151 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ 1249 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
1152#endif 1250#endif
1153 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 1251 dss.dsi_clk_source[0] = DSS_CLK_SRC_FCK;
1154 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 1252 dss.dsi_clk_source[1] = DSS_CLK_SRC_FCK;
1155 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; 1253 dss.dispc_clk_source = DSS_CLK_SRC_FCK;
1156 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 1254 dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
1157 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 1255 dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
1158 1256
1159 rev = dss_read_reg(DSS_REVISION); 1257 rev = dss_read_reg(DSS_REVISION);
1160 printk(KERN_INFO "OMAP DSS rev %d.%d\n", 1258 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h
index 38e6ab50142d..4fd06dc41cb3 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss.h
@@ -102,6 +102,20 @@ enum dss_writeback_channel {
102 DSS_WB_LCD3_MGR = 7, 102 DSS_WB_LCD3_MGR = 7,
103}; 103};
104 104
105enum dss_clk_source {
106 DSS_CLK_SRC_FCK = 0,
107
108 DSS_CLK_SRC_PLL1_1,
109 DSS_CLK_SRC_PLL1_2,
110 DSS_CLK_SRC_PLL1_3,
111
112 DSS_CLK_SRC_PLL2_1,
113 DSS_CLK_SRC_PLL2_2,
114 DSS_CLK_SRC_PLL2_3,
115
116 DSS_CLK_SRC_HDMI_PLL,
117};
118
105enum dss_pll_id { 119enum dss_pll_id {
106 DSS_PLL_DSI1, 120 DSS_PLL_DSI1,
107 DSS_PLL_DSI2, 121 DSS_PLL_DSI2,
@@ -114,6 +128,11 @@ struct dss_pll;
114 128
115#define DSS_PLL_MAX_HSDIVS 4 129#define DSS_PLL_MAX_HSDIVS 4
116 130
131enum dss_pll_type {
132 DSS_PLL_TYPE_A,
133 DSS_PLL_TYPE_B,
134};
135
117/* 136/*
118 * Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7. 137 * Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7.
119 * Type-B PLLs: clkout[0] refers to m2. 138 * Type-B PLLs: clkout[0] refers to m2.
@@ -140,6 +159,8 @@ struct dss_pll_ops {
140}; 159};
141 160
142struct dss_pll_hw { 161struct dss_pll_hw {
162 enum dss_pll_type type;
163
143 unsigned n_max; 164 unsigned n_max;
144 unsigned m_min; 165 unsigned m_min;
145 unsigned m_max; 166 unsigned m_max;
@@ -227,7 +248,7 @@ unsigned long dss_get_dispc_clk_rate(void);
227int dss_dpi_select_source(int port, enum omap_channel channel); 248int dss_dpi_select_source(int port, enum omap_channel channel);
228void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 249void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
229enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 250enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
230const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 251const char *dss_get_clk_source_name(enum dss_clk_source clk_src);
231void dss_dump_clocks(struct seq_file *s); 252void dss_dump_clocks(struct seq_file *s);
232 253
233/* DSS VIDEO PLL */ 254/* DSS VIDEO PLL */
@@ -244,20 +265,18 @@ void dss_debug_dump_clocks(struct seq_file *s);
244#endif 265#endif
245 266
246void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable); 267void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
247void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
248 enum omap_channel channel);
249 268
250void dss_sdi_init(int datapairs); 269void dss_sdi_init(int datapairs);
251int dss_sdi_enable(void); 270int dss_sdi_enable(void);
252void dss_sdi_disable(void); 271void dss_sdi_disable(void);
253 272
254void dss_select_dsi_clk_source(int dsi_module, 273void dss_select_dsi_clk_source(int dsi_module,
255 enum omap_dss_clk_source clk_src); 274 enum dss_clk_source clk_src);
256void dss_select_lcd_clk_source(enum omap_channel channel, 275void dss_select_lcd_clk_source(enum omap_channel channel,
257 enum omap_dss_clk_source clk_src); 276 enum dss_clk_source clk_src);
258enum omap_dss_clk_source dss_get_dispc_clk_source(void); 277enum dss_clk_source dss_get_dispc_clk_source(void);
259enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module); 278enum dss_clk_source dss_get_dsi_clk_source(int dsi_module);
260enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); 279enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
261 280
262void dss_set_venc_output(enum omap_dss_venc_type type); 281void dss_set_venc_output(enum omap_dss_venc_type type);
263void dss_set_dac_pwrdn_bgz(bool enable); 282void dss_set_dac_pwrdn_bgz(bool enable);
@@ -409,17 +428,23 @@ typedef bool (*dss_hsdiv_calc_func)(int m_dispc, unsigned long dispc,
409int dss_pll_register(struct dss_pll *pll); 428int dss_pll_register(struct dss_pll *pll);
410void dss_pll_unregister(struct dss_pll *pll); 429void dss_pll_unregister(struct dss_pll *pll);
411struct dss_pll *dss_pll_find(const char *name); 430struct dss_pll *dss_pll_find(const char *name);
431struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src);
432unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src);
412int dss_pll_enable(struct dss_pll *pll); 433int dss_pll_enable(struct dss_pll *pll);
413void dss_pll_disable(struct dss_pll *pll); 434void dss_pll_disable(struct dss_pll *pll);
414int dss_pll_set_config(struct dss_pll *pll, 435int dss_pll_set_config(struct dss_pll *pll,
415 const struct dss_pll_clock_info *cinfo); 436 const struct dss_pll_clock_info *cinfo);
416 437
417bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco, 438bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
418 unsigned long out_min, unsigned long out_max, 439 unsigned long out_min, unsigned long out_max,
419 dss_hsdiv_calc_func func, void *data); 440 dss_hsdiv_calc_func func, void *data);
420bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin, 441bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
421 unsigned long pll_min, unsigned long pll_max, 442 unsigned long pll_min, unsigned long pll_max,
422 dss_pll_calc_func func, void *data); 443 dss_pll_calc_func func, void *data);
444
445bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
446 unsigned long target_clkout, struct dss_pll_clock_info *cinfo);
447
423int dss_pll_write_config_type_a(struct dss_pll *pll, 448int dss_pll_write_config_type_a(struct dss_pll *pll,
424 const struct dss_pll_clock_info *cinfo); 449 const struct dss_pll_clock_info *cinfo);
425int dss_pll_write_config_type_b(struct dss_pll *pll, 450int dss_pll_write_config_type_b(struct dss_pll *pll,
diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.c b/drivers/gpu/drm/omapdrm/dss/dss_features.c
index c886a2927f73..c025d44ae164 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss_features.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss_features.c
@@ -50,7 +50,6 @@ struct omap_dss_features {
50 const enum omap_dss_output_id *supported_outputs; 50 const enum omap_dss_output_id *supported_outputs;
51 const enum omap_color_mode *supported_color_modes; 51 const enum omap_color_mode *supported_color_modes;
52 const enum omap_overlay_caps *overlay_caps; 52 const enum omap_overlay_caps *overlay_caps;
53 const char * const *clksrc_names;
54 const struct dss_param_range *dss_params; 53 const struct dss_param_range *dss_params;
55 54
56 const enum omap_dss_rotation_type supported_rotation_types; 55 const enum omap_dss_rotation_type supported_rotation_types;
@@ -389,34 +388,6 @@ static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
389 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, 388 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
390}; 389};
391 390
392static const char * const omap2_dss_clk_source_names[] = {
393 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
394 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
395 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1",
396};
397
398static const char * const omap3_dss_clk_source_names[] = {
399 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
400 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
401 [OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
402};
403
404static const char * const omap4_dss_clk_source_names[] = {
405 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
406 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
407 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK",
408 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1",
409 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
410};
411
412static const char * const omap5_dss_clk_source_names[] = {
413 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
414 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
415 [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
416 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
417 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
418};
419
420static const struct dss_param_range omap2_dss_param_range[] = { 391static const struct dss_param_range omap2_dss_param_range[] = {
421 [FEAT_PARAM_DSS_FCK] = { 0, 133000000 }, 392 [FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
422 [FEAT_PARAM_DSS_PCD] = { 2, 255 }, 393 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
@@ -631,7 +602,6 @@ static const struct omap_dss_features omap2_dss_features = {
631 .supported_outputs = omap2_dss_supported_outputs, 602 .supported_outputs = omap2_dss_supported_outputs,
632 .supported_color_modes = omap2_dss_supported_color_modes, 603 .supported_color_modes = omap2_dss_supported_color_modes,
633 .overlay_caps = omap2_dss_overlay_caps, 604 .overlay_caps = omap2_dss_overlay_caps,
634 .clksrc_names = omap2_dss_clk_source_names,
635 .dss_params = omap2_dss_param_range, 605 .dss_params = omap2_dss_param_range,
636 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 606 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
637 .buffer_size_unit = 1, 607 .buffer_size_unit = 1,
@@ -652,7 +622,6 @@ static const struct omap_dss_features omap3430_dss_features = {
652 .supported_outputs = omap3430_dss_supported_outputs, 622 .supported_outputs = omap3430_dss_supported_outputs,
653 .supported_color_modes = omap3_dss_supported_color_modes, 623 .supported_color_modes = omap3_dss_supported_color_modes,
654 .overlay_caps = omap3430_dss_overlay_caps, 624 .overlay_caps = omap3430_dss_overlay_caps,
655 .clksrc_names = omap3_dss_clk_source_names,
656 .dss_params = omap3_dss_param_range, 625 .dss_params = omap3_dss_param_range,
657 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 626 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
658 .buffer_size_unit = 1, 627 .buffer_size_unit = 1,
@@ -676,7 +645,6 @@ static const struct omap_dss_features am35xx_dss_features = {
676 .supported_outputs = omap3430_dss_supported_outputs, 645 .supported_outputs = omap3430_dss_supported_outputs,
677 .supported_color_modes = omap3_dss_supported_color_modes, 646 .supported_color_modes = omap3_dss_supported_color_modes,
678 .overlay_caps = omap3430_dss_overlay_caps, 647 .overlay_caps = omap3430_dss_overlay_caps,
679 .clksrc_names = omap3_dss_clk_source_names,
680 .dss_params = omap3_dss_param_range, 648 .dss_params = omap3_dss_param_range,
681 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 649 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
682 .buffer_size_unit = 1, 650 .buffer_size_unit = 1,
@@ -696,7 +664,6 @@ static const struct omap_dss_features am43xx_dss_features = {
696 .supported_outputs = am43xx_dss_supported_outputs, 664 .supported_outputs = am43xx_dss_supported_outputs,
697 .supported_color_modes = omap3_dss_supported_color_modes, 665 .supported_color_modes = omap3_dss_supported_color_modes,
698 .overlay_caps = omap3430_dss_overlay_caps, 666 .overlay_caps = omap3430_dss_overlay_caps,
699 .clksrc_names = omap2_dss_clk_source_names,
700 .dss_params = am43xx_dss_param_range, 667 .dss_params = am43xx_dss_param_range,
701 .supported_rotation_types = OMAP_DSS_ROT_DMA, 668 .supported_rotation_types = OMAP_DSS_ROT_DMA,
702 .buffer_size_unit = 1, 669 .buffer_size_unit = 1,
@@ -716,7 +683,6 @@ static const struct omap_dss_features omap3630_dss_features = {
716 .supported_outputs = omap3630_dss_supported_outputs, 683 .supported_outputs = omap3630_dss_supported_outputs,
717 .supported_color_modes = omap3_dss_supported_color_modes, 684 .supported_color_modes = omap3_dss_supported_color_modes,
718 .overlay_caps = omap3630_dss_overlay_caps, 685 .overlay_caps = omap3630_dss_overlay_caps,
719 .clksrc_names = omap3_dss_clk_source_names,
720 .dss_params = omap3_dss_param_range, 686 .dss_params = omap3_dss_param_range,
721 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB, 687 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
722 .buffer_size_unit = 1, 688 .buffer_size_unit = 1,
@@ -738,7 +704,6 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
738 .supported_outputs = omap4_dss_supported_outputs, 704 .supported_outputs = omap4_dss_supported_outputs,
739 .supported_color_modes = omap4_dss_supported_color_modes, 705 .supported_color_modes = omap4_dss_supported_color_modes,
740 .overlay_caps = omap4_dss_overlay_caps, 706 .overlay_caps = omap4_dss_overlay_caps,
741 .clksrc_names = omap4_dss_clk_source_names,
742 .dss_params = omap4_dss_param_range, 707 .dss_params = omap4_dss_param_range,
743 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 708 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
744 .buffer_size_unit = 16, 709 .buffer_size_unit = 16,
@@ -759,7 +724,6 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
759 .supported_outputs = omap4_dss_supported_outputs, 724 .supported_outputs = omap4_dss_supported_outputs,
760 .supported_color_modes = omap4_dss_supported_color_modes, 725 .supported_color_modes = omap4_dss_supported_color_modes,
761 .overlay_caps = omap4_dss_overlay_caps, 726 .overlay_caps = omap4_dss_overlay_caps,
762 .clksrc_names = omap4_dss_clk_source_names,
763 .dss_params = omap4_dss_param_range, 727 .dss_params = omap4_dss_param_range,
764 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 728 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
765 .buffer_size_unit = 16, 729 .buffer_size_unit = 16,
@@ -780,7 +744,6 @@ static const struct omap_dss_features omap4_dss_features = {
780 .supported_outputs = omap4_dss_supported_outputs, 744 .supported_outputs = omap4_dss_supported_outputs,
781 .supported_color_modes = omap4_dss_supported_color_modes, 745 .supported_color_modes = omap4_dss_supported_color_modes,
782 .overlay_caps = omap4_dss_overlay_caps, 746 .overlay_caps = omap4_dss_overlay_caps,
783 .clksrc_names = omap4_dss_clk_source_names,
784 .dss_params = omap4_dss_param_range, 747 .dss_params = omap4_dss_param_range,
785 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 748 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
786 .buffer_size_unit = 16, 749 .buffer_size_unit = 16,
@@ -801,7 +764,6 @@ static const struct omap_dss_features omap5_dss_features = {
801 .supported_outputs = omap5_dss_supported_outputs, 764 .supported_outputs = omap5_dss_supported_outputs,
802 .supported_color_modes = omap4_dss_supported_color_modes, 765 .supported_color_modes = omap4_dss_supported_color_modes,
803 .overlay_caps = omap4_dss_overlay_caps, 766 .overlay_caps = omap4_dss_overlay_caps,
804 .clksrc_names = omap5_dss_clk_source_names,
805 .dss_params = omap5_dss_param_range, 767 .dss_params = omap5_dss_param_range,
806 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, 768 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
807 .buffer_size_unit = 16, 769 .buffer_size_unit = 16,
@@ -859,11 +821,6 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
859 color_mode; 821 color_mode;
860} 822}
861 823
862const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
863{
864 return omap_current_dss_features->clksrc_names[id];
865}
866
867u32 dss_feat_get_buffer_size_unit(void) 824u32 dss_feat_get_buffer_size_unit(void)
868{ 825{
869 return omap_current_dss_features->buffer_size_unit; 826 return omap_current_dss_features->buffer_size_unit;
diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.h b/drivers/gpu/drm/omapdrm/dss/dss_features.h
index 3d67d39f192f..bb4b7f0e642b 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss_features.h
+++ b/drivers/gpu/drm/omapdrm/dss/dss_features.h
@@ -91,7 +91,6 @@ unsigned long dss_feat_get_param_max(enum dss_range_param param);
91enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 91enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
92bool dss_feat_color_mode_supported(enum omap_plane plane, 92bool dss_feat_color_mode_supported(enum omap_plane plane,
93 enum omap_color_mode color_mode); 93 enum omap_color_mode color_mode);
94const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
95 94
96u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ 95u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
97u32 dss_feat_get_burst_size_unit(void); /* in bytes */ 96u32 dss_feat_get_burst_size_unit(void); /* in bytes */
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h
index 53616b02b613..597ee204d699 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi.h
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h
@@ -240,6 +240,7 @@ struct hdmi_pll_data {
240 240
241 void __iomem *base; 241 void __iomem *base;
242 242
243 struct platform_device *pdev;
243 struct hdmi_wp_data *wp; 244 struct hdmi_wp_data *wp;
244}; 245};
245 246
@@ -306,8 +307,6 @@ phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
306 307
307/* HDMI PLL funcs */ 308/* HDMI PLL funcs */
308void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); 309void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
309void hdmi_pll_compute(struct hdmi_pll_data *pll,
310 unsigned long target_tmds, struct dss_pll_clock_info *pi);
311int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll, 310int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
312 struct hdmi_wp_data *wp); 311 struct hdmi_wp_data *wp);
313void hdmi_pll_uninit(struct hdmi_pll_data *hpll); 312void hdmi_pll_uninit(struct hdmi_pll_data *hpll);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 4d46cdf7a037..ca4abb499242 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -177,7 +177,11 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
177 if (p->double_pixel) 177 if (p->double_pixel)
178 pc *= 2; 178 pc *= 2;
179 179
180 hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo); 180 /* DSS_HDMI_TCLK is bitclk / 10 */
181 pc *= 10;
182
183 dss_pll_calc_b(&hdmi.pll.pll, clk_get_rate(hdmi.pll.pll.clkin),
184 pc, &hdmi_cinfo);
181 185
182 r = dss_pll_enable(&hdmi.pll.pll); 186 r = dss_pll_enable(&hdmi.pll.pll);
183 if (r) { 187 if (r) {
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index e129245eb8a9..cbcf4bb5248c 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -190,7 +190,11 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
190 if (p->double_pixel) 190 if (p->double_pixel)
191 pc *= 2; 191 pc *= 2;
192 192
193 hdmi_pll_compute(&hdmi.pll, pc, &hdmi_cinfo); 193 /* DSS_HDMI_TCLK is bitclk / 10 */
194 pc *= 10;
195
196 dss_pll_calc_b(&hdmi.pll.pll, clk_get_rate(hdmi.pll.pll.clkin),
197 pc, &hdmi_cinfo);
194 198
195 /* disable and clear irqs */ 199 /* disable and clear irqs */
196 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); 200 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
index f1015e8b8267..dc0212a9754e 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
@@ -17,6 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/seq_file.h> 19#include <linux/seq_file.h>
20#include <linux/pm_runtime.h>
20 21
21#include <video/omapdss.h> 22#include <video/omapdss.h>
22 23
@@ -39,71 +40,14 @@ void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
39 DUMPPLL(PLLCTRL_CFG4); 40 DUMPPLL(PLLCTRL_CFG4);
40} 41}
41 42
42void hdmi_pll_compute(struct hdmi_pll_data *pll,
43 unsigned long target_tmds, struct dss_pll_clock_info *pi)
44{
45 unsigned long fint, clkdco, clkout;
46 unsigned long target_bitclk, target_clkdco;
47 unsigned long min_dco;
48 unsigned n, m, mf, m2, sd;
49 unsigned long clkin;
50 const struct dss_pll_hw *hw = pll->pll.hw;
51
52 clkin = clk_get_rate(pll->pll.clkin);
53
54 DSSDBG("clkin %lu, target tmds %lu\n", clkin, target_tmds);
55
56 target_bitclk = target_tmds * 10;
57
58 /* Fint */
59 n = DIV_ROUND_UP(clkin, hw->fint_max);
60 fint = clkin / n;
61
62 /* adjust m2 so that the clkdco will be high enough */
63 min_dco = roundup(hw->clkdco_min, fint);
64 m2 = DIV_ROUND_UP(min_dco, target_bitclk);
65 if (m2 == 0)
66 m2 = 1;
67
68 target_clkdco = target_bitclk * m2;
69 m = target_clkdco / fint;
70
71 clkdco = fint * m;
72
73 /* adjust clkdco with fractional mf */
74 if (WARN_ON(target_clkdco - clkdco > fint))
75 mf = 0;
76 else
77 mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
78
79 if (mf > 0)
80 clkdco += (u32)div_u64((u64)mf * fint, 262144);
81
82 clkout = clkdco / m2;
83
84 /* sigma-delta */
85 sd = DIV_ROUND_UP(fint * m, 250000000);
86
87 DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
88 n, m, mf, m2, sd);
89 DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
90
91 pi->n = n;
92 pi->m = m;
93 pi->mf = mf;
94 pi->mX[0] = m2;
95 pi->sd = sd;
96
97 pi->fint = fint;
98 pi->clkdco = clkdco;
99 pi->clkout[0] = clkout;
100}
101
102static int hdmi_pll_enable(struct dss_pll *dsspll) 43static int hdmi_pll_enable(struct dss_pll *dsspll)
103{ 44{
104 struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll); 45 struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
105 struct hdmi_wp_data *wp = pll->wp; 46 struct hdmi_wp_data *wp = pll->wp;
106 u16 r = 0; 47 int r;
48
49 r = pm_runtime_get_sync(&pll->pdev->dev);
50 WARN_ON(r < 0);
107 51
108 dss_ctrl_pll_enable(DSS_PLL_HDMI, true); 52 dss_ctrl_pll_enable(DSS_PLL_HDMI, true);
109 53
@@ -118,10 +62,14 @@ static void hdmi_pll_disable(struct dss_pll *dsspll)
118{ 62{
119 struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll); 63 struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
120 struct hdmi_wp_data *wp = pll->wp; 64 struct hdmi_wp_data *wp = pll->wp;
65 int r;
121 66
122 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); 67 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
123 68
124 dss_ctrl_pll_enable(DSS_PLL_HDMI, false); 69 dss_ctrl_pll_enable(DSS_PLL_HDMI, false);
70
71 r = pm_runtime_put_sync(&pll->pdev->dev);
72 WARN_ON(r < 0 && r != -ENOSYS);
125} 73}
126 74
127static const struct dss_pll_ops dsi_pll_ops = { 75static const struct dss_pll_ops dsi_pll_ops = {
@@ -131,6 +79,8 @@ static const struct dss_pll_ops dsi_pll_ops = {
131}; 79};
132 80
133static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = { 81static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
82 .type = DSS_PLL_TYPE_B,
83
134 .n_max = 255, 84 .n_max = 255,
135 .m_min = 20, 85 .m_min = 20,
136 .m_max = 4095, 86 .m_max = 4095,
@@ -154,6 +104,8 @@ static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
154}; 104};
155 105
156static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = { 106static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
107 .type = DSS_PLL_TYPE_B,
108
157 .n_max = 255, 109 .n_max = 255,
158 .m_min = 20, 110 .m_min = 20,
159 .m_max = 2045, 111 .m_max = 2045,
@@ -225,6 +177,7 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
225 int r; 177 int r;
226 struct resource *res; 178 struct resource *res;
227 179
180 pll->pdev = pdev;
228 pll->wp = wp; 181 pll->wp = wp;
229 182
230 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); 183 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c b/drivers/gpu/drm/omapdrm/dss/pll.c
index f974ddcd3b6e..4768a85e6c73 100644
--- a/drivers/gpu/drm/omapdrm/dss/pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/pll.c
@@ -76,6 +76,59 @@ struct dss_pll *dss_pll_find(const char *name)
76 return NULL; 76 return NULL;
77} 77}
78 78
79struct dss_pll *dss_pll_find_by_src(enum dss_clk_source src)
80{
81 struct dss_pll *pll;
82
83 switch (src) {
84 default:
85 case DSS_CLK_SRC_FCK:
86 return NULL;
87
88 case DSS_CLK_SRC_HDMI_PLL:
89 return dss_pll_find("hdmi");
90
91 case DSS_CLK_SRC_PLL1_1:
92 case DSS_CLK_SRC_PLL1_2:
93 case DSS_CLK_SRC_PLL1_3:
94 pll = dss_pll_find("dsi0");
95 if (!pll)
96 pll = dss_pll_find("video0");
97 return pll;
98
99 case DSS_CLK_SRC_PLL2_1:
100 case DSS_CLK_SRC_PLL2_2:
101 case DSS_CLK_SRC_PLL2_3:
102 pll = dss_pll_find("dsi1");
103 if (!pll)
104 pll = dss_pll_find("video1");
105 return pll;
106 }
107}
108
109unsigned dss_pll_get_clkout_idx_for_src(enum dss_clk_source src)
110{
111 switch (src) {
112 case DSS_CLK_SRC_HDMI_PLL:
113 return 0;
114
115 case DSS_CLK_SRC_PLL1_1:
116 case DSS_CLK_SRC_PLL2_1:
117 return 0;
118
119 case DSS_CLK_SRC_PLL1_2:
120 case DSS_CLK_SRC_PLL2_2:
121 return 1;
122
123 case DSS_CLK_SRC_PLL1_3:
124 case DSS_CLK_SRC_PLL2_3:
125 return 2;
126
127 default:
128 return 0;
129 }
130}
131
79int dss_pll_enable(struct dss_pll *pll) 132int dss_pll_enable(struct dss_pll *pll)
80{ 133{
81 int r; 134 int r;
@@ -129,7 +182,7 @@ int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cin
129 return 0; 182 return 0;
130} 183}
131 184
132bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco, 185bool dss_pll_hsdiv_calc_a(const struct dss_pll *pll, unsigned long clkdco,
133 unsigned long out_min, unsigned long out_max, 186 unsigned long out_min, unsigned long out_max,
134 dss_hsdiv_calc_func func, void *data) 187 dss_hsdiv_calc_func func, void *data)
135{ 188{
@@ -154,7 +207,11 @@ bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
154 return false; 207 return false;
155} 208}
156 209
157bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin, 210/*
211 * clkdco = clkin / n * m * 2
212 * clkoutX = clkdco / mX
213 */
214bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
158 unsigned long pll_min, unsigned long pll_max, 215 unsigned long pll_min, unsigned long pll_max,
159 dss_pll_calc_func func, void *data) 216 dss_pll_calc_func func, void *data)
160{ 217{
@@ -195,6 +252,71 @@ bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
195 return false; 252 return false;
196} 253}
197 254
255/*
256 * This calculates a PLL config that will provide the target_clkout rate
257 * for clkout. Additionally clkdco rate will be the same as clkout rate
258 * when clkout rate is >= min_clkdco.
259 *
260 * clkdco = clkin / n * m + clkin / n * mf / 262144
261 * clkout = clkdco / m2
262 */
263bool dss_pll_calc_b(const struct dss_pll *pll, unsigned long clkin,
264 unsigned long target_clkout, struct dss_pll_clock_info *cinfo)
265{
266 unsigned long fint, clkdco, clkout;
267 unsigned long target_clkdco;
268 unsigned long min_dco;
269 unsigned n, m, mf, m2, sd;
270 const struct dss_pll_hw *hw = pll->hw;
271
272 DSSDBG("clkin %lu, target clkout %lu\n", clkin, target_clkout);
273
274 /* Fint */
275 n = DIV_ROUND_UP(clkin, hw->fint_max);
276 fint = clkin / n;
277
278 /* adjust m2 so that the clkdco will be high enough */
279 min_dco = roundup(hw->clkdco_min, fint);
280 m2 = DIV_ROUND_UP(min_dco, target_clkout);
281 if (m2 == 0)
282 m2 = 1;
283
284 target_clkdco = target_clkout * m2;
285 m = target_clkdco / fint;
286
287 clkdco = fint * m;
288
289 /* adjust clkdco with fractional mf */
290 if (WARN_ON(target_clkdco - clkdco > fint))
291 mf = 0;
292 else
293 mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
294
295 if (mf > 0)
296 clkdco += (u32)div_u64((u64)mf * fint, 262144);
297
298 clkout = clkdco / m2;
299
300 /* sigma-delta */
301 sd = DIV_ROUND_UP(fint * m, 250000000);
302
303 DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
304 n, m, mf, m2, sd);
305 DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
306
307 cinfo->n = n;
308 cinfo->m = m;
309 cinfo->mf = mf;
310 cinfo->mX[0] = m2;
311 cinfo->sd = sd;
312
313 cinfo->fint = fint;
314 cinfo->clkdco = clkdco;
315 cinfo->clkout[0] = clkout;
316
317 return true;
318}
319
198static int wait_for_bit_change(void __iomem *reg, int bitnum, int value) 320static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
199{ 321{
200 unsigned long timeout; 322 unsigned long timeout;
diff --git a/drivers/gpu/drm/omapdrm/dss/video-pll.c b/drivers/gpu/drm/omapdrm/dss/video-pll.c
index b1ec59e42940..c13e1accda17 100644
--- a/drivers/gpu/drm/omapdrm/dss/video-pll.c
+++ b/drivers/gpu/drm/omapdrm/dss/video-pll.c
@@ -108,6 +108,8 @@ static const struct dss_pll_ops dss_pll_ops = {
108}; 108};
109 109
110static const struct dss_pll_hw dss_dra7_video_pll_hw = { 110static const struct dss_pll_hw dss_dra7_video_pll_hw = {
111 .type = DSS_PLL_TYPE_A,
112
111 .n_max = (1 << 8) - 1, 113 .n_max = (1 << 8) - 1,
112 .m_max = (1 << 12) - 1, 114 .m_max = (1 << 12) - 1,
113 .mX_max = (1 << 5) - 1, 115 .mX_max = (1 << 5) - 1,
@@ -124,6 +126,10 @@ static const struct dss_pll_hw dss_dra7_video_pll_hw = {
124 .mX_lsb[0] = 21, 126 .mX_lsb[0] = 21,
125 .mX_msb[1] = 30, 127 .mX_msb[1] = 30,
126 .mX_lsb[1] = 26, 128 .mX_lsb[1] = 26,
129 .mX_msb[2] = 4,
130 .mX_lsb[2] = 0,
131 .mX_msb[3] = 9,
132 .mX_lsb[3] = 5,
127 133
128 .has_refsel = true, 134 .has_refsel = true,
129}; 135};