Commit aecdbfe4 authored by Thomas Zimmermann's avatar Thomas Zimmermann
Browse files

drm/gma500: Run DRM default client setup



Rework fbdev probing to support fbdev_probe in struct drm_driver
and remove the old fb_probe callback. Provide an initializer macro
for struct drm_driver that sets the callback according to the kernel
configuration.

Call drm_client_setup() to run the kernel's default client setup
for DRM. Set fbdev_probe in struct drm_driver, so that the client
setup can start the common fbdev client.

v5:
- select DRM_CLIENT_SELECTION

Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Cc: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Acked-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240924071734.98201-76-tzimmermann@suse.de
parent d4016e31
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
config DRM_GMA500
	tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
	depends on DRM && PCI && X86 && MMU
	select DRM_CLIENT_SELECTION
	select DRM_KMS_HELPER
	select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
	select I2C
+7 −93
Original line number Diff line number Diff line
@@ -143,11 +143,14 @@ static const struct fb_ops psb_fbdev_fb_ops = {
	.fb_destroy = psb_fbdev_fb_destroy,
};

static const struct drm_fb_helper_funcs psb_fbdev_fb_helper_funcs = {
};

/*
 * struct drm_fb_helper_funcs
 * struct drm_driver
 */

static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
int psb_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
				 struct drm_fb_helper_surface_size *sizes)
{
	struct drm_device *dev = fb_helper->dev;
@@ -206,6 +209,7 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
		goto err_drm_gem_object_put;
	}

	fb_helper->funcs = &psb_fbdev_fb_helper_funcs;
	fb_helper->fb = fb;

	info = drm_fb_helper_alloc_info(fb_helper);
@@ -246,93 +250,3 @@ static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
	drm_gem_object_put(obj);
	return ret;
}

static const struct drm_fb_helper_funcs psb_fbdev_fb_helper_funcs = {
	.fb_probe = psb_fbdev_fb_probe,
};

/*
 * struct drm_client_funcs and setup code
 */

static void psb_fbdev_client_unregister(struct drm_client_dev *client)
{
	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);

	if (fb_helper->info) {
		drm_fb_helper_unregister_info(fb_helper);
	} else {
		drm_fb_helper_unprepare(fb_helper);
		drm_client_release(&fb_helper->client);
		kfree(fb_helper);
	}
}

static int psb_fbdev_client_restore(struct drm_client_dev *client)
{
	drm_fb_helper_lastclose(client->dev);

	return 0;
}

static int psb_fbdev_client_hotplug(struct drm_client_dev *client)
{
	struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
	struct drm_device *dev = client->dev;
	int ret;

	if (dev->fb_helper)
		return drm_fb_helper_hotplug_event(dev->fb_helper);

	ret = drm_fb_helper_init(dev, fb_helper);
	if (ret)
		goto err_drm_err;

	if (!drm_drv_uses_atomic_modeset(dev))
		drm_helper_disable_unused_functions(dev);

	ret = drm_fb_helper_initial_config(fb_helper);
	if (ret)
		goto err_drm_fb_helper_fini;

	return 0;

err_drm_fb_helper_fini:
	drm_fb_helper_fini(fb_helper);
err_drm_err:
	drm_err(dev, "Failed to setup gma500 fbdev emulation (ret=%d)\n", ret);
	return ret;
}

static const struct drm_client_funcs psb_fbdev_client_funcs = {
	.owner		= THIS_MODULE,
	.unregister	= psb_fbdev_client_unregister,
	.restore	= psb_fbdev_client_restore,
	.hotplug	= psb_fbdev_client_hotplug,
};

void psb_fbdev_setup(struct drm_psb_private *dev_priv)
{
	struct drm_device *dev = &dev_priv->dev;
	struct drm_fb_helper *fb_helper;
	int ret;

	fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
	if (!fb_helper)
		return;
	drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fbdev_fb_helper_funcs);

	ret = drm_client_init(dev, &fb_helper->client, "fbdev-gma500", &psb_fbdev_client_funcs);
	if (ret) {
		drm_err(dev, "Failed to register client: %d\n", ret);
		goto err_drm_fb_helper_unprepare;
	}

	drm_client_register(&fb_helper->client);

	return;

err_drm_fb_helper_unprepare:
	drm_fb_helper_unprepare(fb_helper);
	kfree(fb_helper);
}
+3 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <acpi/video.h>

#include <drm/drm.h>
#include <drm/drm_client_setup.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
@@ -475,7 +476,7 @@ static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (ret)
		return ret;

	psb_fbdev_setup(dev_priv);
	drm_client_setup(dev, NULL);

	return 0;
}
@@ -506,6 +507,7 @@ static const struct drm_driver driver = {
	.num_ioctls = ARRAY_SIZE(psb_ioctls),

	.dumb_create = psb_gem_dumb_create,
	PSB_FBDEV_DRIVER_OPS,
	.ioctls = psb_ioctls,
	.fops = &psb_gem_fops,
	.name = DRIVER_NAME,
+9 −3
Original line number Diff line number Diff line
@@ -184,6 +184,9 @@
#define KSEL_BYPASS_25 6
#define KSEL_BYPASS_83_100 7

struct drm_fb_helper;
struct drm_fb_helper_surface_size;

struct opregion_header;
struct opregion_acpi;
struct opregion_swsci;
@@ -597,10 +600,13 @@ struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,

/* fbdev */
#if defined(CONFIG_DRM_FBDEV_EMULATION)
void psb_fbdev_setup(struct drm_psb_private *dev_priv);
int psb_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
				 struct drm_fb_helper_surface_size *sizes);
#define PSB_FBDEV_DRIVER_OPS \
	.fbdev_probe = psb_fbdev_driver_fbdev_probe
#else
static inline void psb_fbdev_setup(struct drm_psb_private *dev_priv)
{ }
#define PSB_FBDEV_DRIVER_OPS \
	.fbdev_probe = NULL
#endif

/* backlight.c */