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(¶ms, 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, ¶ms, 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 --- |