Commit 0b4c0f3f authored by Dave Airlie's avatar Dave Airlie

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: default avatarDave Airlie <airlied@redhat.com>
parent 8be48d92
...@@ -493,7 +493,6 @@ void drm_connector_cleanup(struct drm_connector *connector) ...@@ -493,7 +493,6 @@ void drm_connector_cleanup(struct drm_connector *connector)
list_for_each_entry_safe(mode, t, &connector->user_modes, head) list_for_each_entry_safe(mode, t, &connector->user_modes, head)
drm_mode_remove(connector, mode); drm_mode_remove(connector, mode);
kfree(connector->fb_helper_private);
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
drm_mode_object_put(dev, &connector->base); drm_mode_object_put(dev, &connector->base);
list_del(&connector->head); list_del(&connector->head);
......
...@@ -41,15 +41,33 @@ MODULE_LICENSE("GPL and additional rights"); ...@@ -41,15 +41,33 @@ MODULE_LICENSE("GPL and additional rights");
static LIST_HEAD(kernel_fb_helper_list); static LIST_HEAD(kernel_fb_helper_list);
int drm_fb_helper_add_connector(struct drm_connector *connector) /* simple single crtc case helper function */
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
{ {
connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL); struct drm_device *dev = fb_helper->dev;
if (!connector->fb_helper_private) struct drm_connector *connector;
return -ENOMEM; int i;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct drm_fb_helper_connector *fb_helper_connector;
fb_helper_connector = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
if (!fb_helper_connector)
goto fail;
fb_helper_connector->connector = connector;
fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
}
return 0; return 0;
fail:
for (i = 0; i < fb_helper->connector_count; i++) {
kfree(fb_helper->connector_info[i]);
fb_helper->connector_info[i] = NULL;
}
fb_helper->connector_count = 0;
return -ENOMEM;
} }
EXPORT_SYMBOL(drm_fb_helper_add_connector); EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
/** /**
* drm_fb_helper_connector_parse_command_line - parse command line for connector * drm_fb_helper_connector_parse_command_line - parse command line for connector
...@@ -64,7 +82,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_connector); ...@@ -64,7 +82,7 @@ EXPORT_SYMBOL(drm_fb_helper_add_connector);
* *
* enable/enable Digital/disable bit at the end * enable/enable Digital/disable bit at the end
*/ */
static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *connector, static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_connector *fb_helper_conn,
const char *mode_option) const char *mode_option)
{ {
const char *name; const char *name;
...@@ -74,13 +92,13 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con ...@@ -74,13 +92,13 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con
int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
int i; int i;
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode; struct drm_fb_helper_cmdline_mode *cmdline_mode;
struct drm_connector *connector = fb_helper_conn->connector;
if (!fb_help_conn) if (!fb_helper_conn)
return false; return false;
cmdline_mode = &fb_help_conn->cmdline_mode; cmdline_mode = &fb_helper_conn->cmdline_mode;
if (!mode_option) if (!mode_option)
mode_option = fb_mode_option; mode_option = fb_mode_option;
...@@ -203,18 +221,21 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con ...@@ -203,18 +221,21 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con
return true; return true;
} }
int drm_fb_helper_parse_command_line(struct drm_device *dev) static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
{ {
struct drm_connector *connector; struct drm_fb_helper_connector *fb_helper_conn;
int i;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { for (i = 0; i < fb_helper->connector_count; i++) {
char *option = NULL; char *option = NULL;
fb_helper_conn = fb_helper->connector_info[i];
/* do something on return - turn off connector maybe */ /* do something on return - turn off connector maybe */
if (fb_get_options(drm_get_connector_name(connector), &option)) if (fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option))
continue; continue;
drm_fb_helper_connector_parse_command_line(connector, option); drm_fb_helper_connector_parse_command_line(fb_helper_conn, option);
} }
return 0; return 0;
} }
...@@ -391,6 +412,9 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) ...@@ -391,6 +412,9 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
{ {
int i; int i;
for (i = 0; i < helper->connector_count; i++)
kfree(helper->connector_info[i]);
kfree(helper->connector_info);
for (i = 0; i < helper->crtc_count; i++) for (i = 0; i < helper->crtc_count; i++)
kfree(helper->crtc_info[i].mode_set.connectors); kfree(helper->crtc_info[i].mode_set.connectors);
kfree(helper->crtc_info); kfree(helper->crtc_info);
...@@ -411,6 +435,13 @@ int drm_fb_helper_init_crtc_count(struct drm_device *dev, ...@@ -411,6 +435,13 @@ int drm_fb_helper_init_crtc_count(struct drm_device *dev,
return -ENOMEM; return -ENOMEM;
helper->crtc_count = crtc_count; helper->crtc_count = crtc_count;
helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
if (!helper->connector_info) {
kfree(helper->crtc_info);
return -ENOMEM;
}
helper->connector_count = 0;
for (i = 0; i < crtc_count; i++) { for (i = 0; i < crtc_count; i++) {
helper->crtc_info[i].mode_set.connectors = helper->crtc_info[i].mode_set.connectors =
kcalloc(max_conn_count, kcalloc(max_conn_count,
...@@ -672,16 +703,12 @@ int drm_fb_helper_set_par(struct fb_info *info) ...@@ -672,16 +703,12 @@ int drm_fb_helper_set_par(struct fb_info *info)
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
for (i = 0; i < fb_helper->crtc_count; i++) { for (i = 0; i < fb_helper->crtc_count; i++) {
crtc = fb_helper->crtc_info[i].mode_set.crtc; crtc = fb_helper->crtc_info[i].mode_set.crtc;
if (crtc->fb != fb_helper->crtc_info[i].mode_set.fb) {
ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set); ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set);
if (ret) { if (ret) {
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
return ret; return ret;
} }
} }
}
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
return 0; return 0;
} }
...@@ -722,8 +749,6 @@ EXPORT_SYMBOL(drm_fb_helper_pan_display); ...@@ -722,8 +749,6 @@ EXPORT_SYMBOL(drm_fb_helper_pan_display);
int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
int preferred_bpp) int preferred_bpp)
{ {
struct drm_device *dev = fb_helper->dev;
struct drm_connector *connector;
int new_fb = 0; int new_fb = 0;
int crtc_count = 0; int crtc_count = 0;
int ret, i; int ret, i;
...@@ -743,14 +768,11 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -743,14 +768,11 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
sizes.surface_depth = sizes.surface_bpp = preferred_bpp; sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
} }
/* first up get a count of crtcs now in use and new min/maxes width/heights */ /* first up get a count of crtcs now in use and new min/maxes width/heights */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { for (i = 0; i < fb_helper->connector_count; i++) {
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private; struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
struct drm_fb_helper_cmdline_mode *cmdline_mode; struct drm_fb_helper_cmdline_mode *cmdline_mode;
if (!fb_help_conn) cmdline_mode = &fb_helper_conn->cmdline_mode;
continue;
cmdline_mode = &fb_help_conn->cmdline_mode;
if (cmdline_mode->bpp_specified) { if (cmdline_mode->bpp_specified) {
switch (cmdline_mode->bpp) { switch (cmdline_mode->bpp) {
...@@ -954,24 +976,27 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe ...@@ -954,24 +976,27 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
} }
EXPORT_SYMBOL(drm_fb_helper_fill_var); EXPORT_SYMBOL(drm_fb_helper_fill_var);
static int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper,
uint32_t maxX,
uint32_t maxY) uint32_t maxY)
{ {
struct drm_connector *connector; struct drm_connector *connector;
int count = 0; int count = 0;
int i;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { for (i = 0; i < fb_helper->connector_count; i++) {
connector = fb_helper->connector_info[i]->connector;
count += connector->funcs->fill_modes(connector, maxX, maxY); count += connector->funcs->fill_modes(connector, maxX, maxY);
} }
return count; return count;
} }
static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, int width, int height)
{ {
struct drm_display_mode *mode; struct drm_display_mode *mode;
list_for_each_entry(mode, &connector->modes, head) { list_for_each_entry(mode, &fb_connector->connector->modes, head) {
if (drm_mode_width(mode) > width || if (drm_mode_width(mode) > width ||
drm_mode_height(mode) > height) drm_mode_height(mode) > height)
continue; continue;
...@@ -981,28 +1006,20 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con ...@@ -981,28 +1006,20 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con
return NULL; return NULL;
} }
static bool drm_has_cmdline_mode(struct drm_connector *connector) static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
{ {
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode; struct drm_fb_helper_cmdline_mode *cmdline_mode;
cmdline_mode = &fb_connector->cmdline_mode;
if (!fb_help_conn)
return false;
cmdline_mode = &fb_help_conn->cmdline_mode;
return cmdline_mode->specified; return cmdline_mode->specified;
} }
static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height) static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
int width, int height)
{ {
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode; struct drm_fb_helper_cmdline_mode *cmdline_mode;
struct drm_display_mode *mode = NULL; struct drm_display_mode *mode = NULL;
if (!fb_help_conn) cmdline_mode = &fb_helper_conn->cmdline_mode;
return mode;
cmdline_mode = &fb_help_conn->cmdline_mode;
if (cmdline_mode->specified == false) if (cmdline_mode->specified == false)
return mode; return mode;
...@@ -1012,7 +1029,7 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *conn ...@@ -1012,7 +1029,7 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *conn
if (cmdline_mode->rb || cmdline_mode->margins) if (cmdline_mode->rb || cmdline_mode->margins)
goto create_mode; goto create_mode;
list_for_each_entry(mode, &connector->modes, head) { list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
/* check width/height */ /* check width/height */
if (mode->hdisplay != cmdline_mode->xres || if (mode->hdisplay != cmdline_mode->xres ||
mode->vdisplay != cmdline_mode->yres) mode->vdisplay != cmdline_mode->yres)
...@@ -1031,13 +1048,13 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *conn ...@@ -1031,13 +1048,13 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *conn
} }
create_mode: create_mode:
mode = drm_cvt_mode(connector->dev, cmdline_mode->xres, mode = drm_cvt_mode(fb_helper_conn->connector->dev, cmdline_mode->xres,
cmdline_mode->yres, cmdline_mode->yres,
cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
cmdline_mode->rb, cmdline_mode->interlace, cmdline_mode->rb, cmdline_mode->interlace,
cmdline_mode->margins); cmdline_mode->margins);
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
list_add(&mode->head, &connector->modes); list_add(&mode->head, &fb_helper_conn->connector->modes);
return mode; return mode;
} }
...@@ -1053,62 +1070,60 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict) ...@@ -1053,62 +1070,60 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
return enable; return enable;
} }
static void drm_enable_connectors(struct drm_device *dev, bool *enabled) static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
bool *enabled)
{ {
bool any_enabled = false; bool any_enabled = false;
struct drm_connector *connector; struct drm_connector *connector;
int i = 0; int i = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { for (i = 0; i < fb_helper->connector_count; i++) {
connector = fb_helper->connector_info[i]->connector;
enabled[i] = drm_connector_enabled(connector, true); enabled[i] = drm_connector_enabled(connector, true);
DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
enabled[i] ? "yes" : "no"); enabled[i] ? "yes" : "no");
any_enabled |= enabled[i]; any_enabled |= enabled[i];
i++;
} }
if (any_enabled) if (any_enabled)
return; return;
i = 0; for (i = 0; i < fb_helper->connector_count; i++) {
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { connector = fb_helper->connector_info[i]->connector;
enabled[i] = drm_connector_enabled(connector, false); enabled[i] = drm_connector_enabled(connector, false);
i++;
} }
} }
static bool drm_target_preferred(struct drm_device *dev, static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
struct drm_display_mode **modes, struct drm_display_mode **modes,
bool *enabled, int width, int height) bool *enabled, int width, int height)
{ {
struct drm_connector *connector; struct drm_fb_helper_connector *fb_helper_conn;
int i = 0; int i;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { for (i = 0; i < fb_helper->connector_count; i++) {
fb_helper_conn = fb_helper->connector_info[i];
if (enabled[i] == false) { if (enabled[i] == false)
i++;
continue; continue;
}
DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
connector->base.id); fb_helper_conn->connector->base.id);
/* got for command line mode first */ /* got for command line mode first */
modes[i] = drm_pick_cmdline_mode(connector, width, height); modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height);
if (!modes[i]) { if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
connector->base.id); fb_helper_conn->connector->base.id);
modes[i] = drm_has_preferred_mode(connector, width, height); modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height);
} }
/* No preferred modes, pick one off the list */ /* No preferred modes, pick one off the list */
if (!modes[i] && !list_empty(&connector->modes)) { if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) {
list_for_each_entry(modes[i], &connector->modes, head) list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head)
break; break;
} }
DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
"none"); "none");
i++;
} }
return true; return true;
} }
...@@ -1126,15 +1141,13 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, ...@@ -1126,15 +1141,13 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_crtc *best_crtc; struct drm_fb_helper_crtc *best_crtc;
int my_score, best_score, score; int my_score, best_score, score;
struct drm_fb_helper_crtc **crtcs, *crtc; struct drm_fb_helper_crtc **crtcs, *crtc;
struct drm_fb_helper_connector *fb_helper_conn;
if (n == fb_helper->dev->mode_config.num_connector) if (n == fb_helper->connector_count)
return 0; return 0;
c = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { fb_helper_conn = fb_helper->connector_info[n];
if (c == n) connector = fb_helper_conn->connector;
break;
c++;
}
best_crtcs[n] = NULL; best_crtcs[n] = NULL;
best_crtc = NULL; best_crtc = NULL;
...@@ -1150,9 +1163,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, ...@@ -1150,9 +1163,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
my_score = 1; my_score = 1;
if (connector->status == connector_status_connected) if (connector->status == connector_status_connected)
my_score++; my_score++;
if (drm_has_cmdline_mode(connector)) if (drm_has_cmdline_mode(fb_helper_conn))
my_score++; my_score++;
if (drm_has_preferred_mode(connector, width, height)) if (drm_has_preferred_mode(fb_helper_conn, width, height))
my_score++; my_score++;
connector_funcs = connector->helper_private; connector_funcs = connector->helper_private;
...@@ -1201,7 +1214,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) ...@@ -1201,7 +1214,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
struct drm_fb_helper_crtc **crtcs; struct drm_fb_helper_crtc **crtcs;
struct drm_display_mode **modes; struct drm_display_mode **modes;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_connector *connector;
struct drm_mode_set *modeset; struct drm_mode_set *modeset;
bool *enabled; bool *enabled;
int width, height; int width, height;
...@@ -1224,9 +1236,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) ...@@ -1224,9 +1236,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
enabled = kcalloc(dev->mode_config.num_connector, enabled = kcalloc(dev->mode_config.num_connector,
sizeof(bool), GFP_KERNEL); sizeof(bool), GFP_KERNEL);
drm_enable_connectors(dev, enabled); drm_enable_connectors(fb_helper, enabled);
ret = drm_target_preferred(dev, modes, enabled, width, height); ret = drm_target_preferred(fb_helper, modes, enabled, width, height);
if (!ret) if (!ret)
DRM_ERROR("Unable to find initial modes\n"); DRM_ERROR("Unable to find initial modes\n");
...@@ -1241,8 +1253,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) ...@@ -1241,8 +1253,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
modeset->num_connectors = 0; modeset->num_connectors = 0;
} }
i = 0; for (i = 0; i < fb_helper->connector_count; i++) {
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct drm_display_mode *mode = modes[i]; struct drm_display_mode *mode = modes[i];
struct drm_fb_helper_crtc *fb_crtc = crtcs[i]; struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
modeset = &fb_crtc->mode_set; modeset = &fb_crtc->mode_set;
...@@ -1255,9 +1266,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) ...@@ -1255,9 +1266,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
drm_mode_destroy(dev, modeset->mode); drm_mode_destroy(dev, modeset->mode);
modeset->mode = drm_mode_duplicate(dev, modeset->mode = drm_mode_duplicate(dev,
fb_crtc->desired_mode); fb_crtc->desired_mode);
modeset->connectors[modeset->num_connectors++] = connector; modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
} }
i++;
} }
kfree(crtcs); kfree(crtcs);
...@@ -1287,9 +1297,9 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper) ...@@ -1287,9 +1297,9 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper)
/* disable all the possible outputs/crtcs before entering KMS mode */ /* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(fb_helper->dev); drm_helper_disable_unused_functions(fb_helper->dev);
drm_fb_helper_parse_command_line(fb_helper->dev); drm_fb_helper_parse_command_line(fb_helper);
count = drm_helper_probe_connector_modes(dev, count = drm_fb_helper_probe_connector_modes(fb_helper,
dev->mode_config.max_width, dev->mode_config.max_width,
dev->mode_config.max_height); dev->mode_config.max_height);
...@@ -1310,7 +1320,7 @@ bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, ...@@ -1310,7 +1320,7 @@ bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper,
{ {
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
drm_helper_probe_connector_modes(fb_helper->dev, max_width, drm_fb_helper_probe_connector_modes(fb_helper, max_width,
max_height); max_height);
drm_setup_crtcs(fb_helper); drm_setup_crtcs(fb_helper);
......
...@@ -249,6 +249,7 @@ int intel_fbdev_init(struct drm_device *dev) ...@@ -249,6 +249,7 @@ int intel_fbdev_init(struct drm_device *dev)
drm_fb_helper_init_crtc_count(dev, &ifbdev->helper, 2, drm_fb_helper_init_crtc_count(dev, &ifbdev->helper, 2,
INTELFB_CONN_LIMIT); INTELFB_CONN_LIMIT);
drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
ifbdev->helper.fb_probe = intel_fb_find_or_create_single; ifbdev->helper.fb_probe = intel_fb_find_or_create_single;
drm_fb_helper_initial_config(&ifbdev->helper); drm_fb_helper_initial_config(&ifbdev->helper);
intelfb_probe(ifbdev); intelfb_probe(ifbdev);
......
...@@ -435,6 +435,8 @@ int nouveau_fbcon_init(struct drm_device *dev) ...@@ -435,6 +435,8 @@ int nouveau_fbcon_init(struct drm_device *dev)
drm_fb_helper_init_crtc_count(dev, &nfbdev->helper, drm_fb_helper_init_crtc_count(dev, &nfbdev->helper,
2, 4); 2, 4);
nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single; nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single;
drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
drm_fb_helper_initial_config(&nfbdev->helper); drm_fb_helper_initial_config(&nfbdev->helper);
nouveau_fbcon_probe(nfbdev); nouveau_fbcon_probe(nfbdev);
return 0; return 0;
......
...@@ -1032,7 +1032,6 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1032,7 +1032,6 @@ radeon_add_atom_connector(struct drm_device *dev,
struct radeon_connector_atom_dig *radeon_dig_connector; struct radeon_connector_atom_dig *radeon_dig_connector;
uint32_t subpixel_order = SubPixelNone; uint32_t subpixel_order = SubPixelNone;
bool shared_ddc = false; bool shared_ddc = false;
int ret;
/* fixme - tv/cv/din */ /* fixme - tv/cv/din */
if (connector_type == DRM_MODE_CONNECTOR_Unknown) if (connector_type == DRM_MODE_CONNECTOR_Unknown)
...@@ -1067,9 +1066,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1067,9 +1066,7 @@ radeon_add_atom_connector(struct drm_device *dev,
switch (connector_type) { switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1082,9 +1079,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1082,9 +1079,7 @@ radeon_add_atom_connector(struct drm_device *dev,
break; break;
case DRM_MODE_CONNECTOR_DVIA: case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1104,9 +1099,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1104,9 +1099,7 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1132,9 +1125,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1132,9 +1125,7 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1154,9 +1145,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1154,9 +1145,7 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
/* add DP i2c bus */ /* add DP i2c bus */
if (connector_type == DRM_MODE_CONNECTOR_eDP) if (connector_type == DRM_MODE_CONNECTOR_eDP)
...@@ -1182,9 +1171,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1182,9 +1171,7 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_9PinDIN: case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) { if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
if (ret)
goto failed;
radeon_connector->dac_load_detect = true; radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
...@@ -1202,9 +1189,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1202,9 +1189,7 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1241,7 +1226,6 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1241,7 +1226,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
struct drm_connector *connector; struct drm_connector *connector;
struct radeon_connector *radeon_connector; struct radeon_connector *radeon_connector;
uint32_t subpixel_order = SubPixelNone; uint32_t subpixel_order = SubPixelNone;
int ret;
/* fixme - tv/cv/din */ /* fixme - tv/cv/din */
if (connector_type == DRM_MODE_CONNECTOR_Unknown) if (connector_type == DRM_MODE_CONNECTOR_Unknown)
...@@ -1269,9 +1253,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1269,9 +1253,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
switch (connector_type) { switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1284,9 +1266,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1284,9 +1266,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
break; break;
case DRM_MODE_CONNECTOR_DVIA: case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1300,9 +1280,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1300,9 +1280,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_DVID:
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -1319,9 +1297,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1319,9 +1297,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_9PinDIN: case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) { if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
if (ret)
goto failed;
radeon_connector->dac_load_detect = true; radeon_connector->dac_load_detect = true;
/* RS400,RC410,RS480 chipset seems to report a lot /* RS400,RC410,RS480 chipset seems to report a lot
* of false positive on load detect, we haven't yet * of false positive on load detect, we haven't yet
...@@ -1340,9 +1316,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1340,9 +1316,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
break; break;
case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_LVDS:
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
......
...@@ -274,8 +274,6 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, ...@@ -274,8 +274,6 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
drm_framebuffer_cleanup(fb); drm_framebuffer_cleanup(fb);
kfree(fb); kfree(fb);
} }
out:
return ret; return ret;
} }
...@@ -380,6 +378,9 @@ int radeon_fbdev_init(struct radeon_device *rdev) ...@@ -380,6 +378,9 @@ int radeon_fbdev_init(struct radeon_device *rdev)
rdev->num_crtc, rdev->num_crtc,
RADEONFB_CONN_LIMIT); RADEONFB_CONN_LIMIT);
rfbdev->helper.fb_probe = radeon_fb_find_or_create_single; rfbdev->helper.fb_probe = radeon_fb_find_or_create_single;
drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
drm_fb_helper_initial_config(&rfbdev->helper); drm_fb_helper_initial_config(&rfbdev->helper);
radeonfb_probe(rfbdev); radeonfb_probe(rfbdev);
return 0; return 0;
......
...@@ -514,7 +514,6 @@ struct drm_connector { ...@@ -514,7 +514,6 @@ struct drm_connector {
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
uint32_t force_encoder_id; uint32_t force_encoder_id;
struct drm_encoder *encoder; /* currently active encoder */ struct drm_encoder *encoder; /* currently active encoder */
void *fb_helper_private;
}; };
/** /**
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include <linux/fb.h> #include <linux/fb.h>
#include "drm_fb_helper.h"
struct drm_crtc_helper_funcs { struct drm_crtc_helper_funcs {
/* /*
* Control power levels on the CRTC. If the mode passed in is * Control power levels on the CRTC. If the mode passed in is
...@@ -96,7 +95,6 @@ struct drm_connector_helper_funcs { ...@@ -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 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 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 int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
...@@ -122,11 +120,10 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder, ...@@ -122,11 +120,10 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder,
encoder->helper_private = (void *)funcs; 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) const struct drm_connector_helper_funcs *funcs)
{ {
connector->helper_private = (void *)funcs; connector->helper_private = (void *)funcs;
return drm_fb_helper_add_connector(connector);
} }
extern int drm_helper_resume_force_mode(struct drm_device *dev); extern int drm_helper_resume_force_mode(struct drm_device *dev);
......
...@@ -69,6 +69,7 @@ struct drm_fb_helper_surface_size { ...@@ -69,6 +69,7 @@ struct drm_fb_helper_surface_size {
struct drm_fb_helper_connector { struct drm_fb_helper_connector {
struct drm_fb_helper_cmdline_mode cmdline_mode; struct drm_fb_helper_cmdline_mode cmdline_mode;
struct drm_connector *connector;
}; };
struct drm_fb_helper { struct drm_fb_helper {
...@@ -77,6 +78,8 @@ struct drm_fb_helper { ...@@ -77,6 +78,8 @@ struct drm_fb_helper {
struct drm_display_mode *mode; struct drm_display_mode *mode;
int crtc_count; int crtc_count;
struct drm_fb_helper_crtc *crtc_info; struct drm_fb_helper_crtc *crtc_info;
int connector_count;
struct drm_fb_helper_connector **connector_info;
struct drm_fb_helper_funcs *funcs; struct drm_fb_helper_funcs *funcs;
int conn_limit; int conn_limit;
struct fb_info *fbdev; struct fb_info *fbdev;
...@@ -113,12 +116,11 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe ...@@ -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, void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
uint32_t depth); 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); 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, bool drm_helper_fb_hotplug_event(struct drm_fb_helper *fb_helper, u32 max_width,
u32 max_height); u32 max_height);
bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper); 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 #endif
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