diff options
Diffstat (limited to 'include/drm')
28 files changed, 2141 insertions, 1056 deletions
diff --git a/include/drm/bridge/mhl.h b/include/drm/bridge/mhl.h new file mode 100644 index 000000000000..3629b2734db6 --- /dev/null +++ b/include/drm/bridge/mhl.h @@ -0,0 +1,291 @@ +/* + * Defines for Mobile High-Definition Link (MHL) interface + * + * Copyright (C) 2015, Samsung Electronics, Co., Ltd. + * Andrzej Hajda <a.hajda@samsung.com> + * + * Based on MHL driver for Android devices. + * Copyright (C) 2013-2014 Silicon Image, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MHL_H__ +#define __MHL_H__ + +/* Device Capabilities Registers */ +enum { + MHL_DCAP_DEV_STATE, + MHL_DCAP_MHL_VERSION, + MHL_DCAP_CAT, + MHL_DCAP_ADOPTER_ID_H, + MHL_DCAP_ADOPTER_ID_L, + MHL_DCAP_VID_LINK_MODE, + MHL_DCAP_AUD_LINK_MODE, + MHL_DCAP_VIDEO_TYPE, + MHL_DCAP_LOG_DEV_MAP, + MHL_DCAP_BANDWIDTH, + MHL_DCAP_FEATURE_FLAG, + MHL_DCAP_DEVICE_ID_H, + MHL_DCAP_DEVICE_ID_L, + MHL_DCAP_SCRATCHPAD_SIZE, + MHL_DCAP_INT_STAT_SIZE, + MHL_DCAP_RESERVED, + MHL_DCAP_SIZE +}; + +#define MHL_DCAP_CAT_SINK 0x01 +#define MHL_DCAP_CAT_SOURCE 0x02 +#define MHL_DCAP_CAT_POWER 0x10 +#define MHL_DCAP_CAT_PLIM(x) ((x) << 5) + +#define MHL_DCAP_VID_LINK_RGB444 0x01 +#define MHL_DCAP_VID_LINK_YCBCR444 0x02 +#define MHL_DCAP_VID_LINK_YCBCR422 0x04 +#define MHL_DCAP_VID_LINK_PPIXEL 0x08 +#define MHL_DCAP_VID_LINK_ISLANDS 0x10 +#define MHL_DCAP_VID_LINK_VGA 0x20 +#define MHL_DCAP_VID_LINK_16BPP 0x40 + +#define MHL_DCAP_AUD_LINK_2CH 0x01 +#define MHL_DCAP_AUD_LINK_8CH 0x02 + +#define MHL_DCAP_VT_GRAPHICS 0x00 +#define MHL_DCAP_VT_PHOTO 0x02 +#define MHL_DCAP_VT_CINEMA 0x04 +#define MHL_DCAP_VT_GAMES 0x08 +#define MHL_DCAP_SUPP_VT 0x80 + +#define MHL_DCAP_LD_DISPLAY 0x01 +#define MHL_DCAP_LD_VIDEO 0x02 +#define MHL_DCAP_LD_AUDIO 0x04 +#define MHL_DCAP_LD_MEDIA 0x08 +#define MHL_DCAP_LD_TUNER 0x10 +#define MHL_DCAP_LD_RECORD 0x20 +#define MHL_DCAP_LD_SPEAKER 0x40 +#define MHL_DCAP_LD_GUI 0x80 +#define MHL_DCAP_LD_ALL 0xFF + +#define MHL_DCAP_FEATURE_RCP_SUPPORT 0x01 +#define MHL_DCAP_FEATURE_RAP_SUPPORT 0x02 +#define MHL_DCAP_FEATURE_SP_SUPPORT 0x04 +#define MHL_DCAP_FEATURE_UCP_SEND_SUPPOR 0x08 +#define MHL_DCAP_FEATURE_UCP_RECV_SUPPORT 0x10 +#define MHL_DCAP_FEATURE_RBP_SUPPORT 0x40 + +/* Extended Device Capabilities Registers */ +enum { + MHL_XDC_ECBUS_SPEEDS, + MHL_XDC_TMDS_SPEEDS, + MHL_XDC_ECBUS_ROLES, + MHL_XDC_LOG_DEV_MAPX, + MHL_XDC_SIZE +}; + +#define MHL_XDC_ECBUS_S_075 0x01 +#define MHL_XDC_ECBUS_S_8BIT 0x02 +#define MHL_XDC_ECBUS_S_12BIT 0x04 +#define MHL_XDC_ECBUS_D_150 0x10 +#define MHL_XDC_ECBUS_D_8BIT 0x20 + +#define MHL_XDC_TMDS_000 0x00 +#define MHL_XDC_TMDS_150 0x01 +#define MHL_XDC_TMDS_300 0x02 +#define MHL_XDC_TMDS_600 0x04 + +/* MHL_XDC_ECBUS_ROLES flags */ +#define MHL_XDC_DEV_HOST 0x01 +#define MHL_XDC_DEV_DEVICE 0x02 +#define MHL_XDC_DEV_CHARGER 0x04 +#define MHL_XDC_HID_HOST 0x08 +#define MHL_XDC_HID_DEVICE 0x10 + +/* MHL_XDC_LOG_DEV_MAPX flags */ +#define MHL_XDC_LD_PHONE 0x01 + +/* Device Status Registers */ +enum { + MHL_DST_CONNECTED_RDY, + MHL_DST_LINK_MODE, + MHL_DST_VERSION, + MHL_DST_SIZE +}; + +/* Offset of DEVSTAT registers */ +#define MHL_DST_OFFSET 0x30 +#define MHL_DST_REG(name) (MHL_DST_OFFSET + MHL_DST_##name) + +#define MHL_DST_CONN_DCAP_RDY 0x01 +#define MHL_DST_CONN_XDEVCAPP_SUPP 0x02 +#define MHL_DST_CONN_POW_STAT 0x04 +#define MHL_DST_CONN_PLIM_STAT_MASK 0x38 + +#define MHL_DST_LM_CLK_MODE_MASK 0x07 +#define MHL_DST_LM_CLK_MODE_PACKED_PIXEL 0x02 +#define MHL_DST_LM_CLK_MODE_NORMAL 0x03 +#define MHL_DST_LM_PATH_EN_MASK 0x08 +#define MHL_DST_LM_PATH_ENABLED 0x08 +#define MHL_DST_LM_PATH_DISABLED 0x00 +#define MHL_DST_LM_MUTED_MASK 0x10 + +/* Extended Device Status Registers */ +enum { + MHL_XDS_CURR_ECBUS_MODE, + MHL_XDS_AVLINK_MODE_STATUS, + MHL_XDS_AVLINK_MODE_CONTROL, + MHL_XDS_MULTI_SINK_STATUS, + MHL_XDS_SIZE +}; + +/* Offset of XDEVSTAT registers */ +#define MHL_XDS_OFFSET 0x90 +#define MHL_XDS_REG(name) (MHL_XDS_OFFSET + MHL_XDS_##name) + +/* MHL_XDS_REG_CURR_ECBUS_MODE flags */ +#define MHL_XDS_SLOT_MODE_8BIT 0x00 +#define MHL_XDS_SLOT_MODE_6BIT 0x01 +#define MHL_XDS_ECBUS_S 0x04 +#define MHL_XDS_ECBUS_D 0x08 + +#define MHL_XDS_LINK_CLOCK_75MHZ 0x00 +#define MHL_XDS_LINK_CLOCK_150MHZ 0x10 +#define MHL_XDS_LINK_CLOCK_300MHZ 0x20 +#define MHL_XDS_LINK_CLOCK_600MHZ 0x30 + +#define MHL_XDS_LINK_STATUS_NO_SIGNAL 0x00 +#define MHL_XDS_LINK_STATUS_CRU_LOCKED 0x01 +#define MHL_XDS_LINK_STATUS_TMDS_NORMAL 0x02 +#define MHL_XDS_LINK_STATUS_TMDS_RESERVED 0x03 + +#define MHL_XDS_LINK_RATE_1_5_GBPS 0x00 +#define MHL_XDS_LINK_RATE_3_0_GBPS 0x01 +#define MHL_XDS_LINK_RATE_6_0_GBPS 0x02 +#define MHL_XDS_ATT_CAPABLE 0x08 + +#define MHL_XDS_SINK_STATUS_1_HPD_LOW 0x00 +#define MHL_XDS_SINK_STATUS_1_HPD_HIGH 0x01 +#define MHL_XDS_SINK_STATUS_2_HPD_LOW 0x00 +#define MHL_XDS_SINK_STATUS_2_HPD_HIGH 0x04 +#define MHL_XDS_SINK_STATUS_3_HPD_LOW 0x00 +#define MHL_XDS_SINK_STATUS_3_HPD_HIGH 0x10 +#define MHL_XDS_SINK_STATUS_4_HPD_LOW 0x00 +#define MHL_XDS_SINK_STATUS_4_HPD_HIGH 0x40 + +/* Interrupt Registers */ +enum { + MHL_INT_RCHANGE, + MHL_INT_DCHANGE, + MHL_INT_SIZE +}; + +/* Offset of DEVSTAT registers */ +#define MHL_INT_OFFSET 0x20 +#define MHL_INT_REG(name) (MHL_INT_OFFSET + MHL_INT_##name) + +#define MHL_INT_RC_DCAP_CHG 0x01 +#define MHL_INT_RC_DSCR_CHG 0x02 +#define MHL_INT_RC_REQ_WRT 0x04 +#define MHL_INT_RC_GRT_WRT 0x08 +#define MHL_INT_RC_3D_REQ 0x10 +#define MHL_INT_RC_FEAT_REQ 0x20 +#define MHL_INT_RC_FEAT_COMPLETE 0x40 + +#define MHL_INT_DC_EDID_CHG 0x02 + +enum { + MHL_ACK = 0x33, /* Command or Data byte acknowledge */ + MHL_NACK = 0x34, /* Command or Data byte not acknowledge */ + MHL_ABORT = 0x35, /* Transaction abort */ + MHL_WRITE_STAT = 0xe0, /* Write one status register */ + MHL_SET_INT = 0x60, /* Write one interrupt register */ + MHL_READ_DEVCAP_REG = 0x61, /* Read one register */ + MHL_GET_STATE = 0x62, /* Read CBUS revision level from follower */ + MHL_GET_VENDOR_ID = 0x63, /* Read vendor ID value from follower */ + MHL_SET_HPD = 0x64, /* Set Hot Plug Detect in follower */ + MHL_CLR_HPD = 0x65, /* Clear Hot Plug Detect in follower */ + MHL_SET_CAP_ID = 0x66, /* Set Capture ID for downstream device */ + MHL_GET_CAP_ID = 0x67, /* Get Capture ID from downstream device */ + MHL_MSC_MSG = 0x68, /* VS command to send RCP sub-commands */ + MHL_GET_SC1_ERRORCODE = 0x69, /* Get Vendor-Specific error code */ + MHL_GET_DDC_ERRORCODE = 0x6A, /* Get DDC channel command error code */ + MHL_GET_MSC_ERRORCODE = 0x6B, /* Get MSC command error code */ + MHL_WRITE_BURST = 0x6C, /* Write 1-16 bytes to responder's scratchpad */ + MHL_GET_SC3_ERRORCODE = 0x6D, /* Get channel 3 command error code */ + MHL_WRITE_XSTAT = 0x70, /* Write one extended status register */ + MHL_READ_XDEVCAP_REG = 0x71, /* Read one extended devcap register */ + /* let the rest of these float, they are software specific */ + MHL_READ_EDID_BLOCK, + MHL_SEND_3D_REQ_OR_FEAT_REQ, + MHL_READ_DEVCAP, + MHL_READ_XDEVCAP +}; + +/* MSC message types */ +enum { + MHL_MSC_MSG_RCP = 0x10, /* RCP sub-command */ + MHL_MSC_MSG_RCPK = 0x11, /* RCP Acknowledge sub-command */ + MHL_MSC_MSG_RCPE = 0x12, /* RCP Error sub-command */ + MHL_MSC_MSG_RAP = 0x20, /* Mode Change Warning sub-command */ + MHL_MSC_MSG_RAPK = 0x21, /* MCW Acknowledge sub-command */ + MHL_MSC_MSG_RBP = 0x22, /* Remote Button Protocol sub-command */ + MHL_MSC_MSG_RBPK = 0x23, /* RBP Acknowledge sub-command */ + MHL_MSC_MSG_RBPE = 0x24, /* RBP Error sub-command */ + MHL_MSC_MSG_UCP = 0x30, /* UCP sub-command */ + MHL_MSC_MSG_UCPK = 0x31, /* UCP Acknowledge sub-command */ + MHL_MSC_MSG_UCPE = 0x32, /* UCP Error sub-command */ + MHL_MSC_MSG_RUSB = 0x40, /* Request USB host role */ + MHL_MSC_MSG_RUSBK = 0x41, /* Acknowledge request for USB host role */ + MHL_MSC_MSG_RHID = 0x42, /* Request HID host role */ + MHL_MSC_MSG_RHIDK = 0x43, /* Acknowledge request for HID host role */ + MHL_MSC_MSG_ATT = 0x50, /* Request attention sub-command */ + MHL_MSC_MSG_ATTK = 0x51, /* ATT Acknowledge sub-command */ + MHL_MSC_MSG_BIST_TRIGGER = 0x60, + MHL_MSC_MSG_BIST_REQUEST_STAT = 0x61, + MHL_MSC_MSG_BIST_READY = 0x62, + MHL_MSC_MSG_BIST_STOP = 0x63, +}; + +/* RAP action codes */ +#define MHL_RAP_POLL 0x00 /* Just do an ack */ +#define MHL_RAP_CONTENT_ON 0x10 /* Turn content stream ON */ +#define MHL_RAP_CONTENT_OFF 0x11 /* Turn content stream OFF */ +#define MHL_RAP_CBUS_MODE_DOWN 0x20 +#define MHL_RAP_CBUS_MODE_UP 0x21 + +/* RAPK status codes */ +#define MHL_RAPK_NO_ERR 0x00 /* RAP action recognized & supported */ +#define MHL_RAPK_UNRECOGNIZED 0x01 /* Unknown RAP action code received */ +#define MHL_RAPK_UNSUPPORTED 0x02 /* Rcvd RAP action code not supported */ +#define MHL_RAPK_BUSY 0x03 /* Responder too busy to respond */ + +/* + * Error status codes for RCPE messages + */ +/* No error. (Not allowed in RCPE messages) */ +#define MHL_RCPE_STATUS_NO_ERROR 0x00 +/* Unsupported/unrecognized key code */ +#define MHL_RCPE_STATUS_INEFFECTIVE_KEY_CODE 0x01 +/* Responder busy. Initiator may retry message */ +#define MHL_RCPE_STATUS_BUSY 0x02 + +/* + * Error status codes for RBPE messages + */ +/* No error. (Not allowed in RBPE messages) */ +#define MHL_RBPE_STATUS_NO_ERROR 0x00 +/* Unsupported/unrecognized button code */ +#define MHL_RBPE_STATUS_INEFFECTIVE_BUTTON_CODE 0x01 +/* Responder busy. Initiator may retry message */ +#define MHL_RBPE_STATUS_BUSY 0x02 + +/* + * Error status codes for UCPE messages + */ +/* No error. (Not allowed in UCPE messages) */ +#define MHL_UCPE_STATUS_NO_ERROR 0x00 +/* Unsupported/unrecognized key code */ +#define MHL_UCPE_STATUS_INEFFECTIVE_KEY_CODE 0x01 + +#endif /* __MHL_H__ */ diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 672644031bd5..192016e2b518 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -57,11 +57,11 @@ #include <linux/types.h> #include <linux/vmalloc.h> #include <linux/workqueue.h> -#include <linux/fence.h> +#include <linux/dma-fence.h> #include <asm/mman.h> #include <asm/pgalloc.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <uapi/drm/drm.h> #include <uapi/drm/drm_mode.h> @@ -76,6 +76,7 @@ #include <drm/drm_os_linux.h> #include <drm/drm_sarea.h> #include <drm/drm_vma_manager.h> +#include <drm/drm_drv.h> struct module; @@ -135,35 +136,12 @@ struct dma_buf_attachment; #define DRM_UT_PRIME 0x08 #define DRM_UT_ATOMIC 0x10 #define DRM_UT_VBL 0x20 - -extern __printf(6, 7) -void drm_dev_printk(const struct device *dev, const char *level, - unsigned int category, const char *function_name, - const char *prefix, const char *format, ...); - -extern __printf(3, 4) -void drm_printk(const char *level, unsigned int category, - const char *format, ...); +#define DRM_UT_STATE 0x40 /***********************************************************************/ /** \name DRM template customization defaults */ /*@{*/ -/* driver capabilities and requirements mask */ -#define DRIVER_USE_AGP 0x1 -#define DRIVER_LEGACY 0x2 -#define DRIVER_PCI_DMA 0x8 -#define DRIVER_SG 0x10 -#define DRIVER_HAVE_DMA 0x20 -#define DRIVER_HAVE_IRQ 0x40 -#define DRIVER_IRQ_SHARED 0x80 -#define DRIVER_GEM 0x1000 -#define DRIVER_MODESET 0x2000 -#define DRIVER_PRIME 0x4000 -#define DRIVER_RENDER 0x8000 -#define DRIVER_ATOMIC 0x10000 -#define DRIVER_KMS_LEGACY_CONTEXT 0x20000 - /***********************************************************************/ /** \name Macros to make printk easier */ /*@{*/ @@ -306,6 +284,27 @@ void drm_printk(const char *level, unsigned int category, #define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \ DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args) +/* Format strings and argument splitters to simplify printing + * various "complex" objects + */ +#define DRM_MODE_FMT "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x" +#define DRM_MODE_ARG(m) \ + (m)->base.id, (m)->name, (m)->vrefresh, (m)->clock, \ + (m)->hdisplay, (m)->hsync_start, (m)->hsync_end, (m)->htotal, \ + (m)->vdisplay, (m)->vsync_start, (m)->vsync_end, (m)->vtotal, \ + (m)->type, (m)->flags + +#define DRM_RECT_FMT "%dx%d%+d%+d" +#define DRM_RECT_ARG(r) drm_rect_width(r), drm_rect_height(r), (r)->x1, (r)->y1 + +/* for rect's in fixed-point format: */ +#define DRM_RECT_FP_FMT "%d.%06ux%d.%06u%+d.%06u%+d.%06u" +#define DRM_RECT_FP_ARG(r) \ + drm_rect_width(r) >> 16, ((drm_rect_width(r) & 0xffff) * 15625) >> 10, \ + drm_rect_height(r) >> 16, ((drm_rect_height(r) & 0xffff) * 15625) >> 10, \ + (r)->x1 >> 16, (((r)->x1 & 0xffff) * 15625) >> 10, \ + (r)->y1 >> 16, (((r)->y1 & 0xffff) * 15625) >> 10 + /*@}*/ /***********************************************************************/ @@ -362,7 +361,7 @@ struct drm_ioctl_desc { struct drm_pending_event { struct completion *completion; struct drm_event *event; - struct fence *fence; + struct dma_fence *fence; struct list_head link; struct list_head pending_link; struct drm_file *file_priv; @@ -458,263 +457,6 @@ struct drm_lock_data { #define DRM_SCANOUTPOS_IN_VBLANK (1 << 1) #define DRM_SCANOUTPOS_ACCURATE (1 << 2) -/** - * DRM driver structure. This structure represent the common code for - * a family of cards. There will one drm_device for each card present - * in this family - */ -struct drm_driver { - int (*load) (struct drm_device *, unsigned long flags); - int (*firstopen) (struct drm_device *); - int (*open) (struct drm_device *, struct drm_file *); - void (*preclose) (struct drm_device *, struct drm_file *file_priv); - void (*postclose) (struct drm_device *, struct drm_file *); - void (*lastclose) (struct drm_device *); - int (*unload) (struct drm_device *); - int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); - int (*dma_quiescent) (struct drm_device *); - int (*context_dtor) (struct drm_device *dev, int context); - int (*set_busid)(struct drm_device *dev, struct drm_master *master); - - /** - * get_vblank_counter - get raw hardware vblank counter - * @dev: DRM device - * @pipe: counter to fetch - * - * Driver callback for fetching a raw hardware vblank counter for @crtc. - * If a device doesn't have a hardware counter, the driver can simply - * use drm_vblank_no_hw_counter() function. The DRM core will account for - * missed vblank events while interrupts where disabled based on system - * timestamps. - * - * Wraparound handling and loss of events due to modesetting is dealt - * with in the DRM core code. - * - * RETURNS - * Raw vblank counter value. - */ - u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe); - - /** - * enable_vblank - enable vblank interrupt events - * @dev: DRM device - * @pipe: which irq to enable - * - * Enable vblank interrupts for @crtc. If the device doesn't have - * a hardware vblank counter, the driver should use the - * drm_vblank_no_hw_counter() function that keeps a virtual counter. - * - * RETURNS - * Zero on success, appropriate errno if the given @crtc's vblank - * interrupt cannot be enabled. - */ - int (*enable_vblank) (struct drm_device *dev, unsigned int pipe); - - /** - * disable_vblank - disable vblank interrupt events - * @dev: DRM device - * @pipe: which irq to enable - * - * Disable vblank interrupts for @crtc. If the device doesn't have - * a hardware vblank counter, the driver should use the - * drm_vblank_no_hw_counter() function that keeps a virtual counter. - */ - void (*disable_vblank) (struct drm_device *dev, unsigned int pipe); - - /** - * Called by \c drm_device_is_agp. Typically used to determine if a - * card is really attached to AGP or not. - * - * \param dev DRM device handle - * - * \returns - * One of three values is returned depending on whether or not the - * card is absolutely \b not AGP (return of 0), absolutely \b is AGP - * (return of 1), or may or may not be AGP (return of 2). - */ - int (*device_is_agp) (struct drm_device *dev); - - /** - * Called by vblank timestamping code. - * - * Return the current display scanout position from a crtc, and an - * optional accurate ktime_get timestamp of when position was measured. - * - * \param dev DRM device. - * \param pipe Id of the crtc to query. - * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0). - * \param *vpos Target location for current vertical scanout position. - * \param *hpos Target location for current horizontal scanout position. - * \param *stime Target location for timestamp taken immediately before - * scanout position query. Can be NULL to skip timestamp. - * \param *etime Target location for timestamp taken immediately after - * scanout position query. Can be NULL to skip timestamp. - * \param mode Current display timings. - * - * Returns vpos as a positive number while in active scanout area. - * Returns vpos as a negative number inside vblank, counting the number - * of scanlines to go until end of vblank, e.g., -1 means "one scanline - * until start of active scanout / end of vblank." - * - * \return Flags, or'ed together as follows: - * - * DRM_SCANOUTPOS_VALID = Query successful. - * DRM_SCANOUTPOS_INVBL = Inside vblank. - * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of - * this flag means that returned position may be offset by a constant - * but unknown small number of scanlines wrt. real scanout position. - * - */ - int (*get_scanout_position) (struct drm_device *dev, unsigned int pipe, - unsigned int flags, int *vpos, int *hpos, - ktime_t *stime, ktime_t *etime, - const struct drm_display_mode *mode); - - /** - * Called by \c drm_get_last_vbltimestamp. Should return a precise - * timestamp when the most recent VBLANK interval ended or will end. - * - * Specifically, the timestamp in @vblank_time should correspond as - * closely as possible to the time when the first video scanline of - * the video frame after the end of VBLANK will start scanning out, - * the time immediately after end of the VBLANK interval. If the - * @crtc is currently inside VBLANK, this will be a time in the future. - * If the @crtc is currently scanning out a frame, this will be the - * past start time of the current scanout. This is meant to adhere - * to the OpenML OML_sync_control extension specification. - * - * \param dev dev DRM device handle. - * \param pipe crtc for which timestamp should be returned. - * \param *max_error Maximum allowable timestamp error in nanoseconds. - * Implementation should strive to provide timestamp - * with an error of at most *max_error nanoseconds. - * Returns true upper bound on error for timestamp. - * \param *vblank_time Target location for returned vblank timestamp. - * \param flags 0 = Defaults, no special treatment needed. - * \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank - * irq handler. Some drivers need to apply some workarounds - * for gpu-specific vblank irq quirks if flag is set. - * - * \returns - * Zero if timestamping isn't supported in current display mode or a - * negative number on failure. A positive status code on success, - * which describes how the vblank_time timestamp was computed. - */ - int (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe, - int *max_error, - struct timeval *vblank_time, - unsigned flags); - - /* these have to be filled in */ - - irqreturn_t(*irq_handler) (int irq, void *arg); - void (*irq_preinstall) (struct drm_device *dev); - int (*irq_postinstall) (struct drm_device *dev); - void (*irq_uninstall) (struct drm_device *dev); - - /* Master routines */ - int (*master_create)(struct drm_device *dev, struct drm_master *master); - void (*master_destroy)(struct drm_device *dev, struct drm_master *master); - /** - * master_set is called whenever the minor master is set. - * master_drop is called whenever the minor master is dropped. - */ - - int (*master_set)(struct drm_device *dev, struct drm_file *file_priv, - bool from_open); - void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv); - - int (*debugfs_init)(struct drm_minor *minor); - void (*debugfs_cleanup)(struct drm_minor *minor); - - /** - * @gem_free_object: deconstructor for drm_gem_objects - * - * This is deprecated and should not be used by new drivers. Use - * @gem_free_object_unlocked instead. - */ - void (*gem_free_object) (struct drm_gem_object *obj); - - /** - * @gem_free_object_unlocked: deconstructor for drm_gem_objects - * - * This is for drivers which are not encumbered with dev->struct_mutex - * legacy locking schemes. Use this hook instead of @gem_free_object. - */ - void (*gem_free_object_unlocked) (struct drm_gem_object *obj); - - int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); - void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); - - /** - * Hook for allocating the GEM object struct, for use by core - * helpers. - */ - struct drm_gem_object *(*gem_create_object)(struct drm_device *dev, - size_t size); - - /* prime: */ - /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */ - int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, - uint32_t handle, uint32_t flags, int *prime_fd); - /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */ - int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, - int prime_fd, uint32_t *handle); - /* export GEM -> dmabuf */ - struct dma_buf * (*gem_prime_export)(struct drm_device *dev, - struct drm_gem_object *obj, int flags); - /* import dmabuf -> GEM */ - struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, - struct dma_buf *dma_buf); - /* low-level interface used by drm_gem_prime_{import,export} */ - int (*gem_prime_pin)(struct drm_gem_object *obj); - void (*gem_prime_unpin)(struct drm_gem_object *obj); - struct reservation_object * (*gem_prime_res_obj)( - struct drm_gem_object *obj); - struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj); - struct drm_gem_object *(*gem_prime_import_sg_table)( - struct drm_device *dev, - struct dma_buf_attachment *attach, - struct sg_table *sgt); - void *(*gem_prime_vmap)(struct drm_gem_object *obj); - void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr); - int (*gem_prime_mmap)(struct drm_gem_object *obj, - struct vm_area_struct *vma); - - /* vga arb irq handler */ - void (*vgaarb_irq)(struct drm_device *dev, bool state); - - /* dumb alloc support */ - int (*dumb_create)(struct drm_file *file_priv, - struct drm_device *dev, - struct drm_mode_create_dumb *args); - int (*dumb_map_offset)(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, - uint64_t *offset); - int (*dumb_destroy)(struct drm_file *file_priv, - struct drm_device *dev, - uint32_t handle); - - /* Driver private ops for this object */ - const struct vm_operations_struct *gem_vm_ops; - - int major; - int minor; - int patchlevel; - char *name; - char *desc; - char *date; - - u32 driver_features; - int dev_priv_size; - const struct drm_ioctl_desc *ioctls; - int num_ioctls; - const struct file_operations *fops; - - /* List of devices hanging off this driver with stealth attach. */ - struct list_head legacy_dev_list; -}; - enum drm_minor_type { DRM_MINOR_PRIMARY, DRM_MINOR_CONTROL, @@ -941,8 +683,13 @@ static inline bool drm_is_primary_client(const struct drm_file *file_priv) extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv); extern long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#else +/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */ +#define drm_compat_ioctl NULL +#endif extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags); /* File Operations (drm_fops.c) */ @@ -980,15 +727,6 @@ void drm_clflush_virt_range(void *addr, unsigned long length); * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. */ -/* Modesetting support */ -extern void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe); -extern void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe); - -/* drm_drv.c */ -void drm_put_dev(struct drm_device *dev); -void drm_unplug_dev(struct drm_device *dev); -extern unsigned int drm_debug; - /* Debugfs support */ #if defined(CONFIG_DEBUG_FS) extern int drm_debugfs_create_files(const struct drm_info_list *files, @@ -1041,19 +779,6 @@ extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah); extern void drm_sysfs_hotplug_event(struct drm_device *dev); -struct drm_device *drm_dev_alloc(struct drm_driver *driver, - struct device *parent); -int drm_dev_init(struct drm_device *dev, - struct drm_driver *driver, - struct device *parent); -void drm_dev_ref(struct drm_device *dev); -void drm_dev_unref(struct drm_device *dev); -int drm_dev_register(struct drm_device *dev, unsigned long flags); -void drm_dev_unregister(struct drm_device *dev); - -struct drm_minor *drm_minor_acquire(unsigned int minor_id); -void drm_minor_release(struct drm_minor *minor); - /*@}*/ /* PCI section */ diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 9701f2dfb784..d6d241f63b9f 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -144,6 +144,7 @@ struct __drm_crtcs_state { struct drm_crtc *ptr; struct drm_crtc_state *state; struct drm_crtc_commit *commit; + s64 __user *out_fence_ptr; }; struct __drm_connnectors_state { @@ -153,6 +154,7 @@ struct __drm_connnectors_state { /** * struct drm_atomic_state - the global state object for atomic updates + * @ref: count of all references to this state (will not be freed until zero) * @dev: parent DRM device * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics @@ -164,6 +166,8 @@ struct __drm_connnectors_state { * @acquire_ctx: acquire context for this atomic modeset state update */ struct drm_atomic_state { + struct kref ref; + struct drm_device *dev; bool allow_modeset : 1; bool legacy_cursor_update : 1; @@ -193,7 +197,33 @@ static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit) struct drm_atomic_state * __must_check drm_atomic_state_alloc(struct drm_device *dev); void drm_atomic_state_clear(struct drm_atomic_state *state); -void drm_atomic_state_free(struct drm_atomic_state *state); + +/** + * drm_atomic_state_get - acquire a reference to the atomic state + * @state: The atomic state + * + * Returns a new reference to the @state + */ +static inline struct drm_atomic_state * +drm_atomic_state_get(struct drm_atomic_state *state) +{ + kref_get(&state->ref); + return state; +} + +void __drm_atomic_state_free(struct kref *ref); + +/** + * drm_atomic_state_put - release a reference to the atomic state + * @state: The atomic state + * + * This releases a reference to @state which is freed after removing the + * final reference. No locking required and callable from any context. + */ +static inline void drm_atomic_state_put(struct drm_atomic_state *state) +{ + kref_put(&state->ref, __drm_atomic_state_free); +} int __must_check drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state); @@ -316,6 +346,8 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, struct drm_crtc *crtc); void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state, struct drm_framebuffer *fb); +void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state, + struct dma_fence *fence); int __must_check drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_crtc *crtc); @@ -335,6 +367,14 @@ int __must_check drm_atomic_check_only(struct drm_atomic_state *state); int __must_check drm_atomic_commit(struct drm_atomic_state *state); int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); +void drm_state_dump(struct drm_device *dev, struct drm_printer *p); + +#ifdef CONFIG_DEBUG_FS +struct drm_minor; +int drm_atomic_debugfs_init(struct drm_minor *minor); +int drm_atomic_debugfs_cleanup(struct drm_minor *minor); +#endif + #define for_each_connector_in_state(__state, connector, connector_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->num_connector && \ @@ -365,11 +405,20 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state); * * To give drivers flexibility struct &drm_crtc_state has 3 booleans to track * whether the state CRTC changed enough to need a full modeset cycle: - * connectors_changed, mode_changed and active_change. This helper simply + * connectors_changed, mode_changed and active_changed. This helper simply * combines these three to compute the overall need for a modeset for @state. + * + * The atomic helper code sets these booleans, but drivers can and should + * change them appropriately to accurately represent whether a modeset is + * really needed. In general, drivers should avoid full modesets whenever + * possible. + * + * For example if the CRTC mode has changed, and the hardware is able to enact + * the requested mode change without going through a full modeset, the driver + * should clear mode_changed during its ->atomic_check. */ static inline bool -drm_atomic_crtc_needs_modeset(struct drm_crtc_state *state) +drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state) { return state->mode_changed || state->active_changed || state->connectors_changed; diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index 36baa175de99..13221cf9b3eb 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -47,8 +47,14 @@ struct drm_atomic_state; #define DRM_REFLECT_Y BIT(5) #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y) -struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, - unsigned int supported_rotations); +static inline bool drm_rotation_90_or_270(unsigned int rotation) +{ + return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270); +} + +int drm_plane_create_rotation_property(struct drm_plane *plane, + unsigned int rotation, + unsigned int supported_rotations); unsigned int drm_rotation_simplify(unsigned int rotation, unsigned int supported_rotations); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index ac9d7d8e0e43..a9b95246e26e 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -37,6 +37,7 @@ struct drm_crtc; struct drm_encoder; struct drm_property; struct drm_property_blob; +struct drm_printer; struct edid; enum drm_connector_force { @@ -194,10 +195,40 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info, unsigned int num_formats); /** + * struct drm_tv_connector_state - TV connector related states + * @subconnector: selected subconnector + * @margins: left/right/top/bottom margins + * @mode: TV mode + * @brightness: brightness in percent + * @contrast: contrast in percent + * @flicker_reduction: flicker reduction in percent + * @overscan: overscan in percent + * @saturation: saturation in percent + * @hue: hue in percent + */ +struct drm_tv_connector_state { + enum drm_mode_subconnector subconnector; + struct { + unsigned int left; + unsigned int right; + unsigned int top; + unsigned int bottom; + } margins; + unsigned int mode; + unsigned int brightness; + unsigned int contrast; + unsigned int flicker_reduction; + unsigned int overscan; + unsigned int saturation; + unsigned int hue; +}; + +/** * struct drm_connector_state - mutable connector state * @connector: backpointer to the connector * @best_encoder: can be used by helpers and drivers to select the encoder * @state: backpointer to global drm_atomic_state + * @tv: TV connector state */ struct drm_connector_state { struct drm_connector *connector; @@ -213,6 +244,8 @@ struct drm_connector_state { struct drm_encoder *best_encoder; struct drm_atomic_state *state; + + struct drm_tv_connector_state tv; }; /** @@ -261,6 +294,9 @@ struct drm_connector_funcs { * connector due to a user request. force can be used by the driver to * avoid expensive, destructive operations during automated probing. * + * This callback is optional, if not implemented the connector will be + * considered as always being attached. + * * FIXME: * * Note that this hook is only called by the probe helper. It's not in @@ -481,6 +517,18 @@ struct drm_connector_funcs { const struct drm_connector_state *state, struct drm_property *property, uint64_t *val); + + /** + * @atomic_print_state: + * + * If driver subclasses struct &drm_connector_state, it should implement + * this optional hook for printing additional driver specific state. + * + * Do not call this directly, use drm_atomic_connector_print_state() + * instead. + */ + void (*atomic_print_state)(struct drm_printer *p, + const struct drm_connector_state *state); }; /* mode specified on the command line */ @@ -762,6 +810,30 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, const struct edid *edid); /** + * struct drm_tile_group - Tile group metadata + * @refcount: reference count + * @dev: DRM device + * @id: tile group id exposed to userspace + * @group_data: Sink-private data identifying this group + * + * @group_data corresponds to displayid vend/prod/serial for external screens + * with an EDID. + */ +struct drm_tile_group { + struct kref refcount; + struct drm_device *dev; + int id; + u8 group_data[8]; +}; + +struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, + char topology[8]); +struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, + char topology[8]); +void drm_mode_put_tile_group(struct drm_device *dev, + struct drm_tile_group *tg); + +/** * drm_for_each_connector - iterate over all connectors * @connector: the loop cursor * @dev: the DRM device diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 0aa292526567..946672f97e1e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -28,7 +28,6 @@ #include <linux/i2c.h> #include <linux/spinlock.h> #include <linux/types.h> -#include <linux/idr.h> #include <linux/fb.h> #include <linux/hdmi.h> #include <linux/media-bus-format.h> @@ -47,13 +46,16 @@ #include <drm/drm_plane.h> #include <drm/drm_blend.h> #include <drm/drm_color_mgmt.h> +#include <drm/drm_debugfs_crc.h> +#include <drm/drm_mode_config.h> struct drm_device; struct drm_mode_set; struct drm_file; struct drm_clip_rect; +struct drm_printer; struct device_node; -struct fence; +struct dma_fence; struct edid; static inline int64_t U642I64(uint64_t val) @@ -65,14 +67,6 @@ static inline uint64_t I642U64(int64_t val) return (uint64_t)*((uint64_t *)&val); } -/* data corresponds to displayid vend/prod/serial */ -struct drm_tile_group { - struct kref refcount; - struct drm_device *dev; - int id; - u8 group_data[8]; -}; - struct drm_crtc; struct drm_encoder; struct drm_pending_vblank_event; @@ -116,6 +110,11 @@ struct drm_plane_helper_funcs; * never return in a failure from the ->atomic_check callback. Userspace assumes * that a DPMS On will always succeed. In other words: @enable controls resource * assignment, @active controls the actual hardware state. + * + * The three booleans active_changed, connectors_changed and mode_changed are + * intended to indicate whether a full modeset is needed, rather than strictly + * describing what has changed in a commit. + * See also: drm_atomic_crtc_needs_modeset() */ struct drm_crtc_state { struct drm_crtc *crtc; @@ -564,6 +563,42 @@ struct drm_crtc_funcs { * before data structures are torndown. */ void (*early_unregister)(struct drm_crtc *crtc); + + /** + * @set_crc_source: + * + * Changes the source of CRC checksums of frames at the request of + * userspace, typically for testing purposes. The sources available are + * specific of each driver and a %NULL value indicates that CRC + * generation is to be switched off. + * + * When CRC generation is enabled, the driver should call + * drm_crtc_add_crc_entry() at each frame, providing any information + * that characterizes the frame contents in the crcN arguments, as + * provided from the configured source. Drivers must accept a "auto" + * source name that will select a default source for this CRTC. + * + * This callback is optional if the driver does not support any CRC + * generation functionality. + * + * RETURNS: + * + * 0 on success or a negative error code on failure. + */ + int (*set_crc_source)(struct drm_crtc *crtc, const char *source, + size_t *values_cnt); + + /** + * @atomic_print_state: + * + * If driver subclasses struct &drm_crtc_state, it should implement + * this optional hook for printing additional driver specific state. + * + * Do not call this directly, use drm_atomic_crtc_print_state() + * instead. + */ + void (*atomic_print_state)(struct drm_printer *p, + const struct drm_crtc_state *state); }; /** @@ -680,660 +715,90 @@ struct drm_crtc { * context. */ struct drm_modeset_acquire_ctx *acquire_ctx; -}; -/** - * struct drm_mode_set - new values for a CRTC config change - * @fb: framebuffer to use for new config - * @crtc: CRTC whose configuration we're about to change - * @mode: mode timings to use - * @x: position of this CRTC relative to @fb - * @y: position of this CRTC relative to @fb - * @connectors: array of connectors to drive with this CRTC if possible - * @num_connectors: size of @connectors array - * - * Represents a single crtc the connectors that it drives with what mode - * and from which framebuffer it scans out from. - * - * This is used to set modes. - */ -struct drm_mode_set { - struct drm_framebuffer *fb; - struct drm_crtc *crtc; - struct drm_display_mode *mode; - - uint32_t x; - uint32_t y; - - struct drm_connector **connectors; - size_t num_connectors; -}; - -/** - * struct drm_mode_config_funcs - basic driver provided mode setting functions - * - * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that - * involve drivers. - */ -struct drm_mode_config_funcs { +#ifdef CONFIG_DEBUG_FS /** - * @fb_create: - * - * Create a new framebuffer object. The core does basic checks on the - * requested metadata, but most of that is left to the driver. See - * struct &drm_mode_fb_cmd2 for details. - * - * If the parameters are deemed valid and the backing storage objects in - * the underlying memory manager all exist, then the driver allocates - * a new &drm_framebuffer structure, subclassed to contain - * driver-specific information (like the internal native buffer object - * references). It also needs to fill out all relevant metadata, which - * should be done by calling drm_helper_mode_fill_fb_struct(). + * @debugfs_entry: * - * The initialization is finalized by calling drm_framebuffer_init(), - * which registers the framebuffer and makes it accessible to other - * threads. - * - * RETURNS: - * - * A new framebuffer with an initial reference count of 1 or a negative - * error code encoded with ERR_PTR(). + * Debugfs directory for this CRTC. */ - struct drm_framebuffer *(*fb_create)(struct drm_device *dev, - struct drm_file *file_priv, - const struct drm_mode_fb_cmd2 *mode_cmd); + struct dentry *debugfs_entry; /** - * @output_poll_changed: - * - * Callback used by helpers to inform the driver of output configuration - * changes. + * @crc: * - * Drivers implementing fbdev emulation with the helpers can call - * drm_fb_helper_hotplug_changed from this hook to inform the fbdev - * helper of output changes. - * - * FIXME: - * - * Except that there's no vtable for device-level helper callbacks - * there's no reason this is a core function. + * Configuration settings of CRC capture. */ - void (*output_poll_changed)(struct drm_device *dev); + struct drm_crtc_crc crc; +#endif /** - * @atomic_check: - * - * This is the only hook to validate an atomic modeset update. This - * function must reject any modeset and state changes which the hardware - * or driver doesn't support. This includes but is of course not limited - * to: - * - * - Checking that the modes, framebuffers, scaling and placement - * requirements and so on are within the limits of the hardware. - * - * - Checking that any hidden shared resources are not oversubscribed. - * This can be shared PLLs, shared lanes, overall memory bandwidth, - * display fifo space (where shared between planes or maybe even - * CRTCs). - * - * - Checking that virtualized resources exported to userspace are not - * oversubscribed. For various reasons it can make sense to expose - * more planes, crtcs or encoders than which are physically there. One - * example is dual-pipe operations (which generally should be hidden - * from userspace if when lockstepped in hardware, exposed otherwise), - * where a plane might need 1 hardware plane (if it's just on one - * pipe), 2 hardware planes (when it spans both pipes) or maybe even - * shared a hardware plane with a 2nd plane (if there's a compatible - * plane requested on the area handled by the other pipe). - * - * - Check that any transitional state is possible and that if - * requested, the update can indeed be done in the vblank period - * without temporarily disabling some functions. - * - * - Check any other constraints the driver or hardware might have. - * - * - This callback also needs to correctly fill out the &drm_crtc_state - * in this update to make sure that drm_atomic_crtc_needs_modeset() - * reflects the nature of the possible update and returns true if and - * only if the update cannot be applied without tearing within one - * vblank on that CRTC. The core uses that information to reject - * updates which require a full modeset (i.e. blanking the screen, or - * at least pausing updates for a substantial amount of time) if - * userspace has disallowed that in its request. - * - * - The driver also does not need to repeat basic input validation - * like done for the corresponding legacy entry points. The core does - * that before calling this hook. - * - * See the documentation of @atomic_commit for an exhaustive list of - * error conditions which don't have to be checked at the - * ->atomic_check() stage? - * - * See the documentation for struct &drm_atomic_state for how exactly - * an atomic modeset update is described. - * - * Drivers using the atomic helpers can implement this hook using - * drm_atomic_helper_check(), or one of the exported sub-functions of - * it. + * @fence_context: * - * RETURNS: - * - * 0 on success or one of the below negative error codes: - * - * - -EINVAL, if any of the above constraints are violated. - * - * - -EDEADLK, when returned from an attempt to acquire an additional - * &drm_modeset_lock through drm_modeset_lock(). - * - * - -ENOMEM, if allocating additional state sub-structures failed due - * to lack of memory. - * - * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. - * This can either be due to a pending signal, or because the driver - * needs to completely bail out to recover from an exceptional - * situation like a GPU hang. From a userspace point all errors are - * treated equally. + * timeline context used for fence operations. */ - int (*atomic_check)(struct drm_device *dev, - struct drm_atomic_state *state); + unsigned int fence_context; /** - * @atomic_commit: - * - * This is the only hook to commit an atomic modeset update. The core - * guarantees that @atomic_check has been called successfully before - * calling this function, and that nothing has been changed in the - * interim. - * - * See the documentation for struct &drm_atomic_state for how exactly - * an atomic modeset update is described. - * - * Drivers using the atomic helpers can implement this hook using - * drm_atomic_helper_commit(), or one of the exported sub-functions of - * it. - * - * Nonblocking commits (as indicated with the nonblock parameter) must - * do any preparatory work which might result in an unsuccessful commit - * in the context of this callback. The only exceptions are hardware - * errors resulting in -EIO. But even in that case the driver must - * ensure that the display pipe is at least running, to avoid - * compositors crashing when pageflips don't work. Anything else, - * specifically committing the update to the hardware, should be done - * without blocking the caller. For updates which do not require a - * modeset this must be guaranteed. - * - * The driver must wait for any pending rendering to the new - * framebuffers to complete before executing the flip. It should also - * wait for any pending rendering from other drivers if the underlying - * buffer is a shared dma-buf. Nonblocking commits must not wait for - * rendering in the context of this callback. - * - * An application can request to be notified when the atomic commit has - * completed. These events are per-CRTC and can be distinguished by the - * CRTC index supplied in &drm_event to userspace. - * - * The drm core will supply a struct &drm_event in the event - * member of each CRTC's &drm_crtc_state structure. See the - * documentation for &drm_crtc_state for more details about the precise - * semantics of this event. - * - * NOTE: - * - * Drivers are not allowed to shut down any display pipe successfully - * enabled through an atomic commit on their own. Doing so can result in - * compositors crashing if a page flip is suddenly rejected because the - * pipe is off. - * - * RETURNS: - * - * 0 on success or one of the below negative error codes: - * - * - -EBUSY, if a nonblocking updated is requested and there is - * an earlier updated pending. Drivers are allowed to support a queue - * of outstanding updates, but currently no driver supports that. - * Note that drivers must wait for preceding updates to complete if a - * synchronous update is requested, they are not allowed to fail the - * commit in that case. - * - * - -ENOMEM, if the driver failed to allocate memory. Specifically - * this can happen when trying to pin framebuffers, which must only - * be done when committing the state. - * - * - -ENOSPC, as a refinement of the more generic -ENOMEM to indicate - * that the driver has run out of vram, iommu space or similar GPU - * address space needed for framebuffer. - * - * - -EIO, if the hardware completely died. + * @fence_lock: * - * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. - * This can either be due to a pending signal, or because the driver - * needs to completely bail out to recover from an exceptional - * situation like a GPU hang. From a userspace point of view all errors are - * treated equally. - * - * This list is exhaustive. Specifically this hook is not allowed to - * return -EINVAL (any invalid requests should be caught in - * @atomic_check) or -EDEADLK (this function must not acquire - * additional modeset locks). - */ - int (*atomic_commit)(struct drm_device *dev, - struct drm_atomic_state *state, - bool nonblock); - - /** - * @atomic_state_alloc: - * - * This optional hook can be used by drivers that want to subclass struct - * &drm_atomic_state to be able to track their own driver-private global - * state easily. If this hook is implemented, drivers must also - * implement @atomic_state_clear and @atomic_state_free. - * - * RETURNS: - * - * A new &drm_atomic_state on success or NULL on failure. + * spinlock to protect the fences in the fence_context. */ - struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev); + spinlock_t fence_lock; /** - * @atomic_state_clear: - * - * This hook must clear any driver private state duplicated into the - * passed-in &drm_atomic_state. This hook is called when the caller - * encountered a &drm_modeset_lock deadlock and needs to drop all - * already acquired locks as part of the deadlock avoidance dance - * implemented in drm_modeset_lock_backoff(). + * @fence_seqno: * - * Any duplicated state must be invalidated since a concurrent atomic - * update might change it, and the drm atomic interfaces always apply - * updates as relative changes to the current state. - * - * Drivers that implement this must call drm_atomic_state_default_clear() - * to clear common state. + * Seqno variable used as monotonic counter for the fences + * created on the CRTC's timeline. */ - void (*atomic_state_clear)(struct drm_atomic_state *state); + unsigned long fence_seqno; /** - * @atomic_state_free: - * - * This hook needs driver private resources and the &drm_atomic_state - * itself. Note that the core first calls drm_atomic_state_clear() to - * avoid code duplicate between the clear and free hooks. + * @timeline_name: * - * Drivers that implement this must call drm_atomic_state_default_free() - * to release common resources. + * The name of the CRTC's fence timeline. */ - void (*atomic_state_free)(struct drm_atomic_state *state); + char timeline_name[32]; }; /** - * struct drm_mode_config - Mode configuration control structure - * @mutex: mutex protecting KMS related lists and structures - * @connection_mutex: ww mutex protecting connector state and routing - * @acquire_ctx: global implicit acquire context used by atomic drivers for - * legacy IOCTLs - * @fb_lock: mutex to protect fb state and lists - * @num_fb: number of fbs available - * @fb_list: list of framebuffers available - * @num_encoder: number of encoders on this device - * @encoder_list: list of encoder objects - * @num_overlay_plane: number of overlay planes on this device - * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device - * @plane_list: list of plane objects - * @num_crtc: number of CRTCs on this device - * @crtc_list: list of CRTC objects - * @property_list: list of property objects - * @min_width: minimum pixel width on this device - * @min_height: minimum pixel height on this device - * @max_width: maximum pixel width on this device - * @max_height: maximum pixel height on this device - * @funcs: core driver provided mode setting functions - * @fb_base: base address of the framebuffer - * @poll_enabled: track polling support for this device - * @poll_running: track polling status for this device - * @delayed_event: track delayed poll uevent deliver for this device - * @output_poll_work: delayed work for polling in process context - * @property_blob_list: list of all the blob property objects - * @blob_lock: mutex for blob property allocation and management - * @*_property: core property tracking - * @preferred_depth: preferred RBG pixel depth, used by fb helpers - * @prefer_shadow: hint to userspace to prefer shadow-fb rendering - * @cursor_width: hint to userspace for max cursor width - * @cursor_height: hint to userspace for max cursor height - * @helper_private: mid-layer private data + * struct drm_mode_set - new values for a CRTC config change + * @fb: framebuffer to use for new config + * @crtc: CRTC whose configuration we're about to change + * @mode: mode timings to use + * @x: position of this CRTC relative to @fb + * @y: position of this CRTC relative to @fb + * @connectors: array of connectors to drive with this CRTC if possible + * @num_connectors: size of @connectors array * - * Core mode resource tracking structure. All CRTC, encoders, and connectors - * enumerated by the driver are added here, as are global properties. Some - * global restrictions are also here, e.g. dimension restrictions. + * Represents a single crtc the connectors that it drives with what mode + * and from which framebuffer it scans out from. + * + * This is used to set modes. */ -struct drm_mode_config { - struct mutex mutex; /* protects configuration (mode lists etc.) */ - struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */ - struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */ - - /** - * @idr_mutex: - * - * Mutex for KMS ID allocation and management. Protects both @crtc_idr - * and @tile_idr. - */ - struct mutex idr_mutex; - - /** - * @crtc_idr: - * - * Main KMS ID tracking object. Use this idr for all IDs, fb, crtc, - * connector, modes - just makes life easier to have only one. - */ - struct idr crtc_idr; - - /** - * @tile_idr: - * - * Use this idr for allocating new IDs for tiled sinks like use in some - * high-res DP MST screens. - */ - struct idr tile_idr; - - struct mutex fb_lock; /* proctects global and per-file fb lists */ - int num_fb; - struct list_head fb_list; - - /** - * @num_connector: Number of connectors on this device. - */ - int num_connector; - /** - * @connector_ida: ID allocator for connector indices. - */ - struct ida connector_ida; - /** - * @connector_list: List of connector objects. - */ - struct list_head connector_list; - int num_encoder; - struct list_head encoder_list; - - /* - * Track # of overlay planes separately from # of total planes. By - * default we only advertise overlay planes to userspace; if userspace - * sets the "universal plane" capability bit, we'll go ahead and - * expose all planes. - */ - int num_overlay_plane; - int num_total_plane; - struct list_head plane_list; - - int num_crtc; - struct list_head crtc_list; - - struct list_head property_list; - - int min_width, min_height; - int max_width, max_height; - const struct drm_mode_config_funcs *funcs; - resource_size_t fb_base; - - /* output poll support */ - bool poll_enabled; - bool poll_running; - bool delayed_event; - struct delayed_work output_poll_work; - - struct mutex blob_lock; - - /* pointers to standard properties */ - struct list_head property_blob_list; - /** - * @edid_property: Default connector property to hold the EDID of the - * currently connected sink, if any. - */ - struct drm_property *edid_property; - /** - * @dpms_property: Default connector property to control the - * connector's DPMS state. - */ - struct drm_property *dpms_property; - /** - * @path_property: Default connector property to hold the DP MST path - * for the port. - */ - struct drm_property *path_property; - /** - * @tile_property: Default connector property to store the tile - * position of a tiled screen, for sinks which need to be driven with - * multiple CRTCs. - */ - struct drm_property *tile_property; - /** - * @plane_type_property: Default plane property to differentiate - * CURSOR, PRIMARY and OVERLAY legacy uses of planes. - */ - struct drm_property *plane_type_property; - /** - * @rotation_property: Optional property for planes or CRTCs to specifiy - * rotation. - */ - struct drm_property *rotation_property; - /** - * @prop_src_x: Default atomic plane property for the plane source - * position in the connected &drm_framebuffer. - */ - struct drm_property *prop_src_x; - /** - * @prop_src_y: Default atomic plane property for the plane source - * position in the connected &drm_framebuffer. - */ - struct drm_property *prop_src_y; - /** - * @prop_src_w: Default atomic plane property for the plane source - * position in the connected &drm_framebuffer. - */ - struct drm_property *prop_src_w; - /** - * @prop_src_h: Default atomic plane property for the plane source - * position in the connected &drm_framebuffer. - */ - struct drm_property *prop_src_h; - /** - * @prop_crtc_x: Default atomic plane property for the plane destination - * position in the &drm_crtc is is being shown on. - */ - struct drm_property *prop_crtc_x; - /** - * @prop_crtc_y: Default atomic plane property for the plane destination - * position in the &drm_crtc is is being shown on. - */ - struct drm_property *prop_crtc_y; - /** - * @prop_crtc_w: Default atomic plane property for the plane destination - * position in the &drm_crtc is is being shown on. - */ - struct drm_property *prop_crtc_w; - /** - * @prop_crtc_h: Default atomic plane property for the plane destination - * position in the &drm_crtc is is being shown on. - */ - struct drm_property *prop_crtc_h; - /** - * @prop_fb_id: Default atomic plane property to specify the - * &drm_framebuffer. - */ - struct drm_property *prop_fb_id; - /** - * @prop_crtc_id: Default atomic plane property to specify the - * &drm_crtc. - */ - struct drm_property *prop_crtc_id; - /** - * @prop_active: Default atomic CRTC property to control the active - * state, which is the simplified implementation for DPMS in atomic - * drivers. - */ - struct drm_property *prop_active; - /** - * @prop_mode_id: Default atomic CRTC property to set the mode for a - * CRTC. A 0 mode implies that the CRTC is entirely disabled - all - * connectors must be of and active must be set to disabled, too. - */ - struct drm_property *prop_mode_id; - - /** - * @dvi_i_subconnector_property: Optional DVI-I property to - * differentiate between analog or digital mode. - */ - struct drm_property *dvi_i_subconnector_property; - /** - * @dvi_i_select_subconnector_property: Optional DVI-I property to - * select between analog or digital mode. - */ - struct drm_property *dvi_i_select_subconnector_property; - - /** - * @tv_subconnector_property: Optional TV property to differentiate - * between different TV connector types. - */ - struct drm_property *tv_subconnector_property; - /** - * @tv_select_subconnector_property: Optional TV property to select - * between different TV connector types. - */ - struct drm_property *tv_select_subconnector_property; - /** - * @tv_mode_property: Optional TV property to select - * the output TV mode. - */ - struct drm_property *tv_mode_property; - /** - * @tv_left_margin_property: Optional TV property to set the left - * margin. - */ - struct drm_property *tv_left_margin_property; - /** - * @tv_right_margin_property: Optional TV property to set the right - * margin. - */ - struct drm_property *tv_right_margin_property; - /** - * @tv_top_margin_property: Optional TV property to set the right - * margin. - */ - struct drm_property *tv_top_margin_property; - /** - * @tv_bottom_margin_property: Optional TV property to set the right - * margin. - */ - struct drm_property *tv_bottom_margin_property; - /** - * @tv_brightness_property: Optional TV property to set the - * brightness. - */ - struct drm_property *tv_brightness_property; - /** - * @tv_contrast_property: Optional TV property to set the - * contrast. - */ - struct drm_property *tv_contrast_property; - /** - * @tv_flicker_reduction_property: Optional TV property to control the - * flicker reduction mode. - */ - struct drm_property *tv_flicker_reduction_property; - /** - * @tv_overscan_property: Optional TV property to control the overscan - * setting. - */ - struct drm_property *tv_overscan_property; - /** - * @tv_saturation_property: Optional TV property to set the - * saturation. - */ - struct drm_property *tv_saturation_property; - /** - * @tv_hue_property: Optional TV property to set the hue. - */ - struct drm_property *tv_hue_property; - - /** - * @scaling_mode_property: Optional connector property to control the - * upscaling, mostly used for built-in panels. - */ - struct drm_property *scaling_mode_property; - /** - * @aspect_ratio_property: Optional connector property to control the - * HDMI infoframe aspect ratio setting. - */ - struct drm_property *aspect_ratio_property; - /** - * @degamma_lut_property: Optional CRTC property to set the LUT used to - * convert the framebuffer's colors to linear gamma. - */ - struct drm_property *degamma_lut_property; - /** - * @degamma_lut_size_property: Optional CRTC property for the size of - * the degamma LUT as supported by the driver (read-only). - */ - struct drm_property *degamma_lut_size_property; - /** - * @ctm_property: Optional CRTC property to set the - * matrix used to convert colors after the lookup in the - * degamma LUT. - */ - struct drm_property *ctm_property; - /** - * @gamma_lut_property: Optional CRTC property to set the LUT used to - * convert the colors, after the CTM matrix, to the gamma space of the - * connected screen. - */ - struct drm_property *gamma_lut_property; - /** - * @gamma_lut_size_property: Optional CRTC property for the size of the - * gamma LUT as supported by the driver (read-only). - */ - struct drm_property *gamma_lut_size_property; - - /** - * @suggested_x_property: Optional connector property with a hint for - * the position of the output on the host's screen. - */ - struct drm_property *suggested_x_property; - /** - * @suggested_y_property: Optional connector property with a hint for - * the position of the output on the host's screen. - */ - struct drm_property *suggested_y_property; - - /* dumb ioctl parameters */ - uint32_t preferred_depth, prefer_shadow; - - /** - * @async_page_flip: Does this device support async flips on the primary - * plane? - */ - bool async_page_flip; - - /** - * @allow_fb_modifiers: - * - * Whether the driver supports fb modifiers in the ADDFB2.1 ioctl call. - */ - bool allow_fb_modifiers; +struct drm_mode_set { + struct drm_framebuffer *fb; + struct drm_crtc *crtc; + struct drm_display_mode *mode; - /* cursor size */ - uint32_t cursor_width, cursor_height; + uint32_t x; + uint32_t y; - struct drm_mode_config_helper_funcs *helper_private; + struct drm_connector **connectors; + size_t num_connectors; }; #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) -extern __printf(6, 7) +__printf(6, 7) 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, ...); -extern void drm_crtc_cleanup(struct drm_crtc *crtc); +void drm_crtc_cleanup(struct drm_crtc *crtc); /** * drm_crtc_index - find the index of a registered CRTC @@ -1354,28 +819,17 @@ static inline unsigned int drm_crtc_index(const struct drm_crtc *crtc) * Given a registered CRTC, return the mask bit of that CRTC for an * encoder's possible_crtcs field. */ -static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc) +static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc) { return 1 << drm_crtc_index(crtc); } -extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, - int *hdisplay, int *vdisplay); -extern int drm_crtc_force_disable(struct drm_crtc *crtc); -extern int drm_crtc_force_disable_all(struct drm_device *dev); - -extern void drm_mode_config_init(struct drm_device *dev); -extern void drm_mode_config_reset(struct drm_device *dev); -extern void drm_mode_config_cleanup(struct drm_device *dev); - -extern int drm_mode_set_config_internal(struct drm_mode_set *set); +void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, + int *hdisplay, int *vdisplay); +int drm_crtc_force_disable(struct drm_crtc *crtc); +int drm_crtc_force_disable_all(struct drm_device *dev); -extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, - char topology[8]); -extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, - char topology[8]); -extern void drm_mode_put_tile_group(struct drm_device *dev, - struct drm_tile_group *tg); +int drm_mode_set_config_internal(struct drm_mode_set *set); /* Helpers */ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev, diff --git a/include/drm/drm_debugfs_crc.h b/include/drm/drm_debugfs_crc.h new file mode 100644 index 000000000000..7d63b1d4adb9 --- /dev/null +++ b/include/drm/drm_debugfs_crc.h @@ -0,0 +1,73 @@ +/* + * Copyright © 2016 Collabora Ltd. + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ +#ifndef __DRM_DEBUGFS_CRC_H__ +#define __DRM_DEBUGFS_CRC_H__ + +#define DRM_MAX_CRC_NR 10 + +/** + * struct drm_crtc_crc_entry - entry describing a frame's content + * @has_frame_counter: whether the source was able to provide a frame number + * @frame: number of the frame this CRC is about, if @has_frame_counter is true + * @crc: array of values that characterize the frame + */ +struct drm_crtc_crc_entry { + bool has_frame_counter; + uint32_t frame; + uint32_t crcs[DRM_MAX_CRC_NR]; +}; + +#define DRM_CRC_ENTRIES_NR 128 + +/** + * struct drm_crtc_crc - data supporting CRC capture on a given CRTC + * @lock: protects the fields in this struct + * @source: name of the currently configured source of CRCs + * @opened: whether userspace has opened the data file for reading + * @entries: array of entries, with size of %DRM_CRC_ENTRIES_NR + * @head: head of circular queue + * @tail: tail of circular queue + * @values_cnt: number of CRC values per entry, up to %DRM_MAX_CRC_NR + * @wq: workqueue used to synchronize reading and writing + */ +struct drm_crtc_crc { + spinlock_t lock; + const char *source; + bool opened; + struct drm_crtc_crc_entry *entries; + int head, tail; + size_t values_cnt; + wait_queue_head_t wq; +}; + +#if defined(CONFIG_DEBUG_FS) +int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, + uint32_t frame, uint32_t *crcs); +#else +static inline int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame, + uint32_t frame, uint32_t *crcs) +{ + return -EINVAL; +} +#endif /* defined(CONFIG_DEBUG_FS) */ + +#endif /* __DRM_DEBUGFS_CRC_H__ */ diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h index e8a9dfd0e055..4c42db81fcb4 100644 --- a/include/drm/drm_dp_dual_mode_helper.h +++ b/include/drm/drm_dp_dual_mode_helper.h @@ -40,6 +40,8 @@ #define DP_DUAL_MODE_REV_TYPE2 0x00 #define DP_DUAL_MODE_TYPE_MASK 0xf0 #define DP_DUAL_MODE_TYPE_TYPE2 0xa0 +/* This field is marked reserved in dual mode spec, used in LSPCON */ +#define DP_DUAL_MODE_TYPE_HAS_DPCD 0x08 #define DP_DUAL_MODE_IEEE_OUI 0x11 /* 11-13*/ #define DP_DUAL_IEEE_OUI_LEN 3 #define DP_DUAL_DEVICE_ID 0x14 /* 14-19 */ @@ -55,6 +57,11 @@ #define DP_DUAL_MODE_CEC_ENABLE 0x01 #define DP_DUAL_MODE_I2C_SPEED_CTRL 0x22 +/* LSPCON specific registers, defined by MCA */ +#define DP_DUAL_MODE_LSPCON_MODE_CHANGE 0x40 +#define DP_DUAL_MODE_LSPCON_CURRENT_MODE 0x41 +#define DP_DUAL_MODE_LSPCON_MODE_PCON 0x1 + struct i2c_adapter; ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter, @@ -63,6 +70,20 @@ ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, u8 offset, const void *buffer, size_t size); /** + * enum drm_lspcon_mode + * @DRM_LSPCON_MODE_INVALID: No LSPCON. + * @DRM_LSPCON_MODE_LS: Level shifter mode of LSPCON + * which drives DP++ to HDMI 1.4 conversion. + * @DRM_LSPCON_MODE_PCON: Protocol converter mode of LSPCON + * which drives DP++ to HDMI 2.0 active conversion. + */ +enum drm_lspcon_mode { + DRM_LSPCON_MODE_INVALID, + DRM_LSPCON_MODE_LS, + DRM_LSPCON_MODE_PCON, +}; + +/** * enum drm_dp_dual_mode_type - Type of the DP dual mode adaptor * @DRM_DP_DUAL_MODE_NONE: No DP dual mode adaptor * @DRM_DP_DUAL_MODE_UNKNOWN: Could be either none or type 1 DVI adaptor @@ -70,6 +91,7 @@ ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter, * @DRM_DP_DUAL_MODE_TYPE1_HDMI: Type 1 HDMI adaptor * @DRM_DP_DUAL_MODE_TYPE2_DVI: Type 2 DVI adaptor * @DRM_DP_DUAL_MODE_TYPE2_HDMI: Type 2 HDMI adaptor + * @DRM_DP_DUAL_MODE_LSPCON: Level shifter / protocol converter */ enum drm_dp_dual_mode_type { DRM_DP_DUAL_MODE_NONE, @@ -78,6 +100,7 @@ enum drm_dp_dual_mode_type { DRM_DP_DUAL_MODE_TYPE1_HDMI, DRM_DP_DUAL_MODE_TYPE2_DVI, DRM_DP_DUAL_MODE_TYPE2_HDMI, + DRM_DP_DUAL_MODE_LSPCON, }; enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter); @@ -89,4 +112,8 @@ int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type, struct i2c_adapter *adapter, bool enable); const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type); +int drm_lspcon_get_mode(struct i2c_adapter *adapter, + enum drm_lspcon_mode *current_mode); +int drm_lspcon_set_mode(struct i2c_adapter *adapter, + enum drm_lspcon_mode reqd_mode); #endif diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 2a79882cb68e..55bbeb0ff594 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -690,6 +690,12 @@ drm_dp_tps3_supported(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED; } +static inline bool +drm_dp_is_branch(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + return dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT; +} + /* * DisplayPort AUX channel */ diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h new file mode 100644 index 000000000000..c4fc49583dc0 --- /dev/null +++ b/include/drm/drm_drv.h @@ -0,0 +1,435 @@ +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * Copyright (c) 2009-2010, Code Aurora Forum. + * Copyright 2016 Intel Corp. + * + * 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 + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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. + */ + +#ifndef _DRM_DRV_H_ +#define _DRM_DRV_H_ + +#include <linux/list.h> +#include <linux/irqreturn.h> + +struct drm_device; +struct drm_file; +struct drm_gem_object; +struct drm_master; +struct drm_minor; +struct dma_buf_attachment; +struct drm_display_mode; +struct drm_mode_create_dumb; + +/* driver capabilities and requirements mask */ +#define DRIVER_USE_AGP 0x1 +#define DRIVER_LEGACY 0x2 +#define DRIVER_PCI_DMA 0x8 +#define DRIVER_SG 0x10 +#define DRIVER_HAVE_DMA 0x20 +#define DRIVER_HAVE_IRQ 0x40 +#define DRIVER_IRQ_SHARED 0x80 +#define DRIVER_GEM 0x1000 +#define DRIVER_MODESET 0x2000 +#define DRIVER_PRIME 0x4000 +#define DRIVER_RENDER 0x8000 +#define DRIVER_ATOMIC 0x10000 +#define DRIVER_KMS_LEGACY_CONTEXT 0x20000 + +/** + * struct drm_driver - DRM driver structure + * + * This structure represent the common code for a family of cards. There will + * one drm_device for each card present in this family. It contains lots of + * vfunc entries, and a pile of those probably should be moved to more + * appropriate places like &drm_mode_config_funcs or into a new operations + * structure for GEM drivers. + */ +struct drm_driver { + int (*load) (struct drm_device *, unsigned long flags); + int (*firstopen) (struct drm_device *); + int (*open) (struct drm_device *, struct drm_file *); + void (*preclose) (struct drm_device *, struct drm_file *file_priv); + void (*postclose) (struct drm_device *, struct drm_file *); + void (*lastclose) (struct drm_device *); + int (*unload) (struct drm_device *); + int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); + int (*dma_quiescent) (struct drm_device *); + int (*context_dtor) (struct drm_device *dev, int context); + int (*set_busid)(struct drm_device *dev, struct drm_master *master); + + /** + * @get_vblank_counter: + * + * Driver callback for fetching a raw hardware vblank counter for the + * CRTC specified with the pipe argument. If a device doesn't have a + * hardware counter, the driver can simply use + * drm_vblank_no_hw_counter() function. The DRM core will account for + * missed vblank events while interrupts where disabled based on system + * timestamps. + * + * Wraparound handling and loss of events due to modesetting is dealt + * with in the DRM core code, as long as drivers call + * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or + * enabling a CRTC. + * + * Returns: + * + * Raw vblank counter value. + */ + u32 (*get_vblank_counter) (struct drm_device *dev, unsigned int pipe); + + /** + * @enable_vblank: + * + * Enable vblank interrupts for the CRTC specified with the pipe + * argument. + * + * Returns: + * + * Zero on success, appropriate errno if the given @crtc's vblank + * interrupt cannot be enabled. + */ + int (*enable_vblank) (struct drm_device *dev, unsigned int pipe); + + /** + * @disable_vblank: + * + * Disable vblank interrupts for the CRTC specified with the pipe + * argument. + */ + void (*disable_vblank) (struct drm_device *dev, unsigned int pipe); + + /** + * @device_is_agp: + * + * Called by drm_device_is_agp(). Typically used to determine if a card + * is really attached to AGP or not. + * + * Returns: + * + * One of three values is returned depending on whether or not the + * card is absolutely not AGP (return of 0), absolutely is AGP + * (return of 1), or may or may not be AGP (return of 2). + */ + int (*device_is_agp) (struct drm_device *dev); + + /** + * @get_scanout_position: + * + * Called by vblank timestamping code. + * + * Returns the current display scanout position from a crtc, and an + * optional accurate ktime_get() timestamp of when position was + * measured. Note that this is a helper callback which is only used if a + * driver uses drm_calc_vbltimestamp_from_scanoutpos() for the + * @get_vblank_timestamp callback. + * + * Parameters: + * + * dev: + * DRM device. + * pipe: + * Id of the crtc to query. + * flags: + * Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0). + * vpos: + * Target location for current vertical scanout position. + * hpos: + * Target location for current horizontal scanout position. + * stime: + * Target location for timestamp taken immediately before + * scanout position query. Can be NULL to skip timestamp. + * etime: + * Target location for timestamp taken immediately after + * scanout position query. Can be NULL to skip timestamp. + * mode: + * Current display timings. + * + * Returns vpos as a positive number while in active scanout area. + * Returns vpos as a negative number inside vblank, counting the number + * of scanlines to go until end of vblank, e.g., -1 means "one scanline + * until start of active scanout / end of vblank." + * + * Returns: + * + * Flags, or'ed together as follows: + * + * DRM_SCANOUTPOS_VALID: + * Query successful. + * DRM_SCANOUTPOS_INVBL: + * Inside vblank. + * DRM_SCANOUTPOS_ACCURATE: Returned position is accurate. A lack of + * this flag means that returned position may be offset by a + * constant but unknown small number of scanlines wrt. real scanout + * position. + * + */ + int (*get_scanout_position) (struct drm_device *dev, unsigned int pipe, + unsigned int flags, int *vpos, int *hpos, + ktime_t *stime, ktime_t *etime, + const struct drm_display_mode *mode); + + /** + * @get_vblank_timestamp: + * + * Called by drm_get_last_vbltimestamp(). Should return a precise + * timestamp when the most recent VBLANK interval ended or will end. + * + * Specifically, the timestamp in @vblank_time should correspond as + * closely as possible to the time when the first video scanline of + * the video frame after the end of VBLANK will start scanning out, + * the time immediately after end of the VBLANK interval. If the + * @crtc is currently inside VBLANK, this will be a time in the future. + * If the @crtc is currently scanning out a frame, this will be the + * past start time of the current scanout. This is meant to adhere + * to the OpenML OML_sync_control extension specification. + * + * Paramters: + * + * dev: + * dev DRM device handle. + * pipe: + * crtc for which timestamp should be returned. + * max_error: + * Maximum allowable timestamp error in nanoseconds. + * Implementation should strive to provide timestamp + * with an error of at most max_error nanoseconds. + * Returns true upper bound on error for timestamp. + * vblank_time: + * Target location for returned vblank timestamp. + * flags: + * 0 = Defaults, no special treatment needed. + * DRM_CALLED_FROM_VBLIRQ = Function is called from vblank + * irq handler. Some drivers need to apply some workarounds + * for gpu-specific vblank irq quirks if flag is set. + * + * Returns: + * + * Zero if timestamping isn't supported in current display mode or a + * negative number on failure. A positive status code on success, + * which describes how the vblank_time timestamp was computed. + */ + int (*get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe, + int *max_error, + struct timeval *vblank_time, + unsigned flags); + + /* these have to be filled in */ + + irqreturn_t(*irq_handler) (int irq, void *arg); + void (*irq_preinstall) (struct drm_device *dev); + int (*irq_postinstall) (struct drm_device *dev); + void (*irq_uninstall) (struct drm_device *dev); + + /** + * @master_create: + * + * Called whenever a new master is created. Only used by vmwgfx. + */ + int (*master_create)(struct drm_device *dev, struct drm_master *master); + + /** + * @master_destroy: + * + * Called whenever a master is destroyed. Only used by vmwgfx. + */ + void (*master_destroy)(struct drm_device *dev, struct drm_master *master); + + /** + * @master_set: + * + * Called whenever the minor master is set. Only used by vmwgfx. + */ + int (*master_set)(struct drm_device *dev, struct drm_file *file_priv, + bool from_open); + /** + * @master_drop: + * + * Called whenever the minor master is dropped. Only used by vmwgfx. + */ + void (*master_drop)(struct drm_device *dev, struct drm_file *file_priv); + + int (*debugfs_init)(struct drm_minor *minor); + void (*debugfs_cleanup)(struct drm_minor *minor); + + /** + * @gem_free_object: deconstructor for drm_gem_objects + * + * This is deprecated and should not be used by new drivers. Use + * @gem_free_object_unlocked instead. + */ + void (*gem_free_object) (struct drm_gem_object *obj); + + /** + * @gem_free_object_unlocked: deconstructor for drm_gem_objects + * + * This is for drivers which are not encumbered with dev->struct_mutex + * legacy locking schemes. Use this hook instead of @gem_free_object. + */ + void (*gem_free_object_unlocked) (struct drm_gem_object *obj); + + int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); + void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); + + /** + * @gem_create_object: constructor for gem objects + * + * Hook for allocating the GEM object struct, for use by core + * helpers. + */ + struct drm_gem_object *(*gem_create_object)(struct drm_device *dev, + size_t size); + + /* prime: */ + /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */ + int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd); + /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */ + int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, + int prime_fd, uint32_t *handle); + /* export GEM -> dmabuf */ + struct dma_buf * (*gem_prime_export)(struct drm_device *dev, + struct drm_gem_object *obj, int flags); + /* import dmabuf -> GEM */ + struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, + struct dma_buf *dma_buf); + /* low-level interface used by drm_gem_prime_{import,export} */ + int (*gem_prime_pin)(struct drm_gem_object *obj); + void (*gem_prime_unpin)(struct drm_gem_object *obj); + struct reservation_object * (*gem_prime_res_obj)( + struct drm_gem_object *obj); + struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj); + struct drm_gem_object *(*gem_prime_import_sg_table)( + struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt); + void *(*gem_prime_vmap)(struct drm_gem_object *obj); + void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr); + int (*gem_prime_mmap)(struct drm_gem_object *obj, + struct vm_area_struct *vma); + + /* vga arb irq handler */ + void (*vgaarb_irq)(struct drm_device *dev, bool state); + + /** + * @dumb_create: + * + * This creates a new dumb buffer in the driver's backing storage manager (GEM, + * TTM or something else entirely) and returns the resulting buffer handle. This + * handle can then be wrapped up into a framebuffer modeset object. + * + * Note that userspace is not allowed to use such objects for render + * acceleration - drivers must create their own private ioctls for such a use + * case. + * + * Width, height and depth are specified in the &drm_mode_create_dumb + * argument. The callback needs to fill the handle, pitch and size for + * the created buffer. + * + * Called by the user via ioctl. + * + * Returns: + * + * Zero on success, negative errno on failure. + */ + int (*dumb_create)(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + /** + * @dumb_map_offset: + * + * Allocate an offset in the drm device node's address space to be able to + * memory map a dumb buffer. GEM-based drivers must use + * drm_gem_create_mmap_offset() to implement this. + * + * Called by the user via ioctl. + * + * Returns: + * + * Zero on success, negative errno on failure. + */ + int (*dumb_map_offset)(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); + /** + * @dumb_destroy: + * + * This destroys the userspace handle for the given dumb backing storage buffer. + * Since buffer objects must be reference counted in the kernel a buffer object + * won't be immediately freed if a framebuffer modeset object still uses it. + * + * Called by the user via ioctl. + * + * Returns: + * + * Zero on success, negative errno on failure. + */ + int (*dumb_destroy)(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); + + /* Driver private ops for this object */ + const struct vm_operations_struct *gem_vm_ops; + + int major; + int minor; + int patchlevel; + char *name; + char *desc; + char *date; + + u32 driver_features; + int dev_priv_size; + const struct drm_ioctl_desc *ioctls; + int num_ioctls; + const struct file_operations *fops; + + /* List of devices hanging off this driver with stealth attach. */ + struct list_head legacy_dev_list; +}; + +extern __printf(6, 7) +void drm_dev_printk(const struct device *dev, const char *level, + unsigned int category, const char *function_name, + const char *prefix, const char *format, ...); +extern __printf(3, 4) +void drm_printk(const char *level, unsigned int category, + const char *format, ...); +extern unsigned int drm_debug; + +int drm_dev_init(struct drm_device *dev, + struct drm_driver *driver, + struct device *parent); +struct drm_device *drm_dev_alloc(struct drm_driver *driver, + struct device *parent); +int drm_dev_register(struct drm_device *dev, unsigned long flags); +void drm_dev_unregister(struct drm_device *dev); + +void drm_dev_ref(struct drm_device *dev); +void drm_dev_unref(struct drm_device *dev); +void drm_put_dev(struct drm_device *dev); +void drm_unplug_dev(struct drm_device *dev); + +int drm_dev_set_unique(struct drm_device *dev, const char *name); + + +#endif diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index c3a7d440bc11..38eabf65f19d 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -330,7 +330,6 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); int drm_av_sync_delay(struct drm_connector *connector, const struct drm_display_mode *mode); -struct drm_connector *drm_select_eld(struct drm_encoder *encoder); #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE int drm_load_edid_firmware(struct drm_connector *connector); diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h index 387e33a4d6ee..c7438ff0d609 100644 --- a/include/drm/drm_encoder.h +++ b/include/drm/drm_encoder.h @@ -189,7 +189,7 @@ static inline unsigned int drm_encoder_index(struct drm_encoder *encoder) } /* FIXME: We have an include file mess still, drm_crtc.h needs untangling. */ -static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc); +static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc); /** * drm_encoder_crtc_ok - can a given crtc drive a given encoder? diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h index f313211f8ed5..3b00f6480b83 100644 --- a/include/drm/drm_fb_cma_helper.h +++ b/include/drm/drm_fb_cma_helper.h @@ -12,6 +12,8 @@ struct drm_fb_helper; struct drm_device; struct drm_file; struct drm_mode_fb_cmd2; +struct drm_plane; +struct drm_plane_state; struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev, unsigned int preferred_bpp, unsigned int num_crtc, @@ -41,6 +43,9 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev, struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, unsigned int plane); +int drm_fb_cma_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state); + #ifdef CONFIG_DEBUG_FS struct seq_file; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index ed8edfef75b2..975deedd593e 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -228,7 +228,9 @@ struct drm_fb_helper { .fb_set_par = drm_fb_helper_set_par, \ .fb_setcmap = drm_fb_helper_setcmap, \ .fb_blank = drm_fb_helper_blank, \ - .fb_pan_display = drm_fb_helper_pan_display + .fb_pan_display = drm_fb_helper_pan_display, \ + .fb_debug_enter = drm_fb_helper_debug_enter, \ + .fb_debug_leave = drm_fb_helper_debug_leave #ifdef CONFIG_DRM_FBDEV_EMULATION void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 30c30fa87ee8..fcc08da850c8 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -25,14 +25,43 @@ #include <linux/types.h> #include <uapi/drm/drm_fourcc.h> +/** + * struct drm_format_info - information about a DRM format + * @format: 4CC format identifier (DRM_FORMAT_*) + * @depth: Color depth (number of bits per pixel excluding padding bits), + * valid for a subset of RGB formats only. This is a legacy field, do not + * use in new code and set to 0 for new formats. + * @num_planes: Number of color planes (1 to 3) + * @cpp: Number of bytes per pixel (per plane) + * @hsub: Horizontal chroma subsampling factor + * @vsub: Vertical chroma subsampling factor + */ +struct drm_format_info { + u32 format; + u8 depth; + u8 num_planes; + u8 cpp[3]; + u8 hsub; + u8 vsub; +}; + +/** + * struct drm_format_name_buf - name of a DRM format + * @str: string buffer containing the format name + */ +struct drm_format_name_buf { + char str[32]; +}; + +const struct drm_format_info *__drm_format_info(u32 format); +const struct drm_format_info *drm_format_info(u32 format); uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); int drm_format_num_planes(uint32_t format); int drm_format_plane_cpp(uint32_t format, int plane); int drm_format_horz_chroma_subsampling(uint32_t format); int drm_format_vert_chroma_subsampling(uint32_t format); int drm_format_plane_width(int width, uint32_t format, int plane); int drm_format_plane_height(int height, uint32_t format, int plane); -char *drm_get_format_name(uint32_t format) __malloc; +const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf); #endif /* __DRM_FOURCC_H__ */ diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index f5ae1f436a4b..1ddfa2928802 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -149,12 +149,12 @@ struct drm_framebuffer { */ unsigned int offsets[4]; /** - * @modifier: Data layout modifier, per buffer. This is used to describe + * @modifier: Data layout modifier. This is used to describe * tiling, or also special layouts (like compression) of auxiliary * buffers. For userspace created object this is copied from * drm_mode_fb_cmd2. */ - uint64_t modifier[4]; + uint64_t modifier; /** * @width: Logical width of the visible area of the framebuffer, in * pixels. @@ -251,6 +251,24 @@ static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb) } /** + * drm_framebuffer_assign - store a reference to the fb + * @p: location to store framebuffer + * @fb: new framebuffer (maybe NULL) + * + * This functions sets the location to store a reference to the framebuffer, + * unreferencing the framebuffer that was previously stored in that location. + */ +static inline void drm_framebuffer_assign(struct drm_framebuffer **p, + struct drm_framebuffer *fb) +{ + if (fb) + drm_framebuffer_reference(fb); + if (*p) + drm_framebuffer_unreference(*p); + *p = fb; +} + +/* * drm_for_each_fb - iterate over all framebuffers * @fb: the loop cursor * @dev: the DRM device diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h index 2401b14d301f..293d08caab60 100644 --- a/include/drm/drm_irq.h +++ b/include/drm/drm_irq.h @@ -130,42 +130,37 @@ struct drm_vblank_crtc { bool enabled; }; -extern int drm_irq_install(struct drm_device *dev, int irq); -extern int drm_irq_uninstall(struct drm_device *dev); +int drm_irq_install(struct drm_device *dev, int irq); +int drm_irq_uninstall(struct drm_device *dev); -extern int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); -extern int drm_wait_vblank(struct drm_device *dev, void *data, - struct drm_file *filp); -extern u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe); -extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc); -extern u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, - struct timeval *vblanktime); -extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc, - struct drm_pending_vblank_event *e); -extern void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, - struct drm_pending_vblank_event *e); -extern bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); -extern bool drm_crtc_handle_vblank(struct drm_crtc *crtc); -extern int drm_crtc_vblank_get(struct drm_crtc *crtc); -extern void drm_crtc_vblank_put(struct drm_crtc *crtc); -extern void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); -extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); -extern void drm_vblank_off(struct drm_device *dev, unsigned int pipe); -extern void drm_vblank_on(struct drm_device *dev, unsigned int pipe); -extern void drm_crtc_vblank_off(struct drm_crtc *crtc); -extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); -extern void drm_crtc_vblank_on(struct drm_crtc *crtc); -extern void drm_vblank_cleanup(struct drm_device *dev); -extern u32 drm_accurate_vblank_count(struct drm_crtc *crtc); -extern u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe); +int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); +u32 drm_crtc_vblank_count(struct drm_crtc *crtc); +u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, + struct timeval *vblanktime); +void drm_crtc_send_vblank_event(struct drm_crtc *crtc, + struct drm_pending_vblank_event *e); +void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, + struct drm_pending_vblank_event *e); +bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); +bool drm_crtc_handle_vblank(struct drm_crtc *crtc); +int drm_crtc_vblank_get(struct drm_crtc *crtc); +void drm_crtc_vblank_put(struct drm_crtc *crtc); +void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe); +void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); +void drm_crtc_vblank_off(struct drm_crtc *crtc); +void drm_crtc_vblank_reset(struct drm_crtc *crtc); +void drm_crtc_vblank_on(struct drm_crtc *crtc); +void drm_vblank_cleanup(struct drm_device *dev); +u32 drm_accurate_vblank_count(struct drm_crtc *crtc); +u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe); -extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, - unsigned int pipe, int *max_error, - struct timeval *vblank_time, - unsigned flags, - const struct drm_display_mode *mode); -extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, - const struct drm_display_mode *mode); +int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, + unsigned int pipe, int *max_error, + struct timeval *vblank_time, + unsigned flags, + const struct drm_display_mode *mode); +void drm_calc_timestamping_constants(struct drm_crtc *crtc, + const struct drm_display_mode *mode); /** * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 205ddcf6d55d..0b8371795aeb 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -44,6 +44,9 @@ #ifdef CONFIG_DEBUG_FS #include <linux/seq_file.h> #endif +#ifdef CONFIG_DRM_DEBUG_MM +#include <linux/stackdepot.h> +#endif enum drm_mm_search_flags { DRM_MM_SEARCH_DEFAULT = 0, @@ -74,6 +77,9 @@ struct drm_mm_node { u64 size; u64 __subtree_last; struct drm_mm *mm; +#ifdef CONFIG_DRM_DEBUG_MM + depot_stack_handle_t stack; +#endif }; struct drm_mm { @@ -302,10 +308,26 @@ void drm_mm_takedown(struct drm_mm *mm); bool drm_mm_clean(struct drm_mm *mm); struct drm_mm_node * -drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last); +__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last); -struct drm_mm_node * -drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last); +/** + * drm_mm_for_each_node_in_range - iterator to walk over a range of + * allocated nodes + * @node__: drm_mm_node structure to assign to in each iteration step + * @mm__: drm_mm allocator to walk + * @start__: starting offset, the first node will overlap this + * @end__: ending offset, the last node will start before this (but may overlap) + * + * This iterator walks over all nodes in the range allocator that lie + * between @start and @end. It is implemented similarly to list_for_each(), + * but using the internal interval tree to accelerate the search for the + * starting node, and so not safe against removal of elements. It assumes + * that @end is within (or is the upper limit of) the drm_mm allocator. + */ +#define drm_mm_for_each_node_in_range(node__, mm__, start__, end__) \ + for (node__ = __drm_mm_interval_first((mm__), (start__), (end__)-1); \ + node__ && node__->start < (end__); \ + node__ = list_next_entry(node__, node_list)) void drm_mm_init_scan(struct drm_mm *mm, u64 size, diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h new file mode 100644 index 000000000000..bf9991b20611 --- /dev/null +++ b/include/drm/drm_mode_config.h @@ -0,0 +1,663 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __DRM_MODE_CONFIG_H__ +#define __DRM_MODE_CONFIG_H__ + +#include <linux/mutex.h> +#include <linux/types.h> +#include <linux/idr.h> +#include <linux/workqueue.h> + +#include <drm/drm_modeset_lock.h> + +struct drm_file; +struct drm_device; +struct drm_atomic_state; +struct drm_mode_fb_cmd2; + +/** + * struct drm_mode_config_funcs - basic driver provided mode setting functions + * + * Some global (i.e. not per-CRTC, connector, etc) mode setting functions that + * involve drivers. + */ +struct drm_mode_config_funcs { + /** + * @fb_create: + * + * Create a new framebuffer object. The core does basic checks on the + * requested metadata, but most of that is left to the driver. See + * struct &drm_mode_fb_cmd2 for details. + * + * If the parameters are deemed valid and the backing storage objects in + * the underlying memory manager all exist, then the driver allocates + * a new &drm_framebuffer structure, subclassed to contain + * driver-specific information (like the internal native buffer object + * references). It also needs to fill out all relevant metadata, which + * should be done by calling drm_helper_mode_fill_fb_struct(). + * + * The initialization is finalized by calling drm_framebuffer_init(), + * which registers the framebuffer and makes it accessible to other + * threads. + * + * RETURNS: + * + * A new framebuffer with an initial reference count of 1 or a negative + * error code encoded with ERR_PTR(). + */ + struct drm_framebuffer *(*fb_create)(struct drm_device *dev, + struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd); + + /** + * @output_poll_changed: + * + * Callback used by helpers to inform the driver of output configuration + * changes. + * + * Drivers implementing fbdev emulation with the helpers can call + * drm_fb_helper_hotplug_changed from this hook to inform the fbdev + * helper of output changes. + * + * FIXME: + * + * Except that there's no vtable for device-level helper callbacks + * there's no reason this is a core function. + */ + void (*output_poll_changed)(struct drm_device *dev); + + /** + * @atomic_check: + * + * This is the only hook to validate an atomic modeset update. This + * function must reject any modeset and state changes which the hardware + * or driver doesn't support. This includes but is of course not limited + * to: + * + * - Checking that the modes, framebuffers, scaling and placement + * requirements and so on are within the limits of the hardware. + * + * - Checking that any hidden shared resources are not oversubscribed. + * This can be shared PLLs, shared lanes, overall memory bandwidth, + * display fifo space (where shared between planes or maybe even + * CRTCs). + * + * - Checking that virtualized resources exported to userspace are not + * oversubscribed. For various reasons it can make sense to expose + * more planes, crtcs or encoders than which are physically there. One + * example is dual-pipe operations (which generally should be hidden + * from userspace if when lockstepped in hardware, exposed otherwise), + * where a plane might need 1 hardware plane (if it's just on one + * pipe), 2 hardware planes (when it spans both pipes) or maybe even + * shared a hardware plane with a 2nd plane (if there's a compatible + * plane requested on the area handled by the other pipe). + * + * - Check that any transitional state is possible and that if + * requested, the update can indeed be done in the vblank period + * without temporarily disabling some functions. + * + * - Check any other constraints the driver or hardware might have. + * + * - This callback also needs to correctly fill out the &drm_crtc_state + * in this update to make sure that drm_atomic_crtc_needs_modeset() + * reflects the nature of the possible update and returns true if and + * only if the update cannot be applied without tearing within one + * vblank on that CRTC. The core uses that information to reject + * updates which require a full modeset (i.e. blanking the screen, or + * at least pausing updates for a substantial amount of time) if + * userspace has disallowed that in its request. + * + * - The driver also does not need to repeat basic input validation + * like done for the corresponding legacy entry points. The core does + * that before calling this hook. + * + * See the documentation of @atomic_commit for an exhaustive list of + * error conditions which don't have to be checked at the + * ->atomic_check() stage? + * + * See the documentation for struct &drm_atomic_state for how exactly + * an atomic modeset update is described. + * + * Drivers using the atomic helpers can implement this hook using + * drm_atomic_helper_check(), or one of the exported sub-functions of + * it. + * + * RETURNS: + * + * 0 on success or one of the below negative error codes: + * + * - -EINVAL, if any of the above constraints are violated. + * + * - -EDEADLK, when returned from an attempt to acquire an additional + * &drm_modeset_lock through drm_modeset_lock(). + * + * - -ENOMEM, if allocating additional state sub-structures failed due + * to lack of memory. + * + * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. + * This can either be due to a pending signal, or because the driver + * needs to completely bail out to recover from an exceptional + * situation like a GPU hang. From a userspace point all errors are + * treated equally. + */ + int (*atomic_check)(struct drm_device *dev, + struct drm_atomic_state *state); + + /** + * @atomic_commit: + * + * This is the only hook to commit an atomic modeset update. The core + * guarantees that @atomic_check has been called successfully before + * calling this function, and that nothing has been changed in the + * interim. + * + * See the documentation for struct &drm_atomic_state for how exactly + * an atomic modeset update is described. + * + * Drivers using the atomic helpers can implement this hook using + * drm_atomic_helper_commit(), or one of the exported sub-functions of + * it. + * + * Nonblocking commits (as indicated with the nonblock parameter) must + * do any preparatory work which might result in an unsuccessful commit + * in the context of this callback. The only exceptions are hardware + * errors resulting in -EIO. But even in that case the driver must + * ensure that the display pipe is at least running, to avoid + * compositors crashing when pageflips don't work. Anything else, + * specifically committing the update to the hardware, should be done + * without blocking the caller. For updates which do not require a + * modeset this must be guaranteed. + * + * The driver must wait for any pending rendering to the new + * framebuffers to complete before executing the flip. It should also + * wait for any pending rendering from other drivers if the underlying + * buffer is a shared dma-buf. Nonblocking commits must not wait for + * rendering in the context of this callback. + * + * An application can request to be notified when the atomic commit has + * completed. These events are per-CRTC and can be distinguished by the + * CRTC index supplied in &drm_event to userspace. + * + * The drm core will supply a struct &drm_event in the event + * member of each CRTC's &drm_crtc_state structure. See the + * documentation for &drm_crtc_state for more details about the precise + * semantics of this event. + * + * NOTE: + * + * Drivers are not allowed to shut down any display pipe successfully + * enabled through an atomic commit on their own. Doing so can result in + * compositors crashing if a page flip is suddenly rejected because the + * pipe is off. + * + * RETURNS: + * + * 0 on success or one of the below negative error codes: + * + * - -EBUSY, if a nonblocking updated is requested and there is + * an earlier updated pending. Drivers are allowed to support a queue + * of outstanding updates, but currently no driver supports that. + * Note that drivers must wait for preceding updates to complete if a + * synchronous update is requested, they are not allowed to fail the + * commit in that case. + * + * - -ENOMEM, if the driver failed to allocate memory. Specifically + * this can happen when trying to pin framebuffers, which must only + * be done when committing the state. + * + * - -ENOSPC, as a refinement of the more generic -ENOMEM to indicate + * that the driver has run out of vram, iommu space or similar GPU + * address space needed for framebuffer. + * + * - -EIO, if the hardware completely died. + * + * - -EINTR, -EAGAIN or -ERESTARTSYS, if the IOCTL should be restarted. + * This can either be due to a pending signal, or because the driver + * needs to completely bail out to recover from an exceptional + * situation like a GPU hang. From a userspace point of view all errors are + * treated equally. + * + * This list is exhaustive. Specifically this hook is not allowed to + * return -EINVAL (any invalid requests should be caught in + * @atomic_check) or -EDEADLK (this function must not acquire + * additional modeset locks). + */ + int (*atomic_commit)(struct drm_device *dev, + struct drm_atomic_state *state, + bool nonblock); + + /** + * @atomic_state_alloc: + * + * This optional hook can be used by drivers that want to subclass struct + * &drm_atomic_state to be able to track their own driver-private global + * state easily. If this hook is implemented, drivers must also + * implement @atomic_state_clear and @atomic_state_free. + * + * RETURNS: + * + * A new &drm_atomic_state on success or NULL on failure. + */ + struct drm_atomic_state *(*atomic_state_alloc)(struct drm_device *dev); + + /** + * @atomic_state_clear: + * + * This hook must clear any driver private state duplicated into the + * passed-in &drm_atomic_state. This hook is called when the caller + * encountered a &drm_modeset_lock deadlock and needs to drop all + * already acquired locks as part of the deadlock avoidance dance + * implemented in drm_modeset_lock_backoff(). + * + * Any duplicated state must be invalidated since a concurrent atomic + * update might change it, and the drm atomic interfaces always apply + * updates as relative changes to the current state. + * + * Drivers that implement this must call drm_atomic_state_default_clear() + * to clear common state. + */ + void (*atomic_state_clear)(struct drm_atomic_state *state); + + /** + * @atomic_state_free: + * + * This hook needs driver private resources and the &drm_atomic_state + * itself. Note that the core first calls drm_atomic_state_clear() to + * avoid code duplicate between the clear and free hooks. + * + * Drivers that implement this must call drm_atomic_state_default_free() + * to release common resources. + */ + void (*atomic_state_free)(struct drm_atomic_state *state); +}; + +/** + * struct drm_mode_config - Mode configuration control structure + * @mutex: mutex protecting KMS related lists and structures + * @connection_mutex: ww mutex protecting connector state and routing + * @acquire_ctx: global implicit acquire context used by atomic drivers for + * legacy IOCTLs + * @fb_lock: mutex to protect fb state and lists + * @num_fb: number of fbs available + * @fb_list: list of framebuffers available + * @num_encoder: number of encoders on this device + * @encoder_list: list of encoder objects + * @num_overlay_plane: number of overlay planes on this device + * @num_total_plane: number of universal (i.e. with primary/curso) planes on this device + * @plane_list: list of plane objects + * @num_crtc: number of CRTCs on this device + * @crtc_list: list of CRTC objects + * @property_list: list of property objects + * @min_width: minimum pixel width on this device + * @min_height: minimum pixel height on this device + * @max_width: maximum pixel width on this device + * @max_height: maximum pixel height on this device + * @funcs: core driver provided mode setting functions + * @fb_base: base address of the framebuffer + * @poll_enabled: track polling support for this device + * @poll_running: track polling status for this device + * @delayed_event: track delayed poll uevent deliver for this device + * @output_poll_work: delayed work for polling in process context + * @property_blob_list: list of all the blob property objects + * @blob_lock: mutex for blob property allocation and management + * @*_property: core property tracking + * @preferred_depth: preferred RBG pixel depth, used by fb helpers + * @prefer_shadow: hint to userspace to prefer shadow-fb rendering + * @cursor_width: hint to userspace for max cursor width + * @cursor_height: hint to userspace for max cursor height + * @helper_private: mid-layer private data + * + * Core mode resource tracking structure. All CRTC, encoders, and connectors + * enumerated by the driver are added here, as are global properties. Some + * global restrictions are also here, e.g. dimension restrictions. + */ +struct drm_mode_config { + struct mutex mutex; /* protects configuration (mode lists etc.) */ + struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */ + struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */ + + /** + * @idr_mutex: + * + * Mutex for KMS ID allocation and management. Protects both @crtc_idr + * and @tile_idr. + */ + struct mutex idr_mutex; + + /** + * @crtc_idr: + * + * Main KMS ID tracking object. Use this idr for all IDs, fb, crtc, + * connector, modes - just makes life easier to have only one. + */ + struct idr crtc_idr; + + /** + * @tile_idr: + * + * Use this idr for allocating new IDs for tiled sinks like use in some + * high-res DP MST screens. + */ + struct idr tile_idr; + + struct mutex fb_lock; /* proctects global and per-file fb lists */ + int num_fb; + struct list_head fb_list; + + /** + * @num_connector: Number of connectors on this device. + */ + int num_connector; + /** + * @connector_ida: ID allocator for connector indices. + */ + struct ida connector_ida; + /** + * @connector_list: List of connector objects. + */ + struct list_head connector_list; + int num_encoder; + struct list_head encoder_list; + + /* + * Track # of overlay planes separately from # of total planes. By + * default we only advertise overlay planes to userspace; if userspace + * sets the "universal plane" capability bit, we'll go ahead and + * expose all planes. + */ + int num_overlay_plane; + int num_total_plane; + struct list_head plane_list; + + int num_crtc; + struct list_head crtc_list; + + struct list_head property_list; + + int min_width, min_height; + int max_width, max_height; + const struct drm_mode_config_funcs *funcs; + resource_size_t fb_base; + + /* output poll support */ + bool poll_enabled; + bool poll_running; + bool delayed_event; + struct delayed_work output_poll_work; + + struct mutex blob_lock; + + /* pointers to standard properties */ + struct list_head property_blob_list; + /** + * @edid_property: Default connector property to hold the EDID of the + * currently connected sink, if any. + */ + struct drm_property *edid_property; + /** + * @dpms_property: Default connector property to control the + * connector's DPMS state. + */ + struct drm_property *dpms_property; + /** + * @path_property: Default connector property to hold the DP MST path + * for the port. + */ + struct drm_property *path_property; + /** + * @tile_property: Default connector property to store the tile + * position of a tiled screen, for sinks which need to be driven with + * multiple CRTCs. + */ + struct drm_property *tile_property; + /** + * @plane_type_property: Default plane property to differentiate + * CURSOR, PRIMARY and OVERLAY legacy uses of planes. + */ + struct drm_property *plane_type_property; + /** + * @prop_src_x: Default atomic plane property for the plane source + * position in the connected &drm_framebuffer. + */ + struct drm_property *prop_src_x; + /** + * @prop_src_y: Default atomic plane property for the plane source + * position in the connected &drm_framebuffer. + */ + struct drm_property *prop_src_y; + /** + * @prop_src_w: Default atomic plane property for the plane source + * position in the connected &drm_framebuffer. + */ + struct drm_property *prop_src_w; + /** + * @prop_src_h: Default atomic plane property for the plane source + * position in the connected &drm_framebuffer. + */ + struct drm_property *prop_src_h; + /** + * @prop_crtc_x: Default atomic plane property for the plane destination + * position in the &drm_crtc is is being shown on. + */ + struct drm_property *prop_crtc_x; + /** + * @prop_crtc_y: Default atomic plane property for the plane destination + * position in the &drm_crtc is is being shown on. + */ + struct drm_property *prop_crtc_y; + /** + * @prop_crtc_w: Default atomic plane property for the plane destination + * position in the &drm_crtc is is being shown on. + */ + struct drm_property *prop_crtc_w; + /** + * @prop_crtc_h: Default atomic plane property for the plane destination + * position in the &drm_crtc is is being shown on. + */ + struct drm_property *prop_crtc_h; + /** + * @prop_fb_id: Default atomic plane property to specify the + * &drm_framebuffer. + */ + struct drm_property *prop_fb_id; + /** + * @prop_in_fence_fd: Sync File fd representing the incoming fences + * for a Plane. + */ + struct drm_property *prop_in_fence_fd; + /** + * @prop_out_fence_ptr: Sync File fd pointer representing the + * outgoing fences for a CRTC. Userspace should provide a pointer to a + * value of type s64, and then cast that pointer to u64. + */ + struct drm_property *prop_out_fence_ptr; + /** + * @prop_crtc_id: Default atomic plane property to specify the + * &drm_crtc. + */ + struct drm_property *prop_crtc_id; + /** + * @prop_active: Default atomic CRTC property to control the active + * state, which is the simplified implementation for DPMS in atomic + * drivers. + */ + struct drm_property *prop_active; + /** + * @prop_mode_id: Default atomic CRTC property to set the mode for a + * CRTC. A 0 mode implies that the CRTC is entirely disabled - all + * connectors must be of and active must be set to disabled, too. + */ + struct drm_property *prop_mode_id; + + /** + * @dvi_i_subconnector_property: Optional DVI-I property to + * differentiate between analog or digital mode. + */ + struct drm_property *dvi_i_subconnector_property; + /** + * @dvi_i_select_subconnector_property: Optional DVI-I property to + * select between analog or digital mode. + */ + struct drm_property *dvi_i_select_subconnector_property; + + /** + * @tv_subconnector_property: Optional TV property to differentiate + * between different TV connector types. + */ + struct drm_property *tv_subconnector_property; + /** + * @tv_select_subconnector_property: Optional TV property to select + * between different TV connector types. + */ + struct drm_property *tv_select_subconnector_property; + /** + * @tv_mode_property: Optional TV property to select + * the output TV mode. + */ + struct drm_property *tv_mode_property; + /** + * @tv_left_margin_property: Optional TV property to set the left + * margin. + */ + struct drm_property *tv_left_margin_property; + /** + * @tv_right_margin_property: Optional TV property to set the right + * margin. + */ + struct drm_property *tv_right_margin_property; + /** + * @tv_top_margin_property: Optional TV property to set the right + * margin. + */ + struct drm_property *tv_top_margin_property; + /** + * @tv_bottom_margin_property: Optional TV property to set the right + * margin. + */ + struct drm_property *tv_bottom_margin_property; + /** + * @tv_brightness_property: Optional TV property to set the + * brightness. + */ + struct drm_property *tv_brightness_property; + /** + * @tv_contrast_property: Optional TV property to set the + * contrast. + */ + struct drm_property *tv_contrast_property; + /** + * @tv_flicker_reduction_property: Optional TV property to control the + * flicker reduction mode. + */ + struct drm_property *tv_flicker_reduction_property; + /** + * @tv_overscan_property: Optional TV property to control the overscan + * setting. + */ + struct drm_property *tv_overscan_property; + /** + * @tv_saturation_property: Optional TV property to set the + * saturation. + */ + struct drm_property *tv_saturation_property; + /** + * @tv_hue_property: Optional TV property to set the hue. + */ + struct drm_property *tv_hue_property; + + /** + * @scaling_mode_property: Optional connector property to control the + * upscaling, mostly used for built-in panels. + */ + struct drm_property *scaling_mode_property; + /** + * @aspect_ratio_property: Optional connector property to control the + * HDMI infoframe aspect ratio setting. + */ + struct drm_property *aspect_ratio_property; + /** + * @degamma_lut_property: Optional CRTC property to set the LUT used to + * convert the framebuffer's colors to linear gamma. + */ + struct drm_property *degamma_lut_property; + /** + * @degamma_lut_size_property: Optional CRTC property for the size of + * the degamma LUT as supported by the driver (read-only). + */ + struct drm_property *degamma_lut_size_property; + /** + * @ctm_property: Optional CRTC property to set the + * matrix used to convert colors after the lookup in the + * degamma LUT. + */ + struct drm_property *ctm_property; + /** + * @gamma_lut_property: Optional CRTC property to set the LUT used to + * convert the colors, after the CTM matrix, to the gamma space of the + * connected screen. + */ + struct drm_property *gamma_lut_property; + /** + * @gamma_lut_size_property: Optional CRTC property for the size of the + * gamma LUT as supported by the driver (read-only). + */ + struct drm_property *gamma_lut_size_property; + + /** + * @suggested_x_property: Optional connector property with a hint for + * the position of the output on the host's screen. + */ + struct drm_property *suggested_x_property; + /** + * @suggested_y_property: Optional connector property with a hint for + * the position of the output on the host's screen. + */ + struct drm_property *suggested_y_property; + + /* dumb ioctl parameters */ + uint32_t preferred_depth, prefer_shadow; + + /** + * @async_page_flip: Does this device support async flips on the primary + * plane? + */ + bool async_page_flip; + + /** + * @allow_fb_modifiers: + * + * Whether the driver supports fb modifiers in the ADDFB2.1 ioctl call. + */ + bool allow_fb_modifiers; + + /* cursor size */ + uint32_t cursor_width, cursor_height; + + struct drm_mode_config_helper_funcs *helper_private; +}; + +void drm_mode_config_init(struct drm_device *dev); +void drm_mode_config_reset(struct drm_device *dev); +void drm_mode_config_cleanup(struct drm_device *dev); + +#endif diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index 10e449c86dbd..69c3974bf133 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -361,8 +361,8 @@ struct drm_crtc_helper_funcs { * * Note that the power state of the display pipe when this function is * called depends upon the exact helpers and calling sequence the driver - * has picked. See drm_atomic_commit_planes() for a discussion of the - * tradeoffs and variants of plane commit helpers. + * has picked. See drm_atomic_helper_commit_planes() for a discussion of + * the tradeoffs and variants of plane commit helpers. * * This callback is used by the atomic modeset helpers and by the * transitional plane helpers, but it is optional. @@ -385,8 +385,8 @@ struct drm_crtc_helper_funcs { * * Note that the power state of the display pipe when this function is * called depends upon the exact helpers and calling sequence the driver - * has picked. See drm_atomic_commit_planes() for a discussion of the - * tradeoffs and variants of plane commit helpers. + * has picked. See drm_atomic_helper_commit_planes() for a discussion of + * the tradeoffs and variants of plane commit helpers. * * This callback is used by the atomic modeset helpers and by the * transitional plane helpers, but it is optional. @@ -940,8 +940,8 @@ struct drm_plane_helper_funcs { * * Note that the power state of the display pipe when this function is * called depends upon the exact helpers and calling sequence the driver - * has picked. See drm_atomic_commit_planes() for a discussion of the - * tradeoffs and variants of plane commit helpers. + * has picked. See drm_atomic_helper_commit_planes() for a discussion of + * the tradeoffs and variants of plane commit helpers. * * This callback is used by the atomic modeset helpers and by the * transitional plane helpers, but it is optional. @@ -963,8 +963,8 @@ struct drm_plane_helper_funcs { * * Note that the power state of the display pipe when this function is * called depends upon the exact helpers and calling sequence the driver - * has picked. See drm_atomic_commit_planes() for a discussion of the - * tradeoffs and variants of plane commit helpers. + * has picked. See drm_atomic_helper_commit_planes() for a discussion of + * the tradeoffs and variants of plane commit helpers. * * This callback is used by the atomic modeset helpers and by the * transitional plane helpers, but it is optional. @@ -999,10 +999,14 @@ struct drm_mode_config_helper_funcs { * to implement blocking and nonblocking commits easily. It is not used * by the atomic helpers * - * This hook should first commit the given atomic state to the hardware. - * But drivers can add more waiting calls at the start of their - * implementation, e.g. to wait for driver-internal request for implicit - * syncing, before starting to commit the update to the hardware. + * This function is called when the new atomic state has already been + * swapped into the various state pointers. The passed in state + * therefore contains copies of the old/previous state. This hook should + * commit the new state into hardware. Note that the helpers have + * already waited for preceeding atomic commits and fences, but drivers + * can add more waiting calls at the start of their implementation, e.g. + * to wait for driver-internal request for implicit syncing, before + * starting to commit the update to the hardware. * * After the atomic update is committed to the hardware this hook needs * to call drm_atomic_helper_commit_hw_done(). Then wait for the upate diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index c5576fbcb909..d918ce45ec2c 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h @@ -82,8 +82,6 @@ struct drm_modeset_lock { struct list_head head; }; -extern struct ww_class crtc_ww_class; - void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, uint32_t flags); void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx); @@ -91,15 +89,7 @@ void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx); void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx); int drm_modeset_backoff_interruptible(struct drm_modeset_acquire_ctx *ctx); -/** - * drm_modeset_lock_init - initialize lock - * @lock: lock to init - */ -static inline void drm_modeset_lock_init(struct drm_modeset_lock *lock) -{ - ww_mutex_init(&lock->mutex, &crtc_ww_class); - INIT_LIST_HEAD(&lock->head); -} +void drm_modeset_lock_init(struct drm_modeset_lock *lock); /** * drm_modeset_lock_fini - cleanup lock diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h index 3fd87b386ed7..26a64805cc15 100644 --- a/include/drm/drm_of.h +++ b/include/drm/drm_of.h @@ -4,6 +4,7 @@ #include <linux/of_graph.h> struct component_master_ops; +struct component_match; struct device; struct drm_device; struct drm_encoder; @@ -12,6 +13,10 @@ struct device_node; #ifdef CONFIG_OF extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, struct device_node *port); +extern void drm_of_component_match_add(struct device *master, + struct component_match **matchptr, + int (*compare)(struct device *, void *), + struct device_node *node); extern int drm_of_component_probe(struct device *dev, int (*compare_of)(struct device *, void *), const struct component_master_ops *m_ops); @@ -25,6 +30,14 @@ static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, return 0; } +static inline void +drm_of_component_match_add(struct device *master, + struct component_match **matchptr, + int (*compare)(struct device *, void *), + struct device_node *node) +{ +} + static inline int drm_of_component_probe(struct device *dev, int (*compare_of)(struct device *, void *), diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 8b4dc62470ff..db3bbdeb36d5 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -28,15 +28,11 @@ #include <drm/drm_mode_object.h> struct drm_crtc; +struct drm_printer; /** * struct drm_plane_state - mutable plane state * @plane: backpointer to the plane - * @crtc: currently bound CRTC, NULL if disabled - * @fb: currently bound framebuffer - * @fence: optional fence to wait for before scanning out @fb - * @crtc_x: left position of visible portion of plane on crtc - * @crtc_y: upper position of visible portion of plane on crtc * @crtc_w: width of visible portion of plane on crtc * @crtc_h: height of visible portion of plane on crtc * @src_x: left position of visible portion of plane within @@ -57,18 +53,51 @@ struct drm_crtc; * it can be trusted. * @src: clipped source coordinates of the plane (in 16.16) * @dst: clipped destination coordinates of the plane - * @visible: visibility of the plane * @state: backpointer to global drm_atomic_state */ struct drm_plane_state { struct drm_plane *plane; - struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */ - struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */ - struct fence *fence; + /** + * @crtc: + * + * Currently bound CRTC, NULL if disabled. Do not this write directly, + * use drm_atomic_set_crtc_for_plane() + */ + struct drm_crtc *crtc; + + /** + * @fb: + * + * Currently bound framebuffer. Do not write this directly, use + * drm_atomic_set_fb_for_plane() + */ + struct drm_framebuffer *fb; + + /** + * @fence: + * + * Optional fence to wait for before scanning out @fb. Do not write this + * directly, use drm_atomic_set_fence_for_plane() + */ + struct dma_fence *fence; + + /** + * @crtc_x: + * + * Left position of visible portion of plane on crtc, signed dest + * location allows it to be partially off screen. + */ + + int32_t crtc_x; + /** + * @crtc_y: + * + * Upper position of visible portion of plane on crtc, signed dest + * location allows it to be partially off screen. + */ + int32_t crtc_y; - /* Signed dest location allows it to be partially off screen */ - int32_t crtc_x, crtc_y; uint32_t crtc_w, crtc_h; /* Source values are 16.16 fixed point */ @@ -85,15 +114,40 @@ struct drm_plane_state { /* Clipped coordinates */ struct drm_rect src, dst; - /* - * Is the plane actually visible? Can be false even - * if fb!=NULL and crtc!=NULL, due to clipping. + /** + * @visible: + * + * Visibility of the plane. This can be false even if fb!=NULL and + * crtc!=NULL, due to clipping. */ bool visible; struct drm_atomic_state *state; }; +static inline struct drm_rect +drm_plane_state_src(const struct drm_plane_state *state) +{ + struct drm_rect src = { + .x1 = state->src_x, + .y1 = state->src_y, + .x2 = state->src_x + state->src_w, + .y2 = state->src_y + state->src_h, + }; + return src; +} + +static inline struct drm_rect +drm_plane_state_dest(const struct drm_plane_state *state) +{ + struct drm_rect dest = { + .x1 = state->crtc_x, + .y1 = state->crtc_y, + .x2 = state->crtc_x + state->crtc_w, + .y2 = state->crtc_y + state->crtc_h, + }; + return dest; +} /** * struct drm_plane_funcs - driver plane control functions @@ -323,6 +377,18 @@ struct drm_plane_funcs { * before data structures are torndown. */ void (*early_unregister)(struct drm_plane *plane); + + /** + * @atomic_print_state: + * + * If driver subclasses struct &drm_plane_state, it should implement + * this optional hook for printing additional driver specific state. + * + * Do not call this directly, use drm_atomic_plane_print_state() + * instead. + */ + void (*atomic_print_state)(struct drm_printer *p, + const struct drm_plane_state *state); }; /** @@ -392,6 +458,7 @@ enum drm_plane_type { * @type: type of plane (overlay, primary, cursor) * @state: current atomic state for this plane * @zpos_property: zpos property for this plane + * @rotation_property: rotation property for this plane * @helper_private: mid-layer private data */ struct drm_plane { @@ -438,6 +505,7 @@ struct drm_plane { struct drm_plane_state *state; struct drm_property *zpos_property; + struct drm_property *rotation_property; }; #define obj_to_plane(x) container_of(x, struct drm_plane, base) @@ -445,7 +513,7 @@ struct drm_plane { extern __printf(8, 9) int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, - unsigned long possible_crtcs, + uint32_t possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, unsigned int format_count, @@ -453,7 +521,7 @@ int drm_universal_plane_init(struct drm_device *dev, const char *name, ...); extern int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, - unsigned long possible_crtcs, + uint32_t possible_crtcs, const struct drm_plane_funcs *funcs, const uint32_t *formats, unsigned int format_count, bool is_primary); diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h new file mode 100644 index 000000000000..1adf84aea622 --- /dev/null +++ b/include/drm/drm_print.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 Red Hat + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: + * Rob Clark <robdclark@gmail.com> + */ + +#ifndef DRM_PRINT_H_ +#define DRM_PRINT_H_ + +#include <linux/seq_file.h> +#include <linux/device.h> + +/** + * DOC: print + * + * A simple wrapper for dev_printk(), seq_printf(), etc. Allows same + * debug code to be used for both debugfs and printk logging. + * + * For example:: + * + * void log_some_info(struct drm_printer *p) + * { + * drm_printf(p, "foo=%d\n", foo); + * drm_printf(p, "bar=%d\n", bar); + * } + * + * #ifdef CONFIG_DEBUG_FS + * void debugfs_show(struct seq_file *f) + * { + * struct drm_printer p = drm_seq_file_printer(f); + * log_some_info(&p); + * } + * #endif + * + * void some_other_function(...) + * { + * struct drm_printer p = drm_info_printer(drm->dev); + * log_some_info(&p); + * } + */ + +/** + * struct drm_printer - drm output "stream" + * @printfn: actual output fxn + * @arg: output fxn specific data + * + * Do not use struct members directly. Use drm_printer_seq_file(), + * drm_printer_info(), etc to initialize. And drm_printf() for output. + */ +struct drm_printer { + void (*printfn)(struct drm_printer *p, struct va_format *vaf); + void *arg; +}; + +void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf); +void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf); + +void drm_printf(struct drm_printer *p, const char *f, ...); + + +/** + * drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file + * @f: the struct &seq_file to output to + * + * RETURNS: + * The &drm_printer object + */ +static inline struct drm_printer drm_seq_file_printer(struct seq_file *f) +{ + struct drm_printer p = { + .printfn = __drm_printfn_seq_file, + .arg = f, + }; + return p; +} + +/** + * drm_info_printer - construct a &drm_printer that outputs to dev_printk() + * @dev: the struct &device pointer + * + * RETURNS: + * The &drm_printer object + */ +static inline struct drm_printer drm_info_printer(struct device *dev) +{ + struct drm_printer p = { + .printfn = __drm_printfn_info, + .arg = dev, + }; + return p; +} + +#endif /* DRM_PRINT_H_ */ diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h index b46fa0ef3005..545c6e0fea7d 100644 --- a/include/drm/i915_component.h +++ b/include/drm/i915_component.h @@ -64,7 +64,7 @@ struct i915_audio_component_ops { * Called from audio driver. After audio driver sets the * sample rate, it will call this function to set n/cts */ - int (*sync_audio_rate)(struct device *, int port, int rate); + int (*sync_audio_rate)(struct device *, int port, int pipe, int rate); /** * @get_eld: fill the audio state and ELD bytes for the given port * @@ -77,7 +77,7 @@ struct i915_audio_component_ops { * Note that the returned size may be over @max_bytes. Then it * implies that only a part of ELD has been copied to the buffer. */ - int (*get_eld)(struct device *, int port, bool *enabled, + int (*get_eld)(struct device *, int port, int pipe, bool *enabled, unsigned char *buf, int max_bytes); }; @@ -97,7 +97,7 @@ struct i915_audio_component_audio_ops { * status accordingly (even when the HDA controller is in power save * mode). */ - void (*pin_eld_notify)(void *audio_ptr, int port); + void (*pin_eld_notify)(void *audio_ptr, int port, int pipe); }; /** diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 9eb940d6755f..652e45be97c8 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -47,6 +47,8 @@ struct drm_mm_node; struct ttm_placement; +struct ttm_place; + /** * struct ttm_bus_placement * @@ -209,7 +211,7 @@ struct ttm_buffer_object { * Members protected by a bo reservation. */ - struct fence *moving; + struct dma_fence *moving; struct drm_vma_offset_node vma_node; @@ -396,6 +398,17 @@ extern void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev, int resched); /** + * ttm_bo_eviction_valuable + * + * @bo: The buffer object to evict + * @place: the placement we need to make room for + * + * Check if it is valuable to evict the BO to make room for the given placement. + */ +bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place); + +/** * ttm_bo_synccpu_write_grab * * @bo: The buffer object: diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 4f0a92185995..cdbdb40eb5bd 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -303,7 +303,7 @@ struct ttm_mem_type_manager { /* * Protected by @move_lock. */ - struct fence *move; + struct dma_fence *move; }; /** @@ -371,9 +371,21 @@ struct ttm_bo_driver { * submission as a consequence. */ - int (*invalidate_caches) (struct ttm_bo_device *bdev, uint32_t flags); - int (*init_mem_type) (struct ttm_bo_device *bdev, uint32_t type, - struct ttm_mem_type_manager *man); + int (*invalidate_caches)(struct ttm_bo_device *bdev, uint32_t flags); + int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type, + struct ttm_mem_type_manager *man); + + /** + * struct ttm_bo_driver member eviction_valuable + * + * @bo: the buffer object to be evicted + * @place: placement we need room for + * + * Check with the driver if it is valuable to evict a BO to make room + * for a certain placement. + */ + bool (*eviction_valuable)(struct ttm_buffer_object *bo, + const struct ttm_place *place); /** * struct ttm_bo_driver member evict_flags: * @@ -384,8 +396,9 @@ struct ttm_bo_driver { * finished, they'll end up in bo->mem.flags */ - void(*evict_flags) (struct ttm_buffer_object *bo, - struct ttm_placement *placement); + void (*evict_flags)(struct ttm_buffer_object *bo, + struct ttm_placement *placement); + /** * struct ttm_bo_driver member move: * @@ -399,10 +412,9 @@ struct ttm_bo_driver { * * Move a buffer between two memory regions. */ - int (*move) (struct ttm_buffer_object *bo, - bool evict, bool interruptible, - bool no_wait_gpu, - struct ttm_mem_reg *new_mem); + int (*move)(struct ttm_buffer_object *bo, bool evict, + bool interruptible, bool no_wait_gpu, + struct ttm_mem_reg *new_mem); /** * struct ttm_bo_driver_member verify_access @@ -416,8 +428,8 @@ struct ttm_bo_driver { * access for all buffer objects. * This function should return 0 if access is granted, -EPERM otherwise. */ - int (*verify_access) (struct ttm_buffer_object *bo, - struct file *filp); + int (*verify_access)(struct ttm_buffer_object *bo, + struct file *filp); /* hook to notify driver about a driver move so it * can do tiling things */ @@ -430,7 +442,7 @@ struct ttm_bo_driver { /** * notify the driver that we're about to swap out this bo */ - void (*swap_notify) (struct ttm_buffer_object *bo); + void (*swap_notify)(struct ttm_buffer_object *bo); /** * Driver callback on when mapping io memory (for bo_move_memcpy @@ -438,8 +450,10 @@ struct ttm_bo_driver { * the mapping is not use anymore. io_mem_reserve & io_mem_free * are balanced. */ - int (*io_mem_reserve)(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); - void (*io_mem_free)(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem); + int (*io_mem_reserve)(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem); + void (*io_mem_free)(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem); /** * Optional driver callback for when BO is removed from the LRU. @@ -1025,7 +1039,7 @@ extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo); */ extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, - struct fence *fence, bool evict, + struct dma_fence *fence, bool evict, struct ttm_mem_reg *new_mem); /** @@ -1040,7 +1054,7 @@ extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, * immediately or hang it on a temporary buffer object. */ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, - struct fence *fence, bool evict, + struct dma_fence *fence, bool evict, struct ttm_mem_reg *new_mem); /** diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h index b620c317c772..47f35b8e6d09 100644 --- a/include/drm/ttm/ttm_execbuf_util.h +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -114,6 +114,6 @@ extern int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, extern void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, struct list_head *list, - struct fence *fence); + struct dma_fence *fence); #endif |