aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2013-03-05 10:07:16 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-04-03 08:19:18 -0400
commit100c826235793345efe06b3558cc9d36166b1e26 (patch)
tree04ed26d04565ce34381a00554f0eca9bdc6c3b7a
parent36816faadff37ac7d29be20471d37a2b938ece5d (diff)
OMAPDSS: DPI: use new clock calculation code
Use the new clock calculation code in the DPI driver. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/dss/dpi.c212
1 files changed, 172 insertions, 40 deletions
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index c8c7776c8cfa..abe1a4e23c36 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -105,31 +105,170 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
105 } 105 }
106} 106}
107 107
108struct dpi_clk_calc_ctx {
109 struct platform_device *dsidev;
110
111 /* inputs */
112
113 unsigned long pck_min, pck_max;
114
115 /* outputs */
116
117 struct dsi_clock_info dsi_cinfo;
118 struct dss_clock_info dss_cinfo;
119 struct dispc_clock_info dispc_cinfo;
120};
121
122static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
123 unsigned long pck, void *data)
124{
125 struct dpi_clk_calc_ctx *ctx = data;
126
127 /*
128 * Odd dividers give us uneven duty cycle, causing problem when level
129 * shifted. So skip all odd dividers when the pixel clock is on the
130 * higher side.
131 */
132 if (ctx->pck_min >= 1000000) {
133 if (lckd > 1 && lckd % 2 != 0)
134 return false;
135
136 if (pckd > 1 && pckd % 2 != 0)
137 return false;
138 }
139
140 ctx->dispc_cinfo.lck_div = lckd;
141 ctx->dispc_cinfo.pck_div = pckd;
142 ctx->dispc_cinfo.lck = lck;
143 ctx->dispc_cinfo.pck = pck;
144
145 return true;
146}
147
148
149static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
150 void *data)
151{
152 struct dpi_clk_calc_ctx *ctx = data;
153
154 /*
155 * Odd dividers give us uneven duty cycle, causing problem when level
156 * shifted. So skip all odd dividers when the pixel clock is on the
157 * higher side.
158 */
159 if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000)
160 return false;
161
162 ctx->dsi_cinfo.regm_dispc = regm_dispc;
163 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
164
165 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
166 dpi_calc_dispc_cb, ctx);
167}
168
169
170static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint,
171 unsigned long pll,
172 void *data)
173{
174 struct dpi_clk_calc_ctx *ctx = data;
175
176 ctx->dsi_cinfo.regn = regn;
177 ctx->dsi_cinfo.regm = regm;
178 ctx->dsi_cinfo.fint = fint;
179 ctx->dsi_cinfo.clkin4ddr = pll;
180
181 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min,
182 dpi_calc_hsdiv_cb, ctx);
183}
184
185static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data)
186{
187 struct dpi_clk_calc_ctx *ctx = data;
188
189 ctx->dss_cinfo.fck = fck;
190 ctx->dss_cinfo.fck_div = fckd;
191
192 return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max,
193 dpi_calc_dispc_cb, ctx);
194}
195
196static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
197{
198 unsigned long clkin;
199 unsigned long pll_min, pll_max;
200
201 clkin = dsi_get_pll_clkin(dpi.dsidev);
202
203 memset(ctx, 0, sizeof(*ctx));
204 ctx->dsidev = dpi.dsidev;
205 ctx->pck_min = pck - 1000;
206 ctx->pck_max = pck + 1000;
207 ctx->dsi_cinfo.clkin = clkin;
208
209 pll_min = 0;
210 pll_max = 0;
211
212 return dsi_pll_calc(dpi.dsidev, clkin,
213 pll_min, pll_max,
214 dpi_calc_pll_cb, ctx);
215}
216
217static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
218{
219 int i;
220
221 /*
222 * DSS fck gives us very few possibilities, so finding a good pixel
223 * clock may not be possible. We try multiple times to find the clock,
224 * each time widening the pixel clock range we look for, up to
225 * +/- 1MHz.
226 */
227
228 for (i = 0; i < 10; ++i) {
229 bool ok;
230
231 memset(ctx, 0, sizeof(*ctx));
232 if (pck > 1000 * i * i * i)
233 ctx->pck_min = max(pck - 1000 * i * i * i, 0lu);
234 else
235 ctx->pck_min = 0;
236 ctx->pck_max = pck + 1000 * i * i * i;
237
238 ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx);
239 if (ok)
240 return ok;
241 }
242
243 return false;
244}
245
246
247
108static int dpi_set_dsi_clk(enum omap_channel channel, 248static int dpi_set_dsi_clk(enum omap_channel channel,
109 unsigned long pck_req, unsigned long *fck, int *lck_div, 249 unsigned long pck_req, unsigned long *fck, int *lck_div,
110 int *pck_div) 250 int *pck_div)
111{ 251{
112 struct dsi_clock_info dsi_cinfo; 252 struct dpi_clk_calc_ctx ctx;
113 struct dispc_clock_info dispc_cinfo;
114 int r; 253 int r;
254 bool ok;
115 255
116 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo, 256 ok = dpi_dsi_clk_calc(pck_req, &ctx);
117 &dispc_cinfo); 257 if (!ok)
118 if (r) 258 return -EINVAL;
119 return r;
120 259
121 r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); 260 r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo);
122 if (r) 261 if (r)
123 return r; 262 return r;
124 263
125 dss_select_lcd_clk_source(channel, 264 dss_select_lcd_clk_source(channel,
126 dpi_get_alt_clk_src(channel)); 265 dpi_get_alt_clk_src(channel));
127 266
128 dpi.mgr_config.clock_info = dispc_cinfo; 267 dpi.mgr_config.clock_info = ctx.dispc_cinfo;
129 268
130 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 269 *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
131 *lck_div = dispc_cinfo.lck_div; 270 *lck_div = ctx.dispc_cinfo.lck_div;
132 *pck_div = dispc_cinfo.pck_div; 271 *pck_div = ctx.dispc_cinfo.pck_div;
133 272
134 return 0; 273 return 0;
135} 274}
@@ -137,23 +276,23 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
137static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, 276static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
138 int *lck_div, int *pck_div) 277 int *lck_div, int *pck_div)
139{ 278{
140 struct dss_clock_info dss_cinfo; 279 struct dpi_clk_calc_ctx ctx;
141 struct dispc_clock_info dispc_cinfo;
142 int r; 280 int r;
281 bool ok;
143 282
144 r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo); 283 ok = dpi_dss_clk_calc(pck_req, &ctx);
145 if (r) 284 if (!ok)
146 return r; 285 return -EINVAL;
147 286
148 r = dss_set_clock_div(&dss_cinfo); 287 r = dss_set_clock_div(&ctx.dss_cinfo);
149 if (r) 288 if (r)
150 return r; 289 return r;
151 290
152 dpi.mgr_config.clock_info = dispc_cinfo; 291 dpi.mgr_config.clock_info = ctx.dispc_cinfo;
153 292
154 *fck = dss_cinfo.fck; 293 *fck = ctx.dss_cinfo.fck;
155 *lck_div = dispc_cinfo.lck_div; 294 *lck_div = ctx.dispc_cinfo.lck_div;
156 *pck_div = dispc_cinfo.pck_div; 295 *pck_div = ctx.dispc_cinfo.pck_div;
157 296
158 return 0; 297 return 0;
159} 298}
@@ -333,12 +472,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings);
333int dpi_check_timings(struct omap_dss_device *dssdev, 472int dpi_check_timings(struct omap_dss_device *dssdev,
334 struct omap_video_timings *timings) 473 struct omap_video_timings *timings)
335{ 474{
336 int r;
337 struct omap_overlay_manager *mgr = dpi.output.manager; 475 struct omap_overlay_manager *mgr = dpi.output.manager;
338 int lck_div, pck_div; 476 int lck_div, pck_div;
339 unsigned long fck; 477 unsigned long fck;
340 unsigned long pck; 478 unsigned long pck;
341 struct dispc_clock_info dispc_cinfo; 479 struct dpi_clk_calc_ctx ctx;
480 bool ok;
342 481
343 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) 482 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings))
344 return -EINVAL; 483 return -EINVAL;
@@ -347,28 +486,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
347 return -EINVAL; 486 return -EINVAL;
348 487
349 if (dpi.dsidev) { 488 if (dpi.dsidev) {
350 struct dsi_clock_info dsi_cinfo; 489 ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx);
351 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, 490 if (!ok)
352 timings->pixel_clock * 1000, 491 return -EINVAL;
353 &dsi_cinfo, &dispc_cinfo);
354 492
355 if (r) 493 fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
356 return r;
357
358 fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
359 } else { 494 } else {
360 struct dss_clock_info dss_cinfo; 495 ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx);
361 r = dss_calc_clock_div(timings->pixel_clock * 1000, 496 if (!ok)
362 &dss_cinfo, &dispc_cinfo); 497 return -EINVAL;
363
364 if (r)
365 return r;
366 498
367 fck = dss_cinfo.fck; 499 fck = ctx.dss_cinfo.fck;
368 } 500 }
369 501
370 lck_div = dispc_cinfo.lck_div; 502 lck_div = ctx.dispc_cinfo.lck_div;
371 pck_div = dispc_cinfo.pck_div; 503 pck_div = ctx.dispc_cinfo.pck_div;
372 504
373 pck = fck / lck_div / pck_div / 1000; 505 pck = fck / lck_div / pck_div / 1000;
374 506