2016-03-08 17:46:19 +02:00
/*
* Copyright © 2012 - 2016 Intel Corporation
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE .
*
*/
# ifndef _INTEL_DPLL_MGR_H_
# define _INTEL_DPLL_MGR_H_
2019-04-29 15:29:22 +03:00
# include <linux/types.h>
# include "intel_display.h"
2019-07-03 16:03:53 -07:00
# include "intel_wakeref.h"
2019-04-29 15:29:22 +03:00
2016-03-08 17:46:23 +02:00
/*FIXME: Move this to a more appropriate place. */
# define abs_diff(a, b) ({ \
typeof ( a ) __a = ( a ) ; \
typeof ( b ) __b = ( b ) ; \
( void ) ( & __a = = & __b ) ; \
__a > __b ? ( __a - __b ) : ( __b - __a ) ; } )
2019-04-29 15:29:22 +03:00
struct drm_device ;
2016-03-08 17:46:19 +02:00
struct drm_i915_private ;
2019-06-28 17:36:28 +03:00
struct intel_atomic_state ;
2016-03-08 17:46:20 +02:00
struct intel_crtc ;
struct intel_crtc_state ;
2016-03-08 17:46:23 +02:00
struct intel_encoder ;
struct intel_shared_dpll ;
2016-03-08 17:46:22 +02:00
2016-12-29 17:22:11 +02:00
/**
* enum intel_dpll_id - possible DPLL ids
*
* Enumeration of possible IDs for a DPLL . Real shared dpll ids must be > = 0.
*/
2016-03-08 17:46:19 +02:00
enum intel_dpll_id {
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_PRIVATE : non - shared dpll in use
*/
DPLL_ID_PRIVATE = - 1 ,
/**
* @ DPLL_ID_PCH_PLL_A : DPLL A in ILK , SNB and IVB
*/
2016-03-08 17:46:19 +02:00
DPLL_ID_PCH_PLL_A = 0 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_PCH_PLL_B : DPLL B in ILK , SNB and IVB
*/
2016-03-08 17:46:19 +02:00
DPLL_ID_PCH_PLL_B = 1 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_WRPLL1 : HSW and BDW WRPLL1
*/
2016-03-08 17:46:19 +02:00
DPLL_ID_WRPLL1 = 0 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_WRPLL2 : HSW and BDW WRPLL2
*/
2016-03-08 17:46:19 +02:00
DPLL_ID_WRPLL2 = 1 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_SPLL : HSW and BDW SPLL
*/
2016-03-08 17:46:19 +02:00
DPLL_ID_SPLL = 2 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_LCPLL_810 : HSW and BDW 0.81 GHz LCPLL
*/
2016-03-08 17:46:26 +02:00
DPLL_ID_LCPLL_810 = 3 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_LCPLL_1350 : HSW and BDW 1.35 GHz LCPLL
*/
2016-03-08 17:46:26 +02:00
DPLL_ID_LCPLL_1350 = 4 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_LCPLL_2700 : HSW and BDW 2.7 GHz LCPLL
*/
2016-03-08 17:46:26 +02:00
DPLL_ID_LCPLL_2700 = 5 ,
2016-03-08 17:46:19 +02:00
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_SKL_DPLL0 : SKL and later DPLL0
*/
2016-03-08 17:46:27 +02:00
DPLL_ID_SKL_DPLL0 = 0 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_SKL_DPLL1 : SKL and later DPLL1
*/
2016-03-08 17:46:27 +02:00
DPLL_ID_SKL_DPLL1 = 1 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_SKL_DPLL2 : SKL and later DPLL2
*/
2016-03-08 17:46:27 +02:00
DPLL_ID_SKL_DPLL2 = 2 ,
2016-12-29 17:22:11 +02:00
/**
* @ DPLL_ID_SKL_DPLL3 : SKL and later DPLL3
*/
2016-03-08 17:46:27 +02:00
DPLL_ID_SKL_DPLL3 = 3 ,
2018-04-27 16:14:36 -07:00
/**
2019-07-11 10:31:04 -07:00
* @ DPLL_ID_ICL_DPLL0 : ICL / TGL combo PHY DPLL0
2018-04-27 16:14:36 -07:00
*/
DPLL_ID_ICL_DPLL0 = 0 ,
/**
2019-07-11 10:31:04 -07:00
* @ DPLL_ID_ICL_DPLL1 : ICL / TGL combo PHY DPLL1
2018-04-27 16:14:36 -07:00
*/
DPLL_ID_ICL_DPLL1 = 1 ,
2019-07-03 16:03:53 -07:00
/**
* @ DPLL_ID_EHL_DPLL4 : EHL combo PHY DPLL4
*/
DPLL_ID_EHL_DPLL4 = 2 ,
2018-05-21 17:25:48 -07:00
/**
2019-07-11 10:31:04 -07:00
* @ DPLL_ID_ICL_TBTPLL : ICL / TGL TBT PLL
2018-05-21 17:25:48 -07:00
*/
DPLL_ID_ICL_TBTPLL = 2 ,
2018-04-27 16:14:36 -07:00
/**
2019-07-11 10:31:04 -07:00
* @ DPLL_ID_ICL_MGPLL1 : ICL MG PLL 1 port 1 ( C ) ,
* TGL TC PLL 1 port 1 ( TC1 )
2018-04-27 16:14:36 -07:00
*/
2018-05-21 17:25:48 -07:00
DPLL_ID_ICL_MGPLL1 = 3 ,
2018-04-27 16:14:36 -07:00
/**
* @ DPLL_ID_ICL_MGPLL2 : ICL MG PLL 1 port 2 ( D )
2019-07-11 10:31:04 -07:00
* TGL TC PLL 1 port 2 ( TC2 )
2018-04-27 16:14:36 -07:00
*/
2018-05-21 17:25:48 -07:00
DPLL_ID_ICL_MGPLL2 = 4 ,
2018-04-27 16:14:36 -07:00
/**
* @ DPLL_ID_ICL_MGPLL3 : ICL MG PLL 1 port 3 ( E )
2019-07-11 10:31:04 -07:00
* TGL TC PLL 1 port 3 ( TC3 )
2018-04-27 16:14:36 -07:00
*/
2018-05-21 17:25:48 -07:00
DPLL_ID_ICL_MGPLL3 = 5 ,
2018-04-27 16:14:36 -07:00
/**
* @ DPLL_ID_ICL_MGPLL4 : ICL MG PLL 1 port 4 ( F )
2019-07-11 10:31:04 -07:00
* TGL TC PLL 1 port 4 ( TC4 )
2018-04-27 16:14:36 -07:00
*/
2018-05-21 17:25:48 -07:00
DPLL_ID_ICL_MGPLL4 = 6 ,
2019-07-11 10:31:04 -07:00
/**
* @ DPLL_ID_TGL_TCPLL5 : TGL TC PLL port 5 ( TC5 )
*/
DPLL_ID_TGL_MGPLL5 = 7 ,
/**
* @ DPLL_ID_TGL_TCPLL6 : TGL TC PLL port 6 ( TC6 )
*/
DPLL_ID_TGL_MGPLL6 = 8 ,
2016-03-08 17:46:19 +02:00
} ;
2019-07-11 10:31:04 -07:00
# define I915_NUM_PLLS 9
2016-03-08 17:46:26 +02:00
2019-06-28 17:36:31 +03:00
enum icl_port_dpll_id {
ICL_PORT_DPLL_DEFAULT ,
ICL_PORT_DPLL_MG_PHY ,
ICL_PORT_DPLL_COUNT ,
} ;
2016-03-08 17:46:19 +02:00
struct intel_dpll_hw_state {
/* i9xx, pch plls */
2019-01-16 11:15:26 +02:00
u32 dpll ;
u32 dpll_md ;
u32 fp0 ;
u32 fp1 ;
2016-03-08 17:46:19 +02:00
/* hsw, bdw */
2019-01-16 11:15:26 +02:00
u32 wrpll ;
u32 spll ;
2016-03-08 17:46:19 +02:00
/* skl */
/*
* DPLL_CTRL1 has 6 bits for each each this DPLL . We store those in
* lower part of ctrl1 and they get shifted into position when writing
* the register . This allows us to easily compare the state to share
* the DPLL .
*/
2019-01-16 11:15:26 +02:00
u32 ctrl1 ;
2016-03-08 17:46:19 +02:00
/* HDMI only, 0 when used for DP */
2019-01-16 11:15:26 +02:00
u32 cfgcr1 , cfgcr2 ;
2016-03-08 17:46:19 +02:00
2017-06-09 15:26:04 -07:00
/* cnl */
2019-01-16 11:15:26 +02:00
u32 cfgcr0 ;
2017-06-09 15:26:04 -07:00
/* CNL also uses cfgcr1 */
2016-03-08 17:46:19 +02:00
/* bxt */
2019-01-16 11:15:26 +02:00
u32 ebb0 , ebb4 , pll0 , pll1 , pll2 , pll3 , pll6 , pll8 , pll9 , pll10 , pcsdw12 ;
2018-04-27 16:14:36 -07:00
/*
* ICL uses the following , already defined :
2019-01-16 11:15:26 +02:00
* u32 cfgcr0 , cfgcr1 ;
*/
u32 mg_refclkin_ctl ;
u32 mg_clktop2_coreclkctl1 ;
u32 mg_clktop2_hsclkctl ;
u32 mg_pll_div0 ;
u32 mg_pll_div1 ;
u32 mg_pll_lf ;
u32 mg_pll_frac_lock ;
u32 mg_pll_ssc ;
u32 mg_pll_bias ;
u32 mg_pll_tdc_coldst_bias ;
u32 mg_pll_bias_mask ;
u32 mg_pll_tdc_coldst_bias_mask ;
2016-03-08 17:46:19 +02:00
} ;
2016-12-29 17:22:11 +02:00
/**
* struct intel_shared_dpll_state - hold the DPLL atomic state
*
* This structure holds an atomic state for the DPLL , that can represent
* either its current state ( in struct & intel_shared_dpll ) or a desired
* future state which would be applied by an atomic mode set ( stored in
* a struct & intel_atomic_state ) .
*
2019-06-28 17:36:28 +03:00
* See also intel_reserve_shared_dplls ( ) and intel_release_shared_dplls ( ) .
2016-12-29 17:22:11 +02:00
*/
2016-12-29 17:22:09 +02:00
struct intel_shared_dpll_state {
2016-12-29 17:22:11 +02:00
/**
* @ crtc_mask : mask of CRTC using this DPLL , active or not
*/
unsigned crtc_mask ;
/**
* @ hw_state : hardware configuration for the DPLL stored in
* struct & intel_dpll_hw_state .
*/
2016-03-08 17:46:19 +02:00
struct intel_dpll_hw_state hw_state ;
} ;
2016-12-29 17:22:11 +02:00
/**
* struct intel_shared_dpll_funcs - platform specific hooks for managing DPLLs
*/
2016-03-08 17:46:21 +02:00
struct intel_shared_dpll_funcs {
2016-12-29 17:22:11 +02:00
/**
* @ prepare :
*
* Optional hook to perform operations prior to enabling the PLL .
* Called from intel_prepare_shared_dpll ( ) function unless the PLL
* is already enabled .
*/
2016-12-29 17:22:10 +02:00
void ( * prepare ) ( struct drm_i915_private * dev_priv ,
struct intel_shared_dpll * pll ) ;
2016-12-29 17:22:11 +02:00
/**
* @ enable :
*
* Hook for enabling the pll , called from intel_enable_shared_dpll ( )
* if the pll is not already enabled .
*/
2016-03-08 17:46:19 +02:00
void ( * enable ) ( struct drm_i915_private * dev_priv ,
struct intel_shared_dpll * pll ) ;
2016-12-29 17:22:11 +02:00
/**
* @ disable :
*
* Hook for disabling the pll , called from intel_disable_shared_dpll ( )
* only when it is safe to disable the pll , i . e . , there are no more
* tracked users for it .
*/
2016-03-08 17:46:19 +02:00
void ( * disable ) ( struct drm_i915_private * dev_priv ,
struct intel_shared_dpll * pll ) ;
2016-12-29 17:22:11 +02:00
/**
* @ get_hw_state :
*
* Hook for reading the values currently programmed to the DPLL
* registers . This is used for initial hw state readout and state
* verification after a mode set .
*/
2016-03-08 17:46:19 +02:00
bool ( * get_hw_state ) ( struct drm_i915_private * dev_priv ,
struct intel_shared_dpll * pll ,
struct intel_dpll_hw_state * hw_state ) ;
} ;
2018-03-20 15:06:31 -07:00
/**
* struct dpll_info - display PLL platform specific info
*/
struct dpll_info {
2018-03-20 15:06:34 -07:00
/**
* @ name : DPLL name ; used for logging
*/
2018-03-20 15:06:31 -07:00
const char * name ;
2018-03-20 15:06:37 -07:00
2018-03-20 15:06:33 -07:00
/**
* @ funcs : platform specific hooks
*/
2018-03-20 15:06:31 -07:00
const struct intel_shared_dpll_funcs * funcs ;
2018-03-20 15:06:37 -07:00
/**
* @ id : unique indentifier for this DPLL ; should match the index in the
* dev_priv - > shared_dplls array
*/
enum intel_dpll_id id ;
2018-03-20 15:06:36 -07:00
# define INTEL_DPLL_ALWAYS_ON (1 << 0)
/**
* @ flags :
*
* INTEL_DPLL_ALWAYS_ON
* Inform the state checker that the DPLL is kept enabled even if
* not in use by any CRTC .
*/
2019-01-16 11:15:26 +02:00
u32 flags ;
2018-03-20 15:06:31 -07:00
} ;
2016-12-29 17:22:11 +02:00
/**
* struct intel_shared_dpll - display PLL with tracked state and users
*/
2016-03-08 17:46:21 +02:00
struct intel_shared_dpll {
2016-12-29 17:22:11 +02:00
/**
* @ state :
*
2019-06-07 13:31:18 +02:00
* Store the state for the pll , including its hw state
2016-12-29 17:22:11 +02:00
* and CRTCs using it .
*/
2016-12-29 17:22:09 +02:00
struct intel_shared_dpll_state state ;
2016-03-08 17:46:21 +02:00
2016-12-29 17:22:11 +02:00
/**
* @ active_mask : mask of active CRTCs ( i . e . DPMS on ) using this DPLL
*/
unsigned active_mask ;
/**
* @ on : is the PLL actually active ? Disabled during modeset
*/
bool on ;
2018-03-20 15:06:32 -07:00
/**
* @ info : platform specific info
*/
const struct dpll_info * info ;
2019-10-08 12:28:49 +03:00
/**
* @ wakeref : In some platforms a device - level runtime pm reference may
* need to be grabbed to disable DC states while this DPLL is enabled
*/
2019-07-03 16:03:53 -07:00
intel_wakeref_t wakeref ;
2016-03-08 17:46:21 +02:00
} ;
2016-03-08 17:46:19 +02:00
# define SKL_DPLL0 0
# define SKL_DPLL1 1
# define SKL_DPLL2 2
# define SKL_DPLL3 3
2016-03-08 17:46:20 +02:00
/* shared dpll functions */
struct intel_shared_dpll *
intel_get_shared_dpll_by_id ( struct drm_i915_private * dev_priv ,
enum intel_dpll_id id ) ;
enum intel_dpll_id
intel_get_shared_dpll_id ( struct drm_i915_private * dev_priv ,
struct intel_shared_dpll * pll ) ;
void assert_shared_dpll ( struct drm_i915_private * dev_priv ,
struct intel_shared_dpll * pll ,
bool state ) ;
# define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
# define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
2019-06-28 17:36:28 +03:00
bool intel_reserve_shared_dplls ( struct intel_atomic_state * state ,
struct intel_crtc * crtc ,
struct intel_encoder * encoder ) ;
void intel_release_shared_dplls ( struct intel_atomic_state * state ,
struct intel_crtc * crtc ) ;
2019-06-28 17:36:31 +03:00
void icl_set_active_port_dpll ( struct intel_crtc_state * crtc_state ,
enum icl_port_dpll_id port_dpll_id ) ;
2019-06-28 17:36:32 +03:00
void intel_update_active_dpll ( struct intel_atomic_state * state ,
struct intel_crtc * crtc ,
struct intel_encoder * encoder ) ;
2018-10-05 11:52:44 +02:00
void intel_prepare_shared_dpll ( const struct intel_crtc_state * crtc_state ) ;
void intel_enable_shared_dpll ( const struct intel_crtc_state * crtc_state ) ;
void intel_disable_shared_dpll ( const struct intel_crtc_state * crtc_state ) ;
2019-07-01 19:05:47 +03:00
void intel_shared_dpll_swap_state ( struct intel_atomic_state * state ) ;
2016-03-08 17:46:20 +02:00
void intel_shared_dpll_init ( struct drm_device * dev ) ;
2016-12-29 17:22:12 +02:00
void intel_dpll_dump_hw_state ( struct drm_i915_private * dev_priv ,
2019-05-17 22:31:31 +03:00
const struct intel_dpll_hw_state * hw_state ) ;
2018-09-03 17:28:41 +03:00
int cnl_hdmi_pll_ref_clock ( struct drm_i915_private * dev_priv ) ;
2019-01-25 14:24:41 -08:00
enum intel_dpll_id icl_tc_port_to_pll_id ( enum tc_port tc_port ) ;
2018-10-03 12:52:00 +05:30
bool intel_dpll_is_combophy ( enum intel_dpll_id id ) ;
2016-12-29 17:22:12 +02:00
2016-03-08 17:46:19 +02:00
# endif /* _INTEL_DPLL_MGR_H_ */