Commit d50ce2ce authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-next-2017-12-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for 4.16:

Core Changes:
- mostly doc updates and some fbdev improvements

* tag 'drm-misc-next-2017-12-21' of git://anongit.freedesktop.org/drm/drm-misc:
  drm/framebuffer: Print task that allocated the fb in debug info.
  drm/fb-helper: Add drm_fb_helper_defio_init()
  drm/fb-helper: Update DOC with new helpers
  drm/docs: Add todo entry for drm_fb_helper_fbdev_setup()
  drm/fb-helper: Add drm_fb_helper_fbdev_setup/teardown()
  drm/fb-helper: Set/clear dev->fb_helper in dummy init/fini
  drm/stm: ltdc: Remove unnecessary platform_get_resource() error check
  drm/stm: dsi: Remove unnecessary platform_get_resource() error check
  drm/doc: Move legacy kms helpers to the very end
  drm/atomic: document how to handle driver private objects
  drm/syncobj: some kerneldoc polish
  drm/print: Unconfuse kerneldoc
  drm/edid: kerneldoc for is_hdmi2_sink
parents df2869ab 8d44e9e6
...@@ -74,15 +74,6 @@ Helper Functions Reference ...@@ -74,15 +74,6 @@ Helper Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
:export: :export:
Legacy CRTC/Modeset Helper Functions Reference
==============================================
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
:export:
Simple KMS Helper Reference Simple KMS Helper Reference
=========================== ===========================
...@@ -282,15 +273,6 @@ Flip-work Helper Reference ...@@ -282,15 +273,6 @@ Flip-work Helper Reference
.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c .. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
:export: :export:
Plane Helper Reference
======================
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
:export:
Auxiliary Modeset Helpers Auxiliary Modeset Helpers
========================= =========================
...@@ -308,3 +290,21 @@ Framebuffer GEM Helper Reference ...@@ -308,3 +290,21 @@ Framebuffer GEM Helper Reference
.. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c .. kernel-doc:: drivers/gpu/drm/drm_gem_framebuffer_helper.c
:export: :export:
Legacy Plane Helper Reference
=============================
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
:export:
Legacy CRTC/Modeset Helper Functions Reference
==============================================
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
:export:
...@@ -263,14 +263,20 @@ Taken all together there's two consequences for the atomic design: ...@@ -263,14 +263,20 @@ Taken all together there's two consequences for the atomic design:
- An atomic update is assembled and validated as an entirely free-standing pile - An atomic update is assembled and validated as an entirely free-standing pile
of structures within the :c:type:`drm_atomic_state <drm_atomic_state>` of structures within the :c:type:`drm_atomic_state <drm_atomic_state>`
container. Again drivers can subclass that container for their own state container. Driver private state structures are also tracked in the same
structure tracking needs. Only when a state is committed is it applied to the structure; see the next chapter. Only when a state is committed is it applied
driver and modeset objects. This way rolling back an update boils down to to the driver and modeset objects. This way rolling back an update boils down
releasing memory and unreferencing objects like framebuffers. to releasing memory and unreferencing objects like framebuffers.
Read on in this chapter, and also in :ref:`drm_atomic_helper` for more detailed Read on in this chapter, and also in :ref:`drm_atomic_helper` for more detailed
coverage of specific topics. coverage of specific topics.
Handling Driver Private State
-----------------------------
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
:doc: handling driver private state
Atomic Mode Setting Function Reference Atomic Mode Setting Function Reference
-------------------------------------- --------------------------------------
......
...@@ -194,6 +194,24 @@ drm_mode_config_helper_suspend/resume(). ...@@ -194,6 +194,24 @@ drm_mode_config_helper_suspend/resume().
Contact: Maintainer of the driver you plan to convert Contact: Maintainer of the driver you plan to convert
Convert drivers to use drm_fb_helper_fbdev_setup/teardown()
-----------------------------------------------------------
Most drivers can use drm_fb_helper_fbdev_setup() except maybe:
- amdgpu which has special logic to decide whether to call
drm_helper_disable_unused_functions()
- armada which isn't atomic and doesn't call
drm_helper_disable_unused_functions()
- i915 which calls drm_fb_helper_initial_config() in a worker
Drivers that use drm_framebuffer_remove() to clean up the fbdev framebuffer can
probably use drm_fb_helper_fbdev_teardown().
Contact: Maintainer of the driver you plan to convert
Core refactorings Core refactorings
================= =================
......
...@@ -50,7 +50,8 @@ EXPORT_SYMBOL(__drm_crtc_commit_free); ...@@ -50,7 +50,8 @@ EXPORT_SYMBOL(__drm_crtc_commit_free);
* @state: atomic state * @state: atomic state
* *
* Free all the memory allocated by drm_atomic_state_init. * Free all the memory allocated by drm_atomic_state_init.
* This is useful for drivers that subclass the atomic state. * This should only be used by drivers which are still subclassing
* &drm_atomic_state and haven't switched to &drm_private_state yet.
*/ */
void drm_atomic_state_default_release(struct drm_atomic_state *state) void drm_atomic_state_default_release(struct drm_atomic_state *state)
{ {
...@@ -67,7 +68,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_release); ...@@ -67,7 +68,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_release);
* @state: atomic state * @state: atomic state
* *
* Default implementation for filling in a new atomic state. * Default implementation for filling in a new atomic state.
* This is useful for drivers that subclass the atomic state. * This should only be used by drivers which are still subclassing
* &drm_atomic_state and haven't switched to &drm_private_state yet.
*/ */
int int
drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state) drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
...@@ -132,7 +134,8 @@ EXPORT_SYMBOL(drm_atomic_state_alloc); ...@@ -132,7 +134,8 @@ EXPORT_SYMBOL(drm_atomic_state_alloc);
* @state: atomic state * @state: atomic state
* *
* Default implementation for clearing atomic state. * Default implementation for clearing atomic state.
* This is useful for drivers that subclass the atomic state. * This should only be used by drivers which are still subclassing
* &drm_atomic_state and haven't switched to &drm_private_state yet.
*/ */
void drm_atomic_state_default_clear(struct drm_atomic_state *state) void drm_atomic_state_default_clear(struct drm_atomic_state *state)
{ {
...@@ -946,6 +949,42 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, ...@@ -946,6 +949,42 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
plane->funcs->atomic_print_state(p, state); plane->funcs->atomic_print_state(p, state);
} }
/**
* DOC: handling driver private state
*
* Very often the DRM objects exposed to userspace in the atomic modeset api
* (&drm_connector, &drm_crtc and &drm_plane) do not map neatly to the
* underlying hardware. Especially for any kind of shared resources (e.g. shared
* clocks, scaler units, bandwidth and fifo limits shared among a group of
* planes or CRTCs, and so on) it makes sense to model these as independent
* objects. Drivers then need to do similar state tracking and commit ordering for
* such private (since not exposed to userpace) objects as the atomic core and
* helpers already provide for connectors, planes and CRTCs.
*
* To make this easier on drivers the atomic core provides some support to track
* driver private state objects using struct &drm_private_obj, with the
* associated state struct &drm_private_state.
*
* Similar to userspace-exposed objects, private state structures can be
* acquired by calling drm_atomic_get_private_obj_state(). Since this function
* does not take care of locking, drivers should wrap it for each type of
* private state object they have with the required call to drm_modeset_lock()
* for the corresponding &drm_modeset_lock.
*
* All private state structures contained in a &drm_atomic_state update can be
* iterated using for_each_oldnew_private_obj_in_state(),
* for_each_new_private_obj_in_state() and for_each_old_private_obj_in_state().
* Drivers are recommended to wrap these for each type of driver private state
* object they have, filtering on &drm_private_obj.funcs using for_each_if(), at
* least if they want to iterate over all objects of a given type.
*
* An earlier way to handle driver private state was by subclassing struct
* &drm_atomic_state. But since that encourages non-standard ways to implement
* the check/commit split atomic requires (by using e.g. "check and rollback or
* commit instead" of "duplicate state, check, then either commit or release
* duplicated state) it is deprecated in favour of using &drm_private_state.
*/
/** /**
* drm_atomic_private_obj_init - initialize private object * drm_atomic_private_obj_init - initialize private object
* @obj: private object * @obj: private object
......
...@@ -4871,6 +4871,11 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode); ...@@ -4871,6 +4871,11 @@ EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
* @mode: DRM display mode * @mode: DRM display mode
* @rgb_quant_range: RGB quantization range (Q) * @rgb_quant_range: RGB quantization range (Q)
* @rgb_quant_range_selectable: Sink support selectable RGB quantization range (QS) * @rgb_quant_range_selectable: Sink support selectable RGB quantization range (QS)
* @is_hdmi2_sink: HDMI 2.0 sink, which has different default recommendations
*
* Note that @is_hdmi2_sink can be derived by looking at the
* &drm_scdc.supported flag stored in &drm_hdmi_info.scdc,
* &drm_display_info.hdmi, which can be found in &drm_connector.display_info.
*/ */
void void
drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame, drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
......
...@@ -66,19 +66,23 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); ...@@ -66,19 +66,23 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* helper functions used by many drivers to implement the kernel mode setting * helper functions used by many drivers to implement the kernel mode setting
* interfaces. * interfaces.
* *
* Initialization is done as a four-step process with drm_fb_helper_prepare(), * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
* drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and * down by calling drm_fb_helper_fbdev_teardown().
* drm_fb_helper_initial_config(). Drivers with fancier requirements than the *
* default behaviour can override the third step with their own code. * Drivers that need to handle connector hotplugging (e.g. dp mst) can't use
* Teardown is done with drm_fb_helper_fini() after the fbdev device is * the setup helper and will need to do the whole four-step setup process with
* unregisters using drm_fb_helper_unregister_fbi(). * drm_fb_helper_prepare(), drm_fb_helper_init(),
* * drm_fb_helper_single_add_all_connectors(), enable hotplugging and
* At runtime drivers should restore the fbdev console by calling * drm_fb_helper_initial_config() to avoid a possible race window.
* drm_fb_helper_restore_fbdev_mode_unlocked() from their &drm_driver.lastclose *
* callback. They should also notify the fb helper code from updates to the * At runtime drivers should restore the fbdev console by using
* output configuration by calling drm_fb_helper_hotplug_event(). For easier * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
* integration with the output polling code in drm_crtc_helper.c the modeset * They should also notify the fb helper code from updates to the output
* code provides a &drm_mode_config_funcs.output_poll_changed callback. * configuration by using drm_fb_helper_output_poll_changed() as their
* &drm_mode_config_funcs.output_poll_changed callback.
*
* For suspend/resume consider using drm_mode_config_helper_suspend() and
* drm_mode_config_helper_resume() which takes care of fbdev as well.
* *
* All other functions exported by the fb helper library can be used to * All other functions exported by the fb helper library can be used to
* implement the fbdev driver interface by the driver. * implement the fbdev driver interface by the driver.
...@@ -103,7 +107,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); ...@@ -103,7 +107,8 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* always run in process context since the fb_*() function could be running in * always run in process context since the fb_*() function could be running in
* atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
* callback it will also schedule dirty_work with the damage collected from the * callback it will also schedule dirty_work with the damage collected from the
* mmap page writes. * mmap page writes. Drivers can use drm_fb_helper_defio_init() to setup
* deferred I/O (coupled with drm_fb_helper_fbdev_teardown()).
*/ */
#define drm_fb_helper_for_each_connector(fbh, i__) \ #define drm_fb_helper_for_each_connector(fbh, i__) \
...@@ -1024,6 +1029,49 @@ void drm_fb_helper_deferred_io(struct fb_info *info, ...@@ -1024,6 +1029,49 @@ void drm_fb_helper_deferred_io(struct fb_info *info,
} }
EXPORT_SYMBOL(drm_fb_helper_deferred_io); EXPORT_SYMBOL(drm_fb_helper_deferred_io);
/**
* drm_fb_helper_defio_init - fbdev deferred I/O initialization
* @fb_helper: driver-allocated fbdev helper
*
* This function allocates &fb_deferred_io, sets callback to
* drm_fb_helper_deferred_io(), delay to 50ms and calls fb_deferred_io_init().
* It should be called from the &drm_fb_helper_funcs->fb_probe callback.
* drm_fb_helper_fbdev_teardown() cleans up deferred I/O.
*
* NOTE: A copy of &fb_ops is made and assigned to &info->fbops. This is done
* because fb_deferred_io_cleanup() clears &fbops->fb_mmap and would thereby
* affect other instances of that &fb_ops.
*
* Returns:
* 0 on success or a negative error code on failure.
*/
int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
{
struct fb_info *info = fb_helper->fbdev;
struct fb_deferred_io *fbdefio;
struct fb_ops *fbops;
fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
if (!fbdefio || !fbops) {
kfree(fbdefio);
kfree(fbops);
return -ENOMEM;
}
info->fbdefio = fbdefio;
fbdefio->delay = msecs_to_jiffies(50);
fbdefio->deferred_io = drm_fb_helper_deferred_io;
*fbops = *info->fbops;
info->fbops = fbops;
fb_deferred_io_init(info);
return 0;
}
EXPORT_SYMBOL(drm_fb_helper_defio_init);
/** /**
* drm_fb_helper_sys_read - wrapper around fb_sys_read * drm_fb_helper_sys_read - wrapper around fb_sys_read
* @info: fb_info struct pointer * @info: fb_info struct pointer
...@@ -1848,6 +1896,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -1848,6 +1896,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (ret < 0) if (ret < 0)
return ret; return ret;
strcpy(fb_helper->fb->comm, "[fbcon]");
return 0; return 0;
} }
...@@ -2729,6 +2778,120 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) ...@@ -2729,6 +2778,120 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
} }
EXPORT_SYMBOL(drm_fb_helper_hotplug_event); EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
/**
* drm_fb_helper_fbdev_setup() - Setup fbdev emulation
* @dev: DRM device
* @fb_helper: fbdev helper structure to set up
* @funcs: fbdev helper functions
* @preferred_bpp: Preferred bits per pixel for the device.
* @dev->mode_config.preferred_depth is used if this is zero.
* @max_conn_count: Maximum number of connectors.
* @dev->mode_config.num_connector is used if this is zero.
*
* This function sets up fbdev emulation and registers fbdev for access by
* userspace. If all connectors are disconnected, setup is deferred to the next
* time drm_fb_helper_hotplug_event() is called.
* The caller must to provide a &drm_fb_helper_funcs->fb_probe callback
* function.
*
* See also: drm_fb_helper_initial_config()
*
* Returns:
* Zero on success or negative error code on failure.
*/
int drm_fb_helper_fbdev_setup(struct drm_device *dev,
struct drm_fb_helper *fb_helper,
const struct drm_fb_helper_funcs *funcs,
unsigned int preferred_bpp,
unsigned int max_conn_count)
{
int ret;
if (!preferred_bpp)
preferred_bpp = dev->mode_config.preferred_depth;
if (!preferred_bpp)
preferred_bpp = 32;
if (!max_conn_count)
max_conn_count = dev->mode_config.num_connector;
if (!max_conn_count) {
DRM_DEV_ERROR(dev->dev, "No connectors\n");
return -EINVAL;
}
drm_fb_helper_prepare(dev, fb_helper, funcs);
ret = drm_fb_helper_init(dev, fb_helper, max_conn_count);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "Failed to initialize fbdev helper\n");
return ret;
}
ret = drm_fb_helper_single_add_all_connectors(fb_helper);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "Failed to add connectors\n");
goto err_drm_fb_helper_fini;
}
if (!drm_drv_uses_atomic_modeset(dev))
drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "Failed to set fbdev configuration\n");
goto err_drm_fb_helper_fini;
}
return 0;
err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
return ret;
}
EXPORT_SYMBOL(drm_fb_helper_fbdev_setup);
/**
* drm_fb_helper_fbdev_teardown - Tear down fbdev emulation
* @dev: DRM device
*
* This function unregisters fbdev if not already done and cleans up the
* associated resources including the &drm_framebuffer.
* The driver is responsible for freeing the &drm_fb_helper structure which is
* stored in &drm_device->fb_helper. Do note that this pointer has been cleared
* when this function returns.
*
* In order to support device removal/unplug while file handles are still open,
* drm_fb_helper_unregister_fbi() should be called on device removal and
* drm_fb_helper_fbdev_teardown() in the &drm_driver->release callback when
* file handles are closed.
*/
void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
{
struct drm_fb_helper *fb_helper = dev->fb_helper;
struct fb_ops *fbops = NULL;
if (!fb_helper)
return;
/* Unregister if it hasn't been done already */
if (fb_helper->fbdev && fb_helper->fbdev->dev)
drm_fb_helper_unregister_fbi(fb_helper);
if (fb_helper->fbdev && fb_helper->fbdev->fbdefio) {
fb_deferred_io_cleanup(fb_helper->fbdev);
kfree(fb_helper->fbdev->fbdefio);
fbops = fb_helper->fbdev->fbops;
}
drm_fb_helper_fini(fb_helper);
kfree(fbops);
if (fb_helper->fb)
drm_framebuffer_remove(fb_helper->fb);
}
EXPORT_SYMBOL(drm_fb_helper_fbdev_teardown);
/** /**
* drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation * drm_fb_helper_lastclose - DRM driver lastclose helper for fbdev emulation
* @dev: DRM device * @dev: DRM device
......
...@@ -664,6 +664,7 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, ...@@ -664,6 +664,7 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
INIT_LIST_HEAD(&fb->filp_head); INIT_LIST_HEAD(&fb->filp_head);
fb->funcs = funcs; fb->funcs = funcs;
strcpy(fb->comm, current->comm);
ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB, ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB,
false, drm_framebuffer_free); false, drm_framebuffer_free);
...@@ -978,6 +979,7 @@ void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, ...@@ -978,6 +979,7 @@ void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent,
struct drm_format_name_buf format_name; struct drm_format_name_buf format_name;
unsigned int i; unsigned int i;
drm_printf_indent(p, indent, "allocated by = %s\n", fb->comm);
drm_printf_indent(p, indent, "refcount=%u\n", drm_printf_indent(p, indent, "refcount=%u\n",
drm_framebuffer_read_refcount(fb)); drm_framebuffer_read_refcount(fb));
drm_printf_indent(p, indent, "format=%s\n", drm_printf_indent(p, indent, "format=%s\n",
......
...@@ -29,9 +29,9 @@ ...@@ -29,9 +29,9 @@
/** /**
* DOC: Overview * DOC: Overview
* *
* DRM synchronisation objects (syncobj) are a persistent objects, * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are
* that contain an optional fence. The fence can be updated with a new * persistent objects that contain an optional fence. The fence can be updated
* fence, or be NULL. * with a new fence, or be NULL.
* *
* syncobj's can be waited upon, where it will wait for the underlying * syncobj's can be waited upon, where it will wait for the underlying
* fence. * fence.
...@@ -61,7 +61,8 @@ ...@@ -61,7 +61,8 @@
* @file_private: drm file private pointer * @file_private: drm file private pointer
* @handle: sync object handle to lookup. * @handle: sync object handle to lookup.
* *
* Returns a reference to the syncobj pointed to by handle or NULL. * Returns a reference to the syncobj pointed to by handle or NULL. The
* reference must be released by calling drm_syncobj_put().
*/ */
struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
u32 handle) u32 handle)
...@@ -229,6 +230,19 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) ...@@ -229,6 +230,19 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
return 0; return 0;
} }
/**
* drm_syncobj_find_fence - lookup and reference the fence in a sync object
* @file_private: drm file private pointer
* @handle: sync object handle to lookup.
* @fence: out parameter for the fence
*
* This is just a convenience function that combines drm_syncobj_find() and
* drm_syncobj_fence_get().
*
* Returns 0 on success or a negative error value on failure. On success @fence
* contains a reference to the fence, which must be released by calling
* dma_fence_put().
*/
int drm_syncobj_find_fence(struct drm_file *file_private, int drm_syncobj_find_fence(struct drm_file *file_private,
u32 handle, u32 handle,
struct dma_fence **fence) struct dma_fence **fence)
...@@ -269,6 +283,12 @@ EXPORT_SYMBOL(drm_syncobj_free); ...@@ -269,6 +283,12 @@ EXPORT_SYMBOL(drm_syncobj_free);
* @out_syncobj: returned syncobj * @out_syncobj: returned syncobj
* @flags: DRM_SYNCOBJ_* flags * @flags: DRM_SYNCOBJ_* flags
* @fence: if non-NULL, the syncobj will represent this fence * @fence: if non-NULL, the syncobj will represent this fence
*
* This is the first function to create a sync object. After creating, drivers
* probably want to make it available to userspace, either through
* drm_syncobj_get_handle() or drm_syncobj_get_fd().
*
* Returns 0 on success or a negative error value on failure.
*/ */
int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
struct dma_fence *fence) struct dma_fence *fence)
...@@ -302,6 +322,14 @@ EXPORT_SYMBOL(drm_syncobj_create); ...@@ -302,6 +322,14 @@ EXPORT_SYMBOL(drm_syncobj_create);
/** /**
* drm_syncobj_get_handle - get a handle from a syncobj * drm_syncobj_get_handle - get a handle from a syncobj
* @file_private: drm file private pointer
* @syncobj: Sync object to export
* @handle: out parameter with the new handle
*
* Exports a sync object created with drm_syncobj_create() as a handle on
* @file_private to userspace.
*
* Returns 0 on success or a negative error value on failure.
*/ */
int drm_syncobj_get_handle(struct drm_file *file_private, int drm_syncobj_get_handle(struct drm_file *file_private,
struct drm_syncobj *syncobj, u32 *handle) struct drm_syncobj *syncobj, u32 *handle)
...@@ -388,6 +416,15 @@ static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj) ...@@ -388,6 +416,15 @@ static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj)
return 0; return 0;
} }
/**
* drm_syncobj_get_fd - get a file descriptor from a syncobj
* @syncobj: Sync object to export
* @p_fd: out parameter with the new file descriptor
*
* Exports a sync object created with drm_syncobj_create() as a file descriptor.
*
* Returns 0 on success or a negative error value on failure.
*/
int drm_syncobj_get_fd(struct drm_syncobj *syncobj, int *p_fd) int drm_syncobj_get_fd(struct drm_syncobj *syncobj, int *p_fd)
{ {
int ret; int ret;
......
...@@ -290,11 +290,6 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) ...@@ -290,11 +290,6 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
DRM_ERROR("Unable to get resource\n");
return -ENODEV;
}
dsi->base = devm_ioremap_resource(dev, res); dsi->base = devm_ioremap_resource(dev, res);
if (IS_ERR(dsi->base)) { if (IS_ERR(dsi->base)) {
DRM_ERROR("Unable to get dsi registers\n"); DRM_ERROR("Unable to get dsi registers\n");
......
...@@ -901,12 +901,6 @@ int ltdc_load(struct drm_device *ddev) ...@@ -901,12 +901,6 @@ int ltdc_load(struct drm_device *ddev)
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
DRM_ERROR("Unable to get resource\n");
ret = -ENODEV;
goto err;
}
ldev->regs = devm_ioremap_resource(dev, res); ldev->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(ldev->regs)) { if (IS_ERR(ldev->regs)) {
DRM_ERROR("Unable to get ltdc registers\n"); DRM_ERROR("Unable to get ltdc registers\n");
......
...@@ -189,12 +189,40 @@ struct drm_private_state_funcs { ...@@ -189,12 +189,40 @@ struct drm_private_state_funcs {
struct drm_private_state *state); struct drm_private_state *state);
}; };
/**
* struct drm_private_obj - base struct for driver private atomic object
*
* A driver private object is initialized by calling
* drm_atomic_private_obj_init() and cleaned up by calling
* drm_atomic_private_obj_fini().
*
* Currently only tracks the state update functions and the opaque driver
* private state itself, but in the future might also track which
* &drm_modeset_lock is required to duplicate and update this object's state.
*/
struct drm_private_obj { struct drm_private_obj {
/**
* @state: Current atomic state for this driver private object.
*/
struct drm_private_state *state; struct drm_private_state *state;
/**
* @funcs:
*
* Functions to manipulate the state of this driver private object, see
* &drm_private_state_funcs.
*/
const struct drm_private_state_funcs *funcs; const struct drm_private_state_funcs *funcs;
}; };
/**
* struct drm_private_state - base struct for driver private object state
* @state: backpointer to global drm_atomic_state
*
* Currently only contains a backpointer to the overall atomic update, but in
* the future also might hold synchronization information similar to e.g.
* &drm_crtc.commit.
*/
struct drm_private_state { struct drm_private_state {
struct drm_atomic_state *state; struct drm_atomic_state *state;
}; };
...@@ -218,6 +246,10 @@ struct __drm_private_objs_state { ...@@ -218,6 +246,10 @@ struct __drm_private_objs_state {
* @num_private_objs: size of the @private_objs array * @num_private_objs: size of the @private_objs array
* @private_objs: pointer to array of private object pointers * @private_objs: pointer to array of private object pointers
* @acquire_ctx: acquire context for this atomic modeset state update * @acquire_ctx: acquire context for this atomic modeset state update
*
* States are added to an atomic update by calling drm_atomic_get_crtc_state(),
* drm_atomic_get_plane_state(), drm_atomic_get_connector_state(), or for
* private state structures, drm_atomic_get_private_obj_state().
*/ */
struct drm_atomic_state { struct drm_atomic_state {
struct kref ref; struct kref ref;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
struct drm_fb_helper; struct drm_fb_helper;
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <linux/kgdb.h> #include <linux/kgdb.h>
enum mode_set_atomic { enum mode_set_atomic {
...@@ -275,6 +276,7 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper); ...@@ -275,6 +276,7 @@ void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper);
void drm_fb_helper_deferred_io(struct fb_info *info, void drm_fb_helper_deferred_io(struct fb_info *info,
struct list_head *pagelist); struct list_head *pagelist);
int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper);
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf, ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos); size_t count, loff_t *ppos);
...@@ -319,6 +321,13 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ ...@@ -319,6 +321,13 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector); struct drm_connector *connector);
int drm_fb_helper_fbdev_setup(struct drm_device *dev,
struct drm_fb_helper *fb_helper,
const struct drm_fb_helper_funcs *funcs,
unsigned int preferred_bpp,
unsigned int max_conn_count);
void drm_fb_helper_fbdev_teardown(struct drm_device *dev);
void drm_fb_helper_lastclose(struct drm_device *dev); void drm_fb_helper_lastclose(struct drm_device *dev);
void drm_fb_helper_output_poll_changed(struct drm_device *dev); void drm_fb_helper_output_poll_changed(struct drm_device *dev);
#else #else
...@@ -332,11 +341,17 @@ static inline int drm_fb_helper_init(struct drm_device *dev, ...@@ -332,11 +341,17 @@ static inline int drm_fb_helper_init(struct drm_device *dev,
struct drm_fb_helper *helper, struct drm_fb_helper *helper,
int max_conn) int max_conn)
{ {
/* So drivers can use it to free the struct */
helper->dev = dev;
dev->fb_helper = helper;
return 0; return 0;
} }
static inline void drm_fb_helper_fini(struct drm_fb_helper *helper) static inline void drm_fb_helper_fini(struct drm_fb_helper *helper)
{ {
if (helper && helper->dev)
helper->dev->fb_helper = NULL;
} }
static inline int drm_fb_helper_blank(int blank, struct fb_info *info) static inline int drm_fb_helper_blank(int blank, struct fb_info *info)
...@@ -409,6 +424,11 @@ static inline void drm_fb_helper_deferred_io(struct fb_info *info, ...@@ -409,6 +424,11 @@ static inline void drm_fb_helper_deferred_io(struct fb_info *info,
{ {
} }
static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
{
return -ENODEV;
}
static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info, static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
char __user *buf, size_t count, char __user *buf, size_t count,
loff_t *ppos) loff_t *ppos)
...@@ -518,6 +538,24 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, ...@@ -518,6 +538,24 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
return 0; return 0;
} }
static inline int
drm_fb_helper_fbdev_setup(struct drm_device *dev,
struct drm_fb_helper *fb_helper,
const struct drm_fb_helper_funcs *funcs,
unsigned int preferred_bpp,
unsigned int max_conn_count)
{
/* So drivers can use it to free the struct */
dev->fb_helper = fb_helper;
return 0;
}
static inline void drm_fb_helper_fbdev_teardown(struct drm_device *dev)
{
dev->fb_helper = NULL;
}
static inline void drm_fb_helper_lastclose(struct drm_device *dev) static inline void drm_fb_helper_lastclose(struct drm_device *dev)
{ {
} }
......
...@@ -121,6 +121,12 @@ struct drm_framebuffer { ...@@ -121,6 +121,12 @@ struct drm_framebuffer {
* @base: base modeset object structure, contains the reference count. * @base: base modeset object structure, contains the reference count.
*/ */
struct drm_mode_object base; struct drm_mode_object base;
/**
* @comm: Name of the process allocating the fb, used for fb dumping.
*/
char comm[TASK_COMM_LEN];
/** /**
* @format: framebuffer format information * @format: framebuffer format information
*/ */
......
...@@ -269,6 +269,9 @@ struct drm_mode_config_funcs { ...@@ -269,6 +269,9 @@ struct drm_mode_config_funcs {
* state easily. If this hook is implemented, drivers must also * state easily. If this hook is implemented, drivers must also
* implement @atomic_state_clear and @atomic_state_free. * implement @atomic_state_clear and @atomic_state_free.
* *
* Subclassing of &drm_atomic_state is deprecated in favour of using
* &drm_private_state and &drm_private_obj.
*
* RETURNS: * RETURNS:
* *
* A new &drm_atomic_state on success or NULL on failure. * A new &drm_atomic_state on success or NULL on failure.
...@@ -290,6 +293,9 @@ struct drm_mode_config_funcs { ...@@ -290,6 +293,9 @@ struct drm_mode_config_funcs {
* *
* Drivers that implement this must call drm_atomic_state_default_clear() * Drivers that implement this must call drm_atomic_state_default_clear()
* to clear common state. * to clear common state.
*
* Subclassing of &drm_atomic_state is deprecated in favour of using
* &drm_private_state and &drm_private_obj.
*/ */
void (*atomic_state_clear)(struct drm_atomic_state *state); void (*atomic_state_clear)(struct drm_atomic_state *state);
...@@ -302,6 +308,9 @@ struct drm_mode_config_funcs { ...@@ -302,6 +308,9 @@ struct drm_mode_config_funcs {
* *
* Drivers that implement this must call * Drivers that implement this must call
* drm_atomic_state_default_release() to release common resources. * drm_atomic_state_default_release() to release common resources.
*
* Subclassing of &drm_atomic_state is deprecated in favour of using
* &drm_private_state and &drm_private_obj.
*/ */
void (*atomic_state_free)(struct drm_atomic_state *state); void (*atomic_state_free)(struct drm_atomic_state *state);
}; };
......
...@@ -80,13 +80,13 @@ void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf); ...@@ -80,13 +80,13 @@ void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
__printf(2, 3) __printf(2, 3)
void drm_printf(struct drm_printer *p, const char *f, ...); void drm_printf(struct drm_printer *p, const char *f, ...);
__printf(2, 0)
/** /**
* drm_vprintf - print to a &drm_printer stream * drm_vprintf - print to a &drm_printer stream
* @p: the &drm_printer * @p: the &drm_printer
* @fmt: format string * @fmt: format string
* @va: the va_list * @va: the va_list
*/ */
__printf(2, 0)
static inline void static inline void
drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va) drm_vprintf(struct drm_printer *p, const char *fmt, va_list *va)
{ {
......
...@@ -33,36 +33,31 @@ struct drm_syncobj_cb; ...@@ -33,36 +33,31 @@ struct drm_syncobj_cb;
/** /**
* struct drm_syncobj - sync object. * struct drm_syncobj - sync object.
* *
* This structure defines a generic sync object which wraps a dma fence. * This structure defines a generic sync object which wraps a &dma_fence.
*/ */
struct drm_syncobj { struct drm_syncobj {
/** /**
* @refcount: * @refcount: Reference count of this object.
*
* Reference count of this object.
*/ */
struct kref refcount; struct kref refcount;
/** /**
* @fence: * @fence:
* NULL or a pointer to the fence bound to this object. * NULL or a pointer to the fence bound to this object.
* *
* This field should not be used directly. Use drm_syncobj_fence_get * This field should not be used directly. Use drm_syncobj_fence_get()
* and drm_syncobj_replace_fence instead. * and drm_syncobj_replace_fence() instead.
*/ */
struct dma_fence __rcu *fence; struct dma_fence __rcu *fence;
/** /**
* @cb_list: * @cb_list: List of callbacks to call when the &fence gets replaced.
* List of callbacks to call when the fence gets replaced
*/ */
struct list_head cb_list; struct list_head cb_list;
/** /**
* @lock: * @lock: Protects &cb_list and write-locks &fence.
* locks cb_list and write-locks fence.
*/ */
spinlock_t lock; spinlock_t lock;
/** /**
* @file: * @file: A file backing for this syncobj.
* a file backing for this syncobj.
*/ */
struct file *file; struct file *file;
}; };
...@@ -73,7 +68,7 @@ typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj, ...@@ -73,7 +68,7 @@ typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj,
/** /**
* struct drm_syncobj_cb - callback for drm_syncobj_add_callback * struct drm_syncobj_cb - callback for drm_syncobj_add_callback
* @node: used by drm_syncob_add_callback to append this struct to * @node: used by drm_syncob_add_callback to append this struct to
* syncobj::cb_list * &drm_syncobj.cb_list
* @func: drm_syncobj_func_t to call * @func: drm_syncobj_func_t to call
* *
* This struct will be initialized by drm_syncobj_add_callback, additional * This struct will be initialized by drm_syncobj_add_callback, additional
...@@ -92,7 +87,7 @@ void drm_syncobj_free(struct kref *kref); ...@@ -92,7 +87,7 @@ void drm_syncobj_free(struct kref *kref);
* drm_syncobj_get - acquire a syncobj reference * drm_syncobj_get - acquire a syncobj reference
* @obj: sync object * @obj: sync object
* *
* This acquires additional reference to @obj. It is illegal to call this * This acquires an additional reference to @obj. It is illegal to call this
* without already holding a reference. No locks required. * without already holding a reference. No locks required.
*/ */
static inline void static inline void
...@@ -111,6 +106,17 @@ drm_syncobj_put(struct drm_syncobj *obj) ...@@ -111,6 +106,17 @@ drm_syncobj_put(struct drm_syncobj *obj)
kref_put(&obj->refcount, drm_syncobj_free); kref_put(&obj->refcount, drm_syncobj_free);
} }
/**
* drm_syncobj_fence_get - get a reference to a fence in a sync object
* @syncobj: sync object.
*
* This acquires additional reference to &drm_syncobj.fence contained in @obj,
* if not NULL. It is illegal to call this without already holding a reference.
* No locks required.
*
* Returns:
* Either the fence of @obj or NULL if there's none.
*/
static inline struct dma_fence * static inline struct dma_fence *
drm_syncobj_fence_get(struct drm_syncobj *syncobj) drm_syncobj_fence_get(struct drm_syncobj *syncobj)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment