Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e420f65b authored by Noralf Trønnes's avatar Noralf Trønnes Committed by Gerrit - the friendly Code Review server
Browse files

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


Patch-mainline: 20190531140117.37751-3-noralf@tronnes.org @ 31/05/19, 02:01 p.m.
[stalek@codeaurora.org:
1. drop changes for the file drm_fb_helper.c,
drm_fb_helper.h as some of the code is not similar and is not require
for our solution.
2. replace drm_device.h with drmP.h as drm_evice.h is not present.].

Change-Id: I07cedd0cd52c82782bcb7036b2d27c737d392d41
Signed-off-by: default avatarShubham Talekar <stalek@codeaurora.org>
parent 795c9baa
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -10,3 +10,6 @@ Kernel clients

.. kernel-doc:: drivers/gpu/drm/drm_client.c
   :export:

.. kernel-doc:: drivers/gpu/drm/drm_client_modeset.c
   :export:
+2 −1
Original line number Diff line number Diff line
@@ -15,7 +15,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
		drm_modeset_lock.o drm_atomic.o drm_bridge.o \
		drm_framebuffer.o drm_connector.o drm_blend.o \
		drm_encoder.o drm_mode_object.o drm_property.o \
		drm_plane.o drm_color_mgmt.o drm_client.o
		drm_plane.o drm_color_mgmt.o drm_client.o \
		drm_client_modeset.o

drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+8 −2
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@
 * DOC: overview
 *
 * 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.
 */
@@ -88,14 +87,20 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
	client->name = name;
	client->funcs = funcs;

	ret = drm_client_open(client);
	ret = drm_client_modeset_create(client);
	if (ret)
		goto err_put_module;

	ret = drm_client_open(client);
	if (ret)
		goto err_free;

	drm_dev_ref(dev);

	return 0;

err_free:
	drm_client_modeset_free(client);
err_put_module:
	if (funcs)
		module_put(funcs->owner);
@@ -144,6 +149,7 @@ void drm_client_release(struct drm_client_dev *client)

	DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);

	drm_client_modeset_free(client);
	drm_client_close(client);
	drm_dev_unref(dev);
	if (client->funcs)
+104 −0
Original line number Diff line number Diff line
// 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/drmP.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_unreference(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);
+30 −0
Original line number Diff line number Diff line
@@ -3,8 +3,12 @@
#ifndef _DRM_CLIENT_H_
#define _DRM_CLIENT_H_

#include <linux/lockdep.h>
#include <linux/mutex.h>
#include <linux/types.h>

#include <drm/drm_crtc.h>

struct drm_client_dev;
struct drm_device;
struct drm_file;
@@ -13,6 +17,8 @@ struct drm_gem_object;
struct drm_minor;
struct module;

#define DRM_CLIENT_MAX_CLONED_CONNECTORS	8

/**
 * struct drm_client_funcs - DRM client callbacks
 */
@@ -85,6 +91,16 @@ struct drm_client_dev {
	 * @file: DRM 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,
@@ -134,6 +150,20 @@ 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_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);

#endif