diff options
author | Eric Anholt <eric@anholt.net> | 2011-03-30 16:01:02 -0400 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2011-05-10 16:54:39 -0400 |
commit | f564048e201ead4d4d02138bc60ae28f83797ac4 (patch) | |
tree | c890841377e17de48002b6b07506cad267ee9f49 | |
parent | d2dff872ac44540622ef77a2b7d6ce4a1b145931 (diff) |
drm/i915: Split the crtc_mode_set function along HAS_PCH_SPLIT() lines.
This path, which shouldn't be *that* complicated, is now so littered
with per-chipset tweaks that it's hard to trace the order of what
happens. HAS_PCH_SPLIT() is the most radical change across chipsets,
so it seems like a natural split to simplify the code.
This first commit just copies the existing code without changing
anything.
v2: updated to track removal of call to intel_enable_plane from i9xx_crtc_mode_set
Signed-off-by: Eric Anholt <eric@anholt.net>
Hella-acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 681 |
2 files changed, 680 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1c1b27c97e5c..3778b238356b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -203,6 +203,12 @@ struct drm_i915_display_funcs { | |||
203 | int (*get_display_clock_speed)(struct drm_device *dev); | 203 | int (*get_display_clock_speed)(struct drm_device *dev); |
204 | int (*get_fifo_size)(struct drm_device *dev, int plane); | 204 | int (*get_fifo_size)(struct drm_device *dev, int plane); |
205 | void (*update_wm)(struct drm_device *dev); | 205 | void (*update_wm)(struct drm_device *dev); |
206 | int (*crtc_mode_set)(struct drm_crtc *crtc, | ||
207 | struct drm_display_mode *mode, | ||
208 | struct drm_display_mode *adjusted_mode, | ||
209 | int x, int y, | ||
210 | struct drm_framebuffer *old_fb); | ||
211 | |||
206 | /* clock updates for mode set */ | 212 | /* clock updates for mode set */ |
207 | /* cursor updates */ | 213 | /* cursor updates */ |
208 | /* render clock increase/decrease */ | 214 | /* render clock increase/decrease */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a47e5ee5dcaa..b62136764a2b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4516,11 +4516,659 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) | |||
4516 | return dev_priv->lvds_use_ssc && i915_panel_use_ssc; | 4516 | return dev_priv->lvds_use_ssc && i915_panel_use_ssc; |
4517 | } | 4517 | } |
4518 | 4518 | ||
4519 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 4519 | static int i9xx_crtc_mode_set(struct drm_crtc *crtc, |
4520 | struct drm_display_mode *mode, | 4520 | struct drm_display_mode *mode, |
4521 | struct drm_display_mode *adjusted_mode, | 4521 | struct drm_display_mode *adjusted_mode, |
4522 | int x, int y, | 4522 | int x, int y, |
4523 | struct drm_framebuffer *old_fb) | 4523 | struct drm_framebuffer *old_fb) |
4524 | { | ||
4525 | struct drm_device *dev = crtc->dev; | ||
4526 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4527 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
4528 | int pipe = intel_crtc->pipe; | ||
4529 | int plane = intel_crtc->plane; | ||
4530 | u32 fp_reg, dpll_reg; | ||
4531 | int refclk, num_connectors = 0; | ||
4532 | intel_clock_t clock, reduced_clock; | ||
4533 | u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; | ||
4534 | bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; | ||
4535 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; | ||
4536 | struct intel_encoder *has_edp_encoder = NULL; | ||
4537 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
4538 | struct intel_encoder *encoder; | ||
4539 | const intel_limit_t *limit; | ||
4540 | int ret; | ||
4541 | struct fdi_m_n m_n = {0}; | ||
4542 | u32 reg, temp; | ||
4543 | u32 lvds_sync = 0; | ||
4544 | int target_clock; | ||
4545 | |||
4546 | drm_vblank_pre_modeset(dev, pipe); | ||
4547 | |||
4548 | list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { | ||
4549 | if (encoder->base.crtc != crtc) | ||
4550 | continue; | ||
4551 | |||
4552 | switch (encoder->type) { | ||
4553 | case INTEL_OUTPUT_LVDS: | ||
4554 | is_lvds = true; | ||
4555 | break; | ||
4556 | case INTEL_OUTPUT_SDVO: | ||
4557 | case INTEL_OUTPUT_HDMI: | ||
4558 | is_sdvo = true; | ||
4559 | if (encoder->needs_tv_clock) | ||
4560 | is_tv = true; | ||
4561 | break; | ||
4562 | case INTEL_OUTPUT_DVO: | ||
4563 | is_dvo = true; | ||
4564 | break; | ||
4565 | case INTEL_OUTPUT_TVOUT: | ||
4566 | is_tv = true; | ||
4567 | break; | ||
4568 | case INTEL_OUTPUT_ANALOG: | ||
4569 | is_crt = true; | ||
4570 | break; | ||
4571 | case INTEL_OUTPUT_DISPLAYPORT: | ||
4572 | is_dp = true; | ||
4573 | break; | ||
4574 | case INTEL_OUTPUT_EDP: | ||
4575 | has_edp_encoder = encoder; | ||
4576 | break; | ||
4577 | } | ||
4578 | |||
4579 | num_connectors++; | ||
4580 | } | ||
4581 | |||
4582 | if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { | ||
4583 | refclk = dev_priv->lvds_ssc_freq * 1000; | ||
4584 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | ||
4585 | refclk / 1000); | ||
4586 | } else if (!IS_GEN2(dev)) { | ||
4587 | refclk = 96000; | ||
4588 | if (HAS_PCH_SPLIT(dev) && | ||
4589 | (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base))) | ||
4590 | refclk = 120000; /* 120Mhz refclk */ | ||
4591 | } else { | ||
4592 | refclk = 48000; | ||
4593 | } | ||
4594 | |||
4595 | /* | ||
4596 | * Returns a set of divisors for the desired target clock with the given | ||
4597 | * refclk, or FALSE. The returned values represent the clock equation: | ||
4598 | * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. | ||
4599 | */ | ||
4600 | limit = intel_limit(crtc, refclk); | ||
4601 | ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); | ||
4602 | if (!ok) { | ||
4603 | DRM_ERROR("Couldn't find PLL settings for mode!\n"); | ||
4604 | drm_vblank_post_modeset(dev, pipe); | ||
4605 | return -EINVAL; | ||
4606 | } | ||
4607 | |||
4608 | /* Ensure that the cursor is valid for the new mode before changing... */ | ||
4609 | intel_crtc_update_cursor(crtc, true); | ||
4610 | |||
4611 | if (is_lvds && dev_priv->lvds_downclock_avail) { | ||
4612 | has_reduced_clock = limit->find_pll(limit, crtc, | ||
4613 | dev_priv->lvds_downclock, | ||
4614 | refclk, | ||
4615 | &reduced_clock); | ||
4616 | if (has_reduced_clock && (clock.p != reduced_clock.p)) { | ||
4617 | /* | ||
4618 | * If the different P is found, it means that we can't | ||
4619 | * switch the display clock by using the FP0/FP1. | ||
4620 | * In such case we will disable the LVDS downclock | ||
4621 | * feature. | ||
4622 | */ | ||
4623 | DRM_DEBUG_KMS("Different P is found for " | ||
4624 | "LVDS clock/downclock\n"); | ||
4625 | has_reduced_clock = 0; | ||
4626 | } | ||
4627 | } | ||
4628 | /* SDVO TV has fixed PLL values depend on its clock range, | ||
4629 | this mirrors vbios setting. */ | ||
4630 | if (is_sdvo && is_tv) { | ||
4631 | if (adjusted_mode->clock >= 100000 | ||
4632 | && adjusted_mode->clock < 140500) { | ||
4633 | clock.p1 = 2; | ||
4634 | clock.p2 = 10; | ||
4635 | clock.n = 3; | ||
4636 | clock.m1 = 16; | ||
4637 | clock.m2 = 8; | ||
4638 | } else if (adjusted_mode->clock >= 140500 | ||
4639 | && adjusted_mode->clock <= 200000) { | ||
4640 | clock.p1 = 1; | ||
4641 | clock.p2 = 10; | ||
4642 | clock.n = 6; | ||
4643 | clock.m1 = 12; | ||
4644 | clock.m2 = 8; | ||
4645 | } | ||
4646 | } | ||
4647 | |||
4648 | /* FDI link */ | ||
4649 | if (HAS_PCH_SPLIT(dev)) { | ||
4650 | int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
4651 | int lane = 0, link_bw, bpp; | ||
4652 | /* CPU eDP doesn't require FDI link, so just set DP M/N | ||
4653 | according to current link config */ | ||
4654 | if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
4655 | target_clock = mode->clock; | ||
4656 | intel_edp_link_config(has_edp_encoder, | ||
4657 | &lane, &link_bw); | ||
4658 | } else { | ||
4659 | /* [e]DP over FDI requires target mode clock | ||
4660 | instead of link clock */ | ||
4661 | if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) | ||
4662 | target_clock = mode->clock; | ||
4663 | else | ||
4664 | target_clock = adjusted_mode->clock; | ||
4665 | |||
4666 | /* FDI is a binary signal running at ~2.7GHz, encoding | ||
4667 | * each output octet as 10 bits. The actual frequency | ||
4668 | * is stored as a divider into a 100MHz clock, and the | ||
4669 | * mode pixel clock is stored in units of 1KHz. | ||
4670 | * Hence the bw of each lane in terms of the mode signal | ||
4671 | * is: | ||
4672 | */ | ||
4673 | link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; | ||
4674 | } | ||
4675 | |||
4676 | /* determine panel color depth */ | ||
4677 | temp = I915_READ(PIPECONF(pipe)); | ||
4678 | temp &= ~PIPE_BPC_MASK; | ||
4679 | if (is_lvds) { | ||
4680 | /* the BPC will be 6 if it is 18-bit LVDS panel */ | ||
4681 | if ((I915_READ(PCH_LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) | ||
4682 | temp |= PIPE_8BPC; | ||
4683 | else | ||
4684 | temp |= PIPE_6BPC; | ||
4685 | } else if (has_edp_encoder) { | ||
4686 | switch (dev_priv->edp.bpp/3) { | ||
4687 | case 8: | ||
4688 | temp |= PIPE_8BPC; | ||
4689 | break; | ||
4690 | case 10: | ||
4691 | temp |= PIPE_10BPC; | ||
4692 | break; | ||
4693 | case 6: | ||
4694 | temp |= PIPE_6BPC; | ||
4695 | break; | ||
4696 | case 12: | ||
4697 | temp |= PIPE_12BPC; | ||
4698 | break; | ||
4699 | } | ||
4700 | } else | ||
4701 | temp |= PIPE_8BPC; | ||
4702 | I915_WRITE(PIPECONF(pipe), temp); | ||
4703 | |||
4704 | switch (temp & PIPE_BPC_MASK) { | ||
4705 | case PIPE_8BPC: | ||
4706 | bpp = 24; | ||
4707 | break; | ||
4708 | case PIPE_10BPC: | ||
4709 | bpp = 30; | ||
4710 | break; | ||
4711 | case PIPE_6BPC: | ||
4712 | bpp = 18; | ||
4713 | break; | ||
4714 | case PIPE_12BPC: | ||
4715 | bpp = 36; | ||
4716 | break; | ||
4717 | default: | ||
4718 | DRM_ERROR("unknown pipe bpc value\n"); | ||
4719 | bpp = 24; | ||
4720 | } | ||
4721 | |||
4722 | if (!lane) { | ||
4723 | /* | ||
4724 | * Account for spread spectrum to avoid | ||
4725 | * oversubscribing the link. Max center spread | ||
4726 | * is 2.5%; use 5% for safety's sake. | ||
4727 | */ | ||
4728 | u32 bps = target_clock * bpp * 21 / 20; | ||
4729 | lane = bps / (link_bw * 8) + 1; | ||
4730 | } | ||
4731 | |||
4732 | intel_crtc->fdi_lanes = lane; | ||
4733 | |||
4734 | if (pixel_multiplier > 1) | ||
4735 | link_bw *= pixel_multiplier; | ||
4736 | ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); | ||
4737 | } | ||
4738 | |||
4739 | /* Ironlake: try to setup display ref clock before DPLL | ||
4740 | * enabling. This is only under driver's control after | ||
4741 | * PCH B stepping, previous chipset stepping should be | ||
4742 | * ignoring this setting. | ||
4743 | */ | ||
4744 | if (HAS_PCH_SPLIT(dev)) { | ||
4745 | temp = I915_READ(PCH_DREF_CONTROL); | ||
4746 | /* Always enable nonspread source */ | ||
4747 | temp &= ~DREF_NONSPREAD_SOURCE_MASK; | ||
4748 | temp |= DREF_NONSPREAD_SOURCE_ENABLE; | ||
4749 | temp &= ~DREF_SSC_SOURCE_MASK; | ||
4750 | temp |= DREF_SSC_SOURCE_ENABLE; | ||
4751 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4752 | |||
4753 | POSTING_READ(PCH_DREF_CONTROL); | ||
4754 | udelay(200); | ||
4755 | |||
4756 | if (has_edp_encoder) { | ||
4757 | if (intel_panel_use_ssc(dev_priv)) { | ||
4758 | temp |= DREF_SSC1_ENABLE; | ||
4759 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4760 | |||
4761 | POSTING_READ(PCH_DREF_CONTROL); | ||
4762 | udelay(200); | ||
4763 | } | ||
4764 | temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; | ||
4765 | |||
4766 | /* Enable CPU source on CPU attached eDP */ | ||
4767 | if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
4768 | if (intel_panel_use_ssc(dev_priv)) | ||
4769 | temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; | ||
4770 | else | ||
4771 | temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; | ||
4772 | } else { | ||
4773 | /* Enable SSC on PCH eDP if needed */ | ||
4774 | if (intel_panel_use_ssc(dev_priv)) { | ||
4775 | DRM_ERROR("enabling SSC on PCH\n"); | ||
4776 | temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; | ||
4777 | } | ||
4778 | } | ||
4779 | I915_WRITE(PCH_DREF_CONTROL, temp); | ||
4780 | POSTING_READ(PCH_DREF_CONTROL); | ||
4781 | udelay(200); | ||
4782 | } | ||
4783 | } | ||
4784 | |||
4785 | if (IS_PINEVIEW(dev)) { | ||
4786 | fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; | ||
4787 | if (has_reduced_clock) | ||
4788 | fp2 = (1 << reduced_clock.n) << 16 | | ||
4789 | reduced_clock.m1 << 8 | reduced_clock.m2; | ||
4790 | } else { | ||
4791 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | ||
4792 | if (has_reduced_clock) | ||
4793 | fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | | ||
4794 | reduced_clock.m2; | ||
4795 | } | ||
4796 | |||
4797 | /* Enable autotuning of the PLL clock (if permissible) */ | ||
4798 | if (HAS_PCH_SPLIT(dev)) { | ||
4799 | int factor = 21; | ||
4800 | |||
4801 | if (is_lvds) { | ||
4802 | if ((intel_panel_use_ssc(dev_priv) && | ||
4803 | dev_priv->lvds_ssc_freq == 100) || | ||
4804 | (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) | ||
4805 | factor = 25; | ||
4806 | } else if (is_sdvo && is_tv) | ||
4807 | factor = 20; | ||
4808 | |||
4809 | if (clock.m1 < factor * clock.n) | ||
4810 | fp |= FP_CB_TUNE; | ||
4811 | } | ||
4812 | |||
4813 | dpll = 0; | ||
4814 | if (!HAS_PCH_SPLIT(dev)) | ||
4815 | dpll = DPLL_VGA_MODE_DIS; | ||
4816 | |||
4817 | if (!IS_GEN2(dev)) { | ||
4818 | if (is_lvds) | ||
4819 | dpll |= DPLLB_MODE_LVDS; | ||
4820 | else | ||
4821 | dpll |= DPLLB_MODE_DAC_SERIAL; | ||
4822 | if (is_sdvo) { | ||
4823 | int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
4824 | if (pixel_multiplier > 1) { | ||
4825 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | ||
4826 | dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
4827 | else if (HAS_PCH_SPLIT(dev)) | ||
4828 | dpll |= (pixel_multiplier - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | ||
4829 | } | ||
4830 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
4831 | } | ||
4832 | if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) | ||
4833 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
4834 | |||
4835 | /* compute bitmask from p1 value */ | ||
4836 | if (IS_PINEVIEW(dev)) | ||
4837 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; | ||
4838 | else { | ||
4839 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; | ||
4840 | /* also FPA1 */ | ||
4841 | if (HAS_PCH_SPLIT(dev)) | ||
4842 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; | ||
4843 | if (IS_G4X(dev) && has_reduced_clock) | ||
4844 | dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; | ||
4845 | } | ||
4846 | switch (clock.p2) { | ||
4847 | case 5: | ||
4848 | dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; | ||
4849 | break; | ||
4850 | case 7: | ||
4851 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; | ||
4852 | break; | ||
4853 | case 10: | ||
4854 | dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; | ||
4855 | break; | ||
4856 | case 14: | ||
4857 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; | ||
4858 | break; | ||
4859 | } | ||
4860 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) | ||
4861 | dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); | ||
4862 | } else { | ||
4863 | if (is_lvds) { | ||
4864 | dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; | ||
4865 | } else { | ||
4866 | if (clock.p1 == 2) | ||
4867 | dpll |= PLL_P1_DIVIDE_BY_TWO; | ||
4868 | else | ||
4869 | dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; | ||
4870 | if (clock.p2 == 4) | ||
4871 | dpll |= PLL_P2_DIVIDE_BY_4; | ||
4872 | } | ||
4873 | } | ||
4874 | |||
4875 | if (is_sdvo && is_tv) | ||
4876 | dpll |= PLL_REF_INPUT_TVCLKINBC; | ||
4877 | else if (is_tv) | ||
4878 | /* XXX: just matching BIOS for now */ | ||
4879 | /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ | ||
4880 | dpll |= 3; | ||
4881 | else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) | ||
4882 | dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; | ||
4883 | else | ||
4884 | dpll |= PLL_REF_INPUT_DREFCLK; | ||
4885 | |||
4886 | /* setup pipeconf */ | ||
4887 | pipeconf = I915_READ(PIPECONF(pipe)); | ||
4888 | |||
4889 | /* Set up the display plane register */ | ||
4890 | dspcntr = DISPPLANE_GAMMA_ENABLE; | ||
4891 | |||
4892 | /* Ironlake's plane is forced to pipe, bit 24 is to | ||
4893 | enable color space conversion */ | ||
4894 | if (!HAS_PCH_SPLIT(dev)) { | ||
4895 | if (pipe == 0) | ||
4896 | dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; | ||
4897 | else | ||
4898 | dspcntr |= DISPPLANE_SEL_PIPE_B; | ||
4899 | } | ||
4900 | |||
4901 | if (pipe == 0 && INTEL_INFO(dev)->gen < 4) { | ||
4902 | /* Enable pixel doubling when the dot clock is > 90% of the (display) | ||
4903 | * core speed. | ||
4904 | * | ||
4905 | * XXX: No double-wide on 915GM pipe B. Is that the only reason for the | ||
4906 | * pipe == 0 check? | ||
4907 | */ | ||
4908 | if (mode->clock > | ||
4909 | dev_priv->display.get_display_clock_speed(dev) * 9 / 10) | ||
4910 | pipeconf |= PIPECONF_DOUBLE_WIDE; | ||
4911 | else | ||
4912 | pipeconf &= ~PIPECONF_DOUBLE_WIDE; | ||
4913 | } | ||
4914 | |||
4915 | if (!HAS_PCH_SPLIT(dev)) | ||
4916 | dpll |= DPLL_VCO_ENABLE; | ||
4917 | |||
4918 | DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); | ||
4919 | drm_mode_debug_printmodeline(mode); | ||
4920 | |||
4921 | /* assign to Ironlake registers */ | ||
4922 | if (HAS_PCH_SPLIT(dev)) { | ||
4923 | fp_reg = PCH_FP0(pipe); | ||
4924 | dpll_reg = PCH_DPLL(pipe); | ||
4925 | } else { | ||
4926 | fp_reg = FP0(pipe); | ||
4927 | dpll_reg = DPLL(pipe); | ||
4928 | } | ||
4929 | |||
4930 | /* PCH eDP needs FDI, but CPU eDP does not */ | ||
4931 | if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
4932 | I915_WRITE(fp_reg, fp); | ||
4933 | I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); | ||
4934 | |||
4935 | POSTING_READ(dpll_reg); | ||
4936 | udelay(150); | ||
4937 | } | ||
4938 | |||
4939 | /* enable transcoder DPLL */ | ||
4940 | if (HAS_PCH_CPT(dev)) { | ||
4941 | temp = I915_READ(PCH_DPLL_SEL); | ||
4942 | switch (pipe) { | ||
4943 | case 0: | ||
4944 | temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL; | ||
4945 | break; | ||
4946 | case 1: | ||
4947 | temp |= TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL; | ||
4948 | break; | ||
4949 | case 2: | ||
4950 | /* FIXME: manage transcoder PLLs? */ | ||
4951 | temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL; | ||
4952 | break; | ||
4953 | default: | ||
4954 | BUG(); | ||
4955 | } | ||
4956 | I915_WRITE(PCH_DPLL_SEL, temp); | ||
4957 | |||
4958 | POSTING_READ(PCH_DPLL_SEL); | ||
4959 | udelay(150); | ||
4960 | } | ||
4961 | |||
4962 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. | ||
4963 | * This is an exception to the general rule that mode_set doesn't turn | ||
4964 | * things on. | ||
4965 | */ | ||
4966 | if (is_lvds) { | ||
4967 | reg = LVDS; | ||
4968 | if (HAS_PCH_SPLIT(dev)) | ||
4969 | reg = PCH_LVDS; | ||
4970 | |||
4971 | temp = I915_READ(reg); | ||
4972 | temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; | ||
4973 | if (pipe == 1) { | ||
4974 | if (HAS_PCH_CPT(dev)) | ||
4975 | temp |= PORT_TRANS_B_SEL_CPT; | ||
4976 | else | ||
4977 | temp |= LVDS_PIPEB_SELECT; | ||
4978 | } else { | ||
4979 | if (HAS_PCH_CPT(dev)) | ||
4980 | temp &= ~PORT_TRANS_SEL_MASK; | ||
4981 | else | ||
4982 | temp &= ~LVDS_PIPEB_SELECT; | ||
4983 | } | ||
4984 | /* set the corresponsding LVDS_BORDER bit */ | ||
4985 | temp |= dev_priv->lvds_border_bits; | ||
4986 | /* Set the B0-B3 data pairs corresponding to whether we're going to | ||
4987 | * set the DPLLs for dual-channel mode or not. | ||
4988 | */ | ||
4989 | if (clock.p2 == 7) | ||
4990 | temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; | ||
4991 | else | ||
4992 | temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); | ||
4993 | |||
4994 | /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) | ||
4995 | * appropriately here, but we need to look more thoroughly into how | ||
4996 | * panels behave in the two modes. | ||
4997 | */ | ||
4998 | /* set the dithering flag on non-PCH LVDS as needed */ | ||
4999 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { | ||
5000 | if (dev_priv->lvds_dither) | ||
5001 | temp |= LVDS_ENABLE_DITHER; | ||
5002 | else | ||
5003 | temp &= ~LVDS_ENABLE_DITHER; | ||
5004 | } | ||
5005 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
5006 | lvds_sync |= LVDS_HSYNC_POLARITY; | ||
5007 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
5008 | lvds_sync |= LVDS_VSYNC_POLARITY; | ||
5009 | if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY)) | ||
5010 | != lvds_sync) { | ||
5011 | char flags[2] = "-+"; | ||
5012 | DRM_INFO("Changing LVDS panel from " | ||
5013 | "(%chsync, %cvsync) to (%chsync, %cvsync)\n", | ||
5014 | flags[!(temp & LVDS_HSYNC_POLARITY)], | ||
5015 | flags[!(temp & LVDS_VSYNC_POLARITY)], | ||
5016 | flags[!(lvds_sync & LVDS_HSYNC_POLARITY)], | ||
5017 | flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]); | ||
5018 | temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); | ||
5019 | temp |= lvds_sync; | ||
5020 | } | ||
5021 | I915_WRITE(reg, temp); | ||
5022 | } | ||
5023 | |||
5024 | /* set the dithering flag and clear for anything other than a panel. */ | ||
5025 | if (HAS_PCH_SPLIT(dev)) { | ||
5026 | pipeconf &= ~PIPECONF_DITHER_EN; | ||
5027 | pipeconf &= ~PIPECONF_DITHER_TYPE_MASK; | ||
5028 | if (dev_priv->lvds_dither && (is_lvds || has_edp_encoder)) { | ||
5029 | pipeconf |= PIPECONF_DITHER_EN; | ||
5030 | pipeconf |= PIPECONF_DITHER_TYPE_ST1; | ||
5031 | } | ||
5032 | } | ||
5033 | |||
5034 | if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
5035 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | ||
5036 | } else if (HAS_PCH_SPLIT(dev)) { | ||
5037 | /* For non-DP output, clear any trans DP clock recovery setting.*/ | ||
5038 | I915_WRITE(TRANSDATA_M1(pipe), 0); | ||
5039 | I915_WRITE(TRANSDATA_N1(pipe), 0); | ||
5040 | I915_WRITE(TRANSDPLINK_M1(pipe), 0); | ||
5041 | I915_WRITE(TRANSDPLINK_N1(pipe), 0); | ||
5042 | } | ||
5043 | |||
5044 | if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
5045 | I915_WRITE(dpll_reg, dpll); | ||
5046 | |||
5047 | /* Wait for the clocks to stabilize. */ | ||
5048 | POSTING_READ(dpll_reg); | ||
5049 | udelay(150); | ||
5050 | |||
5051 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { | ||
5052 | temp = 0; | ||
5053 | if (is_sdvo) { | ||
5054 | temp = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
5055 | if (temp > 1) | ||
5056 | temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; | ||
5057 | else | ||
5058 | temp = 0; | ||
5059 | } | ||
5060 | I915_WRITE(DPLL_MD(pipe), temp); | ||
5061 | } else { | ||
5062 | /* The pixel multiplier can only be updated once the | ||
5063 | * DPLL is enabled and the clocks are stable. | ||
5064 | * | ||
5065 | * So write it again. | ||
5066 | */ | ||
5067 | I915_WRITE(dpll_reg, dpll); | ||
5068 | } | ||
5069 | } | ||
5070 | |||
5071 | intel_crtc->lowfreq_avail = false; | ||
5072 | if (is_lvds && has_reduced_clock && i915_powersave) { | ||
5073 | I915_WRITE(fp_reg + 4, fp2); | ||
5074 | intel_crtc->lowfreq_avail = true; | ||
5075 | if (HAS_PIPE_CXSR(dev)) { | ||
5076 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); | ||
5077 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; | ||
5078 | } | ||
5079 | } else { | ||
5080 | I915_WRITE(fp_reg + 4, fp); | ||
5081 | if (HAS_PIPE_CXSR(dev)) { | ||
5082 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); | ||
5083 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; | ||
5084 | } | ||
5085 | } | ||
5086 | |||
5087 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { | ||
5088 | pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; | ||
5089 | /* the chip adds 2 halflines automatically */ | ||
5090 | adjusted_mode->crtc_vdisplay -= 1; | ||
5091 | adjusted_mode->crtc_vtotal -= 1; | ||
5092 | adjusted_mode->crtc_vblank_start -= 1; | ||
5093 | adjusted_mode->crtc_vblank_end -= 1; | ||
5094 | adjusted_mode->crtc_vsync_end -= 1; | ||
5095 | adjusted_mode->crtc_vsync_start -= 1; | ||
5096 | } else | ||
5097 | pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ | ||
5098 | |||
5099 | I915_WRITE(HTOTAL(pipe), | ||
5100 | (adjusted_mode->crtc_hdisplay - 1) | | ||
5101 | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
5102 | I915_WRITE(HBLANK(pipe), | ||
5103 | (adjusted_mode->crtc_hblank_start - 1) | | ||
5104 | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
5105 | I915_WRITE(HSYNC(pipe), | ||
5106 | (adjusted_mode->crtc_hsync_start - 1) | | ||
5107 | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
5108 | |||
5109 | I915_WRITE(VTOTAL(pipe), | ||
5110 | (adjusted_mode->crtc_vdisplay - 1) | | ||
5111 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
5112 | I915_WRITE(VBLANK(pipe), | ||
5113 | (adjusted_mode->crtc_vblank_start - 1) | | ||
5114 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
5115 | I915_WRITE(VSYNC(pipe), | ||
5116 | (adjusted_mode->crtc_vsync_start - 1) | | ||
5117 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
5118 | |||
5119 | /* pipesrc and dspsize control the size that is scaled from, | ||
5120 | * which should always be the user's requested size. | ||
5121 | */ | ||
5122 | if (!HAS_PCH_SPLIT(dev)) { | ||
5123 | I915_WRITE(DSPSIZE(plane), | ||
5124 | ((mode->vdisplay - 1) << 16) | | ||
5125 | (mode->hdisplay - 1)); | ||
5126 | I915_WRITE(DSPPOS(plane), 0); | ||
5127 | } | ||
5128 | I915_WRITE(PIPESRC(pipe), | ||
5129 | ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | ||
5130 | |||
5131 | if (HAS_PCH_SPLIT(dev)) { | ||
5132 | I915_WRITE(PIPE_DATA_M1(pipe), TU_SIZE(m_n.tu) | m_n.gmch_m); | ||
5133 | I915_WRITE(PIPE_DATA_N1(pipe), m_n.gmch_n); | ||
5134 | I915_WRITE(PIPE_LINK_M1(pipe), m_n.link_m); | ||
5135 | I915_WRITE(PIPE_LINK_N1(pipe), m_n.link_n); | ||
5136 | |||
5137 | if (has_edp_encoder && !intel_encoder_is_pch_edp(&has_edp_encoder->base)) { | ||
5138 | ironlake_set_pll_edp(crtc, adjusted_mode->clock); | ||
5139 | } | ||
5140 | } | ||
5141 | |||
5142 | I915_WRITE(PIPECONF(pipe), pipeconf); | ||
5143 | POSTING_READ(PIPECONF(pipe)); | ||
5144 | if (!HAS_PCH_SPLIT(dev)) | ||
5145 | intel_enable_pipe(dev_priv, pipe, false); | ||
5146 | |||
5147 | intel_wait_for_vblank(dev, pipe); | ||
5148 | |||
5149 | if (IS_GEN5(dev)) { | ||
5150 | /* enable address swizzle for tiling buffer */ | ||
5151 | temp = I915_READ(DISP_ARB_CTL); | ||
5152 | I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); | ||
5153 | } | ||
5154 | |||
5155 | I915_WRITE(DSPCNTR(plane), dspcntr); | ||
5156 | POSTING_READ(DSPCNTR(plane)); | ||
5157 | |||
5158 | ret = intel_pipe_set_base(crtc, x, y, old_fb); | ||
5159 | |||
5160 | intel_update_watermarks(dev); | ||
5161 | |||
5162 | drm_vblank_post_modeset(dev, pipe); | ||
5163 | |||
5164 | return ret; | ||
5165 | } | ||
5166 | |||
5167 | static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | ||
5168 | struct drm_display_mode *mode, | ||
5169 | struct drm_display_mode *adjusted_mode, | ||
5170 | int x, int y, | ||
5171 | struct drm_framebuffer *old_fb) | ||
4524 | { | 5172 | { |
4525 | struct drm_device *dev = crtc->dev; | 5173 | struct drm_device *dev = crtc->dev; |
4526 | struct drm_i915_private *dev_priv = dev->dev_private; | 5174 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -5164,6 +5812,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
5164 | return ret; | 5812 | return ret; |
5165 | } | 5813 | } |
5166 | 5814 | ||
5815 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | ||
5816 | struct drm_display_mode *mode, | ||
5817 | struct drm_display_mode *adjusted_mode, | ||
5818 | int x, int y, | ||
5819 | struct drm_framebuffer *old_fb) | ||
5820 | { | ||
5821 | struct drm_device *dev = crtc->dev; | ||
5822 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
5823 | int ret; | ||
5824 | |||
5825 | ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, | ||
5826 | x, y, old_fb); | ||
5827 | |||
5828 | return ret; | ||
5829 | } | ||
5830 | |||
5167 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ | 5831 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ |
5168 | void intel_crtc_load_lut(struct drm_crtc *crtc) | 5832 | void intel_crtc_load_lut(struct drm_crtc *crtc) |
5169 | { | 5833 | { |
@@ -7329,10 +7993,13 @@ static void intel_init_display(struct drm_device *dev) | |||
7329 | struct drm_i915_private *dev_priv = dev->dev_private; | 7993 | struct drm_i915_private *dev_priv = dev->dev_private; |
7330 | 7994 | ||
7331 | /* We always want a DPMS function */ | 7995 | /* We always want a DPMS function */ |
7332 | if (HAS_PCH_SPLIT(dev)) | 7996 | if (HAS_PCH_SPLIT(dev)) { |
7333 | dev_priv->display.dpms = ironlake_crtc_dpms; | 7997 | dev_priv->display.dpms = ironlake_crtc_dpms; |
7334 | else | 7998 | dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; |
7999 | } else { | ||
7335 | dev_priv->display.dpms = i9xx_crtc_dpms; | 8000 | dev_priv->display.dpms = i9xx_crtc_dpms; |
8001 | dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; | ||
8002 | } | ||
7336 | 8003 | ||
7337 | if (I915_HAS_FBC(dev)) { | 8004 | if (I915_HAS_FBC(dev)) { |
7338 | if (HAS_PCH_SPLIT(dev)) { | 8005 | if (HAS_PCH_SPLIT(dev)) { |