aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/dss/dsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/omap2/dss/dsi.c')
-rw-r--r--drivers/video/omap2/dss/dsi.c557
1 files changed, 544 insertions, 13 deletions
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index a4e0560c2799..de88e69ef0a2 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -255,6 +255,24 @@ struct dsi_isr_tables {
255 struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; 255 struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
256}; 256};
257 257
258struct dsi_clk_calc_ctx {
259 struct platform_device *dsidev;
260
261 /* inputs */
262
263 const struct omap_dss_dsi_config *config;
264
265 unsigned long req_pck_min, req_pck_nom, req_pck_max;
266
267 /* outputs */
268
269 struct dsi_clock_info dsi_cinfo;
270 struct dispc_clock_info dispc_cinfo;
271
272 struct omap_video_timings dispc_vm;
273 struct omap_dss_dsi_videomode_timings dsi_vm;
274};
275
258struct dsi_data { 276struct dsi_data {
259 struct platform_device *pdev; 277 struct platform_device *pdev;
260 void __iomem *base; 278 void __iomem *base;
@@ -1201,6 +1219,25 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1201 return r; 1219 return r;
1202} 1220}
1203 1221
1222static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
1223 unsigned long lp_clk_min, unsigned long lp_clk_max)
1224{
1225 unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
1226 unsigned lp_clk_div;
1227 unsigned long lp_clk;
1228
1229 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2);
1230 lp_clk = dsi_fclk / 2 / lp_clk_div;
1231
1232 if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
1233 return -EINVAL;
1234
1235 cinfo->lp_clk_div = lp_clk_div;
1236 cinfo->lp_clk = lp_clk;
1237
1238 return 0;
1239}
1240
1204static int dsi_set_lp_clk_divisor(struct platform_device *dsidev) 1241static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
1205{ 1242{
1206 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1243 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -1577,8 +1614,7 @@ found:
1577 return 0; 1614 return 0;
1578} 1615}
1579 1616
1580static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, 1617static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
1581 struct dsi_clock_info *cinfo)
1582{ 1618{
1583 unsigned long max_dsi_fck; 1619 unsigned long max_dsi_fck;
1584 1620
@@ -4369,7 +4405,7 @@ static int dsi_set_clocks(struct omap_dss_device *dssdev,
4369 goto err; 4405 goto err;
4370 4406
4371 /* Calculate PLL's DSI clock */ 4407 /* Calculate PLL's DSI clock */
4372 dsi_pll_calc_dsi_fck(dsidev, &cinfo); 4408 dsi_pll_calc_dsi_fck(&cinfo);
4373 4409
4374 /* Calculate PLL's DISPC clock and pck & lck divs */ 4410 /* Calculate PLL's DISPC clock and pck & lck divs */
4375 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; 4411 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
@@ -4693,13 +4729,6 @@ static int dsi_display_init_dispc(struct platform_device *dsidev,
4693 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC); 4729 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC);
4694 4730
4695 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4731 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4696 dsi->timings.hsw = 1;
4697 dsi->timings.hfp = 1;
4698 dsi->timings.hbp = 1;
4699 dsi->timings.vsw = 1;
4700 dsi->timings.vfp = 0;
4701 dsi->timings.vbp = 0;
4702
4703 r = dss_mgr_register_framedone_handler(mgr, 4732 r = dss_mgr_register_framedone_handler(mgr,
4704 dsi_framedone_irq_callback, dsidev); 4733 dsi_framedone_irq_callback, dsidev);
4705 if (r) { 4734 if (r) {
@@ -4941,24 +4970,526 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4941} 4970}
4942EXPORT_SYMBOL(omapdss_dsi_enable_te); 4971EXPORT_SYMBOL(omapdss_dsi_enable_te);
4943 4972
4973#ifdef PRINT_VERBOSE_VM_TIMINGS
4974static void print_dsi_vm(const char *str,
4975 const struct omap_dss_dsi_videomode_timings *t)
4976{
4977 unsigned long byteclk = t->hsclk / 4;
4978 int bl, wc, pps, tot;
4979
4980 wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
4981 pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
4982 bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
4983 tot = bl + pps;
4984
4985#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
4986
4987 pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
4988 "%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
4989 str,
4990 byteclk,
4991 t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
4992 bl, pps, tot,
4993 TO_DSI_T(t->hss),
4994 TO_DSI_T(t->hsa),
4995 TO_DSI_T(t->hse),
4996 TO_DSI_T(t->hbp),
4997 TO_DSI_T(pps),
4998 TO_DSI_T(t->hfp),
4999
5000 TO_DSI_T(bl),
5001 TO_DSI_T(pps),
5002
5003 TO_DSI_T(tot));
5004#undef TO_DSI_T
5005}
5006
5007static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
5008{
5009 unsigned long pck = t->pixel_clock * 1000;
5010 int hact, bl, tot;
5011
5012 hact = t->x_res;
5013 bl = t->hsw + t->hbp + t->hfp;
5014 tot = hact + bl;
5015
5016#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
5017
5018 pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
5019 "%u/%u/%u/%u = %u + %u = %u\n",
5020 str,
5021 pck,
5022 t->hsw, t->hbp, hact, t->hfp,
5023 bl, hact, tot,
5024 TO_DISPC_T(t->hsw),
5025 TO_DISPC_T(t->hbp),
5026 TO_DISPC_T(hact),
5027 TO_DISPC_T(t->hfp),
5028 TO_DISPC_T(bl),
5029 TO_DISPC_T(hact),
5030 TO_DISPC_T(tot));
5031#undef TO_DISPC_T
5032}
5033
5034/* note: this is not quite accurate */
5035static void print_dsi_dispc_vm(const char *str,
5036 const struct omap_dss_dsi_videomode_timings *t)
5037{
5038 struct omap_video_timings vm = { 0 };
5039 unsigned long byteclk = t->hsclk / 4;
5040 unsigned long pck;
5041 u64 dsi_tput;
5042 int dsi_hact, dsi_htot;
5043
5044 dsi_tput = (u64)byteclk * t->ndl * 8;
5045 pck = (u32)div64_u64(dsi_tput, t->bitspp);
5046 dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
5047 dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
5048
5049 vm.pixel_clock = pck / 1000;
5050 vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
5051 vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
5052 vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
5053 vm.x_res = t->hact;
5054
5055 print_dispc_vm(str, &vm);
5056}
5057#endif /* PRINT_VERBOSE_VM_TIMINGS */
5058
5059static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
5060 unsigned long pck, void *data)
5061{
5062 struct dsi_clk_calc_ctx *ctx = data;
5063 struct omap_video_timings *t = &ctx->dispc_vm;
5064
5065 ctx->dispc_cinfo.lck_div = lckd;
5066 ctx->dispc_cinfo.pck_div = pckd;
5067 ctx->dispc_cinfo.lck = lck;
5068 ctx->dispc_cinfo.pck = pck;
5069
5070 *t = *ctx->config->timings;
5071 t->pixel_clock = pck / 1000;
5072 t->x_res = ctx->config->timings->x_res;
5073 t->y_res = ctx->config->timings->y_res;
5074 t->hsw = t->hfp = t->hbp = t->vsw = 1;
5075 t->vfp = t->vbp = 0;
5076
5077 return true;
5078}
5079
5080static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
5081 void *data)
5082{
5083 struct dsi_clk_calc_ctx *ctx = data;
5084
5085 ctx->dsi_cinfo.regm_dispc = regm_dispc;
5086 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
5087
5088 return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
5089 dsi_cm_calc_dispc_cb, ctx);
5090}
5091
5092static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
5093 unsigned long pll, void *data)
5094{
5095 struct dsi_clk_calc_ctx *ctx = data;
5096
5097 ctx->dsi_cinfo.regn = regn;
5098 ctx->dsi_cinfo.regm = regm;
5099 ctx->dsi_cinfo.fint = fint;
5100 ctx->dsi_cinfo.clkin4ddr = pll;
5101
5102 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
5103 dsi_cm_calc_hsdiv_cb, ctx);
5104}
5105
5106static bool dsi_cm_calc(struct dsi_data *dsi,
5107 const struct omap_dss_dsi_config *cfg,
5108 struct dsi_clk_calc_ctx *ctx)
5109{
5110 unsigned long clkin;
5111 int bitspp, ndl;
5112 unsigned long pll_min, pll_max;
5113 unsigned long pck, txbyteclk;
5114
5115 clkin = clk_get_rate(dsi->sys_clk);
5116 bitspp = dsi_get_pixel_size(cfg->pixel_format);
5117 ndl = dsi->num_lanes_used - 1;
5118
5119 /*
5120 * Here we should calculate minimum txbyteclk to be able to send the
5121 * frame in time, and also to handle TE. That's not very simple, though,
5122 * especially as we go to LP between each pixel packet due to HW
5123 * "feature". So let's just estimate very roughly and multiply by 1.5.
5124 */
5125 pck = cfg->timings->pixel_clock * 1000;
5126 pck = pck * 3 / 2;
5127 txbyteclk = pck * bitspp / 8 / ndl;
5128
5129 memset(ctx, 0, sizeof(*ctx));
5130 ctx->dsidev = dsi->pdev;
5131 ctx->config = cfg;
5132 ctx->req_pck_min = pck;
5133 ctx->req_pck_nom = pck;
5134 ctx->req_pck_max = pck * 3 / 2;
5135 ctx->dsi_cinfo.clkin = clkin;
5136
5137 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
5138 pll_max = cfg->hs_clk_max * 4;
5139
5140 return dsi_pll_calc(dsi->pdev, clkin,
5141 pll_min, pll_max,
5142 dsi_cm_calc_pll_cb, ctx);
5143}
5144
5145static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
5146{
5147 struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
5148 const struct omap_dss_dsi_config *cfg = ctx->config;
5149 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
5150 int ndl = dsi->num_lanes_used - 1;
5151 unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
5152 unsigned long byteclk = hsclk / 4;
5153
5154 unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
5155 int xres;
5156 int panel_htot, panel_hbl; /* pixels */
5157 int dispc_htot, dispc_hbl; /* pixels */
5158 int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
5159 int hfp, hsa, hbp;
5160 const struct omap_video_timings *req_vm;
5161 struct omap_video_timings *dispc_vm;
5162 struct omap_dss_dsi_videomode_timings *dsi_vm;
5163 u64 dsi_tput, dispc_tput;
5164
5165 dsi_tput = (u64)byteclk * ndl * 8;
5166
5167 req_vm = cfg->timings;
5168 req_pck_min = ctx->req_pck_min;
5169 req_pck_max = ctx->req_pck_max;
5170 req_pck_nom = ctx->req_pck_nom;
5171
5172 dispc_pck = ctx->dispc_cinfo.pck;
5173 dispc_tput = (u64)dispc_pck * bitspp;
5174
5175 xres = req_vm->x_res;
5176
5177 panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
5178 panel_htot = xres + panel_hbl;
5179
5180 dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
5181
5182 /*
5183 * When there are no line buffers, DISPC and DSI must have the
5184 * same tput. Otherwise DISPC tput needs to be higher than DSI's.
5185 */
5186 if (dsi->line_buffer_size < xres * bitspp / 8) {
5187 if (dispc_tput != dsi_tput)
5188 return false;
5189 } else {
5190 if (dispc_tput < dsi_tput)
5191 return false;
5192 }
5193
5194 /* DSI tput must be over the min requirement */
5195 if (dsi_tput < (u64)bitspp * req_pck_min)
5196 return false;
5197
5198 /* When non-burst mode, DSI tput must be below max requirement. */
5199 if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
5200 if (dsi_tput > (u64)bitspp * req_pck_max)
5201 return false;
5202 }
5203
5204 hss = DIV_ROUND_UP(4, ndl);
5205
5206 if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
5207 if (ndl == 3 && req_vm->hsw == 0)
5208 hse = 1;
5209 else
5210 hse = DIV_ROUND_UP(4, ndl);
5211 } else {
5212 hse = 0;
5213 }
5214
5215 /* DSI htot to match the panel's nominal pck */
5216 dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
5217
5218 /* fail if there would be no time for blanking */
5219 if (dsi_htot < hss + hse + dsi_hact)
5220 return false;
5221
5222 /* total DSI blanking needed to achieve panel's TL */
5223 dsi_hbl = dsi_htot - dsi_hact;
5224
5225 /* DISPC htot to match the DSI TL */
5226 dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
5227
5228 /* verify that the DSI and DISPC TLs are the same */
5229 if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
5230 return false;
5231
5232 dispc_hbl = dispc_htot - xres;
5233
5234 /* setup DSI videomode */
5235
5236 dsi_vm = &ctx->dsi_vm;
5237 memset(dsi_vm, 0, sizeof(*dsi_vm));
5238
5239 dsi_vm->hsclk = hsclk;
5240
5241 dsi_vm->ndl = ndl;
5242 dsi_vm->bitspp = bitspp;
5243
5244 if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
5245 hsa = 0;
5246 } else if (ndl == 3 && req_vm->hsw == 0) {
5247 hsa = 0;
5248 } else {
5249 hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
5250 hsa = max(hsa - hse, 1);
5251 }
5252
5253 hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
5254 hbp = max(hbp, 1);
5255
5256 hfp = dsi_hbl - (hss + hsa + hse + hbp);
5257 if (hfp < 1) {
5258 int t;
5259 /* we need to take cycles from hbp */
5260
5261 t = 1 - hfp;
5262 hbp = max(hbp - t, 1);
5263 hfp = dsi_hbl - (hss + hsa + hse + hbp);
5264
5265 if (hfp < 1 && hsa > 0) {
5266 /* we need to take cycles from hsa */
5267 t = 1 - hfp;
5268 hsa = max(hsa - t, 1);
5269 hfp = dsi_hbl - (hss + hsa + hse + hbp);
5270 }
5271 }
5272
5273 if (hfp < 1)
5274 return false;
5275
5276 dsi_vm->hss = hss;
5277 dsi_vm->hsa = hsa;
5278 dsi_vm->hse = hse;
5279 dsi_vm->hbp = hbp;
5280 dsi_vm->hact = xres;
5281 dsi_vm->hfp = hfp;
5282
5283 dsi_vm->vsa = req_vm->vsw;
5284 dsi_vm->vbp = req_vm->vbp;
5285 dsi_vm->vact = req_vm->y_res;
5286 dsi_vm->vfp = req_vm->vfp;
5287
5288 dsi_vm->trans_mode = cfg->trans_mode;
5289
5290 dsi_vm->blanking_mode = 0;
5291 dsi_vm->hsa_blanking_mode = 1;
5292 dsi_vm->hfp_blanking_mode = 1;
5293 dsi_vm->hbp_blanking_mode = 1;
5294
5295 dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
5296 dsi_vm->window_sync = 4;
5297
5298 /* setup DISPC videomode */
5299
5300 dispc_vm = &ctx->dispc_vm;
5301 *dispc_vm = *req_vm;
5302 dispc_vm->pixel_clock = dispc_pck / 1000;
5303
5304 if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
5305 hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
5306 req_pck_nom);
5307 hsa = max(hsa, 1);
5308 } else {
5309 hsa = 1;
5310 }
5311
5312 hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
5313 hbp = max(hbp, 1);
5314
5315 hfp = dispc_hbl - hsa - hbp;
5316 if (hfp < 1) {
5317 int t;
5318 /* we need to take cycles from hbp */
5319
5320 t = 1 - hfp;
5321 hbp = max(hbp - t, 1);
5322 hfp = dispc_hbl - hsa - hbp;
5323
5324 if (hfp < 1) {
5325 /* we need to take cycles from hsa */
5326 t = 1 - hfp;
5327 hsa = max(hsa - t, 1);
5328 hfp = dispc_hbl - hsa - hbp;
5329 }
5330 }
5331
5332 if (hfp < 1)
5333 return false;
5334
5335 dispc_vm->hfp = hfp;
5336 dispc_vm->hsw = hsa;
5337 dispc_vm->hbp = hbp;
5338
5339 return true;
5340}
5341
5342
5343static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
5344 unsigned long pck, void *data)
5345{
5346 struct dsi_clk_calc_ctx *ctx = data;
5347
5348 ctx->dispc_cinfo.lck_div = lckd;
5349 ctx->dispc_cinfo.pck_div = pckd;
5350 ctx->dispc_cinfo.lck = lck;
5351 ctx->dispc_cinfo.pck = pck;
5352
5353 if (dsi_vm_calc_blanking(ctx) == false)
5354 return false;
5355
5356#ifdef PRINT_VERBOSE_VM_TIMINGS
5357 print_dispc_vm("dispc", &ctx->dispc_vm);
5358 print_dsi_vm("dsi ", &ctx->dsi_vm);
5359 print_dispc_vm("req ", ctx->config->timings);
5360 print_dsi_dispc_vm("act ", &ctx->dsi_vm);
5361#endif
5362
5363 return true;
5364}
5365
5366static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
5367 void *data)
5368{
5369 struct dsi_clk_calc_ctx *ctx = data;
5370 unsigned long pck_max;
5371
5372 ctx->dsi_cinfo.regm_dispc = regm_dispc;
5373 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
5374
5375 /*
5376 * In burst mode we can let the dispc pck be arbitrarily high, but it
5377 * limits our scaling abilities. So for now, don't aim too high.
5378 */
5379
5380 if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
5381 pck_max = ctx->req_pck_max + 10000000;
5382 else
5383 pck_max = ctx->req_pck_max;
5384
5385 return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
5386 dsi_vm_calc_dispc_cb, ctx);
5387}
5388
5389static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
5390 unsigned long pll, void *data)
5391{
5392 struct dsi_clk_calc_ctx *ctx = data;
5393
5394 ctx->dsi_cinfo.regn = regn;
5395 ctx->dsi_cinfo.regm = regm;
5396 ctx->dsi_cinfo.fint = fint;
5397 ctx->dsi_cinfo.clkin4ddr = pll;
5398
5399 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
5400 dsi_vm_calc_hsdiv_cb, ctx);
5401}
5402
5403static bool dsi_vm_calc(struct dsi_data *dsi,
5404 const struct omap_dss_dsi_config *cfg,
5405 struct dsi_clk_calc_ctx *ctx)
5406{
5407 const struct omap_video_timings *t = cfg->timings;
5408 unsigned long clkin;
5409 unsigned long pll_min;
5410 unsigned long pll_max;
5411 int ndl = dsi->num_lanes_used - 1;
5412 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
5413 unsigned long byteclk_min;
5414
5415 clkin = clk_get_rate(dsi->sys_clk);
5416
5417 memset(ctx, 0, sizeof(*ctx));
5418 ctx->dsidev = dsi->pdev;
5419 ctx->config = cfg;
5420
5421 ctx->dsi_cinfo.clkin = clkin;
5422
5423 /* these limits should come from the panel driver */
5424 ctx->req_pck_min = t->pixel_clock * 1000 - 1000;
5425 ctx->req_pck_nom = t->pixel_clock * 1000;
5426 ctx->req_pck_max = t->pixel_clock * 1000 + 1000;
5427
5428 byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
5429 pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
5430
5431 if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
5432 pll_max = cfg->hs_clk_max * 4;
5433 } else {
5434 unsigned long byteclk_max;
5435 byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
5436 ndl * 8);
5437
5438 pll_max = byteclk_max * 4 * 4;
5439 }
5440
5441 return dsi_pll_calc(dsi->pdev, clkin,
5442 pll_min, pll_max,
5443 dsi_vm_calc_pll_cb, ctx);
5444}
5445
4944int omapdss_dsi_set_config(struct omap_dss_device *dssdev, 5446int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
4945 const struct omap_dss_dsi_config *config) 5447 const struct omap_dss_dsi_config *config)
4946{ 5448{
4947 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 5449 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4948 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5450 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5451 struct dsi_clk_calc_ctx ctx;
5452 bool ok;
5453 int r;
4949 5454
4950 mutex_lock(&dsi->lock); 5455 mutex_lock(&dsi->lock);
4951 5456
4952 dsi->timings = *config->timings;
4953 dsi->vm_timings = *config->vm_timings;
4954 dsi->pix_fmt = config->pixel_format; 5457 dsi->pix_fmt = config->pixel_format;
4955 dsi->mode = config->mode; 5458 dsi->mode = config->mode;
4956 5459
4957 dsi_set_clocks(dssdev, config->hs_clk, config->lp_clk); 5460 if (config->mode == OMAP_DSS_DSI_VIDEO_MODE)
5461 ok = dsi_vm_calc(dsi, config, &ctx);
5462 else
5463 ok = dsi_cm_calc(dsi, config, &ctx);
5464
5465 if (!ok) {
5466 DSSERR("failed to find suitable DSI clock settings\n");
5467 r = -EINVAL;
5468 goto err;
5469 }
5470
5471 dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
5472
5473 r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min,
5474 config->lp_clk_max);
5475 if (r) {
5476 DSSERR("failed to find suitable DSI LP clock settings\n");
5477 goto err;
5478 }
5479
5480 dsi->user_dsi_cinfo = ctx.dsi_cinfo;
5481 dsi->user_dispc_cinfo = ctx.dispc_cinfo;
5482
5483 dsi->timings = ctx.dispc_vm;
5484 dsi->vm_timings = ctx.dsi_vm;
4958 5485
4959 mutex_unlock(&dsi->lock); 5486 mutex_unlock(&dsi->lock);
4960 5487
4961 return 0; 5488 return 0;
5489err:
5490 mutex_unlock(&dsi->lock);
5491
5492 return r;
4962} 5493}
4963EXPORT_SYMBOL(omapdss_dsi_set_config); 5494EXPORT_SYMBOL(omapdss_dsi_set_config);
4964 5495