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

Commit 60c2f709 authored by Thierry Reding's avatar Thierry Reding
Browse files

drm/tegra: Make legacy fbdev support optional



A lot of the modern userspace is capable of working without the legacy
fbdev support. kmscon can be used as a replacement for the framebuffer
console, and KMS X drivers create their own framebuffers.

Most people don't have a system where all of this works yet, though, so
leave support enabled by default.

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent d30a91f8
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -3,13 +3,9 @@ config DRM_TEGRA
	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
	depends on DRM
	depends on RESET_CONTROLLER
	select DRM_KMS_FB_HELPER
	select DRM_KMS_HELPER
	select DRM_MIPI_DSI
	select DRM_PANEL
	select FB_SYS_FILLRECT
	select FB_SYS_COPYAREA
	select FB_SYS_IMAGEBLIT
	select TEGRA_HOST1X
	help
	  Choose this option if you have an NVIDIA Tegra SoC.
@@ -19,6 +15,18 @@ config DRM_TEGRA

if DRM_TEGRA

config DRM_TEGRA_FBDEV
	bool "Enable legacy fbdev support"
	select DRM_KMS_FB_HELPER
	select FB_SYS_FILLRECT
	select FB_SYS_COPYAREA
	select FB_SYS_IMAGEBLIT
	default y
	help
	  Choose this option if you have a need for the legacy fbdev support.
	  Note that this support also provides the Linux console on top of
	  the Tegra modesetting driver.

config DRM_TEGRA_DEBUG
	bool "NVIDIA Tegra DRM debug support"
	help
+2 −0
Original line number Diff line number Diff line
@@ -104,9 +104,11 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)

static void tegra_drm_lastclose(struct drm_device *drm)
{
#ifdef CONFIG_TEGRA_DRM_FBDEV
	struct tegra_drm *tegra = drm->dev_private;

	tegra_fbdev_restore_mode(tegra->fbdev);
#endif
}

static struct host1x_bo *
+6 −0
Original line number Diff line number Diff line
@@ -27,10 +27,12 @@ struct tegra_fb {
	unsigned int num_planes;
};

#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_fbdev {
	struct drm_fb_helper base;
	struct tegra_fb *fb;
};
#endif

struct tegra_drm {
	struct drm_device *drm;
@@ -38,7 +40,9 @@ struct tegra_drm {
	struct mutex clients_lock;
	struct list_head clients;

#ifdef CONFIG_DRM_TEGRA_FBDEV
	struct tegra_fbdev *fbdev;
#endif
};

struct tegra_drm_client;
@@ -265,7 +269,9 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
extern int tegra_drm_fb_init(struct drm_device *drm);
extern void tegra_drm_fb_exit(struct drm_device *drm);
#ifdef CONFIG_DRM_TEGRA_FBDEV
extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
#endif

extern struct platform_driver tegra_dc_driver;
extern struct platform_driver tegra_dsi_driver;
+25 −16
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@ static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
	return container_of(fb, struct tegra_fb, base);
}

#ifdef CONFIG_DRM_TEGRA_FBDEV
static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
{
	return container_of(helper, struct tegra_fbdev, base);
}
#endif

struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
				    unsigned int index)
@@ -172,6 +174,7 @@ static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
	return ERR_PTR(err);
}

#ifdef CONFIG_DRM_TEGRA_FBDEV
static struct fb_ops tegra_fb_ops = {
	.owner = THIS_MODULE,
	.fb_fillrect = sys_fillrect,
@@ -339,6 +342,15 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
	kfree(fbdev);
}

void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
{
	if (fbdev) {
		drm_modeset_lock_all(fbdev->base.dev);
		drm_fb_helper_restore_fbdev_mode(&fbdev->base);
		drm_modeset_unlock_all(fbdev->base.dev);
	}
}

static void tegra_fb_output_poll_changed(struct drm_device *drm)
{
	struct tegra_drm *tegra = drm->dev_private;
@@ -346,16 +358,20 @@ static void tegra_fb_output_poll_changed(struct drm_device *drm)
	if (tegra->fbdev)
		drm_fb_helper_hotplug_event(&tegra->fbdev->base);
}
#endif

static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
	.fb_create = tegra_fb_create,
#ifdef CONFIG_DRM_TEGRA_FBDEV
	.output_poll_changed = tegra_fb_output_poll_changed,
#endif
};

int tegra_drm_fb_init(struct drm_device *drm)
{
#ifdef CONFIG_DRM_TEGRA_FBDEV
	struct tegra_drm *tegra = drm->dev_private;
	struct tegra_fbdev *fbdev;
#endif

	drm->mode_config.min_width = 0;
	drm->mode_config.min_height = 0;
@@ -365,28 +381,21 @@ int tegra_drm_fb_init(struct drm_device *drm)

	drm->mode_config.funcs = &tegra_drm_mode_funcs;

	fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
#ifdef CONFIG_DRM_TEGRA_FBDEV
	tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
					  drm->mode_config.num_connector);
	if (IS_ERR(fbdev))
		return PTR_ERR(fbdev);

	tegra->fbdev = fbdev;
	if (IS_ERR(tegra->fbdev))
		return PTR_ERR(tegra->fbdev);
#endif

	return 0;
}

void tegra_drm_fb_exit(struct drm_device *drm)
{
#ifdef CONFIG_DRM_TEGRA_FBDEV
	struct tegra_drm *tegra = drm->dev_private;

	tegra_fbdev_free(tegra->fbdev);
}

void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
{
	if (fbdev) {
		drm_modeset_lock_all(fbdev->base.dev);
		drm_fb_helper_restore_fbdev_mode(&fbdev->base);
		drm_modeset_unlock_all(fbdev->base.dev);
	}
#endif
}