From 386516744ba45d50f42c6999151cc210cb4f96e4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 30 Mar 2010 05:34:13 +0000 Subject: drm/fb: fix fbdev object model + cleanup properly. The fbdev layer in the kms code should act like a consumer of the kms services and avoid having relying on information being store in the kms core structures in order for it to work. This patch a) removes the info pointer/psuedo palette from the core drm_framebuffer structure and moves it to the fbdev helper layer, it also removes the core drm keeping a list of kernel kms fbdevs. b) migrated all the fb helper functions out of the crtc helper file into the fb helper file. c) pushed the fb probing/hotplug control into the driver d) makes the surface sizes into a structure for ease of passing This changes the intel/radeon/nouveau drivers to use the new helper. Signed-off-by: Dave Airlie --- include/drm/drm_crtc.h | 12 ------------ include/drm/drm_crtc_helper.h | 1 - include/drm/drm_fb_helper.h | 24 ++++++++++++++++-------- 3 files changed, 16 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 1347524a8e3..c70814b184e 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -271,8 +271,6 @@ struct drm_framebuffer { unsigned int depth; int bits_per_pixel; int flags; - struct fb_info *fbdev; - u32 pseudo_palette[17]; struct list_head filp_head; /* if you are using the helper */ void *helper_private; @@ -548,16 +546,9 @@ struct drm_mode_set { /** * struct drm_mode_config_funcs - configure CRTCs for a given screen layout - * @resize: adjust CRTCs as necessary for the proposed layout - * - * Currently only a resize hook is available. DRM will call back into the - * driver with a new screen width and height. If the driver can't support - * the proposed size, it can return false. Otherwise it should adjust - * the CRTC<->connector mappings as needed and update its view of the screen. */ struct drm_mode_config_funcs { struct drm_framebuffer *(*fb_create)(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd); - int (*fb_changed)(struct drm_device *dev); }; struct drm_mode_group { @@ -590,9 +581,6 @@ struct drm_mode_config { struct list_head property_list; - /* in-kernel framebuffers - hung of filp_head in drm_framebuffer */ - struct list_head fb_kernel_list; - int min_width, min_height; int max_width, max_height; struct drm_mode_config_funcs *funcs; diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index b29e20168b5..ce7aab77f7d 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -97,7 +97,6 @@ struct drm_connector_helper_funcs { extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); extern void drm_helper_disable_unused_functions(struct drm_device *dev); extern int drm_helper_hotplug_stage_two(struct drm_device *dev); -extern bool drm_helper_initial_config(struct drm_device *dev); extern int drm_crtc_helper_set_config(struct drm_mode_set *set); extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 58c892a2cbf..38ab0daffd1 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -57,6 +57,15 @@ struct drm_fb_helper_cmdline_mode { bool margins; }; +struct drm_fb_helper_surface_size { + u32 fb_width; + u32 fb_height; + u32 surface_width; + u32 surface_height; + u32 surface_bpp; + u32 surface_depth; +}; + struct drm_fb_helper_connector { struct drm_fb_helper_cmdline_mode cmdline_mode; }; @@ -69,19 +78,16 @@ struct drm_fb_helper { struct drm_fb_helper_crtc *crtc_info; struct drm_fb_helper_funcs *funcs; int conn_limit; + struct fb_info *fbdev; + u32 pseudo_palette[17]; struct list_head kernel_fb_list; }; int drm_fb_helper_single_fb_probe(struct drm_device *dev, int preferred_bpp, int (*fb_create)(struct drm_device *dev, - uint32_t fb_width, - uint32_t fb_height, - uint32_t surface_width, - uint32_t surface_height, - uint32_t surface_depth, - uint32_t surface_bpp, - struct drm_framebuffer **fb_ptr)); + struct drm_fb_helper_surface_size *sizes, + struct drm_fb_helper **fb_ptr)); int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn); void drm_fb_helper_free(struct drm_fb_helper *helper); @@ -99,7 +105,7 @@ int drm_fb_helper_setcolreg(unsigned regno, struct fb_info *info); void drm_fb_helper_restore(void); -void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb, +void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, uint32_t fb_width, uint32_t fb_height); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, uint32_t depth); @@ -108,4 +114,6 @@ int drm_fb_helper_add_connector(struct drm_connector *connector); int drm_fb_helper_parse_command_line(struct drm_device *dev); int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); +bool drm_helper_fb_hotplug_event(struct drm_device *dev); +bool drm_helper_initial_config(struct drm_device *dev); #endif -- cgit From 8be48d924c307e72e3797ab5bde81b07a1ccc52d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 30 Mar 2010 05:34:14 +0000 Subject: drm/kms/fb: move to using fb helper crtc grouping instead of core crtc list This move to using the list of crtcs in the fb helper and cleans up the whole picking code, now we store the crtc/connectors we want directly into the modeset and we use the modeset directly to set the mode. Fixes from James Simmons and Ben Skeggs. Signed-off-by: Dave Airlie --- include/drm/drm_crtc.h | 5 ----- include/drm/drm_fb_helper.h | 21 +++++++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c70814b184e..e4e34bae22c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -367,9 +367,6 @@ struct drm_crtc_funcs { * @enabled: is this CRTC enabled? * @x: x position on screen * @y: y position on screen - * @desired_mode: new desired mode - * @desired_x: desired x for desired_mode - * @desired_y: desired y for desired_mode * @funcs: CRTC control functions * * Each CRTC may have one or more connectors associated with it. This structure @@ -389,8 +386,6 @@ struct drm_crtc { struct drm_display_mode mode; int x, y; - struct drm_display_mode *desired_mode; - int desired_x, desired_y; const struct drm_crtc_funcs *funcs; /* CRTC gamma size for reporting to userspace */ diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 38ab0daffd1..b1ea66f11de 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -33,6 +33,7 @@ struct drm_fb_helper_crtc { uint32_t crtc_id; struct drm_mode_set mode_set; + struct drm_display_mode *desired_mode; }; @@ -81,14 +82,16 @@ struct drm_fb_helper { struct fb_info *fbdev; u32 pseudo_palette[17]; struct list_head kernel_fb_list; + + int (*fb_probe)(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes); }; -int drm_fb_helper_single_fb_probe(struct drm_device *dev, - int preferred_bpp, - int (*fb_create)(struct drm_device *dev, - struct drm_fb_helper_surface_size *sizes, - struct drm_fb_helper **fb_ptr)); -int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, +int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper, + int preferred_bpp); + +int drm_fb_helper_init_crtc_count(struct drm_device *dev, + struct drm_fb_helper *helper, int crtc_count, int max_conn); void drm_fb_helper_free(struct drm_fb_helper *helper); int drm_fb_helper_blank(int blank, struct fb_info *info); @@ -114,6 +117,8 @@ int drm_fb_helper_add_connector(struct drm_connector *connector); int drm_fb_helper_parse_command_line(struct drm_device *dev); int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); -bool drm_helper_fb_hotplug_event(struct drm_device *dev); -bool drm_helper_initial_config(struct drm_device *dev); +bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, u32 max_width, + u32 max_height); +bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); + #endif -- cgit From 0b4c0f3f0eceacb691e2b5570d9b16d751ce1b48 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 30 Mar 2010 05:34:15 +0000 Subject: drm/kms/fb: separate fbdev connector list from core drm connectors This breaks the connection between the core drm connector list and the fbdev connector usage, and allows them to become disjoint in the future. It also removes the untype void* that was in the connector struct to support this. All connectors are added to the fbdev now but this could be changed in the future. Signed-off-by: Dave Airlie --- include/drm/drm_crtc.h | 1 - include/drm/drm_crtc_helper.h | 5 +---- include/drm/drm_fb_helper.h | 6 ++++-- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index e4e34bae22c..fce2042ad0a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -514,7 +514,6 @@ struct drm_connector { uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t force_encoder_id; struct drm_encoder *encoder; /* currently active encoder */ - void *fb_helper_private; }; /** diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index ce7aab77f7d..b1fa0f8cfa6 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -39,7 +39,6 @@ #include -#include "drm_fb_helper.h" struct drm_crtc_helper_funcs { /* * Control power levels on the CRTC. If the mode passed in is @@ -96,7 +95,6 @@ struct drm_connector_helper_funcs { extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); extern void drm_helper_disable_unused_functions(struct drm_device *dev); -extern int drm_helper_hotplug_stage_two(struct drm_device *dev); extern int drm_crtc_helper_set_config(struct drm_mode_set *set); extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, @@ -122,11 +120,10 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder, encoder->helper_private = (void *)funcs; } -static inline int drm_connector_helper_add(struct drm_connector *connector, +static inline void drm_connector_helper_add(struct drm_connector *connector, const struct drm_connector_helper_funcs *funcs) { connector->helper_private = (void *)funcs; - return drm_fb_helper_add_connector(connector); } extern int drm_helper_resume_force_mode(struct drm_device *dev); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index b1ea66f11de..50094f94d4c 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -69,6 +69,7 @@ struct drm_fb_helper_surface_size { struct drm_fb_helper_connector { struct drm_fb_helper_cmdline_mode cmdline_mode; + struct drm_connector *connector; }; struct drm_fb_helper { @@ -77,6 +78,8 @@ struct drm_fb_helper { struct drm_display_mode *mode; int crtc_count; struct drm_fb_helper_crtc *crtc_info; + int connector_count; + struct drm_fb_helper_connector **connector_info; struct drm_fb_helper_funcs *funcs; int conn_limit; struct fb_info *fbdev; @@ -113,12 +116,11 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, uint32_t depth); -int drm_fb_helper_add_connector(struct drm_connector *connector); -int drm_fb_helper_parse_command_line(struct drm_device *dev); int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, u32 max_width, u32 max_height); bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); +int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); #endif -- cgit From 5c4426a782bc9509573fc7958a786ebd14fafdf3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 30 Mar 2010 05:34:17 +0000 Subject: drm/kms/fb: add polling support for when nothing is connected. When we are running in a headless environment we have no idea what output the user might plug in later, we only have hotplug detect from the digital outputs. So if we detect no connected outputs at initialisation, start a slow work operation to poll every 5 seconds for an output. this is only hooked up for radeon so far, on hw where we have full hotplug detection there is no need for this. Signed-off-by: Dave Airlie --- include/drm/drm_fb_helper.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 50094f94d4c..a073d73c195 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -30,6 +30,8 @@ #ifndef DRM_FB_HELPER_H #define DRM_FB_HELPER_H +#include + struct drm_fb_helper_crtc { uint32_t crtc_id; struct drm_mode_set mode_set; @@ -86,8 +88,12 @@ struct drm_fb_helper { u32 pseudo_palette[17]; struct list_head kernel_fb_list; + struct delayed_slow_work output_poll_slow_work; + bool poll_enabled; int (*fb_probe)(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); + + void (*fb_poll_changed)(struct drm_fb_helper *helper); }; int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper, @@ -118,9 +124,11 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); -bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, u32 max_width, - u32 max_height); +bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, + u32 max_width, u32 max_height, bool polled); bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); +void drm_fb_helper_poll_init(struct drm_fb_helper *fb_helper); +void drm_fb_helper_poll_fini(struct drm_fb_helper *fb_helper); #endif -- cgit From 4abe35204af82a018ca3ce6db4102aa09719698e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 30 Mar 2010 05:34:18 +0000 Subject: drm/kms/fb: use slow work mechanism for normal hotplug also. a) slow work is always used now for any fbcon hotplug, as its not a fast task and is more suited to being ran under slow work. b) attempt to not do any fbdev changes when X is running as we'll just mess it up. This hooks set_par to hopefully do the changes once X hands control to fbdev. This also adds the nouveau/intel hotplug support. Signed-off-by: Dave Airlie --- include/drm/drm_fb_helper.h | 47 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index a073d73c195..9b55a94fead 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -32,20 +32,14 @@ #include +struct drm_fb_helper; + struct drm_fb_helper_crtc { uint32_t crtc_id; struct drm_mode_set mode_set; struct drm_display_mode *desired_mode; }; - -struct drm_fb_helper_funcs { - void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, - u16 blue, int regno); - void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, int regno); -}; - /* mode specified on the command line */ struct drm_fb_helper_cmdline_mode { bool specified; @@ -69,6 +63,19 @@ struct drm_fb_helper_surface_size { u32 surface_depth; }; +struct drm_fb_helper_funcs { + void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, + u16 blue, int regno); + void (*gamma_get)(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, int regno); + + int (*fb_probe)(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes); + + void (*fb_output_status_changed)(struct drm_fb_helper *helper); + +}; + struct drm_fb_helper_connector { struct drm_fb_helper_cmdline_mode cmdline_mode; struct drm_connector *connector; @@ -88,21 +95,20 @@ struct drm_fb_helper { u32 pseudo_palette[17]; struct list_head kernel_fb_list; - struct delayed_slow_work output_poll_slow_work; + struct delayed_slow_work output_status_change_slow_work; bool poll_enabled; - int (*fb_probe)(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes); - - void (*fb_poll_changed)(struct drm_fb_helper *helper); + /* we got a hotplug but fbdev wasn't running the console + delay until next set_par */ + bool delayed_hotplug; }; int drm_fb_helper_single_fb_probe(struct drm_fb_helper *helper, int preferred_bpp); -int drm_fb_helper_init_crtc_count(struct drm_device *dev, - struct drm_fb_helper *helper, int crtc_count, - int max_conn); -void drm_fb_helper_free(struct drm_fb_helper *helper); +int drm_fb_helper_init(struct drm_device *dev, + struct drm_fb_helper *helper, int crtc_count, + int max_conn, bool polled); +void drm_fb_helper_fini(struct drm_fb_helper *helper); int drm_fb_helper_blank(int blank, struct fb_info *info); int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); @@ -125,10 +131,9 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, - u32 max_width, u32 max_height, bool polled); -bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); + bool polled); +bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); -void drm_fb_helper_poll_init(struct drm_fb_helper *fb_helper); -void drm_fb_helper_poll_fini(struct drm_fb_helper *fb_helper); +void drm_helper_fb_hpd_irq_event(struct drm_fb_helper *fb_helper); #endif -- cgit