2011-10-04 19:19:01 +09:00
/* exynos_drm_crtc.c
*
* Copyright ( c ) 2011 Samsung Electronics Co . , Ltd .
* Authors :
* Inki Dae < inki . dae @ samsung . com >
* Joonyoung Shim < jy0922 . shim @ samsung . com >
* Seung - Woo Kim < sw0312 . kim @ samsung . com >
*
2012-12-18 02:30:17 +09:00
* 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 .
2011-10-04 19:19:01 +09:00
*/
2012-10-02 18:01:07 +01:00
# include <drm/drmP.h>
# include <drm/drm_crtc_helper.h>
2015-06-01 12:04:44 -03:00
# include <drm/drm_atomic.h>
# include <drm/drm_atomic_helper.h>
2011-10-04 19:19:01 +09:00
2013-08-13 00:46:40 +01:00
# include "exynos_drm_crtc.h"
2011-10-04 19:19:01 +09:00
# include "exynos_drm_drv.h"
2012-06-27 14:27:04 +09:00
# include "exynos_drm_plane.h"
2011-10-04 19:19:01 +09:00
2015-06-01 12:04:53 -03:00
static void exynos_drm_crtc_enable ( struct drm_crtc * crtc )
2011-10-04 19:19:01 +09:00
{
2011-11-04 17:04:45 +09:00
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2011-10-04 19:19:01 +09:00
2015-06-01 12:04:55 -03:00
if ( exynos_crtc - > ops - > enable )
exynos_crtc - > ops - > enable ( exynos_crtc ) ;
2014-02-19 21:02:55 +09:00
2015-06-01 12:04:53 -03:00
drm_crtc_vblank_on ( crtc ) ;
2011-10-04 19:19:01 +09:00
}
2015-06-01 12:04:51 -03:00
static void exynos_drm_crtc_disable ( struct drm_crtc * crtc )
{
2015-06-01 12:04:53 -03:00
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2015-06-01 12:04:51 -03:00
2015-06-01 12:04:53 -03:00
drm_crtc_vblank_off ( crtc ) ;
2015-06-01 12:04:55 -03:00
if ( exynos_crtc - > ops - > disable )
exynos_crtc - > ops - > disable ( exynos_crtc ) ;
2015-06-01 12:04:51 -03:00
}
2015-06-01 12:04:43 -03:00
static void
exynos_drm_crtc_mode_set_nofb ( struct drm_crtc * crtc )
2011-10-04 19:19:01 +09:00
{
2012-06-27 14:27:05 +09:00
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2012-09-14 13:29:47 +09:00
2015-06-01 12:04:43 -03:00
if ( exynos_crtc - > ops - > commit )
exynos_crtc - > ops - > commit ( exynos_crtc ) ;
2011-10-04 19:19:01 +09:00
}
2015-10-26 13:03:39 +01:00
static int exynos_crtc_atomic_check ( struct drm_crtc * crtc ,
struct drm_crtc_state * state )
{
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2015-11-27 07:57:31 +01:00
if ( ! state - > enable )
return 0 ;
2015-10-26 13:03:39 +01:00
if ( exynos_crtc - > ops - > atomic_check )
return exynos_crtc - > ops - > atomic_check ( exynos_crtc , state ) ;
return 0 ;
}
2015-07-21 13:28:58 +02:00
static void exynos_crtc_atomic_begin ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_crtc_state )
2015-06-01 12:04:48 -03:00
{
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2016-01-05 13:52:51 +01:00
if ( exynos_crtc - > ops - > atomic_begin )
exynos_crtc - > ops - > atomic_begin ( exynos_crtc ) ;
2015-06-01 12:04:48 -03:00
}
2015-07-21 13:28:58 +02:00
static void exynos_crtc_atomic_flush ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_crtc_state )
2015-06-01 12:04:48 -03:00
{
2015-08-24 20:36:59 +09:00
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2016-09-23 15:21:38 +02:00
struct drm_pending_vblank_event * event ;
unsigned long flags ;
2015-08-24 20:36:59 +09:00
2016-01-05 13:52:51 +01:00
if ( exynos_crtc - > ops - > atomic_flush )
exynos_crtc - > ops - > atomic_flush ( exynos_crtc ) ;
2016-09-23 15:21:38 +02:00
event = crtc - > state - > event ;
if ( event ) {
crtc - > state - > event = NULL ;
spin_lock_irqsave ( & crtc - > dev - > event_lock , flags ) ;
if ( drm_crtc_vblank_get ( crtc ) = = 0 )
drm_crtc_arm_vblank_event ( crtc , event ) ;
else
drm_crtc_send_vblank_event ( crtc , event ) ;
spin_unlock_irqrestore ( & crtc - > dev - > event_lock , flags ) ;
}
2015-06-01 12:04:48 -03:00
}
2015-12-15 12:21:06 +01:00
static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
2015-06-01 12:04:53 -03:00
. enable = exynos_drm_crtc_enable ,
2015-06-01 12:04:51 -03:00
. disable = exynos_drm_crtc_disable ,
2015-06-01 12:04:43 -03:00
. mode_set_nofb = exynos_drm_crtc_mode_set_nofb ,
2015-10-26 13:03:39 +01:00
. atomic_check = exynos_crtc_atomic_check ,
2015-06-01 12:04:48 -03:00
. atomic_begin = exynos_crtc_atomic_begin ,
. atomic_flush = exynos_crtc_atomic_flush ,
2011-10-04 19:19:01 +09:00
} ;
static void exynos_drm_crtc_destroy ( struct drm_crtc * crtc )
{
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
drm_crtc_cleanup ( crtc ) ;
kfree ( exynos_crtc ) ;
}
2015-12-15 12:21:06 +01:00
static const struct drm_crtc_funcs exynos_crtc_funcs = {
2015-06-01 12:04:47 -03:00
. set_config = drm_atomic_helper_set_config ,
2015-06-01 12:04:48 -03:00
. page_flip = drm_atomic_helper_page_flip ,
2011-10-04 19:19:01 +09:00
. destroy = exynos_drm_crtc_destroy ,
2015-06-01 12:04:44 -03:00
. reset = drm_atomic_helper_crtc_reset ,
. atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_crtc_destroy_state ,
2011-10-04 19:19:01 +09:00
} ;
2015-01-18 18:16:23 +09:00
struct exynos_drm_crtc * exynos_drm_crtc_create ( struct drm_device * drm_dev ,
2015-05-07 09:04:45 +09:00
struct drm_plane * plane ,
int pipe ,
enum exynos_drm_output_type type ,
const struct exynos_drm_crtc_ops * ops ,
void * ctx )
2011-10-04 19:19:01 +09:00
{
struct exynos_drm_crtc * exynos_crtc ;
struct drm_crtc * crtc ;
2014-09-19 14:58:53 +02:00
int ret ;
2011-10-04 19:19:01 +09:00
exynos_crtc = kzalloc ( sizeof ( * exynos_crtc ) , GFP_KERNEL ) ;
2013-08-19 19:04:55 +09:00
if ( ! exynos_crtc )
2015-01-18 18:16:23 +09:00
return ERR_PTR ( - ENOMEM ) ;
2011-10-04 19:19:01 +09:00
2014-11-04 18:25:27 -02:00
exynos_crtc - > pipe = pipe ;
2014-11-05 19:51:35 -02:00
exynos_crtc - > type = type ;
2015-01-18 18:16:23 +09:00
exynos_crtc - > ops = ops ;
exynos_crtc - > ctx = ctx ;
2012-06-27 14:27:04 +09:00
2014-11-03 18:20:29 -02:00
crtc = & exynos_crtc - > base ;
2011-10-04 19:19:01 +09:00
2014-11-26 16:43:27 -02:00
ret = drm_crtc_init_with_planes ( drm_dev , crtc , plane , NULL ,
drm: Pass 'name' to drm_crtc_init_with_planes()
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.
I didn't convert drm_crtc_init() since passing the varargs through
would mean either cpp macros or va_list, and I figured we don't
care about these legacy functions enough to warrant the extra pain.
@@
identifier dev, crtc, primary, cursor, funcs;
@@
int drm_crtc_init_with_planes(struct drm_device *dev,
struct drm_crtc *crtc,
struct drm_plane *primary, struct drm_plane *cursor,
const struct drm_crtc_funcs *funcs
+ ,const char *name, int DOTDOTDOT
)
{ ... }
@@
identifier dev, crtc, primary, cursor, funcs;
@@
int drm_crtc_init_with_planes(struct drm_device *dev,
struct drm_crtc *crtc,
struct drm_plane *primary, struct drm_plane *cursor,
const struct drm_crtc_funcs *funcs
+ ,const char *name, int DOTDOTDOT
);
@@
expression E1, E2, E3, E4, E5;
@@
drm_crtc_init_with_planes(E1, E2, E3, E4, E5
+ ,NULL
)
v2: Split crtc and plane changes apart
Pass NULL for no-name instead of ""
Leave drm_crtc_init() alone
v3: 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/1449670771-2751-1-git-send-email-ville.syrjala@linux.intel.com
2015-12-09 16:19:31 +02:00
& exynos_crtc_funcs , NULL ) ;
2014-09-19 14:58:53 +02:00
if ( ret < 0 )
goto err_crtc ;
2011-10-04 19:19:01 +09:00
drm_crtc_helper_add ( crtc , & exynos_crtc_helper_funcs ) ;
2015-01-18 18:16:23 +09:00
return exynos_crtc ;
2014-09-19 14:58:53 +02:00
err_crtc :
plane - > funcs - > destroy ( plane ) ;
kfree ( exynos_crtc ) ;
2015-01-18 18:16:23 +09:00
return ERR_PTR ( ret ) ;
2011-10-04 19:19:01 +09:00
}
2015-09-24 18:35:31 +02:00
int exynos_drm_crtc_enable_vblank ( struct drm_device * dev , unsigned int pipe )
2011-10-04 19:19:01 +09:00
{
2016-03-23 14:25:57 +01:00
struct exynos_drm_crtc * exynos_crtc = exynos_drm_crtc_from_pipe ( dev ,
pipe ) ;
2011-10-04 19:19:01 +09:00
2015-01-18 18:16:23 +09:00
if ( exynos_crtc - > ops - > enable_vblank )
2015-07-16 12:23:39 -03:00
return exynos_crtc - > ops - > enable_vblank ( exynos_crtc ) ;
2011-10-04 19:19:01 +09:00
return 0 ;
}
2015-09-24 18:35:31 +02:00
void exynos_drm_crtc_disable_vblank ( struct drm_device * dev , unsigned int pipe )
2011-10-04 19:19:01 +09:00
{
2016-03-23 14:25:57 +01:00
struct exynos_drm_crtc * exynos_crtc = exynos_drm_crtc_from_pipe ( dev ,
pipe ) ;
2011-10-04 19:19:01 +09:00
2015-01-18 18:16:23 +09:00
if ( exynos_crtc - > ops - > disable_vblank )
exynos_crtc - > ops - > disable_vblank ( exynos_crtc ) ;
2011-10-04 19:19:01 +09:00
}
2013-01-03 05:44:04 -05:00
2014-05-09 14:25:20 +09:00
int exynos_drm_crtc_get_pipe_from_type ( struct drm_device * drm_dev ,
2015-08-11 17:38:06 +09:00
enum exynos_drm_output_type out_type )
2014-05-09 14:25:20 +09:00
{
struct drm_crtc * crtc ;
list_for_each_entry ( crtc , & drm_dev - > mode_config . crtc_list , head ) {
struct exynos_drm_crtc * exynos_crtc ;
exynos_crtc = to_exynos_crtc ( crtc ) ;
2014-11-05 19:51:35 -02:00
if ( exynos_crtc - > type = = out_type )
2014-11-04 18:44:47 -02:00
return exynos_crtc - > pipe ;
2014-05-09 14:25:20 +09:00
}
return - EPERM ;
}
2014-07-17 18:01:19 +09:00
void exynos_drm_crtc_te_handler ( struct drm_crtc * crtc )
{
2015-01-18 18:16:23 +09:00
struct exynos_drm_crtc * exynos_crtc = to_exynos_crtc ( crtc ) ;
2014-07-17 18:01:19 +09:00
2015-01-18 18:16:23 +09:00
if ( exynos_crtc - > ops - > te_handler )
exynos_crtc - > ops - > te_handler ( exynos_crtc ) ;
2014-07-17 18:01:19 +09:00
}