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

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
...@@ -3,13 +3,9 @@ config DRM_TEGRA ...@@ -3,13 +3,9 @@ config DRM_TEGRA
depends on ARCH_TEGRA || (ARM && COMPILE_TEST) depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
depends on DRM depends on DRM
depends on RESET_CONTROLLER depends on RESET_CONTROLLER
select DRM_KMS_FB_HELPER
select DRM_KMS_HELPER select DRM_KMS_HELPER
select DRM_MIPI_DSI select DRM_MIPI_DSI
select DRM_PANEL select DRM_PANEL
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select TEGRA_HOST1X select TEGRA_HOST1X
help help
Choose this option if you have an NVIDIA Tegra SoC. Choose this option if you have an NVIDIA Tegra SoC.
...@@ -19,6 +15,18 @@ config DRM_TEGRA ...@@ -19,6 +15,18 @@ config DRM_TEGRA
if 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 config DRM_TEGRA_DEBUG
bool "NVIDIA Tegra DRM debug support" bool "NVIDIA Tegra DRM debug support"
help help
......
...@@ -104,9 +104,11 @@ static void tegra_drm_context_free(struct tegra_drm_context *context) ...@@ -104,9 +104,11 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
static void tegra_drm_lastclose(struct drm_device *drm) static void tegra_drm_lastclose(struct drm_device *drm)
{ {
#ifdef CONFIG_TEGRA_DRM_FBDEV
struct tegra_drm *tegra = drm->dev_private; struct tegra_drm *tegra = drm->dev_private;
tegra_fbdev_restore_mode(tegra->fbdev); tegra_fbdev_restore_mode(tegra->fbdev);
#endif
} }
static struct host1x_bo * static struct host1x_bo *
......
...@@ -27,10 +27,12 @@ struct tegra_fb { ...@@ -27,10 +27,12 @@ struct tegra_fb {
unsigned int num_planes; unsigned int num_planes;
}; };
#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_fbdev { struct tegra_fbdev {
struct drm_fb_helper base; struct drm_fb_helper base;
struct tegra_fb *fb; struct tegra_fb *fb;
}; };
#endif
struct tegra_drm { struct tegra_drm {
struct drm_device *drm; struct drm_device *drm;
...@@ -38,7 +40,9 @@ struct tegra_drm { ...@@ -38,7 +40,9 @@ struct tegra_drm {
struct mutex clients_lock; struct mutex clients_lock;
struct list_head clients; struct list_head clients;
#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_fbdev *fbdev; struct tegra_fbdev *fbdev;
#endif
}; };
struct tegra_drm_client; struct tegra_drm_client;
...@@ -265,7 +269,9 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); ...@@ -265,7 +269,9 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
extern int tegra_drm_fb_init(struct drm_device *drm); extern int tegra_drm_fb_init(struct drm_device *drm);
extern void tegra_drm_fb_exit(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); extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
#endif
extern struct platform_driver tegra_dc_driver; extern struct platform_driver tegra_dc_driver;
extern struct platform_driver tegra_dsi_driver; extern struct platform_driver tegra_dsi_driver;
......
...@@ -18,10 +18,12 @@ static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb) ...@@ -18,10 +18,12 @@ static inline struct tegra_fb *to_tegra_fb(struct drm_framebuffer *fb)
return container_of(fb, struct tegra_fb, base); 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) static inline struct tegra_fbdev *to_tegra_fbdev(struct drm_fb_helper *helper)
{ {
return container_of(helper, struct tegra_fbdev, base); return container_of(helper, struct tegra_fbdev, base);
} }
#endif
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
unsigned int index) unsigned int index)
...@@ -172,6 +174,7 @@ static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm, ...@@ -172,6 +174,7 @@ static struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
return ERR_PTR(err); return ERR_PTR(err);
} }
#ifdef CONFIG_DRM_TEGRA_FBDEV
static struct fb_ops tegra_fb_ops = { static struct fb_ops tegra_fb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_fillrect = sys_fillrect, .fb_fillrect = sys_fillrect,
...@@ -339,6 +342,15 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev) ...@@ -339,6 +342,15 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
kfree(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) static void tegra_fb_output_poll_changed(struct drm_device *drm)
{ {
struct tegra_drm *tegra = drm->dev_private; struct tegra_drm *tegra = drm->dev_private;
...@@ -346,16 +358,20 @@ static void tegra_fb_output_poll_changed(struct drm_device *drm) ...@@ -346,16 +358,20 @@ static void tegra_fb_output_poll_changed(struct drm_device *drm)
if (tegra->fbdev) if (tegra->fbdev)
drm_fb_helper_hotplug_event(&tegra->fbdev->base); drm_fb_helper_hotplug_event(&tegra->fbdev->base);
} }
#endif
static const struct drm_mode_config_funcs tegra_drm_mode_funcs = { static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
.fb_create = tegra_fb_create, .fb_create = tegra_fb_create,
#ifdef CONFIG_DRM_TEGRA_FBDEV
.output_poll_changed = tegra_fb_output_poll_changed, .output_poll_changed = tegra_fb_output_poll_changed,
#endif
}; };
int tegra_drm_fb_init(struct drm_device *drm) int tegra_drm_fb_init(struct drm_device *drm)
{ {
#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_drm *tegra = drm->dev_private; struct tegra_drm *tegra = drm->dev_private;
struct tegra_fbdev *fbdev; #endif
drm->mode_config.min_width = 0; drm->mode_config.min_width = 0;
drm->mode_config.min_height = 0; drm->mode_config.min_height = 0;
...@@ -365,28 +381,21 @@ int tegra_drm_fb_init(struct drm_device *drm) ...@@ -365,28 +381,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
drm->mode_config.funcs = &tegra_drm_mode_funcs; 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); drm->mode_config.num_connector);
if (IS_ERR(fbdev)) if (IS_ERR(tegra->fbdev))
return PTR_ERR(fbdev); return PTR_ERR(tegra->fbdev);
#endif
tegra->fbdev = fbdev;
return 0; return 0;
} }
void tegra_drm_fb_exit(struct drm_device *drm) void tegra_drm_fb_exit(struct drm_device *drm)
{ {
#ifdef CONFIG_DRM_TEGRA_FBDEV
struct tegra_drm *tegra = drm->dev_private; struct tegra_drm *tegra = drm->dev_private;
tegra_fbdev_free(tegra->fbdev); tegra_fbdev_free(tegra->fbdev);
} #endif
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);
}
} }
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