Commit d81294af authored by Noralf Trønnes's avatar Noralf Trønnes

drm/fb-helper: Remove drm_fb_helper_crtc

struct drm_fb_helper_crtc is now just a wrapper around drm_mode_set so
use that directly instead and attach it as a modeset array onto
drm_client_dev. drm_fb_helper will use this array to store its modesets
which means it will always initialize a drm_client, but it will not
register the client (callbacks) unless it's the generic fbdev emulation.

Code will later be moved to drm_client, so add code there in a new file
drm_client_modeset.c with MIT license to match drm_fb_helper.c.

The modeset connector array size is hardcoded for the cloned case to avoid
having to pass in a value from the driver. A value of 8 is chosen to err
on the safe side. This means that the max connector argument for
drm_fb_helper_init() and drm_fb_helper_fbdev_setup() isn't used anymore,
a todo entry for this is added.

In pan_display_atomic() restore_fbdev_mode_force() is used instead of
restore_fbdev_mode_atomic() because that one will later become internal
to drm_client_modeset.

Locking order:
1. drm_fb_helper->lock
2. drm_master_internal_acquire
3. drm_client_dev->modeset_mutex

v6: Improve commit message (Sam Ravnborg)

v3:
- Use full drm_client_init/release for the modesets (Daniel Vetter)
- drm_client_for_each_modeset: use lockdep_assert_held (Daniel Vetter)
- Hook up to Documentation/gpu/drm-client.rst (Daniel Vetter)

