aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/tegra/sor.c223
1 files changed, 213 insertions, 10 deletions
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index f082ea22f32e..4b554908be5e 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -40,6 +40,16 @@ struct tegra_sor {
40 struct dentry *debugfs; 40 struct dentry *debugfs;
41}; 41};
42 42
43struct tegra_sor_config {
44 u32 bits_per_pixel;
45
46 u32 active_polarity;
47 u32 active_count;
48 u32 tu_size;
49 u32 active_frac;
50 u32 watermark;
51};
52
43static inline struct tegra_sor * 53static inline struct tegra_sor *
44host1x_client_to_sor(struct host1x_client *client) 54host1x_client_to_sor(struct host1x_client *client)
45{ 55{
@@ -293,12 +303,173 @@ static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
293 return -ETIMEDOUT; 303 return -ETIMEDOUT;
294} 304}
295 305
306struct tegra_sor_params {
307 /* number of link clocks per line */
308 unsigned int num_clocks;
309 /* ratio between input and output */
310 u64 ratio;
311 /* precision factor */
312 u64 precision;
313
314 unsigned int active_polarity;
315 unsigned int active_count;
316 unsigned int active_frac;
317 unsigned int tu_size;
318 unsigned int error;
319};
320
321static int tegra_sor_compute_params(struct tegra_sor *sor,
322 struct tegra_sor_params *params,
323 unsigned int tu_size)
324{
325 u64 active_sym, active_count, frac, approx;
326 u32 active_polarity, active_frac = 0;
327 const u64 f = params->precision;
328 s64 error;
329
330 active_sym = params->ratio * tu_size;
331 active_count = div_u64(active_sym, f) * f;
332 frac = active_sym - active_count;
333
334 /* fraction < 0.5 */
335 if (frac >= (f / 2)) {
336 active_polarity = 1;
337 frac = f - frac;
338 } else {
339 active_polarity = 0;
340 }
341
342 if (frac != 0) {
343 frac = div_u64(f * f, frac); /* 1/fraction */
344 if (frac <= (15 * f)) {
345 active_frac = div_u64(frac, f);
346
347 /* round up */
348 if (active_polarity)
349 active_frac++;
350 } else {
351 active_frac = active_polarity ? 1 : 15;
352 }
353 }
354
355 if (active_frac == 1)
356 active_polarity = 0;
357
358 if (active_polarity == 1) {
359 if (active_frac) {
360 approx = active_count + (active_frac * (f - 1)) * f;
361 approx = div_u64(approx, active_frac * f);
362 } else {
363 approx = active_count + f;
364 }
365 } else {
366 if (active_frac)
367 approx = active_count + div_u64(f, active_frac);
368 else
369 approx = active_count;
370 }
371
372 error = div_s64(active_sym - approx, tu_size);
373 error *= params->num_clocks;
374
375 if (error <= 0 && abs64(error) < params->error) {
376 params->active_count = div_u64(active_count, f);
377 params->active_polarity = active_polarity;
378 params->active_frac = active_frac;
379 params->error = abs64(error);
380 params->tu_size = tu_size;
381
382 if (error == 0)
383 return true;
384 }
385
386 return false;
387}
388
389static int tegra_sor_calc_config(struct tegra_sor *sor,
390 struct drm_display_mode *mode,
391 struct tegra_sor_config *config,
392 struct drm_dp_link *link)
393{
394 const u64 f = 100000, link_rate = link->rate * 1000;
395 const u64 pclk = mode->clock * 1000;
396 struct tegra_sor_params params;
397 u64 input, output, watermark;
398 u32 num_syms_per_line;
399 unsigned int i;
400
401 if (!link_rate || !link->num_lanes || !pclk || !config->bits_per_pixel)
402 return -EINVAL;
403
404 output = link_rate * 8 * link->num_lanes;
405 input = pclk * config->bits_per_pixel;
406
407 if (input >= output)
408 return -ERANGE;
409
410 memset(&params, 0, sizeof(params));
411 params.ratio = div64_u64(input * f, output);
412 params.num_clocks = div_u64(link_rate * mode->hdisplay, pclk);
413 params.precision = f;
414 params.error = 64 * f;
415 params.tu_size = 64;
416
417 for (i = params.tu_size; i >= 32; i--)
418 if (tegra_sor_compute_params(sor, &params, i))
419 break;
420
421 if (params.active_frac == 0) {
422 config->active_polarity = 0;
423 config->active_count = params.active_count;
424
425 if (!params.active_polarity)
426 config->active_count--;
427
428 config->tu_size = params.tu_size;
429 config->active_frac = 1;
430 } else {
431 config->active_polarity = params.active_polarity;
432 config->active_count = params.active_count;
433 config->active_frac = params.active_frac;
434 config->tu_size = params.tu_size;
435 }
436
437 dev_dbg(sor->dev,
438 "polarity: %d active count: %d tu size: %d active frac: %d\n",
439 config->active_polarity, config->active_count,
440 config->tu_size, config->active_frac);
441
442 watermark = params.ratio * config->tu_size * (f - params.ratio);
443 watermark = div_u64(watermark, f);
444
445 watermark = div_u64(watermark + params.error, f);
446 config->watermark = watermark + (config->bits_per_pixel / 8) + 2;
447 num_syms_per_line = (mode->hdisplay * config->bits_per_pixel) *
448 (link->num_lanes * 8);
449
450 if (config->watermark > 30) {
451 config->watermark = 30;
452 dev_err(sor->dev,
453 "unable to compute TU size, forcing watermark to %u\n",
454 config->watermark);
455 } else if (config->watermark > num_syms_per_line) {
456 config->watermark = num_syms_per_line;
457 dev_err(sor->dev, "watermark too high, forcing to %u\n",
458 config->watermark);
459 }
460
461 return 0;
462}
463
296static int tegra_output_sor_enable(struct tegra_output *output) 464static int tegra_output_sor_enable(struct tegra_output *output)
297{ 465{
298 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 466 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
299 struct drm_display_mode *mode = &dc->base.mode; 467 struct drm_display_mode *mode = &dc->base.mode;
300 unsigned int vbe, vse, hbe, hse, vbs, hbs, i; 468 unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
301 struct tegra_sor *sor = to_sor(output); 469 struct tegra_sor *sor = to_sor(output);
470 struct tegra_sor_config config;
471 struct drm_dp_link link;
472 struct drm_dp_aux *aux;
302 unsigned long value; 473 unsigned long value;
303 int err = 0; 474 int err = 0;
304 475
@@ -313,16 +484,34 @@ static int tegra_output_sor_enable(struct tegra_output *output)
313 484
314 reset_control_deassert(sor->rst); 485 reset_control_deassert(sor->rst);
315 486
487 /* FIXME: properly convert to struct drm_dp_aux */
488 aux = (struct drm_dp_aux *)sor->dpaux;
489
316 if (sor->dpaux) { 490 if (sor->dpaux) {
317 err = tegra_dpaux_enable(sor->dpaux); 491 err = tegra_dpaux_enable(sor->dpaux);
318 if (err < 0) 492 if (err < 0)
319 dev_err(sor->dev, "failed to enable DP: %d\n", err); 493 dev_err(sor->dev, "failed to enable DP: %d\n", err);
494
495 err = drm_dp_link_probe(aux, &link);
496 if (err < 0) {
497 dev_err(sor->dev, "failed to probe eDP link: %d\n",
498 err);
499 return err;
500 }
320 } 501 }
321 502
322 err = clk_set_parent(sor->clk, sor->clk_safe); 503 err = clk_set_parent(sor->clk, sor->clk_safe);
323 if (err < 0) 504 if (err < 0)
324 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); 505 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
325 506
507 memset(&config, 0, sizeof(config));
508 config.bits_per_pixel = 24; /* XXX: don't hardcode? */
509
510 err = tegra_sor_calc_config(sor, mode, &config, &link);
511 if (err < 0)
512 dev_err(sor->dev, "failed to compute link configuration: %d\n",
513 err);
514
326 value = tegra_sor_readl(sor, SOR_CLK_CNTRL); 515 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
327 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK; 516 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
328 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK; 517 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
@@ -460,7 +649,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
460 value |= SOR_DP_LINKCTL_ENABLE; 649 value |= SOR_DP_LINKCTL_ENABLE;
461 650
462 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK; 651 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
463 value |= SOR_DP_LINKCTL_TU_SIZE(59); /* XXX: don't hardcode? */ 652 value |= SOR_DP_LINKCTL_TU_SIZE(config.tu_size);
464 653
465 value |= SOR_DP_LINKCTL_ENHANCED_FRAME; 654 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
466 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0); 655 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
@@ -476,15 +665,18 @@ static int tegra_output_sor_enable(struct tegra_output *output)
476 665
477 value = tegra_sor_readl(sor, SOR_DP_CONFIG_0); 666 value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
478 value &= ~SOR_DP_CONFIG_WATERMARK_MASK; 667 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
479 value |= SOR_DP_CONFIG_WATERMARK(14); /* XXX: don't hardcode? */ 668 value |= SOR_DP_CONFIG_WATERMARK(config.watermark);
480 669
481 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK; 670 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
482 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(47); /* XXX: don't hardcode? */ 671 value |= SOR_DP_CONFIG_ACTIVE_SYM_COUNT(config.active_count);
483 672
484 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK; 673 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
485 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(9); /* XXX: don't hardcode? */ 674 value |= SOR_DP_CONFIG_ACTIVE_SYM_FRAC(config.active_frac);
486 675
487 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY; /* XXX: don't hardcode? */ 676 if (config.active_polarity)
677 value |= SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
678 else
679 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_POLARITY;
488 680
489 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE; 681 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
490 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */ 682 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */
@@ -506,9 +698,6 @@ static int tegra_output_sor_enable(struct tegra_output *output)
506 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0); 698 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
507 699
508 if (sor->dpaux) { 700 if (sor->dpaux) {
509 /* FIXME: properly convert to struct drm_dp_aux */
510 struct drm_dp_aux *aux = (struct drm_dp_aux *)sor->dpaux;
511 struct drm_dp_link link;
512 u8 rate, lanes; 701 u8 rate, lanes;
513 702
514 err = drm_dp_link_probe(aux, &link); 703 err = drm_dp_link_probe(aux, &link);
@@ -592,12 +781,26 @@ static int tegra_output_sor_enable(struct tegra_output *output)
592 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete 781 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
593 * raster, associate with display controller) 782 * raster, associate with display controller)
594 */ 783 */
595 value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 | 784 value = SOR_STATE_ASY_VSYNCPOL |
596 SOR_STATE_ASY_VSYNCPOL |
597 SOR_STATE_ASY_HSYNCPOL | 785 SOR_STATE_ASY_HSYNCPOL |
598 SOR_STATE_ASY_PROTOCOL_DP_A | 786 SOR_STATE_ASY_PROTOCOL_DP_A |
599 SOR_STATE_ASY_CRC_MODE_COMPLETE | 787 SOR_STATE_ASY_CRC_MODE_COMPLETE |
600 SOR_STATE_ASY_OWNER(dc->pipe + 1); 788 SOR_STATE_ASY_OWNER(dc->pipe + 1);
789
790 switch (config.bits_per_pixel) {
791 case 24:
792 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
793 break;
794
795 case 18:
796 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_18_444;
797 break;
798
799 default:
800 BUG();
801 break;
802 }
803
601 tegra_sor_writel(sor, value, SOR_STATE_1); 804 tegra_sor_writel(sor, value, SOR_STATE_1);
602 805
603 /* 806 /*