sor.c (ca185c68ed626bf91e22e41e2358d39e8508453c) sor.c (34fa183bacf9b5ecfda864857e8a797065b6b7e8)
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8

--- 26 unchanged lines hidden (view full) ---

35 struct tegra_dpaux *dpaux;
36
37 struct mutex lock;
38 bool enabled;
39
40 struct dentry *debugfs;
41};
42
1/*
2 * Copyright (C) 2013 NVIDIA Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8

--- 26 unchanged lines hidden (view full) ---

35 struct tegra_dpaux *dpaux;
36
37 struct mutex lock;
38 bool enabled;
39
40 struct dentry *debugfs;
41};
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 *
44host1x_client_to_sor(struct host1x_client *client)
45{
46 return container_of(client, struct tegra_sor, client);
47}
48
49static inline struct tegra_sor *to_sor(struct tegra_output *output)
50{

--- 237 unchanged lines hidden (view full) ---

288 return 0;
289
290 usleep_range(25, 100);
291 }
292
293 return -ETIMEDOUT;
294}
295
53static inline struct tegra_sor *
54host1x_client_to_sor(struct host1x_client *client)
55{
56 return container_of(client, struct tegra_sor, client);
57}
58
59static inline struct tegra_sor *to_sor(struct tegra_output *output)
60{

--- 237 unchanged lines hidden (view full) ---

298 return 0;
299
300 usleep_range(25, 100);
301 }
302
303 return -ETIMEDOUT;
304}
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)
297{
298 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
299 struct drm_display_mode *mode = &dc->base.mode;
300 unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
301 struct tegra_sor *sor = to_sor(output);
464static int tegra_output_sor_enable(struct tegra_output *output)
465{
466 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
467 struct drm_display_mode *mode = &dc->base.mode;
468 unsigned int vbe, vse, hbe, hse, vbs, hbs, i;
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;
303 int err = 0;
304
305 mutex_lock(&sor->lock);
306
307 if (sor->enabled)
308 goto unlock;
309
310 err = clk_prepare_enable(sor->clk);
311 if (err < 0)
312 goto unlock;
313
314 reset_control_deassert(sor->rst);
315
473 unsigned long value;
474 int err = 0;
475
476 mutex_lock(&sor->lock);
477
478 if (sor->enabled)
479 goto unlock;
480
481 err = clk_prepare_enable(sor->clk);
482 if (err < 0)
483 goto unlock;
484
485 reset_control_deassert(sor->rst);
486
487 /* FIXME: properly convert to struct drm_dp_aux */
488 aux = (struct drm_dp_aux *)sor->dpaux;
489
316 if (sor->dpaux) {
317 err = tegra_dpaux_enable(sor->dpaux);
318 if (err < 0)
319 dev_err(sor->dev, "failed to enable DP: %d\n", err);
490 if (sor->dpaux) {
491 err = tegra_dpaux_enable(sor->dpaux);
492 if (err < 0)
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 }
321
322 err = clk_set_parent(sor->clk, sor->clk_safe);
323 if (err < 0)
324 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
325
501 }
502
503 err = clk_set_parent(sor->clk, sor->clk_safe);
504 if (err < 0)
505 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
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);
327 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
328 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
329 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
330
331 value = tegra_sor_readl(sor, SOR_PLL_2);
332 value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
333 tegra_sor_writel(sor, value, SOR_PLL_2);

--- 121 unchanged lines hidden (view full) ---

455 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
456 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
457
458 /* set linkctl */
459 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
460 value |= SOR_DP_LINKCTL_ENABLE;
461
462 value &= ~SOR_DP_LINKCTL_TU_SIZE_MASK;
515 value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
516 value &= ~SOR_CLK_CNTRL_DP_CLK_SEL_MASK;
517 value |= SOR_CLK_CNTRL_DP_CLK_SEL_SINGLE_DPCLK;
518 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
519
520 value = tegra_sor_readl(sor, SOR_PLL_2);
521 value &= ~SOR_PLL_2_BANDGAP_POWERDOWN;
522 tegra_sor_writel(sor, value, SOR_PLL_2);

--- 121 unchanged lines hidden (view full) ---

