2015-08-19 22:19:49 -04:00
/*
* Copyright 2015 Freescale Semiconductor , Inc .
*
* Freescale DCU drm device driver
*
* 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 <linux/clk.h>
# include <linux/regmap.h>
# include <drm/drmP.h>
# include <drm/drm_atomic.h>
# include <drm/drm_atomic_helper.h>
# include <drm/drm_crtc.h>
# include <drm/drm_crtc_helper.h>
# include "fsl_dcu_drm_crtc.h"
# include "fsl_dcu_drm_drv.h"
# include "fsl_dcu_drm_plane.h"
static void fsl_dcu_drm_crtc_atomic_flush ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_crtc_state )
{
2016-09-05 19:05:12 -07:00
struct drm_device * dev = crtc - > dev ;
struct fsl_dcu_drm_device * fsl_dev = dev - > dev_private ;
2016-06-08 14:18:56 +02:00
struct drm_pending_vblank_event * event = crtc - > state - > event ;
2016-09-05 19:05:12 -07:00
regmap_write ( fsl_dev - > regmap ,
DCU_UPDATE_MODE , DCU_UPDATE_MODE_READREG ) ;
2016-06-08 14:18:56 +02:00
if ( event ) {
crtc - > state - > event = NULL ;
spin_lock_irq ( & crtc - > dev - > event_lock ) ;
if ( drm_crtc_vblank_get ( crtc ) = = 0 )
drm_crtc_arm_vblank_event ( crtc , event ) ;
else
drm_crtc_send_vblank_event ( crtc , event ) ;
spin_unlock_irq ( & crtc - > dev - > event_lock ) ;
}
2015-08-19 22:19:49 -04:00
}
2016-10-31 09:51:19 -07:00
static void fsl_dcu_drm_crtc_atomic_disable ( struct drm_crtc * crtc ,
struct drm_crtc_state * old_crtc_state )
2015-08-19 22:19:49 -04:00
{
struct drm_device * dev = crtc - > dev ;
struct fsl_dcu_drm_device * fsl_dev = dev - > dev_private ;
2016-10-31 09:51:19 -07:00
/* always disable planes on the CRTC */
drm_atomic_helper_disable_planes_on_crtc ( old_crtc_state , true ) ;
2016-04-18 18:22:47 -07:00
drm_crtc_vblank_off ( crtc ) ;
2015-11-18 16:50:55 -08:00
regmap_update_bits ( fsl_dev - > regmap , DCU_DCU_MODE ,
DCU_MODE_DCU_MODE_MASK ,
DCU_MODE_DCU_MODE ( DCU_MODE_OFF ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_UPDATE_MODE ,
DCU_UPDATE_MODE_READREG ) ;
2016-10-04 17:40:29 -07:00
clk_disable_unprepare ( fsl_dev - > pix_clk ) ;
2015-08-19 22:19:49 -04:00
}
static void fsl_dcu_drm_crtc_enable ( struct drm_crtc * crtc )
{
struct drm_device * dev = crtc - > dev ;
struct fsl_dcu_drm_device * fsl_dev = dev - > dev_private ;
2016-10-04 17:40:29 -07:00
clk_prepare_enable ( fsl_dev - > pix_clk ) ;
2015-11-18 16:50:55 -08:00
regmap_update_bits ( fsl_dev - > regmap , DCU_DCU_MODE ,
DCU_MODE_DCU_MODE_MASK ,
DCU_MODE_DCU_MODE ( DCU_MODE_NORMAL ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_UPDATE_MODE ,
DCU_UPDATE_MODE_READREG ) ;
2016-04-18 18:22:47 -07:00
drm_crtc_vblank_on ( crtc ) ;
2015-08-19 22:19:49 -04:00
}
static void fsl_dcu_drm_crtc_mode_set_nofb ( struct drm_crtc * crtc )
{
struct drm_device * dev = crtc - > dev ;
struct fsl_dcu_drm_device * fsl_dev = dev - > dev_private ;
2016-02-08 12:50:13 -08:00
struct drm_connector * con = & fsl_dev - > connector . base ;
2015-08-19 22:19:49 -04:00
struct drm_display_mode * mode = & crtc - > state - > mode ;
2016-03-22 18:06:08 -07:00
unsigned int hbp , hfp , hsw , vbp , vfp , vsw , index , pol = 0 ;
2015-08-19 22:19:49 -04:00
index = drm_crtc_index ( crtc ) ;
2016-03-22 18:06:08 -07:00
clk_set_rate ( fsl_dev - > pix_clk , mode - > clock * 1000 ) ;
2015-08-19 22:19:49 -04:00
/* Configure timings: */
hbp = mode - > htotal - mode - > hsync_end ;
hfp = mode - > hsync_start - mode - > hdisplay ;
hsw = mode - > hsync_end - mode - > hsync_start ;
vbp = mode - > vtotal - mode - > vsync_end ;
vfp = mode - > vsync_start - mode - > vdisplay ;
vsw = mode - > vsync_end - mode - > vsync_start ;
2016-02-08 12:50:13 -08:00
/* INV_PXCK as default (most display sample data on rising edge) */
if ( ! ( con - > display_info . bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE ) )
pol | = DCU_SYN_POL_INV_PXCK ;
2015-11-17 19:10:29 -08:00
if ( mode - > flags & DRM_MODE_FLAG_NHSYNC )
pol | = DCU_SYN_POL_INV_HS_LOW ;
if ( mode - > flags & DRM_MODE_FLAG_NVSYNC )
pol | = DCU_SYN_POL_INV_VS_LOW ;
2015-11-18 16:50:55 -08:00
regmap_write ( fsl_dev - > regmap , DCU_HSYN_PARA ,
DCU_HSYN_PARA_BP ( hbp ) |
DCU_HSYN_PARA_PW ( hsw ) |
DCU_HSYN_PARA_FP ( hfp ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_VSYN_PARA ,
DCU_VSYN_PARA_BP ( vbp ) |
DCU_VSYN_PARA_PW ( vsw ) |
DCU_VSYN_PARA_FP ( vfp ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_DISP_SIZE ,
DCU_DISP_SIZE_DELTA_Y ( mode - > vdisplay ) |
DCU_DISP_SIZE_DELTA_X ( mode - > hdisplay ) ) ;
2015-11-17 19:10:29 -08:00
regmap_write ( fsl_dev - > regmap , DCU_SYN_POL , pol ) ;
2015-11-18 16:50:55 -08:00
regmap_write ( fsl_dev - > regmap , DCU_BGND , DCU_BGND_R ( 0 ) |
DCU_BGND_G ( 0 ) | DCU_BGND_B ( 0 ) ) ;
regmap_write ( fsl_dev - > regmap , DCU_DCU_MODE ,
DCU_MODE_BLEND_ITER ( 1 ) | DCU_MODE_RASTER_EN ) ;
regmap_write ( fsl_dev - > regmap , DCU_THRESHOLD ,
DCU_THRESHOLD_LS_BF_VS ( BF_VS_VAL ) |
DCU_THRESHOLD_OUT_BUF_HIGH ( BUF_MAX_VAL ) |
DCU_THRESHOLD_OUT_BUF_LOW ( BUF_MIN_VAL ) ) ;
2015-08-19 22:19:49 -04:00
return ;
}
static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
2016-10-31 09:51:19 -07:00
. atomic_disable = fsl_dcu_drm_crtc_atomic_disable ,
2015-08-19 22:19:49 -04:00
. atomic_flush = fsl_dcu_drm_crtc_atomic_flush ,
. enable = fsl_dcu_drm_crtc_enable ,
. mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb ,
} ;
static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
. atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_crtc_destroy_state ,
. destroy = drm_crtc_cleanup ,
. page_flip = drm_atomic_helper_page_flip ,
. reset = drm_atomic_helper_crtc_reset ,
. set_config = drm_atomic_helper_set_config ,
} ;
int fsl_dcu_drm_crtc_create ( struct fsl_dcu_drm_device * fsl_dev )
{
struct drm_plane * primary ;
struct drm_crtc * crtc = & fsl_dev - > crtc ;
int ret ;
2016-02-11 16:51:49 -08:00
fsl_dcu_drm_init_planes ( fsl_dev - > drm ) ;
2015-08-19 22:19:49 -04:00
primary = fsl_dcu_drm_primary_create_plane ( fsl_dev - > drm ) ;
2015-11-16 15:43:34 -08:00
if ( ! primary )
return - ENOMEM ;
2015-08-19 22:19:49 -04:00
ret = drm_crtc_init_with_planes ( fsl_dev - > drm , crtc , primary , 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
& fsl_dcu_drm_crtc_funcs , NULL ) ;
2015-11-16 15:43:34 -08:00
if ( ret ) {
primary - > funcs - > destroy ( primary ) ;
2015-08-19 22:19:49 -04:00
return ret ;
2015-11-16 15:43:34 -08:00
}
2015-08-19 22:19:49 -04:00
drm_crtc_helper_add ( crtc , & fsl_dcu_drm_crtc_helper_funcs ) ;
return 0 ;
}