v2:
- Add modesets array to drm_client (Daniel Vetter)
- Use a new file for the modeset code (Daniel Vetter)
- File has to be MIT licensed (Emmanuel Vadot)
- Add copyrights from drm_fb_helper.c
Signed-off-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Reviewed-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190531140117.37751-3-noralf@tronnes.org
parent 1b94f477
...@@ -10,3 +10,6 @@ Kernel clients ...@@ -10,3 +10,6 @@ Kernel clients
.. kernel-doc:: drivers/gpu/drm/drm_client.c .. kernel-doc:: drivers/gpu/drm/drm_client.c
:export: :export:
.. kernel-doc:: drivers/gpu/drm/drm_client_modeset.c
:export:
...@@ -289,6 +289,9 @@ drm_fb_helper tasks ...@@ -289,6 +289,9 @@ drm_fb_helper tasks
these igt tests need to be fixed: kms_fbcon_fbt@psr and these igt tests need to be fixed: kms_fbcon_fbt@psr and
kms_fbcon_fbt@psr-suspend. kms_fbcon_fbt@psr-suspend.
- The max connector argument for drm_fb_helper_init() and
drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
Core refactorings Core refactorings
================= =================
......
...@@ -17,7 +17,7 @@ drm-y := drm_auth.o drm_cache.o \ ...@@ -17,7 +17,7 @@ drm-y := drm_auth.o drm_cache.o \
drm_plane.o drm_color_mgmt.o drm_print.o \ drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \ drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
drm_atomic_uapi.o drm_hdcp.o drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
* DOC: overview * DOC: overview
* *
* This library provides support for clients running in the kernel like fbdev and bootsplash. * This library provides support for clients running in the kernel like fbdev and bootsplash.
* Currently it's only partially implemented, just enough to support fbdev.
* *
* GEM drivers which provide a GEM based dumb buffer with a virtual address are supported. * GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
*/ */
...@@ -92,14 +91,20 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, ...@@ -92,14 +91,20 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
client->name = name; client->name = name;
client->funcs = funcs; client->funcs = funcs;
ret = drm_client_open(client); ret = drm_client_modeset_create(client);
if (ret) if (ret)
goto err_put_module; goto err_put_module;
ret = drm_client_open(client);
if (ret)
goto err_free;
drm_dev_get(dev); drm_dev_get(dev);
return 0; return 0;
err_free:
drm_client_modeset_free(client);
err_put_module: err_put_module:
if (funcs) if (funcs)
module_put(funcs->owner); module_put(funcs->owner);
...@@ -148,6 +153,7 @@ void drm_client_release(struct drm_client_dev *client) ...@@ -148,6 +153,7 @@ void drm_client_release(struct drm_client_dev *client)
DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name); DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
drm_client_modeset_free(client);
drm_client_close(client); drm_client_close(client);
drm_dev_put(dev); drm_dev_put(dev);
if (client->funcs) if (client->funcs)
......
// SPDX-License-Identifier: MIT
/*
* Copyright 2018 Noralf Trønnes
* Copyright (c) 2006-2009 Red Hat Inc.
* Copyright (c) 2006-2008 Intel Corporation
* Jesse Barnes <jesse.barnes@intel.com>
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
*/
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
int drm_client_modeset_create(struct drm_client_dev *client)
{
struct drm_device *dev = client->dev;
unsigned int num_crtc = dev->mode_config.num_crtc;
unsigned int max_connector_count = 1;
struct drm_mode_set *modeset;
struct drm_crtc *crtc;
unsigned int i = 0;
/* Add terminating zero entry to enable index less iteration */
client->modesets = kcalloc(num_crtc + 1, sizeof(*client->modesets), GFP_KERNEL);
if (!client->modesets)
return -ENOMEM;
mutex_init(&client->modeset_mutex);
drm_for_each_crtc(crtc, dev)
client->modesets[i++].crtc = crtc;
/* Cloning is only supported in the single crtc case. */
if (num_crtc == 1)
max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS;
for (modeset = client->modesets; modeset->crtc; modeset++) {
modeset->connectors = kcalloc(max_connector_count,
sizeof(*modeset->connectors), GFP_KERNEL);
if (!modeset->connectors)
goto err_free;
}
return 0;
err_free:
drm_client_modeset_free(client);
return -ENOMEM;
}
void drm_client_modeset_release(struct drm_client_dev *client)
{
struct drm_mode_set *modeset;
unsigned int i;
drm_client_for_each_modeset(modeset, client) {
drm_mode_destroy(client->dev, modeset->mode);
modeset->mode = NULL;
modeset->fb = NULL;
for (i = 0; i < modeset->num_connectors; i++) {
drm_connector_put(modeset->connectors[i]);
modeset->connectors[i] = NULL;
}
modeset->num_connectors = 0;
}
}
/* TODO: Remove export when modeset code has been moved over */
EXPORT_SYMBOL(drm_client_modeset_release);
void drm_client_modeset_free(struct drm_client_dev *client)
{
struct drm_mode_set *modeset;
mutex_lock(&client->modeset_mutex);
drm_client_modeset_release(client);
drm_client_for_each_modeset(modeset, client)
kfree(modeset->connectors);
mutex_unlock(&client->modeset_mutex);
mutex_destroy(&client->modeset_mutex);
kfree(client->modesets);
}
struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
{
struct drm_mode_set *modeset;
drm_client_for_each_modeset(modeset, client)
if (modeset->crtc == crtc)
return modeset;
return NULL;
}
/* TODO: Remove export when modeset code has been moved over */
EXPORT_SYMBOL(drm_client_find_modeset);
This diff is collapsed.
...@@ -3,8 +3,12 @@ ...@@ -3,8 +3,12 @@
#ifndef _DRM_CLIENT_H_ #ifndef _DRM_CLIENT_H_
#define _DRM_CLIENT_H_ #define _DRM_CLIENT_H_
#include <linux/lockdep.h>
#include <linux/mutex.h>
#include <linux/types.h> #include <linux/types.h>
#include <drm/drm_crtc.h>
struct drm_client_dev; struct drm_client_dev;
struct drm_device; struct drm_device;
struct drm_file; struct drm_file;
...@@ -13,6 +17,8 @@ struct drm_gem_object; ...@@ -13,6 +17,8 @@ struct drm_gem_object;
struct drm_minor; struct drm_minor;
struct module; struct module;
#define DRM_CLIENT_MAX_CLONED_CONNECTORS 8
/** /**
* struct drm_client_funcs - DRM client callbacks * struct drm_client_funcs - DRM client callbacks
*/ */
...@@ -85,6 +91,16 @@ struct drm_client_dev { ...@@ -85,6 +91,16 @@ struct drm_client_dev {
* @file: DRM file * @file: DRM file
*/ */
struct drm_file *file; struct drm_file *file;
/**
* @modeset_mutex: Protects @modesets.
*/
struct mutex modeset_mutex;
/**
* @modesets: CRTC configurations
*/
struct drm_mode_set *modesets;
}; };
int drm_client_init(struct drm_device *dev, struct drm_client_dev *client, int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
...@@ -135,6 +151,20 @@ struct drm_client_buffer * ...@@ -135,6 +151,20 @@ struct drm_client_buffer *
drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format); 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); void drm_client_framebuffer_delete(struct drm_client_buffer *buffer);
int drm_client_modeset_create(struct drm_client_dev *client);
void drm_client_modeset_free(struct drm_client_dev *client);
void drm_client_modeset_release(struct drm_client_dev *client);
struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc);
/**
* drm_client_for_each_modeset() - Iterate over client modesets
* @modeset: &drm_mode_set loop cursor
* @client: DRM client
*/
#define drm_client_for_each_modeset(modeset, client) \
for (({ lockdep_assert_held(&(client)->modeset_mutex); }), \
modeset = (client)->modesets; modeset->crtc; modeset++)
int drm_client_debugfs_init(struct drm_minor *minor); int drm_client_debugfs_init(struct drm_minor *minor);
#endif #endif
...@@ -47,10 +47,6 @@ struct drm_fb_offset { ...@@ -47,10 +47,6 @@ struct drm_fb_offset {
int x, y; int x, y;
}; };
struct drm_fb_helper_crtc {
struct drm_mode_set mode_set;
};
/** /**
* struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size
* @fb_width: fbdev width * @fb_width: fbdev width
...@@ -109,8 +105,6 @@ struct drm_fb_helper_connector { ...@@ -109,8 +105,6 @@ struct drm_fb_helper_connector {
* struct drm_fb_helper - main structure to emulate fbdev on top of KMS * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
* @fb: Scanout framebuffer object * @fb: Scanout framebuffer object
* @dev: DRM device * @dev: DRM device
* @crtc_count: number of possible CRTCs
* @crtc_info: per-CRTC helper state (mode, x/y offset, etc)
* @connector_count: number of connected connectors * @connector_count: number of connected connectors
* @connector_info_alloc_count: size of connector_info * @connector_info_alloc_count: size of connector_info
* @funcs: driver callbacks for fb helper * @funcs: driver callbacks for fb helper
...@@ -144,8 +138,6 @@ struct drm_fb_helper { ...@@ -144,8 +138,6 @@ struct drm_fb_helper {
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_device *dev; struct drm_device *dev;
int crtc_count;
struct drm_fb_helper_crtc *crtc_info;
int connector_count; int connector_count;
int connector_info_alloc_count; int connector_info_alloc_count;
/** /**
......
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