644 value |= SOR_CLK_CNTRL_DP_LINK_SPEED_G2_70;
645 tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
646
647 /* set linkctl */
648 value = tegra_sor_readl(sor, SOR_DP_LINKCTL_0);
649 value |= SOR_DP_LINKCTL_ENABLE;
650
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
465 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
466 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
467
468 for (i = 0, value = 0; i < 4; i++) {
469 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
470 SOR_DP_TPG_SCRAMBLER_GALIOS |
471 SOR_DP_TPG_PATTERN_NONE;
472 value = (value << 8) | lane;
473 }
474
475 tegra_sor_writel(sor, value, SOR_DP_TPG);
476
477 value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
478 value &= ~SOR_DP_CONFIG_WATERMARK_MASK;
653
654 value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
655 tegra_sor_writel(sor, value, SOR_DP_LINKCTL_0);
656
657 for (i = 0, value = 0; i < 4; i++) {
658 unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
659 SOR_DP_TPG_SCRAMBLER_GALIOS |
660 SOR_DP_TPG_PATTERN_NONE;
661 value = (value << 8) | lane;
662 }
663
664 tegra_sor_writel(sor, value, SOR_DP_TPG);
665
666 value = tegra_sor_readl(sor, SOR_DP_CONFIG_0);
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
481 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_COUNT_MASK;
669
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
484 value &= ~SOR_DP_CONFIG_ACTIVE_SYM_FRAC_MASK;
672
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
489 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
490 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */
491 tegra_sor_writel(sor, value, SOR_DP_CONFIG_0);
492
493 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
494 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
495 value |= 137; /* XXX: don't hardcode? */

--- 5 unchanged lines hidden (view full) ---

501 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
502
503 /* enable pad calibration logic */
504 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
505 value |= SOR_DP_PADCTL_PAD_CAL_PD;
506 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
507
508 if (sor->dpaux) {
680
681 value |= SOR_DP_CONFIG_ACTIVE_SYM_ENABLE;
682 value |= SOR_DP_CONFIG_DISPARITY_NEGATIVE; /* XXX: don't hardcode? */
683 tegra_sor_writel(sor, value, SOR_DP_CONFIG_0);
684
685 value = tegra_sor_readl(sor, SOR_DP_AUDIO_HBLANK_SYMBOLS);
686 value &= ~SOR_DP_AUDIO_HBLANK_SYMBOLS_MASK;
687 value |= 137; /* XXX: don't hardcode? */

--- 5 unchanged lines hidden (view full) ---

693 tegra_sor_writel(sor, value, SOR_DP_AUDIO_VBLANK_SYMBOLS);
694
695 /* enable pad calibration logic */
696 value = tegra_sor_readl(sor, SOR_DP_PADCTL_0);
697 value |= SOR_DP_PADCTL_PAD_CAL_PD;
698 tegra_sor_writel(sor, value, SOR_DP_PADCTL_0);
699
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;
513
514 err = drm_dp_link_probe(aux, &link);
515 if (err < 0) {
516 dev_err(sor->dev, "failed to probe eDP link: %d\n",
517 err);
518 goto unlock;
519 }

--- 67 unchanged lines hidden (view full) ---

587 value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
588 value &= ~WRITE_MUX;
589 tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
590
591 /*
592 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
593 * raster, associate with display controller)
594 */
701 u8 rate, lanes;
702
703 err = drm_dp_link_probe(aux, &link);
704 if (err < 0) {
705 dev_err(sor->dev, "failed to probe eDP link: %d\n",
706 err);
707 goto unlock;
708 }

--- 67 unchanged lines hidden (view full) ---

776 value = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
777 value &= ~WRITE_MUX;
778 tegra_dc_writel(dc, value, DC_CMD_STATE_ACCESS);
779
780 /*
781 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
782 * raster, associate with display controller)
783 */
595 value = SOR_STATE_ASY_PIXELDEPTH_BPP_24_444 |
596 SOR_STATE_ASY_VSYNCPOL |
784 value = SOR_STATE_ASY_VSYNCPOL |
597 SOR_STATE_ASY_HSYNCPOL |
598 SOR_STATE_ASY_PROTOCOL_DP_A |
599 SOR_STATE_ASY_CRC_MODE_COMPLETE |
600 SOR_STATE_ASY_OWNER(dc->pipe + 1);
785 SOR_STATE_ASY_HSYNCPOL |
786 SOR_STATE_ASY_PROTOCOL_DP_A |
787 SOR_STATE_ASY_CRC_MODE_COMPLETE |
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);
602
603 /*
604 * TODO: The video timing programming below doesn't seem to match the
605 * register definitions.
606 */
607
608 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);

--- 624 unchanged lines hidden ---
804 tegra_sor_writel(sor, value, SOR_STATE_1);
805
806 /*
807 * TODO: The video timing programming below doesn't seem to match the
808 * register definitions.
809 */
810
811 value = ((mode->vtotal & 0x7fff) << 16) | (mode->htotal & 0x7fff);

--- 624 unchanged lines hidden ---