aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2013-03-05 10:21:35 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2013-04-03 08:19:18 -0400
commitf1e0001f973cfbec62d702cbd3d56f6b703cc90e (patch)
treeb78e0b018a32bbd4377e238887ad2eac0b51598a
parent100c826235793345efe06b3558cc9d36166b1e26 (diff)
OMAPDSS: DSI: use new clock calculation code
Use the new clock calculation code in the DSI driver. The new code does not need DSI video mode parameters from the panel driver, like the old code does. Instead the new code is given the normal video timings, and a few DSI parameters, which are used to create DSI video timings. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/video/omap2/displays/panel-taal.c7
-rw-r--r--drivers/video/omap2/dss/dsi.c557
-rw-r--r--include/video/omapdss.h20
3 files changed, 566 insertions, 18 deletions
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index eb86cbae8c2a..2fc923de23cc 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -787,6 +787,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
787 787
788 dssdev->panel.timings.x_res = 864; 788 dssdev->panel.timings.x_res = 864;
789 dssdev->panel.timings.y_res = 480; 789 dssdev->panel.timings.y_res = 480;
790 dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000);
790 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; 791 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
791 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 792 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
792 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 793 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
@@ -923,8 +924,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
923 .mode = OMAP_DSS_DSI_CMD_MODE, 924 .mode = OMAP_DSS_DSI_CMD_MODE,
924 .pixel_format = OMAP_DSS_DSI_FMT_RGB888, 925 .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
925 .timings = &dssdev->panel.timings, 926 .timings = &dssdev->panel.timings,
926 .hs_clk = 216000000, 927 .hs_clk_min = 150000000,
927 .lp_clk = 10000000, 928 .hs_clk_max = 300000000,
929 .lp_clk_min = 7000000,
930 .lp_clk_max = 10000000,
928 }; 931 };
929 932
930 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); 933 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
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
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 7f774c5f8b6b..8821d933d9fd 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -267,9 +267,21 @@ enum omap_dss_dsi_trans_mode {
267}; 267};
268 268
269struct omap_dss_dsi_videomode_timings { 269struct omap_dss_dsi_videomode_timings {
270 unsigned long hsclk;
271
272 unsigned ndl;
273 unsigned bitspp;
274
275 /* pixels */
276 u16 hact;
277 /* lines */
278 u16 vact;
279
270 /* DSI video mode blanking data */ 280 /* DSI video mode blanking data */
271 /* Unit: byte clock cycles */ 281 /* Unit: byte clock cycles */
282 u16 hss;
272 u16 hsa; 283 u16 hsa;
284 u16 hse;
273 u16 hfp; 285 u16 hfp;
274 u16 hbp; 286 u16 hbp;
275 /* Unit: line clocks */ 287 /* Unit: line clocks */
@@ -293,10 +305,12 @@ struct omap_dss_dsi_config {
293 enum omap_dss_dsi_mode mode; 305 enum omap_dss_dsi_mode mode;
294 enum omap_dss_dsi_pixel_format pixel_format; 306 enum omap_dss_dsi_pixel_format pixel_format;
295 const struct omap_video_timings *timings; 307 const struct omap_video_timings *timings;
296 const struct omap_dss_dsi_videomode_timings *vm_timings;
297 308
298 unsigned long hs_clk; 309 unsigned long hs_clk_min, hs_clk_max;
299 unsigned long lp_clk; 310 unsigned long lp_clk_min, lp_clk_max;
311
312 bool ddr_clk_always_on;
313 enum omap_dss_dsi_trans_mode trans_mode;
300}; 314};
301 315
302void dsi_bus_lock(struct omap_dss_device *dssdev); 316void dsi_bus_lock(struct omap_dss_device *dssdev);