2012-03-21 05:55:26 +04:00
/* exynos_drm_vidi.c
*
* Copyright ( C ) 2012 Samsung Electronics Co . Ltd
* Authors :
* Inki Dae < inki . dae @ samsung . 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 .
*
*/
2012-10-02 21:01:07 +04:00
# include <drm/drmP.h>
2012-03-21 05:55:26 +04:00
# include <linux/kernel.h>
# include <linux/platform_device.h>
2014-11-24 08:55:41 +03:00
# include <linux/component.h>
2012-03-21 05:55:26 +04:00
# include <drm/exynos_drm.h>
2012-10-02 21:01:07 +04:00
# include <drm/drm_edid.h>
# include <drm/drm_crtc_helper.h>
2015-06-01 18:04:44 +03:00
# include <drm/drm_atomic_helper.h>
2012-03-21 05:55:26 +04:00
# include "exynos_drm_drv.h"
# include "exynos_drm_crtc.h"
2015-11-30 16:53:21 +03:00
# include "exynos_drm_fb.h"
2015-04-03 15:03:40 +03:00
# include "exynos_drm_plane.h"
2013-08-13 03:46:40 +04:00
# include "exynos_drm_vidi.h"
2012-03-21 05:55:26 +04:00
/* vidi has totally three virtual windows. */
# define WINDOWS_NR 3
2014-01-31 01:38:07 +04:00
# define ctx_from_connector(c) container_of(c, struct vidi_context, \
connector )
2012-03-21 05:55:26 +04:00
struct vidi_context {
2015-08-15 18:14:08 +03:00
struct drm_encoder encoder ;
2014-11-24 08:55:41 +03:00
struct platform_device * pdev ;
2014-02-19 16:02:55 +04:00
struct drm_device * drm_dev ;
2015-01-18 12:16:23 +03:00
struct exynos_drm_crtc * crtc ;
2014-01-31 01:38:07 +04:00
struct drm_connector connector ;
2015-04-03 15:03:40 +03:00
struct exynos_drm_plane planes [ WINDOWS_NR ] ;
2012-03-21 05:55:26 +04:00
struct edid * raw_edid ;
unsigned int clkdiv ;
unsigned long irq_flags ;
unsigned int connected ;
bool vblank_on ;
bool suspended ;
2012-09-19 06:02:43 +04:00
bool direct_vblank ;
2012-03-21 05:55:26 +04:00
struct work_struct work ;
struct mutex lock ;
2014-02-19 16:02:55 +04:00
int pipe ;
2012-03-21 05:55:26 +04:00
} ;
2015-08-15 18:14:08 +03:00
static inline struct vidi_context * encoder_to_vidi ( struct drm_encoder * e )
2014-11-17 11:54:23 +03:00
{
2015-08-11 11:38:06 +03:00
return container_of ( e , struct vidi_context , encoder ) ;
2014-11-17 11:54:23 +03:00
}
2012-03-21 05:55:26 +04:00
static const char fake_edid_info [ ] = {
0x00 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0x00 , 0x4c , 0x2d , 0x05 , 0x05 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x30 , 0x12 , 0x01 , 0x03 , 0x80 , 0x10 , 0x09 , 0x78 ,
0x0a , 0xee , 0x91 , 0xa3 , 0x54 , 0x4c , 0x99 , 0x26 , 0x0f , 0x50 , 0x54 , 0xbd ,
0xee , 0x00 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 ,
0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x66 , 0x21 , 0x50 , 0xb0 , 0x51 , 0x00 ,
0x1b , 0x30 , 0x40 , 0x70 , 0x36 , 0x00 , 0xa0 , 0x5a , 0x00 , 0x00 , 0x00 , 0x1e ,
0x01 , 0x1d , 0x00 , 0x72 , 0x51 , 0xd0 , 0x1e , 0x20 , 0x6e , 0x28 , 0x55 , 0x00 ,
0xa0 , 0x5a , 0x00 , 0x00 , 0x00 , 0x1e , 0x00 , 0x00 , 0x00 , 0xfd , 0x00 , 0x18 ,
0x4b , 0x1a , 0x44 , 0x17 , 0x00 , 0x0a , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 ,
0x00 , 0x00 , 0x00 , 0xfc , 0x00 , 0x53 , 0x41 , 0x4d , 0x53 , 0x55 , 0x4e , 0x47 ,
0x0a , 0x20 , 0x20 , 0x20 , 0x20 , 0x20 , 0x01 , 0xbc , 0x02 , 0x03 , 0x1e , 0xf1 ,
0x46 , 0x84 , 0x05 , 0x03 , 0x10 , 0x20 , 0x22 , 0x23 , 0x09 , 0x07 , 0x07 , 0x83 ,
0x01 , 0x00 , 0x00 , 0xe2 , 0x00 , 0x0f , 0x67 , 0x03 , 0x0c , 0x00 , 0x10 , 0x00 ,
0xb8 , 0x2d , 0x01 , 0x1d , 0x80 , 0x18 , 0x71 , 0x1c , 0x16 , 0x20 , 0x58 , 0x2c ,
0x25 , 0x00 , 0xa0 , 0x5a , 0x00 , 0x00 , 0x00 , 0x9e , 0x8c , 0x0a , 0xd0 , 0x8a ,
0x20 , 0xe0 , 0x2d , 0x10 , 0x10 , 0x3e , 0x96 , 0x00 , 0xa0 , 0x5a , 0x00 , 0x00 ,
0x00 , 0x18 , 0x02 , 0x3a , 0x80 , 0x18 , 0x71 , 0x38 , 0x2d , 0x40 , 0x58 , 0x2c ,
0x45 , 0x00 , 0xa0 , 0x5a , 0x00 , 0x00 , 0x00 , 0x1e , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x06
} ;
2015-08-30 18:53:57 +03:00
static const uint32_t formats [ ] = {
DRM_FORMAT_XRGB8888 ,
DRM_FORMAT_ARGB8888 ,
DRM_FORMAT_NV12 ,
} ;
2015-11-30 16:53:25 +03:00
static const enum drm_plane_type vidi_win_types [ WINDOWS_NR ] = {
DRM_PLANE_TYPE_PRIMARY ,
DRM_PLANE_TYPE_OVERLAY ,
DRM_PLANE_TYPE_CURSOR ,
} ;
2015-01-18 12:16:23 +03:00
static int vidi_enable_vblank ( struct exynos_drm_crtc * crtc )
2012-03-21 05:55:26 +04:00
{
2015-01-18 12:16:23 +03:00
struct vidi_context * ctx = crtc - > ctx ;
2012-03-21 05:55:26 +04:00
if ( ctx - > suspended )
return - EPERM ;
if ( ! test_and_set_bit ( 0 , & ctx - > irq_flags ) )
ctx - > vblank_on = true ;
2012-09-19 06:02:43 +04:00
ctx - > direct_vblank = true ;
/*
* in case of page flip request , vidi_finish_pageflip function
* will not be called because direct_vblank is true and then
2015-08-03 08:38:05 +03:00
* that function will be called by crtc_ops - > update_plane callback
2012-09-19 06:02:43 +04:00
*/
schedule_work ( & ctx - > work ) ;
2012-03-21 05:55:26 +04:00
return 0 ;
}
2015-01-18 12:16:23 +03:00
static void vidi_disable_vblank ( struct exynos_drm_crtc * crtc )
2012-03-21 05:55:26 +04:00
{
2015-01-18 12:16:23 +03:00
struct vidi_context * ctx = crtc - > ctx ;
2012-03-21 05:55:26 +04:00
if ( ctx - > suspended )
return ;
if ( test_and_clear_bit ( 0 , & ctx - > irq_flags ) )
ctx - > vblank_on = false ;
}
2015-08-03 08:39:36 +03:00
static void vidi_update_plane ( struct exynos_drm_crtc * crtc ,
struct exynos_drm_plane * plane )
2012-03-21 05:55:26 +04:00
{
2015-11-30 16:53:21 +03:00
struct drm_plane_state * state = plane - > base . state ;
2015-01-18 12:16:23 +03:00
struct vidi_context * ctx = crtc - > ctx ;
2015-11-30 16:53:21 +03:00
dma_addr_t addr ;
2012-03-21 05:55:26 +04:00
if ( ctx - > suspended )
return ;
2015-11-30 16:53:21 +03:00
addr = exynos_drm_fb_dma_addr ( state - > fb , 0 ) ;
DRM_DEBUG_KMS ( " dma_addr = %pad \n " , & addr ) ;
2012-03-21 05:55:26 +04:00
if ( ctx - > vblank_on )
schedule_work ( & ctx - > work ) ;
}
2015-06-01 18:04:55 +03:00
static void vidi_enable ( struct exynos_drm_crtc * crtc )
2014-01-31 01:19:27 +04:00
{
2015-06-01 18:04:55 +03:00
struct vidi_context * ctx = crtc - > ctx ;
2015-04-03 15:03:40 +03:00
2015-06-01 18:04:55 +03:00
mutex_lock ( & ctx - > lock ) ;
2014-01-31 01:19:27 +04:00
2015-06-01 18:04:55 +03:00
ctx - > suspended = false ;
2014-01-31 01:19:27 +04:00
2015-06-01 18:04:55 +03:00
/* if vblank was enabled status, enable it again. */
if ( test_and_clear_bit ( 0 , & ctx - > irq_flags ) )
vidi_enable_vblank ( ctx - > crtc ) ;
2014-01-31 01:19:27 +04:00
2015-06-01 18:04:55 +03:00
mutex_unlock ( & ctx - > lock ) ;
2014-01-31 01:19:27 +04:00
}
2015-06-01 18:04:55 +03:00
static void vidi_disable ( struct exynos_drm_crtc * crtc )
2014-01-31 01:19:27 +04:00
{
2015-01-18 12:16:23 +03:00
struct vidi_context * ctx = crtc - > ctx ;
2014-01-31 01:19:27 +04:00
mutex_lock ( & ctx - > lock ) ;
2015-06-01 18:04:55 +03:00
ctx - > suspended = true ;
2014-01-31 01:19:27 +04:00
mutex_unlock ( & ctx - > lock ) ;
}
2015-01-18 12:16:23 +03:00
static int vidi_ctx_initialize ( struct vidi_context * ctx ,
2014-05-09 09:25:20 +04:00
struct drm_device * drm_dev )
2014-02-19 16:02:55 +04:00
{
2014-05-09 09:25:20 +04:00
struct exynos_drm_private * priv = drm_dev - > dev_private ;
2014-02-19 16:02:55 +04:00
2014-11-26 21:43:27 +03:00
ctx - > drm_dev = drm_dev ;
2014-11-04 23:44:47 +03:00
ctx - > pipe = priv - > pipe + + ;
2014-02-19 16:02:55 +04:00
return 0 ;
}
2015-05-07 03:04:45 +03:00
static const struct exynos_drm_crtc_ops vidi_crtc_ops = {
2015-06-01 18:04:55 +03:00
. enable = vidi_enable ,
. disable = vidi_disable ,
2014-01-31 01:19:02 +04:00
. enable_vblank = vidi_enable_vblank ,
. disable_vblank = vidi_disable_vblank ,
2015-08-03 08:38:05 +03:00
. update_plane = vidi_update_plane ,
2012-03-21 05:55:26 +04:00
} ;
static void vidi_fake_vblank_handler ( struct work_struct * work )
{
struct vidi_context * ctx = container_of ( work , struct vidi_context ,
work ) ;
2015-08-15 19:26:14 +03:00
int win ;
2012-03-21 05:55:26 +04:00
2014-02-19 16:02:55 +04:00
if ( ctx - > pipe < 0 )
2012-03-21 05:55:26 +04:00
return ;
/* refresh rate is about 50Hz. */
usleep_range ( 16000 , 20000 ) ;
2012-09-19 06:02:43 +04:00
mutex_lock ( & ctx - > lock ) ;
if ( ctx - > direct_vblank ) {
2015-07-16 18:23:32 +03:00
drm_crtc_handle_vblank ( & ctx - > crtc - > base ) ;
2012-09-19 06:02:43 +04:00
ctx - > direct_vblank = false ;
mutex_unlock ( & ctx - > lock ) ;
return ;
}
mutex_unlock ( & ctx - > lock ) ;
2015-08-15 19:26:14 +03:00
for ( win = 0 ; win < WINDOWS_NR ; win + + ) {
struct exynos_drm_plane * plane = & ctx - > planes [ win ] ;
if ( ! plane - > pending_fb )
continue ;
exynos_drm_crtc_finish_update ( ctx - > crtc , plane ) ;
}
2012-03-21 05:55:26 +04:00
}
static int vidi_show_connection ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
2014-11-17 11:54:16 +03:00
struct vidi_context * ctx = dev_get_drvdata ( dev ) ;
2012-03-21 05:55:26 +04:00
int rc ;
mutex_lock ( & ctx - > lock ) ;
rc = sprintf ( buf , " %d \n " , ctx - > connected ) ;
mutex_unlock ( & ctx - > lock ) ;
return rc ;
}
static int vidi_store_connection ( struct device * dev ,
struct device_attribute * attr ,
const char * buf , size_t len )
{
2014-11-17 11:54:16 +03:00
struct vidi_context * ctx = dev_get_drvdata ( dev ) ;
2012-03-21 05:55:26 +04:00
int ret ;
ret = kstrtoint ( buf , 0 , & ctx - > connected ) ;
if ( ret )
return ret ;
if ( ctx - > connected > 1 )
return - EINVAL ;
2012-06-27 11:00:56 +04:00
/* use fake edid data for test. */
if ( ! ctx - > raw_edid )
ctx - > raw_edid = ( struct edid * ) fake_edid_info ;
2012-06-27 11:16:26 +04:00
/* if raw_edid isn't same as fake data then it can't be tested. */
if ( ctx - > raw_edid ! = ( struct edid * ) fake_edid_info ) {
DRM_DEBUG_KMS ( " edid data is not fake data. \n " ) ;
return - EINVAL ;
}
2012-03-21 05:55:26 +04:00
DRM_DEBUG_KMS ( " requested connection. \n " ) ;
2014-02-19 16:02:55 +04:00
drm_helper_hpd_irq_event ( ctx - > drm_dev ) ;
2012-03-21 05:55:26 +04:00
return len ;
}
static DEVICE_ATTR ( connection , 0644 , vidi_show_connection ,
vidi_store_connection ) ;
int vidi_connection_ioctl ( struct drm_device * drm_dev , void * data ,
struct drm_file * file_priv )
{
2015-08-11 11:38:06 +03:00
struct vidi_context * ctx = dev_get_drvdata ( drm_dev - > dev ) ;
2012-03-21 05:55:26 +04:00
struct drm_exynos_vidi_connection * vidi = data ;
if ( ! vidi ) {
DRM_DEBUG_KMS ( " user data for vidi is null. \n " ) ;
return - EINVAL ;
}
if ( vidi - > connection > 1 ) {
DRM_DEBUG_KMS ( " connection should be 0 or 1. \n " ) ;
return - EINVAL ;
}
if ( ctx - > connected = = vidi - > connection ) {
DRM_DEBUG_KMS ( " same connection request. \n " ) ;
return - EINVAL ;
}
2012-06-27 11:36:12 +04:00
if ( vidi - > connection ) {
2013-01-10 14:35:06 +04:00
struct edid * raw_edid = ( struct edid * ) ( uint32_t ) vidi - > edid ;
if ( ! drm_edid_is_valid ( raw_edid ) ) {
DRM_DEBUG_KMS ( " edid data is invalid. \n " ) ;
2012-06-27 11:36:12 +04:00
return - EINVAL ;
}
2013-09-27 16:08:29 +04:00
ctx - > raw_edid = drm_edid_duplicate ( raw_edid ) ;
2012-06-27 11:36:12 +04:00
if ( ! ctx - > raw_edid ) {
DRM_DEBUG_KMS ( " failed to allocate raw_edid. \n " ) ;
return - ENOMEM ;
}
} else {
/*
* with connection = 0 , free raw_edid
* only if raw edid data isn ' t same as fake data .
*/
if ( ctx - > raw_edid & & ctx - > raw_edid ! =
( struct edid * ) fake_edid_info ) {
kfree ( ctx - > raw_edid ) ;
ctx - > raw_edid = NULL ;
}
}
2012-03-21 05:55:26 +04:00
ctx - > connected = vidi - > connection ;
2014-02-19 16:02:55 +04:00
drm_helper_hpd_irq_event ( ctx - > drm_dev ) ;
2012-03-21 05:55:26 +04:00
return 0 ;
}
2014-01-31 01:38:07 +04:00
static enum drm_connector_status vidi_detect ( struct drm_connector * connector ,
bool force )
{
struct vidi_context * ctx = ctx_from_connector ( connector ) ;
/*
* connection request would come from user side
* to do hotplug through specific ioctl .
*/
return ctx - > connected ? connector_status_connected :
connector_status_disconnected ;
}
static void vidi_connector_destroy ( struct drm_connector * connector )
{
}
2015-12-15 14:21:06 +03:00
static const struct drm_connector_funcs vidi_connector_funcs = {
2015-06-01 18:04:53 +03:00
. dpms = drm_atomic_helper_connector_dpms ,
2014-01-31 01:38:07 +04:00
. fill_modes = drm_helper_probe_single_connector_modes ,
. detect = vidi_detect ,
. destroy = vidi_connector_destroy ,
2015-06-01 18:04:44 +03:00
. reset = drm_atomic_helper_connector_reset ,
. atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state ,
. atomic_destroy_state = drm_atomic_helper_connector_destroy_state ,
2014-01-31 01:38:07 +04:00
} ;
static int vidi_get_modes ( struct drm_connector * connector )
{
struct vidi_context * ctx = ctx_from_connector ( connector ) ;
struct edid * edid ;
int edid_len ;
/*
* the edid data comes from user side and it would be set
* to ctx - > raw_edid through specific ioctl .
*/
if ( ! ctx - > raw_edid ) {
DRM_DEBUG_KMS ( " raw_edid is null. \n " ) ;
return - EFAULT ;
}
edid_len = ( 1 + ctx - > raw_edid - > extensions ) * EDID_LENGTH ;
edid = kmemdup ( ctx - > raw_edid , edid_len , GFP_KERNEL ) ;
if ( ! edid ) {
DRM_DEBUG_KMS ( " failed to allocate edid \n " ) ;
return - ENOMEM ;
}
drm_mode_connector_update_edid_property ( connector , edid ) ;
return drm_add_edid_modes ( connector , edid ) ;
}
static struct drm_encoder * vidi_best_encoder ( struct drm_connector * connector )
{
struct vidi_context * ctx = ctx_from_connector ( connector ) ;
2015-08-15 18:14:08 +03:00
return & ctx - > encoder ;
2014-01-31 01:38:07 +04:00
}
2015-12-15 14:21:06 +03:00
static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
2014-01-31 01:38:07 +04:00
. get_modes = vidi_get_modes ,
. best_encoder = vidi_best_encoder ,
} ;
2015-08-15 18:14:08 +03:00
static int vidi_create_connector ( struct drm_encoder * encoder )
2014-01-31 01:38:07 +04:00
{
2015-08-15 18:14:08 +03:00
struct vidi_context * ctx = encoder_to_vidi ( encoder ) ;
2014-01-31 01:38:07 +04:00
struct drm_connector * connector = & ctx - > connector ;
int ret ;
connector - > polled = DRM_CONNECTOR_POLL_HPD ;
ret = drm_connector_init ( ctx - > drm_dev , connector ,
& vidi_connector_funcs , DRM_MODE_CONNECTOR_VIRTUAL ) ;
if ( ret ) {
DRM_ERROR ( " Failed to initialize connector with drm \n " ) ;
return ret ;
}
drm_connector_helper_add ( connector , & vidi_connector_helper_funcs ) ;
2014-05-29 19:57:41 +04:00
drm_connector_register ( connector ) ;
2014-01-31 01:38:07 +04:00
drm_mode_connector_attach_encoder ( connector , encoder ) ;
return 0 ;
}
2015-08-15 18:14:08 +03:00
static bool exynos_vidi_mode_fixup ( struct drm_encoder * encoder ,
const struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode )
{
return true ;
}
static void exynos_vidi_mode_set ( struct drm_encoder * encoder ,
struct drm_display_mode * mode ,
struct drm_display_mode * adjusted_mode )
{
}
static void exynos_vidi_enable ( struct drm_encoder * encoder )
{
}
static void exynos_vidi_disable ( struct drm_encoder * encoder )
{
}
2015-12-15 14:21:06 +03:00
static const struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = {
2015-08-15 18:14:08 +03:00
. mode_fixup = exynos_vidi_mode_fixup ,
. mode_set = exynos_vidi_mode_set ,
. enable = exynos_vidi_enable ,
. disable = exynos_vidi_disable ,
} ;
2015-12-15 14:21:06 +03:00
static const struct drm_encoder_funcs exynos_vidi_encoder_funcs = {
2015-08-15 18:14:08 +03:00
. destroy = drm_encoder_cleanup ,
} ;
2014-11-24 08:55:41 +03:00
static int vidi_bind ( struct device * dev , struct device * master , void * data )
2014-05-09 09:25:20 +04:00
{
2014-11-17 11:54:16 +03:00
struct vidi_context * ctx = dev_get_drvdata ( dev ) ;
2014-11-24 08:55:41 +03:00
struct drm_device * drm_dev = data ;
2015-08-15 18:14:08 +03:00
struct drm_encoder * encoder = & ctx - > encoder ;
2015-04-03 15:03:40 +03:00
struct exynos_drm_plane * exynos_plane ;
2015-11-30 16:53:25 +03:00
struct exynos_drm_plane_config plane_config = { 0 } ;
unsigned int i ;
2015-08-15 18:14:08 +03:00
int pipe , ret ;
2014-05-09 09:25:20 +04:00
2015-01-30 10:43:01 +03:00
vidi_ctx_initialize ( ctx , drm_dev ) ;
2015-11-30 16:53:25 +03:00
plane_config . pixel_formats = formats ;
plane_config . num_pixel_formats = ARRAY_SIZE ( formats ) ;
for ( i = 0 ; i < WINDOWS_NR ; i + + ) {
plane_config . zpos = i ;
plane_config . type = vidi_win_types [ i ] ;
ret = exynos_plane_init ( drm_dev , & ctx - > planes [ i ] ,
1 < < ctx - > pipe , & plane_config ) ;
2015-04-03 15:03:40 +03:00
if ( ret )
return ret ;
}
2015-10-12 16:07:48 +03:00
exynos_plane = & ctx - > planes [ DEFAULT_WIN ] ;
2015-04-03 15:03:40 +03:00
ctx - > crtc = exynos_drm_crtc_create ( drm_dev , & exynos_plane - > base ,
ctx - > pipe , EXYNOS_DISPLAY_TYPE_VIDI ,
2015-01-18 12:16:23 +03:00
& vidi_crtc_ops , ctx ) ;
if ( IS_ERR ( ctx - > crtc ) ) {
2014-05-09 09:25:20 +04:00
DRM_ERROR ( " failed to create crtc. \n " ) ;
2015-01-18 12:16:23 +03:00
return PTR_ERR ( ctx - > crtc ) ;
2014-05-09 09:25:20 +04:00
}
2015-08-15 18:14:08 +03:00
pipe = exynos_drm_crtc_get_pipe_from_type ( drm_dev ,
EXYNOS_DISPLAY_TYPE_VIDI ) ;
if ( pipe < 0 )
return pipe ;
encoder - > possible_crtcs = 1 < < pipe ;
DRM_DEBUG_KMS ( " possible_crtcs = 0x%x \n " , encoder - > possible_crtcs ) ;
drm_encoder_init ( drm_dev , encoder , & exynos_vidi_encoder_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 17:20:18 +03:00
DRM_MODE_ENCODER_TMDS , NULL ) ;
2015-08-15 18:14:08 +03:00
drm_encoder_helper_add ( encoder , & exynos_vidi_encoder_helper_funcs ) ;
2015-08-06 02:24:20 +03:00
2015-08-15 18:14:08 +03:00
ret = vidi_create_connector ( encoder ) ;
2014-05-09 09:25:20 +04:00
if ( ret ) {
2015-08-06 02:24:20 +03:00
DRM_ERROR ( " failed to create connector ret = %d \n " , ret ) ;
2015-08-15 18:14:08 +03:00
drm_encoder_cleanup ( encoder ) ;
2014-05-09 09:25:20 +04:00
return ret ;
}
return 0 ;
}
2014-11-24 08:55:41 +03:00
static void vidi_unbind ( struct device * dev , struct device * master , void * data )
{
}
static const struct component_ops vidi_component_ops = {
. bind = vidi_bind ,
. unbind = vidi_unbind ,
} ;
2012-12-22 03:09:25 +04:00
static int vidi_probe ( struct platform_device * pdev )
2012-03-21 05:55:26 +04:00
{
struct vidi_context * ctx ;
int ret ;
2014-05-09 09:25:20 +04:00
ctx = devm_kzalloc ( & pdev - > dev , sizeof ( * ctx ) , GFP_KERNEL ) ;
2012-03-21 05:55:26 +04:00
if ( ! ctx )
return - ENOMEM ;
2014-11-24 08:55:41 +03:00
ctx - > pdev = pdev ;
2012-03-21 05:55:26 +04:00
INIT_WORK ( & ctx - > work , vidi_fake_vblank_handler ) ;
mutex_init ( & ctx - > lock ) ;
2014-11-17 11:54:16 +03:00
platform_set_drvdata ( pdev , ctx ) ;
2012-03-21 05:55:26 +04:00
2014-05-09 09:25:20 +04:00
ret = device_create_file ( & pdev - > dev , & dev_attr_connection ) ;
if ( ret < 0 ) {
2014-11-24 08:55:41 +03:00
DRM_ERROR ( " failed to create connection sysfs. \n " ) ;
2015-06-11 17:23:37 +03:00
return ret ;
2014-05-09 09:25:20 +04:00
}
2012-03-21 05:55:26 +04:00
2014-11-24 08:55:41 +03:00
ret = component_add ( & pdev - > dev , & vidi_component_ops ) ;
if ( ret )
goto err_remove_file ;
return ret ;
err_remove_file :
device_remove_file ( & pdev - > dev , & dev_attr_connection ) ;
return ret ;
2012-03-21 05:55:26 +04:00
}
2012-12-22 03:09:25 +04:00
static int vidi_remove ( struct platform_device * pdev )
2012-03-21 05:55:26 +04:00
{
2014-11-17 11:54:16 +03:00
struct vidi_context * ctx = platform_get_drvdata ( pdev ) ;
2012-03-21 05:55:26 +04:00
2012-06-27 11:36:12 +04:00
if ( ctx - > raw_edid ! = ( struct edid * ) fake_edid_info ) {
kfree ( ctx - > raw_edid ) ;
ctx - > raw_edid = NULL ;
2014-05-09 09:25:20 +04:00
return - EINVAL ;
2012-06-27 11:36:12 +04:00
}
2014-11-24 08:55:41 +03:00
component_del ( & pdev - > dev , & vidi_component_ops ) ;
2012-03-21 05:55:26 +04:00
return 0 ;
}
struct platform_driver vidi_driver = {
. probe = vidi_probe ,
2012-12-22 03:09:25 +04:00
. remove = vidi_remove ,
2012-03-21 05:55:26 +04:00
. driver = {
. name = " exynos-drm-vidi " ,
. owner = THIS_MODULE ,
} ,
} ;