2014-05-02 14:02:48 +10:00
/*
* Copyright © 2008 Intel Corporation
* 2014 Red Hat Inc .
*
* 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 .
*
*/
# include <drm/drmP.h>
# include "i915_drv.h"
# include "intel_drv.h"
2015-01-22 16:50:32 -08:00
# include <drm/drm_atomic_helper.h>
2014-05-02 14:02:48 +10:00
# include <drm/drm_crtc_helper.h>
# include <drm/drm_edid.h>
static bool intel_dp_mst_compute_config ( struct intel_encoder * encoder ,
2015-01-15 14:55:21 +02:00
struct intel_crtc_state * pipe_config )
2014-05-02 14:02:48 +10:00
{
2015-08-31 11:23:28 +03:00
struct drm_device * dev = encoder - > base . dev ;
2014-05-02 14:02:48 +10:00
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
struct intel_digital_port * intel_dig_port = intel_mst - > primary ;
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
2015-03-20 16:18:13 +02:00
struct drm_atomic_state * state ;
int bpp , i ;
2015-07-06 15:10:06 +03:00
int lane_count , slots ;
2015-09-08 13:40:49 +03:00
const struct drm_display_mode * adjusted_mode = & pipe_config - > base . adjusted_mode ;
2015-04-21 17:12:59 +03:00
struct drm_connector * drm_connector ;
struct intel_connector * connector , * found = NULL ;
struct drm_connector_state * connector_state ;
2014-05-02 14:02:48 +10:00
int mst_pbn ;
pipe_config - > dp_encoder_is_mst = true ;
pipe_config - > has_pch_encoder = false ;
pipe_config - > has_dp_encoder = true ;
bpp = 24 ;
/*
* for MST we always configure max link bw - the spec doesn ' t
* seem to suggest we should do otherwise .
*/
lane_count = drm_dp_max_lane_count ( intel_dp - > dpcd ) ;
2015-03-12 17:10:36 +02:00
2015-07-06 16:39:15 +03:00
pipe_config - > lane_count = lane_count ;
2014-05-02 14:02:48 +10:00
pipe_config - > pipe_bpp = 24 ;
2015-07-06 15:10:06 +03:00
pipe_config - > port_clock = intel_dp_max_link_rate ( intel_dp ) ;
2014-05-02 14:02:48 +10:00
2015-03-20 16:18:13 +02:00
state = pipe_config - > base . state ;
2015-04-21 17:12:59 +03:00
for_each_connector_in_state ( state , drm_connector , connector_state , i ) {
connector = to_intel_connector ( drm_connector ) ;
2015-03-20 16:18:13 +02:00
2015-04-21 17:12:59 +03:00
if ( connector_state - > best_encoder = = & encoder - > base ) {
found = connector ;
2014-05-02 14:02:48 +10:00
break ;
}
}
if ( ! found ) {
DRM_ERROR ( " can't find connector \n " ) ;
return false ;
}
2015-12-02 14:09:44 +08:00
if ( drm_dp_mst_port_has_audio ( & intel_dp - > mst_mgr , found - > port ) )
pipe_config - > has_audio = true ;
2015-09-25 16:38:56 +03:00
mst_pbn = drm_dp_calc_pbn_mode ( adjusted_mode - > crtc_clock , bpp ) ;
2014-05-02 14:02:48 +10:00
pipe_config - > pbn = mst_pbn ;
slots = drm_dp_find_vcpi_slots ( & intel_dp - > mst_mgr , mst_pbn ) ;
intel_link_compute_m_n ( bpp , lane_count ,
adjusted_mode - > crtc_clock ,
pipe_config - > port_clock ,
& pipe_config - > dp_m_n ) ;
pipe_config - > dp_m_n . tu = slots ;
2015-08-31 11:23:28 +03:00
if ( IS_HASWELL ( dev ) | | IS_BROADWELL ( dev ) )
hsw_dp_set_ddi_pll_sel ( pipe_config ) ;
2014-05-02 14:02:48 +10:00
return true ;
}
static void intel_mst_disable_dp ( struct intel_encoder * encoder )
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
struct intel_digital_port * intel_dig_port = intel_mst - > primary ;
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
2015-12-02 14:09:44 +08:00
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
struct drm_crtc * crtc = encoder - > base . crtc ;
struct intel_crtc * intel_crtc = to_intel_crtc ( crtc ) ;
2014-05-02 14:02:48 +10:00
int ret ;
DRM_DEBUG_KMS ( " %d \n " , intel_dp - > active_mst_links ) ;
drm_dp_mst_reset_vcpi_slots ( & intel_dp - > mst_mgr , intel_mst - > port ) ;
ret = drm_dp_update_payload_part1 ( & intel_dp - > mst_mgr ) ;
if ( ret ) {
DRM_ERROR ( " failed to update payload %d \n " , ret ) ;
}
2015-12-02 14:09:44 +08:00
if ( intel_crtc - > config - > has_audio ) {
intel_audio_codec_disable ( encoder ) ;
intel_display_power_put ( dev_priv , POWER_DOMAIN_AUDIO ) ;
}
2014-05-02 14:02:48 +10:00
}
static void intel_mst_post_disable_dp ( struct intel_encoder * encoder )
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
struct intel_digital_port * intel_dig_port = intel_mst - > primary ;
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
DRM_DEBUG_KMS ( " %d \n " , intel_dp - > active_mst_links ) ;
/* this can fail */
drm_dp_check_act_status ( & intel_dp - > mst_mgr ) ;
/* and this can also fail */
drm_dp_update_payload_part2 ( & intel_dp - > mst_mgr ) ;
drm_dp_mst_deallocate_vcpi ( & intel_dp - > mst_mgr , intel_mst - > port ) ;
intel_dp - > active_mst_links - - ;
intel_mst - > port = NULL ;
if ( intel_dp - > active_mst_links = = 0 ) {
intel_dig_port - > base . post_disable ( & intel_dig_port - > base ) ;
intel_dp_sink_dpms ( intel_dp , DRM_MODE_DPMS_OFF ) ;
}
}
static void intel_mst_pre_enable_dp ( struct intel_encoder * encoder )
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
struct intel_digital_port * intel_dig_port = intel_mst - > primary ;
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
enum port port = intel_dig_port - > port ;
int ret ;
uint32_t temp ;
2015-04-02 14:48:01 +03:00
struct intel_connector * found = NULL , * connector ;
2014-05-02 14:02:48 +10:00
int slots ;
struct drm_crtc * crtc = encoder - > base . crtc ;
struct intel_crtc * intel_crtc = to_intel_crtc ( crtc ) ;
2015-04-02 14:48:01 +03:00
for_each_intel_connector ( dev , connector ) {
if ( connector - > base . state - > best_encoder = = & encoder - > base ) {
found = connector ;
2014-05-02 14:02:48 +10:00
break ;
}
}
if ( ! found ) {
DRM_ERROR ( " can't find connector \n " ) ;
return ;
}
2015-08-27 13:13:31 +02:00
/* MST encoders are bound to a crtc, not to a connector,
* force the mapping here for get_hw_state .
*/
found - > encoder = encoder ;
2014-05-02 14:02:48 +10:00
DRM_DEBUG_KMS ( " %d \n " , intel_dp - > active_mst_links ) ;
intel_mst - > port = found - > port ;
if ( intel_dp - > active_mst_links = = 0 ) {
2015-12-08 19:59:44 +02:00
intel_prepare_ddi_buffer ( & intel_dig_port - > base ) ;
2015-12-08 19:59:36 +02:00
intel_ddi_clk_select ( & intel_dig_port - > base , intel_crtc - > config ) ;
2014-05-02 14:02:48 +10:00
2015-08-17 18:05:12 +03:00
intel_dp_set_link_params ( intel_dp , intel_crtc - > config ) ;
2014-05-02 14:02:48 +10:00
intel_ddi_init_dp_buf_reg ( & intel_dig_port - > base ) ;
intel_dp_sink_dpms ( intel_dp , DRM_MODE_DPMS_ON ) ;
intel_dp_start_link_train ( intel_dp ) ;
intel_dp_stop_link_train ( intel_dp ) ;
}
ret = drm_dp_mst_allocate_vcpi ( & intel_dp - > mst_mgr ,
2015-01-15 14:55:25 +02:00
intel_mst - > port ,
intel_crtc - > config - > pbn , & slots ) ;
2014-05-02 14:02:48 +10:00
if ( ret = = false ) {
DRM_ERROR ( " failed to allocate vcpi \n " ) ;
return ;
}
intel_dp - > active_mst_links + + ;
temp = I915_READ ( DP_TP_STATUS ( port ) ) ;
I915_WRITE ( DP_TP_STATUS ( port ) , temp ) ;
ret = drm_dp_update_payload_part1 ( & intel_dp - > mst_mgr ) ;
}
static void intel_mst_enable_dp ( struct intel_encoder * encoder )
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
struct intel_digital_port * intel_dig_port = intel_mst - > primary ;
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
struct drm_device * dev = intel_dig_port - > base . base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
2015-12-02 14:09:44 +08:00
struct intel_crtc * crtc = to_intel_crtc ( encoder - > base . crtc ) ;
2014-05-02 14:02:48 +10:00
enum port port = intel_dig_port - > port ;
int ret ;
DRM_DEBUG_KMS ( " %d \n " , intel_dp - > active_mst_links ) ;
if ( wait_for ( ( I915_READ ( DP_TP_STATUS ( port ) ) & DP_TP_STATUS_ACT_SENT ) ,
1 ) )
DRM_ERROR ( " Timed out waiting for ACT sent \n " ) ;
ret = drm_dp_check_act_status ( & intel_dp - > mst_mgr ) ;
ret = drm_dp_update_payload_part2 ( & intel_dp - > mst_mgr ) ;
2015-12-02 14:09:44 +08:00
if ( crtc - > config - > has_audio ) {
DRM_DEBUG_DRIVER ( " Enabling DP audio on pipe %c \n " ,
pipe_name ( crtc - > pipe ) ) ;
intel_display_power_get ( dev_priv , POWER_DOMAIN_AUDIO ) ;
intel_audio_codec_enable ( encoder ) ;
}
2014-05-02 14:02:48 +10:00
}
static bool intel_dp_mst_enc_get_hw_state ( struct intel_encoder * encoder ,
enum pipe * pipe )
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
* pipe = intel_mst - > pipe ;
if ( intel_mst - > port )
return true ;
return false ;
}
static void intel_dp_mst_enc_get_config ( struct intel_encoder * encoder ,
2015-01-15 14:55:21 +02:00
struct intel_crtc_state * pipe_config )
2014-05-02 14:02:48 +10:00
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( & encoder - > base ) ;
struct intel_digital_port * intel_dig_port = intel_mst - > primary ;
struct intel_crtc * crtc = to_intel_crtc ( encoder - > base . crtc ) ;
struct drm_device * dev = encoder - > base . dev ;
struct drm_i915_private * dev_priv = dev - > dev_private ;
2015-01-30 12:17:23 +02:00
enum transcoder cpu_transcoder = pipe_config - > cpu_transcoder ;
2014-05-02 14:02:48 +10:00
u32 temp , flags = 0 ;
pipe_config - > has_dp_encoder = true ;
2015-12-02 14:09:44 +08:00
pipe_config - > has_audio =
intel_ddi_is_audio_enabled ( dev_priv , crtc ) ;
2014-05-02 14:02:48 +10:00
temp = I915_READ ( TRANS_DDI_FUNC_CTL ( cpu_transcoder ) ) ;
if ( temp & TRANS_DDI_PHSYNC )
flags | = DRM_MODE_FLAG_PHSYNC ;
else
flags | = DRM_MODE_FLAG_NHSYNC ;
if ( temp & TRANS_DDI_PVSYNC )
flags | = DRM_MODE_FLAG_PVSYNC ;
else
flags | = DRM_MODE_FLAG_NVSYNC ;
switch ( temp & TRANS_DDI_BPC_MASK ) {
case TRANS_DDI_BPC_6 :
pipe_config - > pipe_bpp = 18 ;
break ;
case TRANS_DDI_BPC_8 :
pipe_config - > pipe_bpp = 24 ;
break ;
case TRANS_DDI_BPC_10 :
pipe_config - > pipe_bpp = 30 ;
break ;
case TRANS_DDI_BPC_12 :
pipe_config - > pipe_bpp = 36 ;
break ;
default :
break ;
}
2015-01-15 14:55:22 +02:00
pipe_config - > base . adjusted_mode . flags | = flags ;
2015-07-06 16:39:15 +03:00
pipe_config - > lane_count =
( ( temp & DDI_PORT_WIDTH_MASK ) > > DDI_PORT_WIDTH_SHIFT ) + 1 ;
2014-05-02 14:02:48 +10:00
intel_dp_get_m_n ( crtc , pipe_config ) ;
intel_ddi_clock_get ( & intel_dig_port - > base , pipe_config ) ;
}
static int intel_dp_mst_get_ddc_modes ( struct drm_connector * connector )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct intel_dp * intel_dp = intel_connector - > mst_port ;
struct edid * edid ;
int ret ;
edid = drm_dp_mst_get_edid ( connector , & intel_dp - > mst_mgr , intel_connector - > port ) ;
if ( ! edid )
return 0 ;
ret = intel_connector_update_modes ( connector , edid ) ;
kfree ( edid ) ;
return ret ;
}
static enum drm_connector_status
2014-10-22 11:06:44 +02:00
intel_dp_mst_detect ( struct drm_connector * connector , bool force )
2014-05-02 14:02:48 +10:00
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct intel_dp * intel_dp = intel_connector - > mst_port ;
2014-10-20 16:28:02 +10:00
return drm_dp_mst_detect_port ( connector , & intel_dp - > mst_mgr , intel_connector - > port ) ;
2014-05-02 14:02:48 +10:00
}
static int
intel_dp_mst_set_property ( struct drm_connector * connector ,
struct drm_property * property ,
uint64_t val )
{
return 0 ;
}
static void
intel_dp_mst_connector_destroy ( struct drm_connector * connector )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
if ( ! IS_ERR_OR_NULL ( intel_connector - > edid ) )
kfree ( intel_connector - > edid ) ;
drm_connector_cleanup ( connector ) ;
kfree ( connector ) ;
}
static const struct drm_connector_funcs intel_dp_mst_connector_funcs = {
2015-08-05 12:37:06 +02:00
. dpms = drm_atomic_helper_connector_dpms ,
2014-05-02 14:02:48 +10:00
. detect = intel_dp_mst_detect ,
. fill_modes = drm_helper_probe_single_connector_modes ,
. set_property = intel_dp_mst_set_property ,
2015-01-22 16:51:27 -08:00
. atomic_get_property = intel_connector_atomic_get_property ,
2014-05-02 14:02:48 +10:00
. destroy = intel_dp_mst_connector_destroy ,
2015-01-22 16:50:32 -08:00
. atomic_destroy_state = drm_atomic_helper_connector_destroy_state ,
2015-03-20 16:18:06 +02:00
. atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state ,
2014-05-02 14:02:48 +10:00
} ;
static int intel_dp_mst_get_modes ( struct drm_connector * connector )
{
return intel_dp_mst_get_ddc_modes ( connector ) ;
}
static enum drm_mode_status
intel_dp_mst_mode_valid ( struct drm_connector * connector ,
struct drm_display_mode * mode )
{
2016-02-02 15:16:40 +02:00
int max_dotclk = to_i915 ( connector - > dev ) - > max_dotclk_freq ;
2014-05-02 14:02:48 +10:00
/* TODO - validate mode against available PBN for link */
if ( mode - > clock < 10000 )
return MODE_CLOCK_LOW ;
if ( mode - > flags & DRM_MODE_FLAG_DBLCLK )
return MODE_H_ILLEGAL ;
2016-02-02 15:16:40 +02:00
if ( mode - > clock > max_dotclk )
return MODE_CLOCK_HIGH ;
2014-05-02 14:02:48 +10:00
return MODE_OK ;
}
2015-08-03 17:24:09 +02:00
static struct drm_encoder * intel_mst_atomic_best_encoder ( struct drm_connector * connector ,
struct drm_connector_state * state )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct intel_dp * intel_dp = intel_connector - > mst_port ;
struct intel_crtc * crtc = to_intel_crtc ( state - > crtc ) ;
return & intel_dp - > mst_encoders [ crtc - > pipe ] - > base . base ;
}
2014-05-02 14:02:48 +10:00
static struct drm_encoder * intel_mst_best_encoder ( struct drm_connector * connector )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct intel_dp * intel_dp = intel_connector - > mst_port ;
return & intel_dp - > mst_encoders [ 0 ] - > base . base ;
}
static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
. get_modes = intel_dp_mst_get_modes ,
. mode_valid = intel_dp_mst_mode_valid ,
2015-08-03 17:24:09 +02:00
. atomic_best_encoder = intel_mst_atomic_best_encoder ,
2014-05-02 14:02:48 +10:00
. best_encoder = intel_mst_best_encoder ,
} ;
static void intel_dp_mst_encoder_destroy ( struct drm_encoder * encoder )
{
struct intel_dp_mst_encoder * intel_mst = enc_to_mst ( encoder ) ;
drm_encoder_cleanup ( encoder ) ;
kfree ( intel_mst ) ;
}
static const struct drm_encoder_funcs intel_dp_mst_enc_funcs = {
. destroy = intel_dp_mst_encoder_destroy ,
} ;
static bool intel_dp_mst_get_hw_state ( struct intel_connector * connector )
{
2015-08-27 13:13:31 +02:00
if ( connector - > encoder & & connector - > base . state - > crtc ) {
2014-05-02 14:02:48 +10:00
enum pipe pipe ;
if ( ! connector - > encoder - > get_hw_state ( connector - > encoder , & pipe ) )
return false ;
return true ;
}
return false ;
}
2014-07-22 20:10:28 +10:00
static void intel_connector_add_to_fbdev ( struct intel_connector * connector )
{
2015-08-10 13:34:08 +02:00
# ifdef CONFIG_DRM_FBDEV_EMULATION
2014-07-22 20:10:28 +10:00
struct drm_i915_private * dev_priv = to_i915 ( connector - > base . dev ) ;
2015-11-18 13:43:20 +01:00
if ( dev_priv - > fbdev )
drm_fb_helper_add_one_connector ( & dev_priv - > fbdev - > helper ,
& connector - > base ) ;
2014-07-22 20:10:28 +10:00
# endif
}
static void intel_connector_remove_from_fbdev ( struct intel_connector * connector )
{
2015-08-10 13:34:08 +02:00
# ifdef CONFIG_DRM_FBDEV_EMULATION
2014-07-22 20:10:28 +10:00
struct drm_i915_private * dev_priv = to_i915 ( connector - > base . dev ) ;
2015-11-18 13:43:20 +01:00
if ( dev_priv - > fbdev )
drm_fb_helper_remove_one_connector ( & dev_priv - > fbdev - > helper ,
& connector - > base ) ;
2014-07-22 20:10:28 +10:00
# endif
}
2014-05-13 11:38:36 +02:00
static struct drm_connector * intel_dp_add_mst_connector ( struct drm_dp_mst_topology_mgr * mgr , struct drm_dp_mst_port * port , const char * pathprop )
2014-05-02 14:02:48 +10:00
{
struct intel_dp * intel_dp = container_of ( mgr , struct intel_dp , mst_mgr ) ;
struct intel_digital_port * intel_dig_port = dp_to_dig_port ( intel_dp ) ;
struct drm_device * dev = intel_dig_port - > base . base . dev ;
struct intel_connector * intel_connector ;
struct drm_connector * connector ;
int i ;
2015-04-10 10:59:10 +03:00
intel_connector = intel_connector_alloc ( ) ;
2014-05-02 14:02:48 +10:00
if ( ! intel_connector )
return NULL ;
connector = & intel_connector - > base ;
drm_connector_init ( dev , connector , & intel_dp_mst_connector_funcs , DRM_MODE_CONNECTOR_DisplayPort ) ;
drm_connector_helper_add ( connector , & intel_dp_mst_connector_helper_funcs ) ;
intel_connector - > unregister = intel_connector_unregister ;
intel_connector - > get_hw_state = intel_dp_mst_get_hw_state ;
intel_connector - > mst_port = intel_dp ;
intel_connector - > port = port ;
for ( i = PIPE_A ; i < = PIPE_C ; i + + ) {
drm_mode_connector_attach_encoder ( & intel_connector - > base ,
& intel_dp - > mst_encoders [ i ] - > base . base ) ;
}
intel_dp_add_properties ( intel_dp , connector ) ;
drm_object_attach_property ( & connector - > base , dev - > mode_config . path_property , 0 ) ;
2014-10-20 16:30:50 +10:00
drm_object_attach_property ( & connector - > base , dev - > mode_config . tile_property , 0 ) ;
2014-05-02 14:02:48 +10:00
drm_mode_connector_set_path_property ( connector , pathprop ) ;
2015-09-16 17:55:23 +10:00
return connector ;
}
static void intel_dp_register_mst_connector ( struct drm_connector * connector )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct drm_device * dev = connector - > dev ;
2015-07-09 23:44:31 +02:00
drm_modeset_lock_all ( dev ) ;
2014-07-22 20:10:28 +10:00
intel_connector_add_to_fbdev ( intel_connector ) ;
2015-07-09 23:44:31 +02:00
drm_modeset_unlock_all ( dev ) ;
2014-05-02 14:02:48 +10:00
drm_connector_register ( & intel_connector - > base ) ;
}
static void intel_dp_destroy_mst_connector ( struct drm_dp_mst_topology_mgr * mgr ,
struct drm_connector * connector )
{
struct intel_connector * intel_connector = to_intel_connector ( connector ) ;
struct drm_device * dev = connector - > dev ;
2015-08-06 13:47:36 +02:00
2014-05-02 14:02:48 +10:00
/* need to nuke the connector */
2015-07-09 23:44:31 +02:00
drm_modeset_lock_all ( dev ) ;
2015-08-06 13:47:36 +02:00
if ( connector - > state - > crtc ) {
struct drm_mode_set set ;
int ret ;
memset ( & set , 0 , sizeof ( set ) ) ;
set . crtc = connector - > state - > crtc ,
ret = drm_atomic_helper_set_config ( & set ) ;
WARN ( ret , " Disabling mst crtc failed with %i \n " , ret ) ;
}
2015-07-09 23:44:31 +02:00
drm_modeset_unlock_all ( dev ) ;
2014-05-02 14:02:48 +10:00
intel_connector - > unregister ( intel_connector ) ;
2015-07-09 23:44:31 +02:00
drm_modeset_lock_all ( dev ) ;
2014-07-22 20:10:28 +10:00
intel_connector_remove_from_fbdev ( intel_connector ) ;
2014-05-02 14:02:48 +10:00
drm_connector_cleanup ( connector ) ;
2015-07-09 23:44:31 +02:00
drm_modeset_unlock_all ( dev ) ;
2014-05-02 14:02:48 +10:00
kfree ( intel_connector ) ;
DRM_DEBUG_KMS ( " \n " ) ;
}
static void intel_dp_mst_hotplug ( struct drm_dp_mst_topology_mgr * mgr )
{
struct intel_dp * intel_dp = container_of ( mgr , struct intel_dp , mst_mgr ) ;
struct intel_digital_port * intel_dig_port = dp_to_dig_port ( intel_dp ) ;
struct drm_device * dev = intel_dig_port - > base . base . dev ;
drm_kms_helper_hotplug_event ( dev ) ;
}
2015-12-30 22:20:30 +01:00
static const struct drm_dp_mst_topology_cbs mst_cbs = {
2014-05-02 14:02:48 +10:00
. add_connector = intel_dp_add_mst_connector ,
2015-09-16 17:55:23 +10:00
. register_connector = intel_dp_register_mst_connector ,
2014-05-02 14:02:48 +10:00
. destroy_connector = intel_dp_destroy_mst_connector ,
. hotplug = intel_dp_mst_hotplug ,
} ;
static struct intel_dp_mst_encoder *
intel_dp_create_fake_mst_encoder ( struct intel_digital_port * intel_dig_port , enum pipe pipe )
{
struct intel_dp_mst_encoder * intel_mst ;
struct intel_encoder * intel_encoder ;
struct drm_device * dev = intel_dig_port - > base . base . dev ;
intel_mst = kzalloc ( sizeof ( * intel_mst ) , GFP_KERNEL ) ;
if ( ! intel_mst )
return NULL ;
intel_mst - > pipe = pipe ;
intel_encoder = & intel_mst - > base ;
intel_mst - > primary = intel_dig_port ;
drm_encoder_init ( dev , & intel_encoder - > base , & intel_dp_mst_enc_funcs ,
drm: Pass 'name' to drm_encoder_init()
Done with coccinelle for the most part. However, it thinks '...' is
part of the semantic patch, so I put an 'int DOTDOTDOT' placeholder
in its place and got rid of it with sed afterwards.
@@
identifier dev, encoder, funcs;
@@
int drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
const struct drm_encoder_funcs *funcs,
int encoder_type
+ ,const char *name, int DOTDOTDOT
)
{ ... }
@@
identifier dev, encoder, funcs;
@@
int drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
const struct drm_encoder_funcs *funcs,
int encoder_type
+ ,const char *name, int DOTDOTDOT
);
@@
expression E1, E2, E3, E4;
@@
drm_encoder_init(E1, E2, E3, E4
+ ,NULL
)
v2: Add ', or NULL...' to @name kernel doc (Jani)
Annotate the function with __printf() attribute (Jani)
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1449670818-2966-1-git-send-email-ville.syrjala@linux.intel.com
2015-12-09 16:20:18 +02:00
DRM_MODE_ENCODER_DPMST , NULL ) ;
2014-05-02 14:02:48 +10:00
intel_encoder - > type = INTEL_OUTPUT_DP_MST ;
intel_encoder - > crtc_mask = 0x7 ;
intel_encoder - > cloneable = 0 ;
intel_encoder - > compute_config = intel_dp_mst_compute_config ;
intel_encoder - > disable = intel_mst_disable_dp ;
intel_encoder - > post_disable = intel_mst_post_disable_dp ;
intel_encoder - > pre_enable = intel_mst_pre_enable_dp ;
intel_encoder - > enable = intel_mst_enable_dp ;
intel_encoder - > get_hw_state = intel_dp_mst_enc_get_hw_state ;
intel_encoder - > get_config = intel_dp_mst_enc_get_config ;
return intel_mst ;
}
static bool
intel_dp_create_fake_mst_encoders ( struct intel_digital_port * intel_dig_port )
{
int i ;
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
for ( i = PIPE_A ; i < = PIPE_C ; i + + )
intel_dp - > mst_encoders [ i ] = intel_dp_create_fake_mst_encoder ( intel_dig_port , i ) ;
return true ;
}
int
intel_dp_mst_encoder_init ( struct intel_digital_port * intel_dig_port , int conn_base_id )
{
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
struct drm_device * dev = intel_dig_port - > base . base . dev ;
int ret ;
intel_dp - > can_mst = true ;
intel_dp - > mst_mgr . cbs = & mst_cbs ;
/* create encoders */
intel_dp_create_fake_mst_encoders ( intel_dig_port ) ;
ret = drm_dp_mst_topology_mgr_init ( & intel_dp - > mst_mgr , dev - > dev , & intel_dp - > aux , 16 , 3 , conn_base_id ) ;
if ( ret ) {
intel_dp - > can_mst = false ;
return ret ;
}
return 0 ;
}
void
intel_dp_mst_encoder_cleanup ( struct intel_digital_port * intel_dig_port )
{
struct intel_dp * intel_dp = & intel_dig_port - > dp ;
if ( ! intel_dp - > can_mst )
return ;
drm_dp_mst_topology_mgr_destroy ( & intel_dp - > mst_mgr ) ;
/* encoders will get killed by normal cleanup */
}