aboutsummaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
Diffstat (limited to 'include/drm')
-rw-r--r--include/drm/drmP.h18
-rw-r--r--include/drm/drm_atomic.h14
-rw-r--r--include/drm/drm_atomic_helper.h1
-rw-r--r--include/drm/drm_audio_component.h118
-rw-r--r--include/drm/drm_bridge.h48
-rw-r--r--include/drm/drm_client.h139
-rw-r--r--include/drm/drm_connector.h279
-rw-r--r--include/drm/drm_crtc.h276
-rw-r--r--include/drm/drm_debugfs_crc.h3
-rw-r--r--include/drm/drm_device.h21
-rw-r--r--include/drm/drm_dp_helper.h56
-rw-r--r--include/drm/drm_drv.h29
-rw-r--r--include/drm/drm_encoder.h16
-rw-r--r--include/drm/drm_fb_cma_helper.h6
-rw-r--r--include/drm/drm_fb_helper.h38
-rw-r--r--include/drm/drm_file.h7
-rw-r--r--include/drm/drm_fourcc.h2
-rw-r--r--include/drm/drm_mm.h34
-rw-r--r--include/drm/drm_mode_config.h36
-rw-r--r--include/drm/drm_modes.h2
-rw-r--r--include/drm/drm_modeset_helper_vtables.h17
-rw-r--r--include/drm/drm_of.h8
-rw-r--r--include/drm/drm_panel.h3
-rw-r--r--include/drm/drm_pci.h7
-rw-r--r--include/drm/drm_plane.h197
-rw-r--r--include/drm/drm_plane_helper.h6
-rw-r--r--include/drm/drm_prime.h6
-rw-r--r--include/drm/drm_print.h77
-rw-r--r--include/drm/drm_property.h4
-rw-r--r--include/drm/drm_vma_manager.h1
-rw-r--r--include/drm/drm_writeback.h136
-rw-r--r--include/drm/gpu_scheduler.h174
-rw-r--r--include/drm/i915_component.h85
-rw-r--r--include/drm/i915_drm.h4
-rw-r--r--include/drm/i915_pciids.h37
-rw-r--r--include/drm/tinydrm/tinydrm.h23
-rw-r--r--include/drm/ttm/ttm_bo_api.h25
-rw-r--r--include/drm/ttm/ttm_set_memory.h150
38 files changed, 1697 insertions, 406 deletions
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index f5099c12c6a6..f7a19c2a7a80 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -97,29 +97,11 @@ struct pci_controller;
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-/**
- * drm_drv_uses_atomic_modeset - check if the driver implements
- * atomic_commit()
- * @dev: DRM device
- *
- * This check is useful if drivers do not have DRIVER_ATOMIC set but
- * have atomic modesetting internally implemented.
- */
-static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev)
-{
- return dev->mode_config.funcs->atomic_commit != NULL;
-}
-
#define DRM_SWITCH_POWER_ON 0
#define DRM_SWITCH_POWER_OFF 1
#define DRM_SWITCH_POWER_CHANGING 2
#define DRM_SWITCH_POWER_DYNAMIC_OFF 3
-static inline bool drm_core_check_feature(struct drm_device *dev, int feature)
-{
- return dev->driver->driver_features & feature;
-}
-
/* returns true if currently okay to sleep */
static inline bool drm_can_sleep(void)
{
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index a57a8aa90ffb..da9d95a19580 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -160,6 +160,14 @@ struct __drm_crtcs_state {
struct __drm_connnectors_state {
struct drm_connector *ptr;
struct drm_connector_state *state, *old_state, *new_state;
+ /**
+ * @out_fence_ptr:
+ *
+ * User-provided pointer which the kernel uses to return a sync_file
+ * file descriptor. Used by writeback connectors to signal completion of
+ * the writeback.
+ */
+ s32 __user *out_fence_ptr;
};
struct drm_private_obj;
@@ -594,6 +602,9 @@ void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
int __must_check
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
struct drm_crtc *crtc);
+int drm_atomic_set_writeback_fb_for_connector(
+ struct drm_connector_state *conn_state,
+ struct drm_framebuffer *fb);
int __must_check
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
struct drm_crtc *crtc);
@@ -601,9 +612,6 @@ int __must_check
drm_atomic_add_affected_planes(struct drm_atomic_state *state,
struct drm_crtc *crtc);
-void
-drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
-
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);
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 26aaba58d6ce..99e2a5297c69 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -100,6 +100,7 @@ int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
bool nonblock);
void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state);
+void drm_atomic_helper_fake_vblank(struct drm_atomic_state *state);
void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state);
void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state);
diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h
new file mode 100644
index 000000000000..4923b00328c1
--- /dev/null
+++ b/include/drm/drm_audio_component.h
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2014 Intel Corporation
+
+#ifndef _DRM_AUDIO_COMPONENT_H_
+#define _DRM_AUDIO_COMPONENT_H_
+
+struct drm_audio_component;
+
+/**
+ * struct drm_audio_component_ops - Ops implemented by DRM driver, called by hda driver
+ */
+struct drm_audio_component_ops {
+ /**
+ * @owner: drm module to pin down
+ */
+ struct module *owner;
+ /**
+ * @get_power: get the POWER_DOMAIN_AUDIO power well
+ *
+ * Request the power well to be turned on.
+ */
+ void (*get_power)(struct device *);
+ /**
+ * @put_power: put the POWER_DOMAIN_AUDIO power well
+ *
+ * Allow the power well to be turned off.
+ */
+ void (*put_power)(struct device *);
+ /**
+ * @codec_wake_override: Enable/disable codec wake signal
+ */
+ void (*codec_wake_override)(struct device *, bool enable);
+ /**
+ * @get_cdclk_freq: Get the Core Display Clock in kHz
+ */
+ int (*get_cdclk_freq)(struct device *);
+ /**
+ * @sync_audio_rate: set n/cts based on the sample rate
+ *
+ * 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 pipe, int rate);
+ /**
+ * @get_eld: fill the audio state and ELD bytes for the given port
+ *
+ * Called from audio driver to get the HDMI/DP audio state of the given
+ * digital port, and also fetch ELD bytes to the given pointer.
+ *
+ * It returns the byte size of the original ELD (not the actually
+ * copied size), zero for an invalid ELD, or a negative error code.
+ *
+ * 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, int pipe, bool *enabled,
+ unsigned char *buf, int max_bytes);
+};
+
+/**
+ * struct drm_audio_component_audio_ops - Ops implemented by hda driver, called by DRM driver
+ */
+struct drm_audio_component_audio_ops {
+ /**
+ * @audio_ptr: Pointer to be used in call to pin_eld_notify
+ */
+ void *audio_ptr;
+ /**
+ * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed
+ *
+ * Called when the DRM driver has set up audio pipeline or has just
+ * begun to tear it down. This allows the HDA driver to update its
+ * status accordingly (even when the HDA controller is in power save
+ * mode).
+ */
+ void (*pin_eld_notify)(void *audio_ptr, int port, int pipe);
+ /**
+ * @pin2port: Check and convert from pin node to port number
+ *
+ * Called by HDA driver to check and convert from the pin widget node
+ * number to a port number in the graphics side.
+ */
+ int (*pin2port)(void *audio_ptr, int pin);
+ /**
+ * @master_bind: (Optional) component master bind callback
+ *
+ * Called at binding master component, for HDA codec-specific
+ * handling of dynamic binding.
+ */
+ int (*master_bind)(struct device *dev, struct drm_audio_component *);
+ /**
+ * @master_unbind: (Optional) component master unbind callback
+ *
+ * Called at unbinding master component, for HDA codec-specific
+ * handling of dynamic unbinding.
+ */
+ void (*master_unbind)(struct device *dev, struct drm_audio_component *);
+};
+
+/**
+ * struct drm_audio_component - Used for direct communication between DRM and hda drivers
+ */
+struct drm_audio_component {
+ /**
+ * @dev: DRM device, used as parameter for ops
+ */
+ struct device *dev;
+ /**
+ * @ops: Ops implemented by DRM driver, called by hda driver
+ */
+ const struct drm_audio_component_ops *ops;
+ /**
+ * @audio_ops: Ops implemented by hda driver, called by DRM driver
+ */
+ const struct drm_audio_component_audio_ops *audio_ops;
+};
+
+#endif /* _DRM_AUDIO_COMPONENT_H_ */
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index 3270fec46979..bd850747ce54 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -97,7 +97,7 @@ struct drm_bridge_funcs {
/**
* @mode_fixup:
*
- * This callback is used to validate and adjust a mode. The paramater
+ * This callback is used to validate and adjust a mode. The parameter
* mode is the display mode that should be fed to the next element in
* the display chain, either the final &drm_connector or the next
* &drm_bridge. The parameter adjusted_mode is the input mode the bridge
@@ -178,6 +178,22 @@ struct drm_bridge_funcs {
* then this would be &drm_encoder_helper_funcs.mode_set. The display
* pipe (i.e. clocks and timing signals) is off when this function is
* called.
+ *
+ * The adjusted_mode parameter is the mode output by the CRTC for the
+ * first bridge in the chain. It can be different from the mode
+ * parameter that contains the desired mode for the connector at the end
+ * of the bridges chain, for instance when the first bridge in the chain
+ * performs scaling. The adjusted mode is mostly useful for the first
+ * bridge in the chain and is likely irrelevant for the other bridges.
+ *
+ * For atomic drivers the adjusted_mode is the mode stored in
+ * &drm_crtc_state.adjusted_mode.
+ *
+ * NOTE:
+ *
+ * If a need arises to store and access modes adjusted for other
+ * locations than the connection between the CRTC and the first bridge,
+ * the DRM framework will have to be extended with DRM bridge states.
*/
void (*mode_set)(struct drm_bridge *bridge,
struct drm_display_mode *mode,
@@ -254,27 +270,29 @@ struct drm_bridge_timings {
/**
* struct drm_bridge - central DRM bridge control structure
- * @dev: DRM device this bridge belongs to
- * @encoder: encoder to which this bridge is connected
- * @next: the next bridge in the encoder chain
- * @of_node: device node pointer to the bridge
- * @list: to keep track of all added bridges
- * @timings: the timing specification for the bridge, if any (may
- * be NULL)
- * @funcs: control functions
- * @driver_private: pointer to the bridge driver's internal context
*/
struct drm_bridge {
+ /** @dev: DRM device this bridge belongs to */
struct drm_device *dev;
+ /** @encoder: encoder to which this bridge is connected */
struct drm_encoder *encoder;
+ /** @next: the next bridge in the encoder chain */
struct drm_bridge *next;
#ifdef CONFIG_OF
+ /** @of_node: device node pointer to the bridge */
struct device_node *of_node;
#endif
+ /** @list: to keep track of all added bridges */
struct list_head list;
+ /**
+ * @timings:
+ *
+ * the timing specification for the bridge, if any (may be NULL)
+ */
const struct drm_bridge_timings *timings;
-
+ /** @funcs: control functions */
const struct drm_bridge_funcs *funcs;
+ /** @driver_private: pointer to the bridge driver's internal context */
void *driver_private;
};
@@ -285,15 +303,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
struct drm_bridge *previous);
bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode);
void drm_bridge_disable(struct drm_bridge *bridge);
void drm_bridge_post_disable(struct drm_bridge *bridge);
void drm_bridge_mode_set(struct drm_bridge *bridge,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode);
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode);
void drm_bridge_pre_enable(struct drm_bridge *bridge);
void drm_bridge_enable(struct drm_bridge *bridge);
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
new file mode 100644
index 000000000000..989f8e52864d
--- /dev/null
+++ b/include/drm/drm_client.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _DRM_CLIENT_H_
+#define _DRM_CLIENT_H_
+
+#include <linux/types.h>
+
+struct drm_client_dev;
+struct drm_device;
+struct drm_file;
+struct drm_framebuffer;
+struct drm_gem_object;
+struct drm_minor;
+struct module;
+
+/**
+ * struct drm_client_funcs - DRM client callbacks
+ */
+struct drm_client_funcs {
+ /**
+ * @owner: The module owner
+ */
+ struct module *owner;
+
+ /**
+ * @unregister:
+ *
+ * Called when &drm_device is unregistered. The client should respond by
+ * releasing it's resources using drm_client_release().
+ *
+ * This callback is optional.
+ */
+ void (*unregister)(struct drm_client_dev *client);
+
+ /**
+ * @restore:
+ *
+ * Called on drm_lastclose(). The first client instance in the list that
+ * returns zero gets the privilege to restore and no more clients are
+ * called. This callback is not called after @unregister has been called.
+ *
+ * This callback is optional.
+ */
+ int (*restore)(struct drm_client_dev *client);
+
+ /**
+ * @hotplug:
+ *
+ * Called on drm_kms_helper_hotplug_event().
+ * This callback is not called after @unregister has been called.
+ *
+ * This callback is optional.
+ */
+ int (*hotplug)(struct drm_client_dev *client);
+};
+
+/**
+ * struct drm_client_dev - DRM client instance
+ */
+struct drm_client_dev {
+ /**
+ * @dev: DRM device
+ */
+ struct drm_device *dev;
+
+ /**
+ * @name: Name of the client.
+ */
+ const char *name;
+
+ /**
+ * @list:
+ *
+ * List of all clients of a DRM device, linked into
+ * &drm_device.clientlist. Protected by &drm_device.clientlist_mutex.
+ */
+ struct list_head list;
+
+ /**
+ * @funcs: DRM client functions (optional)
+ */
+ const struct drm_client_funcs *funcs;
+
+ /**
+ * @file: DRM file
+ */
+ struct drm_file *file;
+};
+
+int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
+ const char *name, const struct drm_client_funcs *funcs);
+void drm_client_release(struct drm_client_dev *client);
+
+void drm_client_dev_unregister(struct drm_device *dev);
+void drm_client_dev_hotplug(struct drm_device *dev);
+void drm_client_dev_restore(struct drm_device *dev);
+
+/**
+ * struct drm_client_buffer - DRM client buffer
+ */
+struct drm_client_buffer {
+ /**
+ * @client: DRM client
+ */
+ struct drm_client_dev *client;
+
+ /**
+ * @handle: Buffer handle
+ */
+ u32 handle;
+
+ /**
+ * @pitch: Buffer pitch
+ */
+ u32 pitch;
+
+ /**
+ * @gem: GEM object backing this buffer
+ */
+ struct drm_gem_object *gem;
+
+ /**
+ * @vaddr: Virtual address for the buffer
+ */
+ void *vaddr;
+
+ /**
+ * @fb: DRM framebuffer
+ */
+ struct drm_framebuffer *fb;
+};
+
+struct drm_client_buffer *
+drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format);
+void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
+
+int drm_client_debugfs_init(struct drm_minor *minor);
+
+#endif
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 675cc3f8cf85..97ea41dc678f 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -290,6 +290,10 @@ struct drm_display_info {
#define DRM_BUS_FLAG_DATA_MSB_TO_LSB (1<<4)
/* data is transmitted LSB to MSB on the bus */
#define DRM_BUS_FLAG_DATA_LSB_TO_MSB (1<<5)
+/* drive sync on pos. edge */
+#define DRM_BUS_FLAG_SYNC_POSEDGE (1<<6)
+/* drive sync on neg. edge */
+#define DRM_BUS_FLAG_SYNC_NEGEDGE (1<<7)
/**
* @bus_flags: Additional information (like pixel signal polarity) for
@@ -374,12 +378,9 @@ struct drm_tv_connector_state {
/**
* 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 {
+ /** @connector: backpointer to the connector */
struct drm_connector *connector;
/**
@@ -390,6 +391,13 @@ struct drm_connector_state {
*/
struct drm_crtc *crtc;
+ /**
+ * @best_encoder:
+ *
+ * Used by the atomic helpers to select the encoder, through the
+ * &drm_connector_helper_funcs.atomic_best_encoder or
+ * &drm_connector_helper_funcs.best_encoder callbacks.
+ */
struct drm_encoder *best_encoder;
/**
@@ -398,6 +406,7 @@ struct drm_connector_state {
*/
enum drm_link_status link_status;
+ /** @state: backpointer to global drm_atomic_state */
struct drm_atomic_state *state;
/**
@@ -407,6 +416,7 @@ struct drm_connector_state {
*/
struct drm_crtc_commit *commit;
+ /** @tv: TV connector state */
struct drm_tv_connector_state tv;
/**
@@ -419,6 +429,14 @@ struct drm_connector_state {
enum hdmi_picture_aspect picture_aspect_ratio;
/**
+ * @content_type: Connector property to control the
+ * HDMI infoframe content type setting.
+ * The %DRM_MODE_CONTENT_TYPE_\* values much
+ * match the values.
+ */
+ unsigned int content_type;
+
+ /**
* @scaling_mode: Connector property to control the
* upscaling, mostly used for built-in panels.
*/
@@ -429,6 +447,19 @@ struct drm_connector_state {
* protection. This is most commonly used for HDCP.
*/
unsigned int content_protection;
+
+ /**
+ * @writeback_job: Writeback job for writeback connectors
+ *
+ * Holds the framebuffer and out-fence for a writeback connector. As
+ * the writeback completion may be asynchronous to the normal commit
+ * cycle, the writeback job lifetime is managed separately from the
+ * normal atomic state by this object.
+ *
+ * See also: drm_writeback_queue_job() and
+ * drm_writeback_signal_completion()
+ */
+ struct drm_writeback_job *writeback_job;
};
/**
@@ -530,8 +561,7 @@ struct drm_connector_funcs {
* received for this output connector->edid must be NULL.
*
* Drivers using the probe helpers should use
- * drm_helper_probe_single_connector_modes() or
- * drm_helper_probe_single_connector_modes_nomerge() to implement this
+ * drm_helper_probe_single_connector_modes() to implement this
* function.
*
* RETURNS:
@@ -608,6 +638,8 @@ struct drm_connector_funcs {
* cleaned up by calling the @atomic_destroy_state hook in this
* structure.
*
+ * This callback is mandatory for atomic drivers.
+ *
* Atomic drivers which don't subclass &struct drm_connector_state should use
* drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
* state structure to extend it with driver-private state should use
@@ -634,6 +666,8 @@ struct drm_connector_funcs {
*
* Destroy a state duplicated with @atomic_duplicate_state and release
* or unreference all resources it references
+ *
+ * This callback is mandatory for atomic drivers.
*/
void (*atomic_destroy_state)(struct drm_connector *connector,
struct drm_connector_state *state);
@@ -738,45 +772,6 @@ struct drm_cmdline_mode {
/**
* struct drm_connector - central DRM connector control structure
- * @dev: parent DRM device
- * @kdev: kernel device for sysfs attributes
- * @attr: sysfs attributes
- * @head: list management
- * @base: base KMS object
- * @name: human readable name, can be overwritten by the driver
- * @connector_type: one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
- * @connector_type_id: index into connector type enum
- * @interlace_allowed: can this connector handle interlaced modes?
- * @doublescan_allowed: can this connector handle doublescan?
- * @stereo_allowed: can this connector handle stereo modes?
- * @funcs: connector control functions
- * @edid_blob_ptr: DRM property containing EDID if present
- * @properties: property tracking for this connector
- * @dpms: current dpms state
- * @helper_private: mid-layer private data
- * @cmdline_mode: mode line parsed from the kernel cmdline for this connector
- * @force: a DRM_FORCE_<foo> state for forced mode sets
- * @override_edid: has the EDID been overwritten through debugfs for testing?
- * @encoder_ids: valid encoders for this connector
- * @eld: EDID-like data, if present
- * @latency_present: AV delay info from ELD, if found
- * @video_latency: video latency info from ELD, if found
- * @audio_latency: audio latency info from ELD, if found
- * @null_edid_counter: track sinks that give us all zeros for the EDID
- * @bad_edid_counter: track sinks that give us an EDID with invalid checksum
- * @edid_corrupt: indicates whether the last read EDID was corrupt
- * @debugfs_entry: debugfs directory for this connector
- * @has_tile: is this connector connected to a tiled monitor
- * @tile_group: tile group for the connected monitor
- * @tile_is_single_monitor: whether the tile is one monitor housing
- * @num_h_tile: number of horizontal tiles in the tile group
- * @num_v_tile: number of vertical tiles in the tile group
- * @tile_h_loc: horizontal location of this tile
- * @tile_v_loc: vertical location of this tile
- * @tile_h_size: horizontal size of this tile.
- * @tile_v_size: vertical size of this tile.
- * @scaling_mode_property: Optional atomic property to control the upscaling.
- * @content_protection_property: Optional property to control content protection
*
* Each connector may be connected to one or more CRTCs, or may be clonable by
* another connector if they can share a CRTC. Each connector also has a specific
@@ -784,13 +779,27 @@ struct drm_cmdline_mode {
* span multiple monitors).
*/
struct drm_connector {
+ /** @dev: parent DRM device */
struct drm_device *dev;
+ /** @kdev: kernel device for sysfs attributes */
struct device *kdev;
+ /** @attr: sysfs attributes */
struct device_attribute *attr;
+
+ /**
+ * @head:
+ *
+ * List of all connectors on a @dev, linked from
+ * &drm_mode_config.connector_list. Protected by
+ * &drm_mode_config.connector_list_lock, but please only use
+ * &drm_connector_list_iter to walk this list.
+ */
struct list_head head;
+ /** @base: base KMS object */
struct drm_mode_object base;
+ /** @name: human readable name, can be overwritten by the driver */
char *name;
/**
@@ -808,10 +817,30 @@ struct drm_connector {
*/
unsigned index;
+ /**
+ * @connector_type:
+ * one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
+ */
int connector_type;
+ /** @connector_type_id: index into connector type enum */
int connector_type_id;
+ /**
+ * @interlace_allowed:
+ * Can this connector handle interlaced modes? Only used by
+ * drm_helper_probe_single_connector_modes() for mode filtering.
+ */
bool interlace_allowed;
+ /**
+ * @doublescan_allowed:
+ * Can this connector handle doublescan? Only used by
+ * drm_helper_probe_single_connector_modes() for mode filtering.
+ */
bool doublescan_allowed;
+ /**
+ * @stereo_allowed:
+ * Can this connector handle stereo modes? Only used by
+ * drm_helper_probe_single_connector_modes() for mode filtering.
+ */
bool stereo_allowed;
/**
@@ -860,45 +889,42 @@ struct drm_connector {
* Protected by &drm_mode_config.mutex.
*/
struct drm_display_info display_info;
+
+ /** @funcs: connector control functions */
const struct drm_connector_funcs *funcs;
+ /**
+ * @edid_blob_ptr: DRM property containing EDID if present. Protected by
+ * &drm_mode_config.mutex. This should be updated only by calling
+ * drm_connector_update_edid_property().
+ */
struct drm_property_blob *edid_blob_ptr;
+
+ /** @properties: property tracking for this connector */
struct drm_object_properties properties;
+ /**
+ * @scaling_mode_property: Optional atomic property to control the
+ * upscaling. See drm_connector_attach_content_protection_property().
+ */
struct drm_property *scaling_mode_property;
/**
* @content_protection_property: DRM ENUM property for content
- * protection
+ * protection. See drm_connector_attach_content_protection_property().
*/
struct drm_property *content_protection_property;
/**
* @path_blob_ptr:
*
- * DRM blob property data for the DP MST path property.
+ * DRM blob property data for the DP MST path property. This should only
+ * be updated by calling drm_connector_set_path_property().
*/
struct drm_property_blob *path_blob_ptr;
- /**
- * @tile_blob_ptr:
- *
- * DRM blob property data for the tile property (used mostly by DP MST).
- * This is meant for screens which are driven through separate display
- * pipelines represented by &drm_crtc, which might not be running with
- * genlocked clocks. For tiled panels which are genlocked, like
- * dual-link LVDS or dual-link DSI, the driver should try to not expose
- * the tiling and virtualize both &drm_crtc and &drm_plane if needed.
- */
- struct drm_property_blob *tile_blob_ptr;
-
-/* should we poll this connector for connects and disconnects */
-/* hot plug detectable */
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
-/* poll for connections */
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
-/* can cleanly poll for disconnections without flickering the screen */
-/* DACs should rarely do this without a lot of testing */
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
/**
@@ -915,25 +941,40 @@ struct drm_connector {
* Periodically poll the connector for connection.
*
* DRM_CONNECTOR_POLL_DISCONNECT
- * Periodically poll the connector for disconnection.
+ * Periodically poll the connector for disconnection, without
+ * causing flickering even when the connector is in use. DACs should
+ * rarely do this without a lot of testing.
*
* Set to 0 for connectors that don't support connection status
* discovery.
*/
uint8_t polled;
- /* requested DPMS state */
+ /**
+ * @dpms: Current dpms state. For legacy drivers the
+ * &drm_connector_funcs.dpms callback must update this. For atomic
+ * drivers, this is handled by the core atomic code, and drivers must
+ * only take &drm_crtc_state.active into account.
+ */
int dpms;
+ /** @helper_private: mid-layer private data */
const struct drm_connector_helper_funcs *helper_private;
- /* forced on connector */
+ /** @cmdline_mode: mode line parsed from the kernel cmdline for this connector */
struct drm_cmdline_mode cmdline_mode;
+ /** @force: a DRM_FORCE_<foo> state for forced mode sets */
enum drm_connector_force force;
+ /** @override_edid: has the EDID been overwritten through debugfs for testing? */
bool override_edid;
#define DRM_CONNECTOR_MAX_ENCODER 3
+ /**
+ * @encoder_ids: Valid encoders for this connector. Please only use
+ * drm_connector_for_each_possible_encoder() to enumerate these.
+ */
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
+
/**
* @encoder: Currently bound encoder driving this connector, if any.
* Only really meaningful for non-atomic drivers. Atomic drivers should
@@ -943,19 +984,37 @@ struct drm_connector {
struct drm_encoder *encoder;
#define MAX_ELD_BYTES 128
- /* EDID bits */
+ /** @eld: EDID-like data, if present */
uint8_t eld[MAX_ELD_BYTES];
+ /** @latency_present: AV delay info from ELD, if found */
bool latency_present[2];
- int video_latency[2]; /* [0]: progressive, [1]: interlaced */
+ /**
+ * @video_latency: Video latency info from ELD, if found.
+ * [0]: progressive, [1]: interlaced
+ */
+ int video_latency[2];
+ /**
+ * @audio_latency: audio latency info from ELD, if found
+ * [0]: progressive, [1]: interlaced
+ */
int audio_latency[2];
- int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
+ /**
+ * @null_edid_counter: track sinks that give us all zeros for the EDID.
+ * Needed to workaround some HW bugs where we get all 0s
+ */
+ int null_edid_counter;
+
+ /** @bad_edid_counter: track sinks that give us an EDID with invalid checksum */
unsigned bad_edid_counter;
- /* Flag for raw EDID header corruption - used in Displayport
- * compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
+ /**
+ * @edid_corrupt: Indicates whether the last read EDID was corrupt. Used
+ * in Displayport compliance testing - Displayport Link CTS Core 1.2
+ * rev1.1 4.2.2.6
*/
bool edid_corrupt;
+ /** @debugfs_entry: debugfs directory for this connector */
struct dentry *debugfs_entry;
/**
@@ -963,7 +1022,7 @@ struct drm_connector {
*
* Current atomic state for this connector.
*
- * This is protected by @drm_mode_config.connection_mutex. Note that
+ * This is protected by &drm_mode_config.connection_mutex. Note that
* nonblocking atomic commits access the current connector state without
* taking locks. Either by going through the &struct drm_atomic_state
* pointers, see for_each_oldnew_connector_in_state(),
@@ -974,19 +1033,44 @@ struct drm_connector {
*/
struct drm_connector_state *state;
- /* DisplayID bits */
+ /* DisplayID bits. FIXME: Extract into a substruct? */
+
+ /**
+ * @tile_blob_ptr:
+ *
+ * DRM blob property data for the tile property (used mostly by DP MST).
+ * This is meant for screens which are driven through separate display
+ * pipelines represented by &drm_crtc, which might not be running with
+ * genlocked clocks. For tiled panels which are genlocked, like
+ * dual-link LVDS or dual-link DSI, the driver should try to not expose
+ * the tiling and virtualize both &drm_crtc and &drm_plane if needed.
+ *
+ * This should only be updated by calling
+ * drm_connector_set_tile_property().
+ */
+ struct drm_property_blob *tile_blob_ptr;
+
+ /** @has_tile: is this connector connected to a tiled monitor */
bool has_tile;
+ /** @tile_group: tile group for the connected monitor */
struct drm_tile_group *tile_group;
+ /** @tile_is_single_monitor: whether the tile is one monitor housing */
bool tile_is_single_monitor;
+ /** @num_h_tile: number of horizontal tiles in the tile group */
+ /** @num_v_tile: number of vertical tiles in the tile group */
uint8_t num_h_tile, num_v_tile;
+ /** @tile_h_loc: horizontal location of this tile */
+ /** @tile_v_loc: vertical location of this tile */
uint8_t tile_h_loc, tile_v_loc;
+ /** @tile_h_size: horizontal size of this tile. */
+ /** @tile_v_size: vertical size of this tile. */
uint16_t tile_h_size, tile_v_size;
/**
* @free_node:
*
- * List used only by &drm_connector_iter to be able to clean up a
+ * List used only by &drm_connector_list_iter to be able to clean up a
* connector from any context, in conjunction with
* &drm_mode_config.connector_free_work.
*/
@@ -1001,15 +1085,21 @@ int drm_connector_init(struct drm_device *dev,
int connector_type);
int drm_connector_register(struct drm_connector *connector);
void drm_connector_unregister(struct drm_connector *connector);
-int drm_mode_connector_attach_encoder(struct drm_connector *connector,
+int drm_connector_attach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder);
void drm_connector_cleanup(struct drm_connector *connector);
-static inline unsigned drm_connector_index(struct drm_connector *connector)
+
+static inline unsigned int drm_connector_index(const struct drm_connector *connector)
{
return connector->index;
}
+static inline u32 drm_connector_mask(const struct drm_connector *connector)
+{
+ return 1 << connector->index;
+}
+
/**
* drm_connector_lookup - lookup connector object
* @dev: DRM device
@@ -1089,20 +1179,25 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
unsigned int num_modes,
const char * const modes[]);
int drm_mode_create_scaling_mode_property(struct drm_device *dev);
+int drm_connector_attach_content_type_property(struct drm_connector *dev);
int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
u32 scaling_mode_mask);
int drm_connector_attach_content_protection_property(
struct drm_connector *connector);
int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
+int drm_mode_create_content_type_property(struct drm_device *dev);
+void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame,
+ const struct drm_connector_state *conn_state);
+
int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
-int drm_mode_connector_set_path_property(struct drm_connector *connector,
- const char *path);
-int drm_mode_connector_set_tile_property(struct drm_connector *connector);
-int drm_mode_connector_update_edid_property(struct drm_connector *connector,
- const struct edid *edid);
-void drm_mode_connector_set_link_status_property(struct drm_connector *connector,
- uint64_t link_status);
+int drm_connector_set_path_property(struct drm_connector *connector,
+ const char *path);
+int drm_connector_set_tile_property(struct drm_connector *connector);
+int drm_connector_update_edid_property(struct drm_connector *connector,
+ const struct edid *edid);
+void drm_connector_set_link_status_property(struct drm_connector *connector,
+ uint64_t link_status);
int drm_connector_init_panel_orientation_property(
struct drm_connector *connector, int width, int height);
@@ -1151,6 +1246,9 @@ struct drm_connector *
drm_connector_list_iter_next(struct drm_connector_list_iter *iter);
void drm_connector_list_iter_end(struct drm_connector_list_iter *iter);
+bool drm_connector_has_possible_encoder(struct drm_connector *connector,
+ struct drm_encoder *encoder);
+
/**
* drm_for_each_connector_iter - connector_list iterator macro
* @connector: &struct drm_connector pointer used as cursor
@@ -1163,4 +1261,17 @@ void drm_connector_list_iter_end(struct drm_connector_list_iter *iter);
#define drm_for_each_connector_iter(connector, iter) \
while ((connector = drm_connector_list_iter_next(iter)))
+/**
+ * drm_connector_for_each_possible_encoder - iterate connector's possible encoders
+ * @connector: &struct drm_connector pointer
+ * @encoder: &struct drm_encoder pointer used as cursor
+ * @__i: int iteration cursor, for macro-internal use
+ */
+#define drm_connector_for_each_possible_encoder(connector, encoder, __i) \
+ for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) && \
+ (connector)->encoder_ids[(__i)] != 0; (__i)++) \
+ for_each_if((encoder) = \
+ drm_encoder_find((connector)->dev, NULL, \
+ (connector)->encoder_ids[(__i)])) \
+
#endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index a2d81d2907a9..92e7fc7f05a4 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -77,21 +77,6 @@ struct drm_plane_helper_funcs;
/**
* struct drm_crtc_state - mutable CRTC state
- * @crtc: backpointer to the CRTC
- * @enable: whether the CRTC should be enabled, gates all other state
- * @active: whether the CRTC is actively displaying (used for DPMS)
- * @planes_changed: planes on this crtc are updated
- * @mode_changed: @mode or @enable has been changed
- * @active_changed: @active has been toggled.
- * @connectors_changed: connectors to this crtc have been updated
- * @zpos_changed: zpos values of planes on this crtc have been updated
- * @color_mgmt_changed: color management properties have changed (degamma or
- * gamma LUT or CSC matrix)
- * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
- * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
- * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
- * @mode_blob: &drm_property_blob for @mode
- * @state: backpointer to global drm_atomic_state
*
* Note that the distinction between @enable and @active is rather subtile:
* Flipping @active while @enable is set without changing anything else may
@@ -102,31 +87,127 @@ struct drm_plane_helper_funcs;
*
* 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()
+ * describing what has changed in a commit. See also:
+ * drm_atomic_crtc_needs_modeset()
+ *
+ * WARNING: Transitional helpers (like drm_helper_crtc_mode_set() or
+ * drm_helper_crtc_mode_set_base()) do not maintain many of the derived control
+ * state like @plane_mask so drivers not converted over to atomic helpers should
+ * not rely on these being accurate!
*/
struct drm_crtc_state {
+ /** @crtc: backpointer to the CRTC */
struct drm_crtc *crtc;
+ /**
+ * @enable: Whether the CRTC should be enabled, gates all other state.
+ * This controls reservations of shared resources. Actual hardware state
+ * is controlled by @active.
+ */
bool enable;
+
+ /**
+ * @active: Whether the CRTC is actively displaying (used for DPMS).
+ * Implies that @enable is set. The driver must not release any shared
+ * resources if @active is set to false but @enable still true, because
+ * userspace expects that a DPMS ON always succeeds.
+ *
+ * Hence drivers must not consult @active in their various
+ * &drm_mode_config_funcs.atomic_check callback to reject an atomic
+ * commit. They can consult it to aid in the computation of derived
+ * hardware state, since even in the DPMS OFF state the display hardware
+ * should be as much powered down as when the CRTC is completely
+ * disabled through setting @enable to false.
+ */
bool active;
- /* computed state bits used by helpers and drivers */
+ /**
+ * @planes_changed: Planes on this crtc are updated. Used by the atomic
+ * helpers and drivers to steer the atomic commit control flow.
+ */
bool planes_changed : 1;
+
+ /**
+ * @mode_changed: @mode or @enable has been changed. Used by the atomic
+ * helpers and drivers to steer the atomic commit control flow. See also
+ * drm_atomic_crtc_needs_modeset().
+ *
+ * Drivers are supposed to set this for any CRTC state changes that
+ * require a full modeset. They can also reset it to false if e.g. a
+ * @mode change can be done without a full modeset by only changing
+ * scaler settings.
+ */
bool mode_changed : 1;
+
+ /**
+ * @active_changed: @active has been toggled. Used by the atomic
+ * helpers and drivers to steer the atomic commit control flow. See also
+ * drm_atomic_crtc_needs_modeset().
+ */
bool active_changed : 1;
+
+ /**
+ * @connectors_changed: Connectors to this crtc have been updated,
+ * either in their state or routing. Used by the atomic
+ * helpers and drivers to steer the atomic commit control flow. See also
+ * drm_atomic_crtc_needs_modeset().
+ *
+ * Drivers are supposed to set this as-needed from their own atomic
+ * check code, e.g. from &drm_encoder_helper_funcs.atomic_check
+ */
bool connectors_changed : 1;
+ /**
+ * @zpos_changed: zpos values of planes on this crtc have been updated.
+ * Used by the atomic helpers and drivers to steer the atomic commit
+ * control flow.
+ */
bool zpos_changed : 1;
+ /**
+ * @color_mgmt_changed: Color management properties have changed
+ * (@gamma_lut, @degamma_lut or @ctm). Used by the atomic helpers and
+ * drivers to steer the atomic commit control flow.
+ */
bool color_mgmt_changed : 1;
- /* attached planes bitmask:
- * WARNING: transitional helpers do not maintain plane_mask so
- * drivers not converted over to atomic helpers should not rely
- * on plane_mask being accurate!
+ /**
+ * @no_vblank:
+ *
+ * Reflects the ability of a CRTC to send VBLANK events. This state
+ * usually depends on the pipeline configuration, and the main usuage
+ * is CRTCs feeding a writeback connector operating in oneshot mode.
+ * In this case the VBLANK event is only generated when a job is queued
+ * to the writeback connector, and we want the core to fake VBLANK
+ * events when this part of the pipeline hasn't changed but others had
+ * or when the CRTC and connectors are being disabled.
+ *
+ * __drm_atomic_helper_crtc_duplicate_state() will not reset the value
+ * from the current state, the CRTC driver is then responsible for
+ * updating this field when needed.
+ *
+ * Note that the combination of &drm_crtc_state.event == NULL and
+ * &drm_crtc_state.no_blank == true is valid and usually used when the
+ * writeback connector attached to the CRTC has a new job queued. In
+ * this case the driver will send the VBLANK event on its own when the
+ * writeback job is complete.
+ */
+ bool no_vblank : 1;
+
+ /**
+ * @plane_mask: Bitmask of drm_plane_mask(plane) of planes attached to
+ * this CRTC.
*/
u32 plane_mask;
+ /**
+ * @connector_mask: Bitmask of drm_connector_mask(connector) of
+ * connectors attached to this CRTC.
+ */
u32 connector_mask;
+
+ /**
+ * @encoder_mask: Bitmask of drm_encoder_mask(encoder) of encoders
+ * attached to this CRTC.
+ */
u32 encoder_mask;
/**
@@ -134,10 +215,13 @@ struct drm_crtc_state {
*
* Internal display timings which can be used by the driver to handle
* differences between the mode requested by userspace in @mode and what
- * is actually programmed into the hardware. It is purely driver
- * implementation defined what exactly this adjusted mode means. Usually
- * it is used to store the hardware display timings used between the
- * CRTC and encoder blocks.
+ * is actually programmed into the hardware.
+ *
+ * For drivers using &drm_bridge, this stores hardware display timings
+ * used between the CRTC and the first bridge. For other drivers, the
+ * meaning of the adjusted_mode field is purely driver implementation
+ * defined information, and will usually be used to store the hardware
+ * display timings used between the CRTC and encoder blocks.
*/
struct drm_display_mode adjusted_mode;
@@ -158,7 +242,10 @@ struct drm_crtc_state {
*/
struct drm_display_mode mode;
- /* blob property to expose current mode to atomic userspace */
+ /**
+ * @mode_blob: &drm_property_blob for @mode, for exposing the mode to
+ * atomic userspace.
+ */
struct drm_property_blob *mode_blob;
/**
@@ -262,6 +349,7 @@ struct drm_crtc_state {
*/
struct drm_crtc_commit *commit;
+ /** @state: backpointer to global drm_atomic_state */
struct drm_atomic_state *state;
};
@@ -503,6 +591,8 @@ struct drm_crtc_funcs {
* cleaned up by calling the @atomic_destroy_state hook in this
* structure.
*
+ * This callback is mandatory for atomic drivers.
+ *
* Atomic drivers which don't subclass &struct drm_crtc_state should use
* drm_atomic_helper_crtc_duplicate_state(). Drivers that subclass the
* state structure to extend it with driver-private state should use
@@ -529,6 +619,8 @@ struct drm_crtc_funcs {
*
* Destroy a state duplicated with @atomic_duplicate_state and release
* or unreference all resources it references
+ *
+ * This callback is mandatory for atomic drivers.
*/
void (*atomic_destroy_state)(struct drm_crtc *crtc,
struct drm_crtc_state *state);
@@ -717,35 +809,25 @@ struct drm_crtc_funcs {
/**
* struct drm_crtc - central CRTC control structure
- * @dev: parent DRM device
- * @port: OF node used by drm_of_find_possible_crtcs()
- * @head: list management
- * @name: human readable name, can be overwritten by the driver
- * @mutex: per-CRTC locking
- * @base: base KMS object for ID tracking etc.
- * @primary: primary plane for this CRTC
- * @cursor: cursor plane for this CRTC
- * @cursor_x: current x position of the cursor, used for universal cursor planes
- * @cursor_y: current y position of the cursor, used for universal cursor planes
- * @enabled: is this CRTC enabled?
- * @mode: current mode timings
- * @hwmode: mode timings as programmed to hw regs
- * @x: x position on screen
- * @y: y position on screen
- * @funcs: CRTC control functions
- * @gamma_size: size of gamma ramp
- * @gamma_store: gamma ramp values
- * @helper_private: mid-layer private data
- * @properties: property tracking for this CRTC
*
* Each CRTC may have one or more connectors associated with it. This structure
* allows the CRTC to be controlled.
*/
struct drm_crtc {
+ /** @dev: parent DRM device */
struct drm_device *dev;
+ /** @port: OF node used by drm_of_find_possible_crtcs(). */
struct device_node *port;
+ /**
+ * @head:
+ *
+ * List of all CRTCs on @dev, linked from &drm_mode_config.crtc_list.
+ * Invariant over the lifetime of @dev and therefore does not need
+ * locking.
+ */
struct list_head head;
+ /** @name: human readable name, can be overwritten by the driver */
char *name;
/**
@@ -760,10 +842,25 @@ struct drm_crtc {
*/
struct drm_modeset_lock mutex;
+ /** @base: base KMS object for ID tracking etc. */
struct drm_mode_object base;
- /* primary and cursor planes for CRTC */
+ /**
+ * @primary:
+ * Primary plane for this CRTC. Note that this is only
+ * relevant for legacy IOCTL, it specifies the plane implicitly used by
+ * the SETCRTC and PAGE_FLIP IOCTLs. It does not have any significance
+ * beyond that.
+ */
struct drm_plane *primary;
+
+ /**
+ * @cursor:
+ * Cursor plane for this CRTC. Note that this is only relevant for
+ * legacy IOCTL, it specifies the plane implicitly used by the SETCURSOR
+ * and SETCURSOR2 IOCTLs. It does not have any significance
+ * beyond that.
+ */
struct drm_plane *cursor;
/**
@@ -772,30 +869,94 @@ struct drm_crtc {
*/
unsigned index;
- /* position of cursor plane on crtc */
+ /**
+ * @cursor_x: Current x position of the cursor, used for universal
+ * cursor planes because the SETCURSOR IOCTL only can update the
+ * framebuffer without supplying the coordinates. Drivers should not use
+ * this directly, atomic drivers should look at &drm_plane_state.crtc_x
+ * of the cursor plane instead.
+ */
int cursor_x;
+ /**
+ * @cursor_y: Current y position of the cursor, used for universal
+ * cursor planes because the SETCURSOR IOCTL only can update the
+ * framebuffer without supplying the coordinates. Drivers should not use
+ * this directly, atomic drivers should look at &drm_plane_state.crtc_y
+ * of the cursor plane instead.
+ */
int cursor_y;
+ /**
+ * @enabled:
+ *
+ * Is this CRTC enabled? Should only be used by legacy drivers, atomic
+ * drivers should instead consult &drm_crtc_state.enable and
+ * &drm_crtc_state.active. Atomic drivers can update this by calling
+ * drm_atomic_helper_update_legacy_modeset_state().
+ */
bool enabled;
- /* Requested mode from modesetting. */
+ /**
+ * @mode:
+ *
+ * Current mode timings. Should only be used by legacy drivers, atomic
+ * drivers should instead consult &drm_crtc_state.mode. Atomic drivers
+ * can update this by calling
+ * drm_atomic_helper_update_legacy_modeset_state().
+ */
struct drm_display_mode mode;
- /* Programmed mode in hw, after adjustments for encoders,
- * crtc, panel scaling etc. Needed for timestamping etc.
+ /**
+ * @hwmode:
+ *
+ * Programmed mode in hw, after adjustments for encoders, crtc, panel
+ * scaling etc. Should only be used by legacy drivers, for high
+ * precision vblank timestamps in
+ * drm_calc_vbltimestamp_from_scanoutpos().
+ *
+ * Note that atomic drivers should not use this, but instead use
+ * &drm_crtc_state.adjusted_mode. And for high-precision timestamps
+ * drm_calc_vbltimestamp_from_scanoutpos() used &drm_vblank_crtc.hwmode,
+ * which is filled out by calling drm_calc_timestamping_constants().
*/
struct drm_display_mode hwmode;
- int x, y;
+ /**
+ * @x:
+ * x position on screen. Should only be used by legacy drivers, atomic
+ * drivers should look at &drm_plane_state.crtc_x of the primary plane
+ * instead. Updated by calling
+ * drm_atomic_helper_update_legacy_modeset_state().
+ */
+ int x;
+ /**
+ * @y:
+ * y position on screen. Should only be used by legacy drivers, atomic
+ * drivers should look at &drm_plane_state.crtc_y of the primary plane
+ * instead. Updated by calling
+ * drm_atomic_helper_update_legacy_modeset_state().
+ */
+ int y;
+
+ /** @funcs: CRTC control functions */
const struct drm_crtc_funcs *funcs;
- /* Legacy FB CRTC gamma size for reporting to userspace */
+ /**
+ * @gamma_size: Size of legacy gamma ramp reported to userspace. Set up
+ * by calling drm_mode_crtc_set_gamma_size().
+ */
uint32_t gamma_size;
+
+ /**
+ * @gamma_store: Gamma ramp values used by the legacy SETGAMMA and
+ * GETGAMMA IOCTls. Set up by calling drm_mode_crtc_set_gamma_size().
+ */
uint16_t *gamma_store;
- /* if you are using the helper */
+ /** @helper_private: mid-layer private data */
const struct drm_crtc_helper_funcs *helper_private;
+ /** @properties: property tracking for this CRTC */
struct drm_object_properties properties;
/**
@@ -865,7 +1026,6 @@ struct drm_crtc {
*
* spinlock to protect the fences in the fence_context.
*/
-
spinlock_t fence_lock;
/**
* @fence_seqno:
@@ -935,8 +1095,8 @@ static inline unsigned int drm_crtc_index(const struct drm_crtc *crtc)
* drm_crtc_mask - find the mask of a registered CRTC
* @crtc: CRTC to find mask for
*
- * Given a registered CRTC, return the mask bit of that CRTC for an
- * encoder's possible_crtcs field.
+ * Given a registered CRTC, return the mask bit of that CRTC for the
+ * &drm_encoder.possible_crtcs and &drm_plane.possible_crtcs fields.
*/
static inline uint32_t drm_crtc_mask(const struct drm_crtc *crtc)
{
diff --git a/include/drm/drm_debugfs_crc.h b/include/drm/drm_debugfs_crc.h
index 7d63b1d4adb9..b225eeb30d05 100644
--- a/include/drm/drm_debugfs_crc.h
+++ b/include/drm/drm_debugfs_crc.h
@@ -43,6 +43,7 @@ struct drm_crtc_crc_entry {
* @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
+ * @overflow: whether an overflow occured.
* @entries: array of entries, with size of %DRM_CRC_ENTRIES_NR
* @head: head of circular queue
* @tail: tail of circular queue
@@ -52,7 +53,7 @@ struct drm_crtc_crc_entry {
struct drm_crtc_crc {
spinlock_t lock;
const char *source;
- bool opened;
+ bool opened, overflow;
struct drm_crtc_crc_entry *entries;
int head, tail;
size_t values_cnt;
diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h
index 858ba19a3e29..f9c6e0e3aec7 100644
--- a/include/drm/drm_device.h
+++ b/include/drm/drm_device.h
@@ -74,6 +74,27 @@ struct drm_device {
struct mutex filelist_mutex;
struct list_head filelist;
+ /**
+ * @filelist_internal:
+ *
+ * List of open DRM files for in-kernel clients. Protected by @filelist_mutex.
+ */
+ struct list_head filelist_internal;
+
+ /**
+ * @clientlist_mutex:
+ *
+ * Protects @clientlist access.
+ */
+ struct mutex clientlist_mutex;
+
+ /**
+ * @clientlist:
+ *
+ * List of in-kernel clients. Protected by @clientlist_mutex.
+ */
+ struct list_head clientlist;
+
/** \name Memory management */
/*@{ */
struct list_head maplist; /**< Linked list of regions */
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index c01564991a9f..05cc31b5db16 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1078,6 +1078,25 @@ struct drm_dp_aux_msg {
size_t size;
};
+struct cec_adapter;
+struct edid;
+
+/**
+ * struct drm_dp_aux_cec - DisplayPort CEC-Tunneling-over-AUX
+ * @lock: mutex protecting this struct
+ * @adap: the CEC adapter for CEC-Tunneling-over-AUX support.
+ * @name: name of the CEC adapter
+ * @parent: parent device of the CEC adapter
+ * @unregister_work: unregister the CEC adapter
+ */
+struct drm_dp_aux_cec {
+ struct mutex lock;
+ struct cec_adapter *adap;
+ const char *name;
+ struct device *parent;
+ struct delayed_work unregister_work;
+};
+
/**
* struct drm_dp_aux - DisplayPort AUX channel
* @name: user-visible name of this AUX channel and the I2C-over-AUX adapter
@@ -1136,6 +1155,10 @@ struct drm_dp_aux {
* @i2c_defer_count: Counts I2C DEFERs, used for DP validation.
*/
unsigned i2c_defer_count;
+ /**
+ * @cec: struct containing fields used for CEC-Tunneling-over-AUX.
+ */
+ struct drm_dp_aux_cec cec;
};
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
@@ -1258,4 +1281,37 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk)
return desc->quirks & BIT(quirk);
}
+#ifdef CONFIG_DRM_DP_CEC
+void drm_dp_cec_irq(struct drm_dp_aux *aux);
+void drm_dp_cec_register_connector(struct drm_dp_aux *aux, const char *name,
+ struct device *parent);
+void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux);
+void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid);
+void drm_dp_cec_unset_edid(struct drm_dp_aux *aux);
+#else
+static inline void drm_dp_cec_irq(struct drm_dp_aux *aux)
+{
+}
+
+static inline void drm_dp_cec_register_connector(struct drm_dp_aux *aux,
+ const char *name,
+ struct device *parent)
+{
+}
+
+static inline void drm_dp_cec_unregister_connector(struct drm_dp_aux *aux)
+{
+}
+
+static inline void drm_dp_cec_set_edid(struct drm_dp_aux *aux,
+ const struct edid *edid)
+{
+}
+
+static inline void drm_dp_cec_unset_edid(struct drm_dp_aux *aux)
+{
+}
+
+#endif
+
#endif /* _DRM_DP_HELPER_H_ */
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 7e545f5f94d3..46a8009784df 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -649,6 +649,35 @@ static inline bool drm_dev_is_unplugged(struct drm_device *dev)
return true;
}
+/**
+ * drm_core_check_feature - check driver feature flags
+ * @dev: DRM device to check
+ * @feature: feature flag
+ *
+ * This checks @dev for driver features, see &drm_driver.driver_features and the
+ * various DRIVER_\* flags.
+ *
+ * Returns true if the @feature is supported, false otherwise.
+ */
+static inline bool drm_core_check_feature(struct drm_device *dev, int feature)
+{
+ return dev->driver->driver_features & feature;
+}
+
+/**
+ * drm_drv_uses_atomic_modeset - check if the driver implements
+ * atomic_commit()
+ * @dev: DRM device
+ *
+ * This check is useful if drivers do not have DRIVER_ATOMIC set but
+ * have atomic modesetting internally implemented.
+ */
+static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev)
+{
+ return drm_core_check_feature(dev, DRIVER_ATOMIC) ||
+ dev->mode_config.funcs->atomic_commit != NULL;
+}
+
int drm_dev_set_unique(struct drm_device *dev, const char *name);
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index fb299696c7c4..4f597c0730b4 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -191,12 +191,24 @@ int drm_encoder_init(struct drm_device *dev,
* Given a registered encoder, return the index of that encoder within a DRM
* device's list of encoders.
*/
-static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
+static inline unsigned int drm_encoder_index(const struct drm_encoder *encoder)
{
return encoder->index;
}
/**
+ * drm_encoder_mask - find the mask of a registered ENCODER
+ * @encoder: encoder to find mask for
+ *
+ * Given a registered encoder, return the mask bit of that encoder for an
+ * encoder's possible_clones field.
+ */
+static inline u32 drm_encoder_mask(const struct drm_encoder *encoder)
+{
+ return 1 << drm_encoder_index(encoder);
+}
+
+/**
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
* @encoder: encoder to test
* @crtc: crtc to test
@@ -241,7 +253,7 @@ void drm_encoder_cleanup(struct drm_encoder *encoder);
*/
#define drm_for_each_encoder_mask(encoder, dev, encoder_mask) \
list_for_each_entry((encoder), &(dev)->mode_config.encoder_list, head) \
- for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder)))
+ for_each_if ((encoder_mask) & drm_encoder_mask(encoder))
/**
* drm_for_each_encoder - iterate over all encoders
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index d532f88a8d55..96e26e3b9a0c 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -16,16 +16,10 @@ struct drm_mode_fb_cmd2;
struct drm_plane;
struct drm_plane_state;
-int drm_fb_cma_fbdev_init_with_funcs(struct drm_device *dev,
- unsigned int preferred_bpp, unsigned int max_conn_count,
- const struct drm_framebuffer_funcs *funcs);
int drm_fb_cma_fbdev_init(struct drm_device *dev, unsigned int preferred_bpp,
unsigned int max_conn_count);
void drm_fb_cma_fbdev_fini(struct drm_device *dev);
-struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
- unsigned int preferred_bpp, unsigned int max_conn_count,
- const struct drm_framebuffer_funcs *funcs);
struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int max_conn_count);
void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma);
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index b069433e7fc1..5db08c8f1d25 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -32,6 +32,7 @@
struct drm_fb_helper;
+#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <linux/kgdb.h>
@@ -154,6 +155,20 @@ struct drm_fb_helper_connector {
* operations.
*/
struct drm_fb_helper {
+ /**
+ * @client:
+ *
+ * DRM client used by the generic fbdev emulation.
+ */
+ struct drm_client_dev client;
+
+ /**
+ * @buffer:
+ *
+ * Framebuffer used by the generic fbdev emulation.
+ */
+ struct drm_client_buffer *buffer;
+
struct drm_framebuffer *fb;
struct drm_device *dev;
int crtc_count;
@@ -234,6 +249,12 @@ struct drm_fb_helper {
int preferred_bpp;
};
+static inline struct drm_fb_helper *
+drm_fb_helper_from_client(struct drm_client_dev *client)
+{
+ return container_of(client, struct drm_fb_helper, client);
+}
+
/**
* define DRM_FB_HELPER_DEFAULT_OPS - helper define for drm drivers
*
@@ -330,6 +351,10 @@ void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
void drm_fb_helper_lastclose(struct drm_device *dev);
void drm_fb_helper_output_poll_changed(struct drm_device *dev);
+
+int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes);
+int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp);
#else
static inline void drm_fb_helper_prepare(struct drm_device *dev,
struct drm_fb_helper *helper,
@@ -564,6 +589,19 @@ static inline void drm_fb_helper_output_poll_changed(struct drm_device *dev)
{
}
+static inline int
+drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ return 0;
+}
+
+static inline int
+drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
+{
+ return 0;
+}
+
#endif
static inline int
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 027ac16da3d1..26485acc51d7 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -193,6 +193,13 @@ struct drm_file {
unsigned aspect_ratio_allowed:1;
/**
+ * @writeback_connectors:
+ *
+ * True if client understands writeback connectors
+ */
+ unsigned writeback_connectors:1;
+
+ /**
* @is_master:
*
* This client is the creator of @master. Protected by struct
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 3e86408dac9f..f9c15845f465 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -39,6 +39,7 @@ struct drm_mode_fb_cmd2;
* @hsub: Horizontal chroma subsampling factor
* @vsub: Vertical chroma subsampling factor
* @has_alpha: Does the format embeds an alpha component?
+ * @is_yuv: Is it a YUV format?
*/
struct drm_format_info {
u32 format;
@@ -48,6 +49,7 @@ struct drm_format_info {
u8 hsub;
u8 vsub;
bool has_alpha;
+ bool is_yuv;
};
/**
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 101f566ae43d..2c3bbb43c7d1 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -109,6 +109,38 @@ enum drm_mm_insert_mode {
* Allocates the node from the bottom of the found hole.
*/
DRM_MM_INSERT_EVICT,
+
+ /**
+ * @DRM_MM_INSERT_ONCE:
+ *
+ * Only check the first hole for suitablity and report -ENOSPC
+ * immediately otherwise, rather than check every hole until a
+ * suitable one is found. Can only be used in conjunction with another
+ * search method such as DRM_MM_INSERT_HIGH or DRM_MM_INSERT_LOW.
+ */
+ DRM_MM_INSERT_ONCE = BIT(31),
+
+ /**
+ * @DRM_MM_INSERT_HIGHEST:
+ *
+ * Only check the highest hole (the hole with the largest address) and
+ * insert the node at the top of the hole or report -ENOSPC if
+ * unsuitable.
+ *
+ * Does not search all holes.
+ */
+ DRM_MM_INSERT_HIGHEST = DRM_MM_INSERT_HIGH | DRM_MM_INSERT_ONCE,
+
+ /**
+ * @DRM_MM_INSERT_LOWEST:
+ *
+ * Only check the lowest hole (the hole with the smallest address) and
+ * insert the node at the bottom of the hole or report -ENOSPC if
+ * unsuitable.
+ *
+ * Does not search all holes.
+ */
+ DRM_MM_INSERT_LOWEST = DRM_MM_INSERT_LOW | DRM_MM_INSERT_ONCE,
};
/**
@@ -173,7 +205,7 @@ struct drm_mm {
struct drm_mm_node head_node;
/* Keep an interval_tree for fast lookup of drm_mm_nodes by address. */
struct rb_root_cached interval_tree;
- struct rb_root holes_size;
+ struct rb_root_cached holes_size;
struct rb_root holes_addr;
unsigned long scan_active;
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 33b3a96d66d0..a0b202e1d69a 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -329,10 +329,10 @@ struct drm_mode_config_funcs {
/**
* struct drm_mode_config - Mode configuration control structure
- * @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
+ * @min_width: minimum fb pixel width on this device
+ * @min_height: minimum fb pixel height on this device
+ * @max_width: maximum fb pixel width on this device
+ * @max_height: maximum fb 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
@@ -727,6 +727,11 @@ struct drm_mode_config {
*/
struct drm_property *aspect_ratio_property;
/**
+ * @content_type_property: Optional connector property to control the
+ * HDMI infoframe content type setting.
+ */
+ struct drm_property *content_type_property;
+ /**
* @degamma_lut_property: Optional CRTC property to set the LUT used to
* convert the framebuffer's colors to linear gamma.
*/
@@ -779,6 +784,29 @@ struct drm_mode_config {
*/
struct drm_property *panel_orientation_property;
+ /**
+ * @writeback_fb_id_property: Property for writeback connectors, storing
+ * the ID of the output framebuffer.
+ * See also: drm_writeback_connector_init()
+ */
+ struct drm_property *writeback_fb_id_property;
+
+ /**
+ * @writeback_pixel_formats_property: Property for writeback connectors,
+ * storing an array of the supported pixel formats for the writeback
+ * engine (read-only).
+ * See also: drm_writeback_connector_init()
+ */
+ struct drm_property *writeback_pixel_formats_property;
+ /**
+ * @writeback_out_fence_ptr_property: Property for writeback connectors,
+ * fd pointer representing the outgoing fences for a writeback
+ * connector. Userspace should provide a pointer to a value of type s32,
+ * and then cast that pointer to u64.
+ * See also: drm_writeback_connector_init()
+ */
+ struct drm_property *writeback_out_fence_ptr_property;
+
/* dumb ioctl parameters */
uint32_t preferred_depth, prefer_shadow;
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index b159fe07fcf9..baded6514456 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -530,7 +530,7 @@ drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
void drm_mode_prune_invalid(struct drm_device *dev,
struct list_head *mode_list, bool verbose);
void drm_mode_sort(struct list_head *mode_list);
-void drm_mode_connector_list_update(struct drm_connector *connector);
+void drm_connector_list_update(struct drm_connector *connector);
/* parsing cmdline modes */
bool
diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
index 35e2a3a79fc5..61142aa0ab23 100644
--- a/include/drm/drm_modeset_helper_vtables.h
+++ b/include/drm/drm_modeset_helper_vtables.h
@@ -785,7 +785,7 @@ struct drm_connector_helper_funcs {
*
* This function should fill in all modes currently valid for the sink
* into the &drm_connector.probed_modes list. It should also update the
- * EDID property by calling drm_mode_connector_update_edid_property().
+ * EDID property by calling drm_connector_update_edid_property().
*
* The usual way to implement this is to cache the EDID retrieved in the
* probe callback somewhere in the driver-private connector structure.
@@ -974,6 +974,21 @@ struct drm_connector_helper_funcs {
*/
int (*atomic_check)(struct drm_connector *connector,
struct drm_connector_state *state);
+
+ /**
+ * @atomic_commit:
+ *
+ * This hook is to be used by drivers implementing writeback connectors
+ * that need a point when to commit the writeback job to the hardware.
+ * The writeback_job to commit is available in
+ * &drm_connector_state.writeback_job.
+ *
+ * This hook is optional.
+ *
+ * This callback is used by the atomic modeset helpers.
+ */
+ void (*atomic_commit)(struct drm_connector *connector,
+ struct drm_connector_state *state);
};
/**
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index b93c239afb60..ead34ab5ca4e 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -17,6 +17,8 @@ struct drm_bridge;
struct device_node;
#ifdef CONFIG_OF
+uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
+ struct device_node *port);
uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port);
void drm_of_component_match_add(struct device *master,
@@ -34,6 +36,12 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
struct drm_panel **panel,
struct drm_bridge **bridge);
#else
+static inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev,
+ struct device_node *port)
+{
+ return 0;
+}
+
static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port)
{
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 14ac240a1f64..582a0ec0aa70 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -89,6 +89,7 @@ struct drm_panel {
struct drm_device *drm;
struct drm_connector *connector;
struct device *dev;
+ struct device_link *link;
const struct drm_panel_funcs *funcs;
@@ -199,7 +200,7 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np);
#else
static inline struct drm_panel *of_drm_find_panel(const struct device_node *np)
{
- return NULL;
+ return ERR_PTR(-ENODEV);
}
#endif
diff --git a/include/drm/drm_pci.h b/include/drm/drm_pci.h
index 674599025d7d..8181e9e7cf1d 100644
--- a/include/drm/drm_pci.h
+++ b/include/drm/drm_pci.h
@@ -58,11 +58,4 @@ static inline int drm_get_pci_dev(struct pci_dev *pdev,
}
#endif
-#define DRM_PCIE_SPEED_25 1
-#define DRM_PCIE_SPEED_50 2
-#define DRM_PCIE_SPEED_80 4
-
-int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
-int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
-
#endif /* _DRM_PCI_H_ */
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 26fa50c2a50e..8a152dc16ea5 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -34,31 +34,15 @@ struct drm_modeset_acquire_ctx;
/**
* struct drm_plane_state - mutable plane state
- * @plane: backpointer to the plane
- * @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
- * plane (in 16.16)
- * @src_y: upper position of visible portion of plane within
- * plane (in 16.16)
- * @src_w: width of visible portion of plane (in 16.16)
- * @src_h: height of visible portion of plane (in 16.16)
- * @alpha: opacity of the plane
- * @rotation: rotation of the plane
- * @zpos: priority of the given plane on crtc (optional)
- * Note that multiple active planes on the same crtc can have an identical
- * zpos value. The rule to solving the conflict is to compare the plane
- * object IDs; the plane with a higher ID must be stacked on top of a
- * plane with a lower ID.
- * @normalized_zpos: normalized value of zpos: unique, range from 0 to N-1
- * where N is the number of active planes for given crtc. Note that
- * the driver must set drm_mode_config.normalize_zpos or call
- * drm_atomic_normalize_zpos() to update this before it can be trusted.
- * @src: clipped source coordinates of the plane (in 16.16)
- * @dst: clipped destination coordinates of the plane
- * @state: backpointer to global drm_atomic_state
+ *
+ * Please not that the destination coordinates @crtc_x, @crtc_y, @crtc_h and
+ * @crtc_w and the source coordinates @src_x, @src_y, @src_h and @src_w are the
+ * raw coordinates provided by userspace. Drivers should use
+ * drm_atomic_helper_check_plane_state() and only use the derived rectangles in
+ * @src and @dst to program the hardware.
*/
struct drm_plane_state {
+ /** @plane: backpointer to the plane */
struct drm_plane *plane;
/**
@@ -87,7 +71,7 @@ struct drm_plane_state {
* preserved.
*
* Drivers should store any implicit fence in this from their
- * &drm_plane_helper.prepare_fb callback. See drm_gem_fb_prepare_fb()
+ * &drm_plane_helper_funcs.prepare_fb callback. See drm_gem_fb_prepare_fb()
* and drm_gem_fb_simple_display_pipe_prepare_fb() for suitable helpers.
*/
struct dma_fence *fence;
@@ -108,20 +92,60 @@ struct drm_plane_state {
*/
int32_t crtc_y;
+ /** @crtc_w: width of visible portion of plane on crtc */
+ /** @crtc_h: height of visible portion of plane on crtc */
uint32_t crtc_w, crtc_h;
- /* Source values are 16.16 fixed point */
- uint32_t src_x, src_y;
+ /**
+ * @src_x: left position of visible portion of plane within plane (in
+ * 16.16 fixed point).
+ */
+ uint32_t src_x;
+ /**
+ * @src_y: upper position of visible portion of plane within plane (in
+ * 16.16 fixed point).
+ */
+ uint32_t src_y;
+ /** @src_w: width of visible portion of plane (in 16.16) */
+ /** @src_h: height of visible portion of plane (in 16.16) */
uint32_t src_h, src_w;
- /* Plane opacity */
+ /**
+ * @alpha:
+ * Opacity of the plane with 0 as completely transparent and 0xffff as
+ * completely opaque. See drm_plane_create_alpha_property() for more
+ * details.
+ */
u16 alpha;
- /* Plane rotation */
+ /**
+ * @rotation:
+ * Rotation of the plane. See drm_plane_create_rotation_property() for
+ * more details.
+ */
unsigned int rotation;
- /* Plane zpos */
+ /**
+ * @zpos:
+ * Priority of the given plane on crtc (optional).
+ *
+ * Note that multiple active planes on the same crtc can have an
+ * identical zpos value. The rule to solving the conflict is to compare
+ * the plane object IDs; the plane with a higher ID must be stacked on
+ * top of a plane with a lower ID.
+ *
+ * See drm_plane_create_zpos_property() and
+ * drm_plane_create_zpos_immutable_property() for more details.
+ */
unsigned int zpos;
+
+ /**
+ * @normalized_zpos:
+ * Normalized value of zpos: unique, range from 0 to N-1 where N is the
+ * number of active planes for given crtc. Note that the driver must set
+ * &drm_mode_config.normalize_zpos or call drm_atomic_normalize_zpos() to
+ * update this before it can be trusted.
+ */
unsigned int normalized_zpos;
/**
@@ -138,7 +162,8 @@ struct drm_plane_state {
*/
enum drm_color_range color_range;
- /* Clipped coordinates */
+ /** @src: clipped source coordinates of the plane (in 16.16) */
+ /** @dst: clipped destination coordinates of the plane */
struct drm_rect src, dst;
/**
@@ -157,6 +182,7 @@ struct drm_plane_state {
*/
struct drm_crtc_commit *commit;
+ /** @state: backpointer to global drm_atomic_state */
struct drm_atomic_state *state;
};
@@ -288,6 +314,8 @@ struct drm_plane_funcs {
* cleaned up by calling the @atomic_destroy_state hook in this
* structure.
*
+ * This callback is mandatory for atomic drivers.
+ *
* Atomic drivers which don't subclass &struct drm_plane_state should use
* drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the
* state structure to extend it with driver-private state should use
@@ -314,6 +342,8 @@ struct drm_plane_funcs {
*
* Destroy a state duplicated with @atomic_duplicate_state and release
* or unreference all resources it references
+ *
+ * This callback is mandatory for atomic drivers.
*/
void (*atomic_destroy_state)(struct drm_plane *plane,
struct drm_plane_state *state);
@@ -431,7 +461,10 @@ struct drm_plane_funcs {
* This optional hook is used for the DRM to determine if the given
* format/modifier combination is valid for the plane. This allows the
* DRM to generate the correct format bitmask (which formats apply to
- * which modifier).
+ * which modifier), and to valdiate modifiers at atomic_check time.
+ *
+ * If not present, then any modifier in the plane's modifier
+ * list is allowed with any of the plane's formats.
*
* Returns:
*
@@ -492,30 +525,27 @@ enum drm_plane_type {
/**
* struct drm_plane - central DRM plane control structure
- * @dev: DRM device this plane belongs to
- * @head: for list management
- * @name: human readable name, can be overwritten by the driver
- * @base: base mode object
- * @possible_crtcs: pipes this plane can be bound to
- * @format_types: array of formats supported by this plane
- * @format_count: number of formats supported
- * @format_default: driver hasn't supplied supported formats for the plane
- * @modifiers: array of modifiers supported by this plane
- * @modifier_count: number of modifiers supported
- * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
- * drm_mode_set_config_internal() to implement correct refcounting.
- * @funcs: helper functions
- * @properties: property tracking for this plane
- * @type: type of plane (overlay, primary, cursor)
- * @alpha_property: alpha property for this plane
- * @zpos_property: zpos property for this plane
- * @rotation_property: rotation property for this plane
- * @helper_private: mid-layer private data
+ *
+ * Planes represent the scanout hardware of a display block. They receive their
+ * input data from a &drm_framebuffer and feed it to a &drm_crtc. Planes control
+ * the color conversion, see `Plane Composition Properties`_ for more details,
+ * and are also involved in the color conversion of input pixels, see `Color
+ * Management Properties`_ for details on that.
*/
struct drm_plane {
+ /** @dev: DRM device this plane belongs to */
struct drm_device *dev;
+
+ /**
+ * @head:
+ *
+ * List of all planes on @dev, linked from &drm_mode_config.plane_list.
+ * Invariant over the lifetime of @dev and therefore does not need
+ * locking.
+ */
struct list_head head;
+ /** @name: human readable name, can be overwritten by the driver */
char *name;
/**
@@ -529,35 +559,62 @@ struct drm_plane {
*/
struct drm_modeset_lock mutex;
+ /** @base: base mode object */
struct drm_mode_object base;
+ /**
+ * @possible_crtcs: pipes this plane can be bound to constructed from
+ * drm_crtc_mask()
+ */
uint32_t possible_crtcs;
+ /** @format_types: array of formats supported by this plane */
uint32_t *format_types;
+ /** @format_count: Size of the array pointed at by @format_types. */
unsigned int format_count;
+ /**
+ * @format_default: driver hasn't supplied supported formats for the
+ * plane. Used by the drm_plane_init compatibility wrapper only.
+ */
bool format_default;
+ /** @modifiers: array of modifiers supported by this plane */
uint64_t *modifiers;
+ /** @modifier_count: Size of the array pointed at by @modifier_count. */
unsigned int modifier_count;
/**
- * @crtc: Currently bound CRTC, only really meaningful for non-atomic
- * drivers. Atomic drivers should instead check &drm_plane_state.crtc.
+ * @crtc:
+ *
+ * Currently bound CRTC, only meaningful for non-atomic drivers. For
+ * atomic drivers this is forced to be NULL, atomic drivers should
+ * instead check &drm_plane_state.crtc.
*/
struct drm_crtc *crtc;
/**
- * @fb: Currently bound framebuffer, only really meaningful for
- * non-atomic drivers. Atomic drivers should instead check
- * &drm_plane_state.fb.
+ * @fb:
+ *
+ * Currently bound framebuffer, only meaningful for non-atomic drivers.
+ * For atomic drivers this is forced to be NULL, atomic drivers should
+ * instead check &drm_plane_state.fb.
*/
struct drm_framebuffer *fb;
+ /**
+ * @old_fb:
+ *
+ * Temporary tracking of the old fb while a modeset is ongoing. Only
+ * used by non-atomic drivers, forced to be NULL for atomic drivers.
+ */
struct drm_framebuffer *old_fb;
+ /** @funcs: plane control functions */
const struct drm_plane_funcs *funcs;
+ /** @properties: property tracking for this plane */
struct drm_object_properties properties;
+ /** @type: Type of plane, see &enum drm_plane_type for details. */
enum drm_plane_type type;
/**
@@ -566,6 +623,7 @@ struct drm_plane {
*/
unsigned index;
+ /** @helper_private: mid-layer private data */
const struct drm_plane_helper_funcs *helper_private;
/**
@@ -583,8 +641,23 @@ struct drm_plane {
*/
struct drm_plane_state *state;
+ /**
+ * @alpha_property:
+ * Optional alpha property for this plane. See
+ * drm_plane_create_alpha_property().
+ */
struct drm_property *alpha_property;
+ /**
+ * @zpos_property:
+ * Optional zpos property for this plane. See
+ * drm_plane_create_zpos_property().
+ */
struct drm_property *zpos_property;
+ /**
+ * @rotation_property:
+ * Optional rotation property for this plane. See
+ * drm_plane_create_rotation_property().
+ */
struct drm_property *rotation_property;
/**
@@ -632,10 +705,20 @@ void drm_plane_cleanup(struct drm_plane *plane);
* Given a registered plane, return the index of that plane within a DRM
* device's list of planes.
*/
-static inline unsigned int drm_plane_index(struct drm_plane *plane)
+static inline unsigned int drm_plane_index(const struct drm_plane *plane)
{
return plane->index;
}
+
+/**
+ * drm_plane_mask - find the mask of a registered plane
+ * @plane: plane to find mask for
+ */
+static inline u32 drm_plane_mask(const struct drm_plane *plane)
+{
+ return 1 << drm_plane_index(plane);
+}
+
struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
void drm_plane_force_disable(struct drm_plane *plane);
@@ -671,7 +754,7 @@ static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
*/
#define drm_for_each_plane_mask(plane, dev, plane_mask) \
list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
- for_each_if ((plane_mask) & (1 << drm_plane_index(plane)))
+ for_each_if ((plane_mask) & drm_plane_mask(plane))
/**
* drm_for_each_legacy_plane - iterate over all planes for legacy userspace
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
index 28d7ce620729..26cee2934781 100644
--- a/include/drm/drm_plane_helper.h
+++ b/include/drm/drm_plane_helper.h
@@ -67,8 +67,10 @@ int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h);
-int drm_plane_helper_disable(struct drm_plane *plane);
+ uint32_t src_w, uint32_t src_h,
+ struct drm_modeset_acquire_ctx *ctx);
+int drm_plane_helper_disable(struct drm_plane *plane,
+ struct drm_modeset_acquire_ctx *ctx);
/* For use by drm_crtc_helper.c */
int drm_plane_helper_commit(struct drm_plane *plane,
diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
index 4d5f5d6cf6a6..d716d653b096 100644
--- a/include/drm/drm_prime.h
+++ b/include/drm/drm_prime.h
@@ -82,7 +82,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
struct dma_buf_export_info *exp_info);
void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
-int drm_gem_map_attach(struct dma_buf *dma_buf, struct device *target_dev,
+int drm_gem_map_attach(struct dma_buf *dma_buf,
struct dma_buf_attachment *attach);
void drm_gem_map_detach(struct dma_buf *dma_buf,
struct dma_buf_attachment *attach);
@@ -93,10 +93,6 @@ void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir);
void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf);
void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr);
-void *drm_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf,
- unsigned long page_num);
-void drm_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf,
- unsigned long page_num, void *addr);
void *drm_gem_dmabuf_kmap(struct dma_buf *dma_buf, unsigned long page_num);
void drm_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_num,
void *addr);
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index e1a46e9991cc..f3e6eed3e79c 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -69,16 +69,21 @@
struct drm_printer {
/* private: */
void (*printfn)(struct drm_printer *p, struct va_format *vaf);
+ void (*puts)(struct drm_printer *p, const char *str);
void *arg;
const char *prefix;
};
+void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf);
+void __drm_puts_coredump(struct drm_printer *p, const char *str);
void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
+void __drm_puts_seq_file(struct drm_printer *p, const char *str);
void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
__printf(2, 3)
void drm_printf(struct drm_printer *p, const char *f, ...);
+void drm_puts(struct drm_printer *p, const char *str);
__printf(2, 0)
/**
@@ -105,6 +110,71 @@ drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va)
drm_printf((printer), "%.*s" fmt, (indent), "\t\t\t\t\tX", ##__VA_ARGS__)
/**
+ * struct drm_print_iterator - local struct used with drm_printer_coredump
+ * @data: Pointer to the devcoredump output buffer
+ * @start: The offset within the buffer to start writing
+ * @remain: The number of bytes to write for this iteration
+ */
+struct drm_print_iterator {
+ void *data;
+ ssize_t start;
+ ssize_t remain;
+ /* private: */
+ ssize_t offset;
+};
+
+/**
+ * drm_coredump_printer - construct a &drm_printer that can output to a buffer
+ * from the read function for devcoredump
+ * @iter: A pointer to a struct drm_print_iterator for the read instance
+ *
+ * This wrapper extends drm_printf() to work with a dev_coredumpm() callback
+ * function. The passed in drm_print_iterator struct contains the buffer
+ * pointer, size and offset as passed in from devcoredump.
+ *
+ * For example::
+ *
+ * void coredump_read(char *buffer, loff_t offset, size_t count,
+ * void *data, size_t datalen)
+ * {
+ * struct drm_print_iterator iter;
+ * struct drm_printer p;
+ *
+ * iter.data = buffer;
+ * iter.start = offset;
+ * iter.remain = count;
+ *
+ * p = drm_coredump_printer(&iter);
+ *
+ * drm_printf(p, "foo=%d\n", foo);
+ * }
+ *
+ * void makecoredump(...)
+ * {
+ * ...
+ * dev_coredumpm(dev, THIS_MODULE, data, 0, GFP_KERNEL,
+ * coredump_read, ...)
+ * }
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer
+drm_coredump_printer(struct drm_print_iterator *iter)
+{
+ struct drm_printer p = {
+ .printfn = __drm_printfn_coredump,
+ .puts = __drm_puts_coredump,
+ .arg = iter,
+ };
+
+ /* Set the internal offset of the iterator to zero */
+ iter->offset = 0;
+
+ return p;
+}
+
+/**
* drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file
* @f: the &struct seq_file to output to
*
@@ -115,6 +185,7 @@ static inline struct drm_printer drm_seq_file_printer(struct seq_file *f)
{
struct drm_printer p = {
.printfn = __drm_printfn_seq_file,
+ .puts = __drm_puts_seq_file,
.arg = f,
};
return p;
@@ -195,6 +266,7 @@ static inline struct drm_printer drm_debug_printer(const char *prefix)
#define DRM_UT_VBL 0x20
#define DRM_UT_STATE 0x40
#define DRM_UT_LEASE 0x80
+#define DRM_UT_DP 0x100
__printf(3, 4)
void drm_dev_printk(const struct device *dev, const char *level,
@@ -307,6 +379,11 @@ void drm_err(const char *format, ...);
#define DRM_DEBUG_LEASE(fmt, ...) \
drm_dbg(DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+#define DRM_DEV_DEBUG_DP(dev, fmt, ...) \
+ drm_dev_dbg(dev, DRM_UT_DP, fmt, ## __VA_ARGS__)
+#define DRM_DEBUG_DP(dev, fmt, ...) \
+ drm_dbg(DRM_UT_DP, fmt, ## __VA_ARGS__)
+
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, category, fmt, ...) \
({ \
static DEFINE_RATELIMIT_STATE(_rs, \
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index 1d5c0b2a8956..c030f6ccab99 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -147,10 +147,10 @@ struct drm_property {
* properties are not exposed to legacy userspace.
*
* DRM_MODE_PROP_IMMUTABLE
- * Set for properties where userspace cannot be changed by
+ * Set for properties whose values cannot be changed by
* userspace. The kernel is allowed to update the value of these
* properties. This is generally used to expose probe state to
- * usersapce, e.g. the EDID, or the connector path property on DP
+ * userspace, e.g. the EDID, or the connector path property on DP
* MST sinks.
*/
uint32_t flags;
diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h
index 8758df94e9a0..c7987daeaed0 100644
--- a/include/drm/drm_vma_manager.h
+++ b/include/drm/drm_vma_manager.h
@@ -41,6 +41,7 @@ struct drm_vma_offset_node {
rwlock_t vm_lock;
struct drm_mm_node vm_node;
struct rb_root vm_files;
+ bool readonly:1;
};
struct drm_vma_offset_manager {
diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h
new file mode 100644
index 000000000000..23df9d463003
--- /dev/null
+++ b/include/drm/drm_writeback.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
+ * Author: Brian Starkey <brian.starkey@arm.com>
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ */
+
+#ifndef __DRM_WRITEBACK_H__
+#define __DRM_WRITEBACK_H__
+#include <drm/drm_connector.h>
+#include <drm/drm_encoder.h>
+#include <linux/workqueue.h>
+
+struct drm_writeback_connector {
+ struct drm_connector base;
+
+ /**
+ * @encoder: Internal encoder used by the connector to fulfill
+ * the DRM framework requirements. The users of the
+ * @drm_writeback_connector control the behaviour of the @encoder
+ * by passing the @enc_funcs parameter to drm_writeback_connector_init()
+ * function.
+ */
+ struct drm_encoder encoder;
+
+ /**
+ * @pixel_formats_blob_ptr:
+ *
+ * DRM blob property data for the pixel formats list on writeback
+ * connectors
+ * See also drm_writeback_connector_init()
+ */
+ struct drm_property_blob *pixel_formats_blob_ptr;
+
+ /** @job_lock: Protects job_queue */
+ spinlock_t job_lock;
+
+ /**
+ * @job_queue:
+ *
+ * Holds a list of a connector's writeback jobs; the last item is the
+ * most recent. The first item may be either waiting for the hardware
+ * to begin writing, or currently being written.
+ *
+ * See also: drm_writeback_queue_job() and
+ * drm_writeback_signal_completion()
+ */
+ struct list_head job_queue;
+
+ /**
+ * @fence_context:
+ *
+ * timeline context used for fence operations.
+ */
+ unsigned int fence_context;
+ /**
+ * @fence_lock:
+ *
+ * spinlock to protect the fences in the fence_context.
+ */
+ spinlock_t fence_lock;
+ /**
+ * @fence_seqno:
+ *
+ * Seqno variable used as monotonic counter for the fences
+ * created on the connector's timeline.
+ */
+ unsigned long fence_seqno;
+ /**
+ * @timeline_name:
+ *
+ * The name of the connector's fence timeline.
+ */
+ char timeline_name[32];
+};
+
+struct drm_writeback_job {
+ /**
+ * @cleanup_work:
+ *
+ * Used to allow drm_writeback_signal_completion to defer dropping the
+ * framebuffer reference to a workqueue
+ */
+ struct work_struct cleanup_work;
+
+ /**
+ * @list_entry:
+ *
+ * List item for the writeback connector's @job_queue
+ */
+ struct list_head list_entry;
+
+ /**
+ * @fb:
+ *
+ * Framebuffer to be written to by the writeback connector. Do not set
+ * directly, use drm_atomic_set_writeback_fb_for_connector()
+ */
+ struct drm_framebuffer *fb;
+
+ /**
+ * @out_fence:
+ *
+ * Fence which will signal once the writeback has completed
+ */
+ struct dma_fence *out_fence;
+};
+
+static inline struct drm_writeback_connector *
+drm_connector_to_writeback(struct drm_connector *connector)
+{
+ return container_of(connector, struct drm_writeback_connector, base);
+}
+
+int drm_writeback_connector_init(struct drm_device *dev,
+ struct drm_writeback_connector *wb_connector,
+ const struct drm_connector_funcs *con_funcs,
+ const struct drm_encoder_helper_funcs *enc_helper_funcs,
+ const u32 *formats, int n_formats);
+
+void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector,
+ struct drm_writeback_job *job);
+
+void drm_writeback_cleanup_job(struct drm_writeback_job *job);
+
+void
+drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector,
+ int status);
+
+struct dma_fence *
+drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector);
+#endif
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index dec655894d08..21c648b0b2a1 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -27,6 +27,8 @@
#include <drm/spsc_queue.h>
#include <linux/dma-fence.h>
+#define MAX_WAIT_SCHED_ENTITY_Q_EMPTY msecs_to_jiffies(1000)
+
struct drm_gpu_scheduler;
struct drm_sched_rq;
@@ -43,18 +45,37 @@ enum drm_sched_priority {
};
/**
- * drm_sched_entity - A wrapper around a job queue (typically attached
- * to the DRM file_priv).
+ * struct drm_sched_entity - A wrapper around a job queue (typically
+ * attached to the DRM file_priv).
+ *
+ * @list: used to append this struct to the list of entities in the
+ * runqueue.
+ * @rq: runqueue to which this entity belongs.
+ * @rq_lock: lock to modify the runqueue to which this entity belongs.
+ * @job_queue: the list of jobs of this entity.
+ * @fence_seq: a linearly increasing seqno incremented with each
+ * new &drm_sched_fence which is part of the entity.
+ * @fence_context: a unique context for all the fences which belong
+ * to this entity.
+ * The &drm_sched_fence.scheduled uses the
+ * fence_context but &drm_sched_fence.finished uses
+ * fence_context + 1.
+ * @dependency: the dependency fence of the job which is on the top
+ * of the job queue.
+ * @cb: callback for the dependency fence above.
+ * @guilty: points to ctx's guilty.
+ * @fini_status: contains the exit status in case the process was signalled.
+ * @last_scheduled: points to the finished fence of the last scheduled job.
+ * @last_user: last group leader pushing a job into the entity.
*
* Entities will emit jobs in order to their corresponding hardware
* ring, and the scheduler will alternate between entities based on
* scheduling policy.
-*/
+ */
struct drm_sched_entity {
struct list_head list;
struct drm_sched_rq *rq;
spinlock_t rq_lock;
- struct drm_gpu_scheduler *sched;
struct spsc_queue job_queue;
@@ -63,47 +84,98 @@ struct drm_sched_entity {
struct dma_fence *dependency;
struct dma_fence_cb cb;
- atomic_t *guilty; /* points to ctx's guilty */
- int fini_status;
- struct dma_fence *last_scheduled;
+ atomic_t *guilty;
+ struct dma_fence *last_scheduled;
+ struct task_struct *last_user;
};
/**
+ * struct drm_sched_rq - queue of entities to be scheduled.
+ *
+ * @lock: to modify the entities list.
+ * @sched: the scheduler to which this rq belongs to.
+ * @entities: list of the entities to be scheduled.
+ * @current_entity: the entity which is to be scheduled.
+ *
* Run queue is a set of entities scheduling command submissions for
* one specific ring. It implements the scheduling policy that selects
* the next entity to emit commands from.
-*/
+ */
struct drm_sched_rq {
spinlock_t lock;
+ struct drm_gpu_scheduler *sched;
struct list_head entities;
struct drm_sched_entity *current_entity;
};
+/**
+ * struct drm_sched_fence - fences corresponding to the scheduling of a job.
+ */
struct drm_sched_fence {
+ /**
+ * @scheduled: this fence is what will be signaled by the scheduler
+ * when the job is scheduled.
+ */
struct dma_fence scheduled;
- /* This fence is what will be signaled by the scheduler when
- * the job is completed.
- *
- * When setting up an out fence for the job, you should use
- * this, since it's available immediately upon
- * drm_sched_job_init(), and the fence returned by the driver
- * from run_job() won't be created until the dependencies have
- * resolved.
- */
+ /**
+ * @finished: this fence is what will be signaled by the scheduler
+ * when the job is completed.
+ *
+ * When setting up an out fence for the job, you should use
+ * this, since it's available immediately upon
+ * drm_sched_job_init(), and the fence returned by the driver
+ * from run_job() won't be created until the dependencies have
+ * resolved.
+ */
struct dma_fence finished;
+ /**
+ * @cb: the callback for the parent fence below.
+ */
struct dma_fence_cb cb;
+ /**
+ * @parent: the fence returned by &drm_sched_backend_ops.run_job
+ * when scheduling the job on hardware. We signal the
+ * &drm_sched_fence.finished fence once parent is signalled.
+ */
struct dma_fence *parent;
+ /**
+ * @sched: the scheduler instance to which the job having this struct
+ * belongs to.
+ */
struct drm_gpu_scheduler *sched;
+ /**
+ * @lock: the lock used by the scheduled and the finished fences.
+ */
spinlock_t lock;
+ /**
+ * @owner: job owner for debugging
+ */
void *owner;
};
struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f);
/**
- * drm_sched_job - A job to be run by an entity.
+ * struct drm_sched_job - A job to be run by an entity.
+ *
+ * @queue_node: used to append this struct to the queue of jobs in an entity.
+ * @sched: the scheduler instance on which this job is scheduled.
+ * @s_fence: contains the fences for the scheduling of job.
+ * @finish_cb: the callback for the finished fence.
+ * @finish_work: schedules the function @drm_sched_job_finish once the job has
+ * finished to remove the job from the
+ * @drm_gpu_scheduler.ring_mirror_list.
+ * @node: used to append this struct to the @drm_gpu_scheduler.ring_mirror_list.
+ * @work_tdr: schedules a delayed call to @drm_sched_job_timedout after the timeout
+ * interval is over.
+ * @id: a unique id assigned to each job scheduled on the scheduler.
+ * @karma: increment on every hang caused by this job. If this exceeds the hang
+ * limit of the scheduler then the job is marked guilty and will not
+ * be scheduled further.
+ * @s_priority: the priority of the job.
+ * @entity: the entity to which this job belongs.
*
* A job is created by the driver using drm_sched_job_init(), and
* should call drm_sched_entity_push_job() once it wants the scheduler
@@ -130,38 +202,64 @@ static inline bool drm_sched_invalidate_job(struct drm_sched_job *s_job,
}
/**
+ * struct drm_sched_backend_ops
+ *
* Define the backend operations called by the scheduler,
- * these functions should be implemented in driver side
-*/
+ * these functions should be implemented in driver side.
+ */
struct drm_sched_backend_ops {
- /* Called when the scheduler is considering scheduling this
- * job next, to get another struct dma_fence for this job to
+ /**
+ * @dependency: Called when the scheduler is considering scheduling
+ * this job next, to get another struct dma_fence for this job to
* block on. Once it returns NULL, run_job() may be called.
*/
struct dma_fence *(*dependency)(struct drm_sched_job *sched_job,
struct drm_sched_entity *s_entity);
- /* Called to execute the job once all of the dependencies have
- * been resolved. This may be called multiple times, if
+ /**
+ * @run_job: Called to execute the job once all of the dependencies
+ * have been resolved. This may be called multiple times, if
* timedout_job() has happened and drm_sched_job_recovery()
* decides to try it again.
*/
struct dma_fence *(*run_job)(struct drm_sched_job *sched_job);
- /* Called when a job has taken too long to execute, to trigger
- * GPU recovery.
+ /**
+ * @timedout_job: Called when a job has taken too long to execute,
+ * to trigger GPU recovery.
*/
void (*timedout_job)(struct drm_sched_job *sched_job);
- /* Called once the job's finished fence has been signaled and
- * it's time to clean it up.
+ /**
+ * @free_job: Called once the job's finished fence has been signaled
+ * and it's time to clean it up.
*/
void (*free_job)(struct drm_sched_job *sched_job);
};
/**
- * One scheduler is implemented for each hardware ring
-*/
+ * struct drm_gpu_scheduler
+ *
+ * @ops: backend operations provided by the driver.
+ * @hw_submission_limit: the max size of the hardware queue.
+ * @timeout: the time after which a job is removed from the scheduler.
+ * @name: name of the ring for which this scheduler is being used.
+ * @sched_rq: priority wise array of run queues.
+ * @wake_up_worker: the wait queue on which the scheduler sleeps until a job
+ * is ready to be scheduled.
+ * @job_scheduled: once @drm_sched_entity_do_release is called the scheduler
+ * waits on this wait queue until all the scheduled jobs are
+ * finished.
+ * @hw_rq_count: the number of jobs currently in the hardware queue.
+ * @job_id_count: used to assign unique id to the each job.
+ * @thread: the kthread on which the scheduler which run.
+ * @ring_mirror_list: the list of jobs which are currently in the job queue.
+ * @job_list_lock: lock to protect the ring_mirror_list.
+ * @hang_limit: once the hangs by a job crosses this limit then it is marked
+ * guilty and it will be considered for scheduling further.
+ *
+ * One scheduler is implemented for each hardware ring.
+ */
struct drm_gpu_scheduler {
const struct drm_sched_backend_ops *ops;
uint32_t hw_submission_limit;
@@ -184,16 +282,13 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
const char *name);
void drm_sched_fini(struct drm_gpu_scheduler *sched);
-int drm_sched_entity_init(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity,
- struct drm_sched_rq *rq,
+int drm_sched_entity_init(struct drm_sched_entity *entity,
+ struct drm_sched_rq **rq_list,
+ unsigned int num_rq_list,
atomic_t *guilty);
-void drm_sched_entity_do_release(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity);
-void drm_sched_entity_cleanup(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity);
-void drm_sched_entity_fini(struct drm_gpu_scheduler *sched,
- struct drm_sched_entity *entity);
+long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout);
+void drm_sched_entity_fini(struct drm_sched_entity *entity);
+void drm_sched_entity_destroy(struct drm_sched_entity *entity);
void drm_sched_entity_push_job(struct drm_sched_job *sched_job,
struct drm_sched_entity *entity);
void drm_sched_entity_set_rq(struct drm_sched_entity *entity,
@@ -204,7 +299,6 @@ struct drm_sched_fence *drm_sched_fence_create(
void drm_sched_fence_scheduled(struct drm_sched_fence *fence);
void drm_sched_fence_finished(struct drm_sched_fence *fence);
int drm_sched_job_init(struct drm_sched_job *job,
- struct drm_gpu_scheduler *sched,
struct drm_sched_entity *entity,
void *owner);
void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched,
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
index 346b1f5cb180..fca22d463e1b 100644
--- a/include/drm/i915_component.h
+++ b/include/drm/i915_component.h
@@ -24,101 +24,26 @@
#ifndef _I915_COMPONENT_H_
#define _I915_COMPONENT_H_
+#include "drm_audio_component.h"
+
/* MAX_PORT is the number of port
* It must be sync with I915_MAX_PORTS defined i915_drv.h
*/
#define MAX_PORTS 6
/**
- * struct i915_audio_component_ops - Ops implemented by i915 driver, called by hda driver
- */
-struct i915_audio_component_ops {
- /**
- * @owner: i915 module
- */
- struct module *owner;
- /**
- * @get_power: get the POWER_DOMAIN_AUDIO power well
- *
- * Request the power well to be turned on.
- */
- void (*get_power)(struct device *);
- /**
- * @put_power: put the POWER_DOMAIN_AUDIO power well
- *
- * Allow the power well to be turned off.
- */
- void (*put_power)(struct device *);
- /**
- * @codec_wake_override: Enable/disable codec wake signal
- */
- void (*codec_wake_override)(struct device *, bool enable);
- /**
- * @get_cdclk_freq: Get the Core Display Clock in kHz
- */
- int (*get_cdclk_freq)(struct device *);
- /**
- * @sync_audio_rate: set n/cts based on the sample rate
- *
- * 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 pipe, int rate);
- /**
- * @get_eld: fill the audio state and ELD bytes for the given port
- *
- * Called from audio driver to get the HDMI/DP audio state of the given
- * digital port, and also fetch ELD bytes to the given pointer.
- *
- * It returns the byte size of the original ELD (not the actually
- * copied size), zero for an invalid ELD, or a negative error code.
- *
- * 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, int pipe, bool *enabled,
- unsigned char *buf, int max_bytes);
-};
-
-/**
- * struct i915_audio_component_audio_ops - Ops implemented by hda driver, called by i915 driver
- */
-struct i915_audio_component_audio_ops {
- /**
- * @audio_ptr: Pointer to be used in call to pin_eld_notify
- */
- void *audio_ptr;
- /**
- * @pin_eld_notify: Notify the HDA driver that pin sense and/or ELD information has changed
- *
- * Called when the i915 driver has set up audio pipeline or has just
- * begun to tear it down. This allows the HDA driver to update its
- * status accordingly (even when the HDA controller is in power save
- * mode).
- */
- void (*pin_eld_notify)(void *audio_ptr, int port, int pipe);
-};
-
-/**
* struct i915_audio_component - Used for direct communication between i915 and hda drivers
*/
struct i915_audio_component {
/**
- * @dev: i915 device, used as parameter for ops
+ * @base: the drm_audio_component base class
*/
- struct device *dev;
+ struct drm_audio_component base;
+
/**
* @aud_sample_rate: the array of audio sample rate per port
*/
int aud_sample_rate[MAX_PORTS];
- /**
- * @ops: Ops implemented by i915 driver, called by hda driver
- */
- const struct i915_audio_component_ops *ops;
- /**
- * @audio_ops: Ops implemented by hda driver, called by i915 driver
- */
- const struct i915_audio_component_audio_ops *audio_ops;
};
#endif /* _I915_COMPONENT_H_ */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index c9e5a6621b95..c44703f471b3 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -95,7 +95,9 @@ extern struct resource intel_graphics_stolen_res;
#define I845_TSEG_SIZE_512K (2 << 1)
#define I845_TSEG_SIZE_1M (3 << 1)
-#define INTEL_BSM 0x5c
+#define INTEL_BSM 0x5c
+#define INTEL_GEN11_BSM_DW0 0xc0
+#define INTEL_GEN11_BSM_DW1 0xc4
#define INTEL_BSM_MASK (-(1u << 20))
#endif /* _I915_DRM_H_ */
diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h
index bab70ff6e78b..fbf5cfc9b352 100644
--- a/include/drm/i915_pciids.h
+++ b/include/drm/i915_pciids.h
@@ -349,7 +349,6 @@
#define INTEL_KBL_GT2_IDS(info) \
INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */ \
INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */ \
- INTEL_VGA_DEVICE(0x591C, info), /* ULX GT2 */ \
INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */ \
INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */ \
INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */ \
@@ -365,11 +364,17 @@
#define INTEL_KBL_GT4_IDS(info) \
INTEL_VGA_DEVICE(0x593B, info) /* Halo GT4 */
+/* AML/KBL Y GT2 */
+#define INTEL_AML_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x591C, info), /* ULX GT2 */ \
+ INTEL_VGA_DEVICE(0x87C0, info) /* ULX GT2 */
+
#define INTEL_KBL_IDS(info) \
INTEL_KBL_GT1_IDS(info), \
INTEL_KBL_GT2_IDS(info), \
INTEL_KBL_GT3_IDS(info), \
- INTEL_KBL_GT4_IDS(info)
+ INTEL_KBL_GT4_IDS(info), \
+ INTEL_AML_GT2_IDS(info)
/* CFL S */
#define INTEL_CFL_S_GT1_IDS(info) \
@@ -388,32 +393,40 @@
INTEL_VGA_DEVICE(0x3E9B, info), /* Halo GT2 */ \
INTEL_VGA_DEVICE(0x3E94, info) /* Halo GT2 */
-/* CFL U GT1 */
-#define INTEL_CFL_U_GT1_IDS(info) \
- INTEL_VGA_DEVICE(0x3EA1, info), \
- INTEL_VGA_DEVICE(0x3EA4, info)
-
/* CFL U GT2 */
#define INTEL_CFL_U_GT2_IDS(info) \
- INTEL_VGA_DEVICE(0x3EA0, info), \
- INTEL_VGA_DEVICE(0x3EA3, info), \
INTEL_VGA_DEVICE(0x3EA9, info)
/* CFL U GT3 */
#define INTEL_CFL_U_GT3_IDS(info) \
- INTEL_VGA_DEVICE(0x3EA2, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x3EA5, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x3EA6, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x3EA7, info), /* ULT GT3 */ \
INTEL_VGA_DEVICE(0x3EA8, info) /* ULT GT3 */
+/* WHL/CFL U GT1 */
+#define INTEL_WHL_U_GT1_IDS(info) \
+ INTEL_VGA_DEVICE(0x3EA1, info)
+
+/* WHL/CFL U GT2 */
+#define INTEL_WHL_U_GT2_IDS(info) \
+ INTEL_VGA_DEVICE(0x3EA0, info)
+
+/* WHL/CFL U GT3 */
+#define INTEL_WHL_U_GT3_IDS(info) \
+ INTEL_VGA_DEVICE(0x3EA2, info), \
+ INTEL_VGA_DEVICE(0x3EA3, info), \
+ INTEL_VGA_DEVICE(0x3EA4, info)
+
#define INTEL_CFL_IDS(info) \
INTEL_CFL_S_GT1_IDS(info), \
INTEL_CFL_S_GT2_IDS(info), \
INTEL_CFL_H_GT2_IDS(info), \
- INTEL_CFL_U_GT1_IDS(info), \
INTEL_CFL_U_GT2_IDS(info), \
- INTEL_CFL_U_GT3_IDS(info)
+ INTEL_CFL_U_GT3_IDS(info), \
+ INTEL_WHL_U_GT1_IDS(info), \
+ INTEL_WHL_U_GT2_IDS(info), \
+ INTEL_WHL_U_GT3_IDS(info)
/* CNL */
#define INTEL_CNL_IDS(info) \
diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h
index 56e4a916b5e8..fe9827d0ca8a 100644
--- a/include/drm/tinydrm/tinydrm.h
+++ b/include/drm/tinydrm/tinydrm.h
@@ -16,16 +16,31 @@
/**
* struct tinydrm_device - tinydrm device
- * @drm: DRM device
- * @pipe: Display pipe structure
- * @dirty_lock: Serializes framebuffer flushing
- * @fb_funcs: Framebuffer functions used when creating framebuffers
*/
struct tinydrm_device {
+ /**
+ * @drm: DRM device
+ */
struct drm_device *drm;
+
+ /**
+ * @pipe: Display pipe structure
+ */
struct drm_simple_display_pipe pipe;
+
+ /**
+ * @dirty_lock: Serializes framebuffer flushing
+ */
struct mutex dirty_lock;
+
+ /**
+ * @fb_funcs: Framebuffer functions used when creating framebuffers
+ */
const struct drm_framebuffer_funcs *fb_funcs;
+
+ /**
+ * @fb_dirty: Framebuffer dirty callback
+ */
int (*fb_dirty)(struct drm_framebuffer *framebuffer,
struct drm_file *file_priv, unsigned flags,
unsigned color, struct drm_clip_rect *clips,
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index c67977aa1a0e..a01ba2032f0e 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -284,17 +284,29 @@ struct ttm_operation_ctx {
#define TTM_OPT_FLAG_FORCE_ALLOC 0x2
/**
+ * ttm_bo_get - reference a struct ttm_buffer_object
+ *
+ * @bo: The buffer object.
+ */
+static inline void ttm_bo_get(struct ttm_buffer_object *bo)
+{
+ kref_get(&bo->kref);
+}
+
+/**
* ttm_bo_reference - reference a struct ttm_buffer_object
*
* @bo: The buffer object.
*
* Returns a refcounted pointer to a buffer object.
+ *
+ * This function is deprecated. Use @ttm_bo_get instead.
*/
static inline struct ttm_buffer_object *
ttm_bo_reference(struct ttm_buffer_object *bo)
{
- kref_get(&bo->kref);
+ ttm_bo_get(bo);
return bo;
}
@@ -346,11 +358,22 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
struct ttm_operation_ctx *ctx);
/**
+ * ttm_bo_put
+ *
+ * @bo: The buffer object.
+ *
+ * Unreference a buffer object.
+ */
+void ttm_bo_put(struct ttm_buffer_object *bo);
+
+/**
* ttm_bo_unref
*
* @bo: The buffer object.
*
* Unreference and clear a pointer to a buffer object.
+ *
+ * This function is deprecated. Use @ttm_bo_put instead.
*/
void ttm_bo_unref(struct ttm_buffer_object **bo);
diff --git a/include/drm/ttm/ttm_set_memory.h b/include/drm/ttm/ttm_set_memory.h
new file mode 100644
index 000000000000..7c492b49e38c
--- /dev/null
+++ b/include/drm/ttm/ttm_set_memory.h
@@ -0,0 +1,150 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2018 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Huang Rui <ray.huang@amd.com>
+ */
+
+#ifndef TTM_SET_MEMORY
+#define TTM_SET_MEMORY
+
+#include <linux/mm.h>
+
+#ifdef CONFIG_X86
+
+#include <asm/set_memory.h>
+
+static inline int ttm_set_pages_array_wb(struct page **pages, int addrinarray)
+{
+ return set_pages_array_wb(pages, addrinarray);
+}
+
+static inline int ttm_set_pages_array_wc(struct page **pages, int addrinarray)
+{
+ return set_pages_array_wc(pages, addrinarray);
+}
+
+static inline int ttm_set_pages_array_uc(struct page **pages, int addrinarray)
+{
+ return set_pages_array_uc(pages, addrinarray);
+}
+
+static inline int ttm_set_pages_wb(struct page *page, int numpages)
+{
+ return set_pages_wb(page, numpages);
+}
+
+static inline int ttm_set_pages_wc(struct page *page, int numpages)
+{
+ unsigned long addr = (unsigned long)page_address(page);
+
+ return set_memory_wc(addr, numpages);
+}
+
+static inline int ttm_set_pages_uc(struct page *page, int numpages)
+{
+ return set_pages_uc(page, numpages);
+}
+
+#else /* for CONFIG_X86 */
+
+#if IS_ENABLED(CONFIG_AGP)
+
+#include <asm/agp.h>
+
+static inline int ttm_set_pages_array_wb(struct page **pages, int addrinarray)
+{
+ int i;
+
+ for (i = 0; i < addrinarray; i++)
+ unmap_page_from_agp(pages[i]);
+ return 0;
+}
+
+static inline int ttm_set_pages_array_wc(struct page **pages, int addrinarray)
+{
+ int i;
+
+ for (i = 0; i < addrinarray; i++)
+ map_page_into_agp(pages[i]);
+ return 0;
+}
+
+static inline int ttm_set_pages_array_uc(struct page **pages, int addrinarray)
+{
+ int i;
+
+ for (i = 0; i < addrinarray; i++)
+ map_page_into_agp(pages[i]);
+ return 0;
+}
+
+static inline int ttm_set_pages_wb(struct page *page, int numpages)
+{
+ int i;
+
+ for (i = 0; i < numpages; i++)
+ unmap_page_from_agp(page++);
+ return 0;
+}
+
+#else /* for CONFIG_AGP */
+
+static inline int ttm_set_pages_array_wb(struct page **pages, int addrinarray)
+{
+ return 0;
+}
+
+static inline int ttm_set_pages_array_wc(struct page **pages, int addrinarray)
+{
+ return 0;
+}
+
+static inline int ttm_set_pages_array_uc(struct page **pages, int addrinarray)
+{
+ return 0;
+}
+
+static inline int ttm_set_pages_wb(struct page *page, int numpages)
+{
+ return 0;
+}
+
+#endif /* for CONFIG_AGP */
+
+static inline int ttm_set_pages_wc(struct page *page, int numpages)
+{
+ return 0;
+}
+
+static inline int ttm_set_pages_uc(struct page *page, int numpages)
+{
+ return 0;
+}
+
+#endif /* for CONFIG_X86 */
+
+#endif