2013-06-15 14:21:51 +02:00
/*
* rcar_du_lvdscon . c - - R - Car Display Unit LVDS Connector
*
2014-02-06 18:13:52 +01:00
* Copyright ( C ) 2013 - 2014 Renesas Electronics Corporation
2013-06-15 14:21:51 +02:00
*
* Contact : Laurent Pinchart ( laurent . pinchart @ ideasonboard . com )
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <drm/drmP.h>
2015-02-20 11:30:59 +02:00
# include <drm/drm_atomic_helper.h>
2013-06-15 14:21:51 +02:00
# include <drm/drm_crtc.h>
# include <drm/drm_crtc_helper.h>
2016-11-18 03:22:37 +02:00
# include <drm/drm_panel.h>
2013-06-15 14:21:51 +02:00
2014-01-21 15:57:26 +01:00
# include <video/display_timing.h>
# include <video/of_display_timing.h>
# include <video/videomode.h>
2013-06-15 14:21:51 +02:00
# include "rcar_du_drv.h"
2013-06-15 15:02:12 +02:00
# include "rcar_du_encoder.h"
2013-06-15 14:21:51 +02:00
# include "rcar_du_kms.h"
# include "rcar_du_lvdscon.h"
static int rcar_du_lvds_connector_get_modes ( struct drm_connector * connector )
{
2016-11-18 03:22:37 +02:00
struct rcar_du_connector * rcon = to_rcar_connector ( connector ) ;
2013-06-15 14:21:51 +02:00
2016-11-18 03:22:37 +02:00
return drm_panel_get_modes ( rcon - > panel ) ;
2013-06-15 14:21:51 +02:00
}
static const struct drm_connector_helper_funcs connector_helper_funcs = {
. get_modes = rcar_du_lvds_connector_get_modes ,
} ;
2016-11-18 03:22:37 +02:00
static void rcar_du_lvds_connector_destroy ( struct drm_connector * connector )
{
struct rcar_du_connector * rcon = to_rcar_connector ( connector ) ;
drm_panel_detach ( rcon - > panel ) ;
drm_connector_cleanup ( connector ) ;
}
2013-06-15 14:21:51 +02:00
static const struct drm_connector_funcs connector_funcs = {
2015-02-20 11:30:59 +02:00
. reset = drm_atomic_helper_connector_reset ,
2013-06-15 14:21:51 +02:00
. fill_modes = drm_helper_probe_single_connector_modes ,
2016-11-18 03:22:37 +02:00
. destroy = rcar_du_lvds_connector_destroy ,
2015-02-20 11:30:59 +02:00
. atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_connector_destroy_state ,
2013-06-15 14:21:51 +02:00
} ;
int rcar_du_lvds_connector_init ( struct rcar_du_device * rcdu ,
struct rcar_du_encoder * renc ,
2016-10-03 16:56:48 +03:00
const struct device_node * np )
2013-06-15 14:21:51 +02:00
{
2014-03-31 01:50:16 +02:00
struct drm_encoder * encoder = rcar_encoder_to_drm_encoder ( renc ) ;
2016-11-18 03:22:37 +02:00
struct rcar_du_connector * rcon ;
2013-06-15 14:21:51 +02:00
struct drm_connector * connector ;
int ret ;
2016-11-18 03:22:37 +02:00
rcon = devm_kzalloc ( rcdu - > dev , sizeof ( * rcon ) , GFP_KERNEL ) ;
if ( rcon = = NULL )
2013-06-15 14:21:51 +02:00
return - ENOMEM ;
2016-11-18 03:22:37 +02:00
connector = & rcon - > connector ;
2014-01-21 15:57:26 +01:00
2016-11-18 03:22:37 +02:00
rcon - > panel = of_drm_find_panel ( np ) ;
if ( ! rcon - > panel )
return - EPROBE_DEFER ;
2013-06-15 14:21:51 +02:00
ret = drm_connector_init ( rcdu - > ddev , connector , & connector_funcs ,
DRM_MODE_CONNECTOR_LVDS ) ;
if ( ret < 0 )
return ret ;
drm_connector_helper_add ( connector , & connector_helper_funcs ) ;
2015-02-22 01:49:11 +02:00
connector - > dpms = DRM_MODE_DPMS_OFF ;
2013-06-15 14:21:51 +02:00
drm_object_property_set_value ( & connector - > base ,
rcdu - > ddev - > mode_config . dpms_property , DRM_MODE_DPMS_OFF ) ;
2014-03-31 01:50:16 +02:00
ret = drm_mode_connector_attach_encoder ( connector , encoder ) ;
2013-06-15 14:21:51 +02:00
if ( ret < 0 )
return ret ;
2016-11-18 03:22:37 +02:00
ret = drm_panel_attach ( rcon - > panel , connector ) ;
if ( ret < 0 )
return ret ;
rcon - > encoder = renc ;
2013-06-15 14:21:51 +02:00
return 0 ;
}