@@ -1321,7 +1321,6 @@ static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
13211321 return true;
13221322}
13231323
1324-
13251324static bool
13261325skl_ddi_dp_set_dpll_hw_state (int clock ,
13271326 struct intel_dpll_hw_state * dpll_hw_state )
@@ -1967,6 +1966,301 @@ static const struct intel_dpll_mgr bxt_pll_mgr = {
19671966 .dump_hw_state = bxt_dump_hw_state ,
19681967};
19691968
1969+ static void cnl_ddi_pll_enable (struct drm_i915_private * dev_priv ,
1970+ struct intel_shared_dpll * pll )
1971+ {
1972+ uint32_t val ;
1973+
1974+ /* 1. Enable DPLL power in DPLL_ENABLE. */
1975+ val = I915_READ (CNL_DPLL_ENABLE (pll -> id ));
1976+ val |= PLL_POWER_ENABLE ;
1977+ I915_WRITE (CNL_DPLL_ENABLE (pll -> id ), val );
1978+
1979+ /* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */
1980+ if (intel_wait_for_register (dev_priv ,
1981+ CNL_DPLL_ENABLE (pll -> id ),
1982+ PLL_POWER_STATE ,
1983+ PLL_POWER_STATE ,
1984+ 5 ))
1985+ DRM_ERROR ("PLL %d Power not enabled\n" , pll -> id );
1986+
1987+ /*
1988+ * 3. Configure DPLL_CFGCR0 to set SSC enable/disable,
1989+ * select DP mode, and set DP link rate.
1990+ */
1991+ val = pll -> state .hw_state .cfgcr0 ;
1992+ I915_WRITE (CNL_DPLL_CFGCR0 (pll -> id ), val );
1993+
1994+ /* 4. Reab back to ensure writes completed */
1995+ POSTING_READ (CNL_DPLL_CFGCR0 (pll -> id ));
1996+
1997+ /* 3. Configure DPLL_CFGCR0 */
1998+ /* Avoid touch CFGCR1 if HDMI mode is not enabled */
1999+ if (pll -> state .hw_state .cfgcr0 & DPLL_CTRL1_HDMI_MODE (pll -> id )) {
2000+ val = pll -> state .hw_state .cfgcr1 ;
2001+ I915_WRITE (CNL_DPLL_CFGCR1 (pll -> id ), val );
2002+ /* 4. Reab back to ensure writes completed */
2003+ POSTING_READ (CNL_DPLL_CFGCR1 (pll -> id ));
2004+ }
2005+
2006+ /*
2007+ * 5. If the frequency will result in a change to the voltage
2008+ * requirement, follow the Display Voltage Frequency Switching
2009+ * Sequence Before Frequency Change
2010+ *
2011+ * FIXME: (DVFS) is used to adjust the display voltage to match the
2012+ * display clock frequencies
2013+ */
2014+
2015+ /* 6. Enable DPLL in DPLL_ENABLE. */
2016+ val = I915_READ (CNL_DPLL_ENABLE (pll -> id ));
2017+ val |= PLL_ENABLE ;
2018+ I915_WRITE (CNL_DPLL_ENABLE (pll -> id ), val );
2019+
2020+ /* 7. Wait for PLL lock status in DPLL_ENABLE. */
2021+ if (intel_wait_for_register (dev_priv ,
2022+ CNL_DPLL_ENABLE (pll -> id ),
2023+ PLL_LOCK ,
2024+ PLL_LOCK ,
2025+ 5 ))
2026+ DRM_ERROR ("PLL %d not locked\n" , pll -> id );
2027+
2028+ /*
2029+ * 8. If the frequency will result in a change to the voltage
2030+ * requirement, follow the Display Voltage Frequency Switching
2031+ * Sequence After Frequency Change
2032+ *
2033+ * FIXME: (DVFS) is used to adjust the display voltage to match the
2034+ * display clock frequencies
2035+ */
2036+
2037+ /*
2038+ * 9. turn on the clock for the DDI and map the DPLL to the DDI
2039+ * Done at intel_ddi_clk_select
2040+ */
2041+ }
2042+
2043+ static void cnl_ddi_pll_disable (struct drm_i915_private * dev_priv ,
2044+ struct intel_shared_dpll * pll )
2045+ {
2046+ uint32_t val ;
2047+
2048+ /*
2049+ * 1. Configure DPCLKA_CFGCR0 to turn off the clock for the DDI.
2050+ * Done at intel_ddi_post_disable
2051+ */
2052+
2053+ /*
2054+ * 2. If the frequency will result in a change to the voltage
2055+ * requirement, follow the Display Voltage Frequency Switching
2056+ * Sequence Before Frequency Change
2057+ *
2058+ * FIXME: (DVFS) is used to adjust the display voltage to match the
2059+ * display clock frequencies
2060+ */
2061+
2062+ /* 3. Disable DPLL through DPLL_ENABLE. */
2063+ val = I915_READ (CNL_DPLL_ENABLE (pll -> id ));
2064+ val &= ~PLL_ENABLE ;
2065+ I915_WRITE (CNL_DPLL_ENABLE (pll -> id ), val );
2066+
2067+ /* 4. Wait for PLL not locked status in DPLL_ENABLE. */
2068+ if (intel_wait_for_register (dev_priv ,
2069+ CNL_DPLL_ENABLE (pll -> id ),
2070+ PLL_LOCK ,
2071+ 0 ,
2072+ 5 ))
2073+ DRM_ERROR ("PLL %d locked\n" , pll -> id );
2074+
2075+ /*
2076+ * 5. If the frequency will result in a change to the voltage
2077+ * requirement, follow the Display Voltage Frequency Switching
2078+ * Sequence After Frequency Change
2079+ *
2080+ * FIXME: (DVFS) is used to adjust the display voltage to match the
2081+ * display clock frequencies
2082+ */
2083+
2084+ /* 6. Disable DPLL power in DPLL_ENABLE. */
2085+ val = I915_READ (CNL_DPLL_ENABLE (pll -> id ));
2086+ val &= ~PLL_POWER_ENABLE ;
2087+ I915_WRITE (CNL_DPLL_ENABLE (pll -> id ), val );
2088+
2089+ /* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */
2090+ if (intel_wait_for_register (dev_priv ,
2091+ CNL_DPLL_ENABLE (pll -> id ),
2092+ PLL_POWER_STATE ,
2093+ 0 ,
2094+ 5 ))
2095+ DRM_ERROR ("PLL %d Power not disabled\n" , pll -> id );
2096+ }
2097+
2098+ static bool cnl_ddi_pll_get_hw_state (struct drm_i915_private * dev_priv ,
2099+ struct intel_shared_dpll * pll ,
2100+ struct intel_dpll_hw_state * hw_state )
2101+ {
2102+ uint32_t val ;
2103+ bool ret ;
2104+
2105+ if (!intel_display_power_get_if_enabled (dev_priv , POWER_DOMAIN_PLLS ))
2106+ return false;
2107+
2108+ ret = false;
2109+
2110+ val = I915_READ (CNL_DPLL_ENABLE (pll -> id ));
2111+ if (!(val & PLL_ENABLE ))
2112+ goto out ;
2113+
2114+ val = I915_READ (CNL_DPLL_CFGCR0 (pll -> id ));
2115+ hw_state -> cfgcr0 = val ;
2116+
2117+ /* avoid reading back stale values if HDMI mode is not enabled */
2118+ if (val & DPLL_CFGCR0_HDMI_MODE ) {
2119+ hw_state -> cfgcr1 = I915_READ (CNL_DPLL_CFGCR1 (pll -> id ));
2120+ }
2121+ ret = true;
2122+
2123+ out :
2124+ intel_display_power_put (dev_priv , POWER_DOMAIN_PLLS );
2125+
2126+ return ret ;
2127+ }
2128+
2129+ static bool cnl_ddi_hdmi_pll_dividers (struct intel_crtc * crtc ,
2130+ struct intel_crtc_state * crtc_state ,
2131+ int clock )
2132+ {
2133+ uint32_t cfgcr0 , cfgcr1 ;
2134+ struct skl_wrpll_params wrpll_params = { 0 , };
2135+
2136+ cfgcr0 = DPLL_CFGCR0_HDMI_MODE ;
2137+
2138+ /* FIXME: Proper wrpll calculation done in a following patch */
2139+ return false;
2140+
2141+ cfgcr0 |= DPLL_CFGCR0_DCO_FRACTION (wrpll_params .dco_fraction ) |
2142+ wrpll_params .dco_integer ;
2143+
2144+ cfgcr1 = DPLL_CFGCR1_QDIV_RATIO (wrpll_params .qdiv_ratio ) |
2145+ DPLL_CFGCR1_QDIV_MODE (wrpll_params .qdiv_mode ) |
2146+ DPLL_CFGCR1_KDIV (wrpll_params .kdiv ) |
2147+ DPLL_CFGCR1_PDIV (wrpll_params .pdiv ) |
2148+ wrpll_params .central_freq |
2149+ DPLL_CFGCR1_CENTRAL_FREQ ;
2150+
2151+ memset (& crtc_state -> dpll_hw_state , 0 ,
2152+ sizeof (crtc_state -> dpll_hw_state ));
2153+
2154+ crtc_state -> dpll_hw_state .cfgcr0 = cfgcr0 ;
2155+ crtc_state -> dpll_hw_state .cfgcr1 = cfgcr1 ;
2156+ return true;
2157+ }
2158+
2159+ bool cnl_ddi_dp_set_dpll_hw_state (int clock ,
2160+ struct intel_dpll_hw_state * dpll_hw_state )
2161+ {
2162+ uint32_t cfgcr0 ;
2163+
2164+ cfgcr0 = DPLL_CFGCR0_SSC_ENABLE ;
2165+
2166+ switch (clock / 2 ) {
2167+ case 81000 :
2168+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_810 ;
2169+ break ;
2170+ case 135000 :
2171+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1350 ;
2172+ break ;
2173+ case 270000 :
2174+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2700 ;
2175+ break ;
2176+ /* eDP 1.4 rates */
2177+ case 162000 :
2178+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1620 ;
2179+ break ;
2180+ case 108000 :
2181+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1080 ;
2182+ break ;
2183+ case 216000 :
2184+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2160 ;
2185+ break ;
2186+ case 324000 :
2187+ /* Some SKUs may require elevated I/O voltage to support this */
2188+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_3240 ;
2189+ break ;
2190+ case 405000 :
2191+ /* Some SKUs may require elevated I/O voltage to support this */
2192+ cfgcr0 |= DPLL_CFGCR0_LINK_RATE_4050 ;
2193+ break ;
2194+ }
2195+
2196+ dpll_hw_state -> cfgcr0 = cfgcr0 ;
2197+ return true;
2198+ }
2199+
2200+ static struct intel_shared_dpll *
2201+ cnl_get_dpll (struct intel_crtc * crtc , struct intel_crtc_state * crtc_state ,
2202+ struct intel_encoder * encoder )
2203+ {
2204+ struct intel_shared_dpll * pll ;
2205+ int clock = crtc_state -> port_clock ;
2206+ bool bret ;
2207+ struct intel_dpll_hw_state dpll_hw_state ;
2208+
2209+ memset (& dpll_hw_state , 0 , sizeof (dpll_hw_state ));
2210+
2211+ if (encoder -> type == INTEL_OUTPUT_HDMI ) {
2212+ bret = cnl_ddi_hdmi_pll_dividers (crtc , crtc_state , clock );
2213+ if (!bret ) {
2214+ DRM_DEBUG_KMS ("Could not get HDMI pll dividers.\n" );
2215+ return NULL ;
2216+ }
2217+ } else if (encoder -> type == INTEL_OUTPUT_DP ||
2218+ encoder -> type == INTEL_OUTPUT_DP_MST ||
2219+ encoder -> type == INTEL_OUTPUT_EDP ) {
2220+ bret = cnl_ddi_dp_set_dpll_hw_state (clock , & dpll_hw_state );
2221+ if (!bret ) {
2222+ DRM_DEBUG_KMS ("Could not set DP dpll HW state.\n" );
2223+ return NULL ;
2224+ }
2225+ crtc_state -> dpll_hw_state = dpll_hw_state ;
2226+ } else {
2227+ DRM_DEBUG_KMS ("Skip DPLL setup for encoder %d\n" ,
2228+ encoder -> type );
2229+ return NULL ;
2230+ }
2231+
2232+ pll = intel_find_shared_dpll (crtc , crtc_state ,
2233+ DPLL_ID_SKL_DPLL0 ,
2234+ DPLL_ID_SKL_DPLL2 );
2235+ if (!pll ) {
2236+ DRM_DEBUG_KMS ("No PLL selected\n" );
2237+ return NULL ;
2238+ }
2239+
2240+ intel_reference_shared_dpll (pll , crtc_state );
2241+
2242+ return pll ;
2243+ }
2244+
2245+ static const struct intel_shared_dpll_funcs cnl_ddi_pll_funcs = {
2246+ .enable = cnl_ddi_pll_enable ,
2247+ .disable = cnl_ddi_pll_disable ,
2248+ .get_hw_state = cnl_ddi_pll_get_hw_state ,
2249+ };
2250+
2251+ static const struct dpll_info cnl_plls [] = {
2252+ { "DPLL 0" , DPLL_ID_SKL_DPLL0 , & cnl_ddi_pll_funcs , 0 },
2253+ { "DPLL 1" , DPLL_ID_SKL_DPLL1 , & cnl_ddi_pll_funcs , 0 },
2254+ { "DPLL 2" , DPLL_ID_SKL_DPLL2 , & cnl_ddi_pll_funcs , 0 },
2255+ { NULL , -1 , NULL , },
2256+ };
2257+
2258+ static const struct intel_dpll_mgr cnl_pll_mgr = {
2259+ .dpll_info = cnl_plls ,
2260+ .get_dpll = cnl_get_dpll ,
2261+ .dump_hw_state = skl_dump_hw_state ,
2262+ };
2263+
19702264/**
19712265 * intel_shared_dpll_init - Initialize shared DPLLs
19722266 * @dev: drm device
@@ -1980,7 +2274,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
19802274 const struct dpll_info * dpll_info ;
19812275 int i ;
19822276
1983- if (IS_GEN9_BC (dev_priv ))
2277+ if (IS_CANNONLAKE (dev_priv ))
2278+ dpll_mgr = & cnl_pll_mgr ;
2279+ else if (IS_GEN9_BC (dev_priv ))
19842280 dpll_mgr = & skl_pll_mgr ;
19852281 else if (IS_GEN9_LP (dev_priv ))
19862282 dpll_mgr = & bxt_pll_mgr ;
0 commit comments