Commit e5852bee authored by Noralf Trønnes's avatar Noralf Trønnes

drm/fb-helper: Remove drm_fb_helper_connector

All drivers add all their connectors so there's no need to keep around an
array of available connectors. Instead we just put the useable (not
writeback) connectors in a temporary array using
drm_client_for_each_connector_iter() everytime we probe the outputs.
Other places where it's necessary to look at the connectors, we just
iterate over them using the same iterator function.

Rename functions which signature is changed since they will be moved to
drm_client in a later patch.

v6: Improve commit message (Sam Ravnborg)
Signed-off-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Reviewed-by: default avatarSam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190608152657.36613-2-noralf@tronnes.org
parent 9ff3a5c8
...@@ -292,6 +292,10 @@ drm_fb_helper tasks ...@@ -292,6 +292,10 @@ drm_fb_helper tasks
- The max connector argument for drm_fb_helper_init() and - The max connector argument for drm_fb_helper_init() and
drm_fb_helper_fbdev_setup() isn't used anymore and can be removed. drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
- The helper doesn't keep an array of connectors anymore so these can be
removed: drm_fb_helper_single_add_all_connectors(),
drm_fb_helper_add_one_connector() and drm_fb_helper_remove_one_connector().
Core refactorings Core refactorings
================= =================
......
...@@ -95,12 +95,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); ...@@ -95,12 +95,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it * Setup fbdev emulation by calling drm_fb_helper_fbdev_setup() and tear it
* down by calling drm_fb_helper_fbdev_teardown(). * down by calling drm_fb_helper_fbdev_teardown().
* *
* Drivers that need to handle connector hotplugging (e.g. dp mst) can't use
* the setup helper and will need to do the whole four-step setup process with
* drm_fb_helper_prepare(), drm_fb_helper_init(),
* drm_fb_helper_single_add_all_connectors(), enable hotplugging and
* drm_fb_helper_initial_config() to avoid a possible race window.
*
* At runtime drivers should restore the fbdev console by using * At runtime drivers should restore the fbdev console by using
* drm_fb_helper_lastclose() as their &drm_driver.lastclose callback. * drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
* They should also notify the fb helper code from updates to the output * They should also notify the fb helper code from updates to the output
...@@ -123,8 +117,7 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); ...@@ -123,8 +117,7 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* encoders and connectors. To finish up the fbdev helper initialization, the * encoders and connectors. To finish up the fbdev helper initialization, the
* drm_fb_helper_init() function is called. To probe for all attached displays * drm_fb_helper_init() function is called. To probe for all attached displays
* and set up an initial configuration using the detected hardware, drivers * and set up an initial configuration using the detected hardware, drivers
* should call drm_fb_helper_single_add_all_connectors() followed by * should call drm_fb_helper_initial_config().
* drm_fb_helper_initial_config().
* *
* If &drm_framebuffer_funcs.dirty is set, the * If &drm_framebuffer_funcs.dirty is set, the
* drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
...@@ -137,165 +130,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); ...@@ -137,165 +130,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* deferred I/O (coupled with drm_fb_helper_fbdev_teardown()). * deferred I/O (coupled with drm_fb_helper_fbdev_teardown()).
*/ */
#define drm_fb_helper_for_each_connector(fbh, i__) \
for (({ lockdep_assert_held(&(fbh)->lock); }), \
i__ = 0; i__ < (fbh)->connector_count; i__++)
static int __drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
struct drm_fb_helper_connector *fb_conn;
struct drm_fb_helper_connector **temp;
unsigned int count;
if (!drm_fbdev_emulation)
return 0;
lockdep_assert_held(&fb_helper->lock);
count = fb_helper->connector_count + 1;
if (count > fb_helper->connector_info_alloc_count) {
size_t size = count * sizeof(fb_conn);
temp = krealloc(fb_helper->connector_info, size, GFP_KERNEL);
if (!temp)
return -ENOMEM;
fb_helper->connector_info_alloc_count = count;
fb_helper->connector_info = temp;
}
fb_conn = kzalloc(sizeof(*fb_conn), GFP_KERNEL);
if (!fb_conn)
return -ENOMEM;
drm_connector_get(connector);
fb_conn->connector = connector;
fb_helper->connector_info[fb_helper->connector_count++] = fb_conn;
return 0;
}
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
int err;
if (!fb_helper)
return 0;
mutex_lock(&fb_helper->lock);
err = __drm_fb_helper_add_one_connector(fb_helper, connector);
mutex_unlock(&fb_helper->lock);
return err;
}
EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
/**
* drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
* emulation helper
* @fb_helper: fbdev initialized with drm_fb_helper_init, can be NULL
*
* This functions adds all the available connectors for use with the given
* fb_helper. This is a separate step to allow drivers to freely assign
* connectors to the fbdev, e.g. if some are reserved for special purposes or
* not adequate to be used for the fbcon.
*
* This function is protected against concurrent connector hotadds/removals
* using drm_fb_helper_add_one_connector() and
* drm_fb_helper_remove_one_connector().
*/
int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
int i, ret = 0;
if (!drm_fbdev_emulation || !fb_helper)
return 0;
dev = fb_helper->dev;
mutex_lock(&fb_helper->lock);
drm_connector_list_iter_begin(dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
ret = __drm_fb_helper_add_one_connector(fb_helper, connector);
if (ret)
goto fail;
}
goto out;
fail:
drm_fb_helper_for_each_connector(fb_helper, i) {
struct drm_fb_helper_connector *fb_helper_connector =
fb_helper->connector_info[i];
drm_connector_put(fb_helper_connector->connector);
kfree(fb_helper_connector);
fb_helper->connector_info[i] = NULL;
}
fb_helper->connector_count = 0;
out:
drm_connector_list_iter_end(&conn_iter);
mutex_unlock(&fb_helper->lock);
return ret;
}
EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
static int __drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
struct drm_fb_helper_connector *fb_helper_connector;
int i, j;
if (!drm_fbdev_emulation)
return 0;
lockdep_assert_held(&fb_helper->lock);
drm_fb_helper_for_each_connector(fb_helper, i) {
if (fb_helper->connector_info[i]->connector == connector)
break;
}
if (i == fb_helper->connector_count)
return -EINVAL;
fb_helper_connector = fb_helper->connector_info[i];
drm_connector_put(fb_helper_connector->connector);
for (j = i + 1; j < fb_helper->connector_count; j++)
fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
fb_helper->connector_count--;
kfree(fb_helper_connector);
return 0;
}
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
int err;
if (!fb_helper)
return 0;
mutex_lock(&fb_helper->lock);
err = __drm_fb_helper_remove_one_connector(fb_helper, connector);
mutex_unlock(&fb_helper->lock);
return err;
}
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
{ {
uint16_t *r_base, *g_base, *b_base; uint16_t *r_base, *g_base, *b_base;
...@@ -645,20 +479,9 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -645,20 +479,9 @@ int drm_fb_helper_init(struct drm_device *dev,
return ret; return ret;
} }
fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
if (!fb_helper->connector_info)
goto out_free;
fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
fb_helper->connector_count = 0;
dev->fb_helper = fb_helper; dev->fb_helper = fb_helper;
return 0; return 0;
out_free:
drm_client_release(&fb_helper->client);
return -ENOMEM;
} }
EXPORT_SYMBOL(drm_fb_helper_init); EXPORT_SYMBOL(drm_fb_helper_init);
...@@ -733,7 +556,6 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi); ...@@ -733,7 +556,6 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{ {
struct fb_info *info; struct fb_info *info;
int i;
if (!fb_helper) if (!fb_helper)
return; return;
...@@ -766,12 +588,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) ...@@ -766,12 +588,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
if (!fb_helper->client.funcs) if (!fb_helper->client.funcs)
drm_client_release(&fb_helper->client); drm_client_release(&fb_helper->client);
for (i = 0; i < fb_helper->connector_count; i++) {
drm_connector_put(fb_helper->connector_info[i]->connector);
kfree(fb_helper->connector_info[i]);
}
kfree(fb_helper->connector_info);
} }
EXPORT_SYMBOL(drm_fb_helper_fini); EXPORT_SYMBOL(drm_fb_helper_fini);
...@@ -1650,8 +1466,9 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -1650,8 +1466,9 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_client_dev *client = &fb_helper->client; struct drm_client_dev *client = &fb_helper->client;
int ret = 0; int ret = 0;
int crtc_count = 0; int crtc_count = 0;
int i; struct drm_connector_list_iter conn_iter;
struct drm_fb_helper_surface_size sizes; struct drm_fb_helper_surface_size sizes;
struct drm_connector *connector;
struct drm_mode_set *mode_set; struct drm_mode_set *mode_set;
int best_depth = 0; int best_depth = 0;
...@@ -1668,11 +1485,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -1668,11 +1485,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (preferred_bpp != sizes.surface_bpp) if (preferred_bpp != sizes.surface_bpp)
sizes.surface_depth = sizes.surface_bpp = preferred_bpp; sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
drm_fb_helper_for_each_connector(fb_helper, i) { drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; drm_client_for_each_connector_iter(connector, &conn_iter) {
struct drm_cmdline_mode *cmdline_mode; struct drm_cmdline_mode *cmdline_mode;
cmdline_mode = &fb_helper_conn->connector->cmdline_mode; cmdline_mode = &connector->cmdline_mode;
if (cmdline_mode->bpp_specified) { if (cmdline_mode->bpp_specified) {
switch (cmdline_mode->bpp) { switch (cmdline_mode->bpp) {
...@@ -1697,6 +1514,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, ...@@ -1697,6 +1514,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
break; break;
} }
} }
drm_connector_list_iter_end(&conn_iter);
/* /*
* If we run into a situation where, for example, the primary plane * If we run into a situation where, for example, the primary plane
...@@ -1881,26 +1699,12 @@ void drm_fb_helper_fill_info(struct fb_info *info, ...@@ -1881,26 +1699,12 @@ void drm_fb_helper_fill_info(struct fb_info *info,
} }
EXPORT_SYMBOL(drm_fb_helper_fill_info); EXPORT_SYMBOL(drm_fb_helper_fill_info);
static int drm_fb_helper_probe_connector_modes(struct drm_fb_helper *fb_helper, static struct drm_display_mode *
uint32_t maxX, drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height)
uint32_t maxY)
{
struct drm_connector *connector;
int i, count = 0;
drm_fb_helper_for_each_connector(fb_helper, i) {
connector = fb_helper->connector_info[i]->connector;
count += connector->funcs->fill_modes(connector, maxX, maxY);
}
return count;
}
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, &fb_connector->connector->modes, head) { list_for_each_entry(mode, &connector->modes, head) {
if (mode->hdisplay > width || if (mode->hdisplay > width ||
mode->vdisplay > height) mode->vdisplay > height)
continue; continue;
...@@ -1909,20 +1713,15 @@ struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector * ...@@ -1909,20 +1713,15 @@ struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_connector *
} }
return NULL; return NULL;
} }
EXPORT_SYMBOL(drm_has_preferred_mode);
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
{
return fb_connector->connector->cmdline_mode.specified;
}
struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn) static struct drm_display_mode *
drm_connector_pick_cmdline_mode(struct drm_connector *connector)
{ {
struct drm_cmdline_mode *cmdline_mode; struct drm_cmdline_mode *cmdline_mode;
struct drm_display_mode *mode; struct drm_display_mode *mode;
bool prefer_non_interlace; bool prefer_non_interlace;
cmdline_mode = &fb_helper_conn->connector->cmdline_mode; cmdline_mode = &connector->cmdline_mode;
if (cmdline_mode->specified == false) if (cmdline_mode->specified == false)
return NULL; return NULL;
...@@ -1934,7 +1733,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f ...@@ -1934,7 +1733,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
prefer_non_interlace = !cmdline_mode->interlace; prefer_non_interlace = !cmdline_mode->interlace;
again: again:
list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) { list_for_each_entry(mode, &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)
...@@ -1961,12 +1760,11 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f ...@@ -1961,12 +1760,11 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
} }
create_mode: create_mode:
mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, mode = drm_mode_create_from_cmdline_mode(connector->dev, cmdline_mode);
cmdline_mode); list_add(&mode->head, &connector->modes);
list_add(&mode->head, &fb_helper_conn->connector->modes);
return mode; return mode;
} }
EXPORT_SYMBOL(drm_pick_cmdline_mode);
static bool drm_connector_enabled(struct drm_connector *connector, bool strict) static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
{ {
...@@ -1983,15 +1781,16 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict) ...@@ -1983,15 +1781,16 @@ static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
return enable; return enable;
} }
static void drm_enable_connectors(struct drm_fb_helper *fb_helper, static void drm_client_connectors_enabled(struct drm_connector **connectors,
unsigned int connector_count,
bool *enabled) bool *enabled)
{ {
bool any_enabled = false; bool any_enabled = false;
struct drm_connector *connector; struct drm_connector *connector;
int i = 0; int i = 0;
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
connector = fb_helper->connector_info[i]->connector; connector = connectors[i];
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,
connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no"); connector->display_info.non_desktop ? "non desktop" : enabled[i] ? "yes" : "no");
...@@ -2002,28 +1801,27 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper, ...@@ -2002,28 +1801,27 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper,
if (any_enabled) if (any_enabled)
return; return;
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++)
connector = fb_helper->connector_info[i]->connector; enabled[i] = drm_connector_enabled(connectors[i], false);
enabled[i] = drm_connector_enabled(connector, false);
}
} }
static bool drm_target_cloned(struct drm_fb_helper *fb_helper, static bool drm_client_target_cloned(struct drm_device *dev,
struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes, struct drm_display_mode **modes,
struct drm_fb_offset *offsets, struct drm_fb_offset *offsets,
bool *enabled, int width, int height) bool *enabled, int width, int height)
{ {
int count, i, j; int count, i, j;
bool can_clone = false; bool can_clone = false;
struct drm_fb_helper_connector *fb_helper_conn;
struct drm_display_mode *dmt_mode, *mode; struct drm_display_mode *dmt_mode, *mode;
/* only contemplate cloning in the single crtc case */ /* only contemplate cloning in the single crtc case */
if (fb_helper->dev->mode_config.num_crtc > 1) if (dev->mode_config.num_crtc > 1)
return false; return false;
count = 0; count = 0;
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
if (enabled[i]) if (enabled[i])
count++; count++;
} }
...@@ -2034,11 +1832,10 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, ...@@ -2034,11 +1832,10 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
/* check the command line or if nothing common pick 1024x768 */ /* check the command line or if nothing common pick 1024x768 */
can_clone = true; can_clone = true;
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
if (!enabled[i]) if (!enabled[i])
continue; continue;
fb_helper_conn = fb_helper->connector_info[i]; modes[i] = drm_connector_pick_cmdline_mode(connectors[i]);
modes[i] = drm_pick_cmdline_mode(fb_helper_conn);
if (!modes[i]) { if (!modes[i]) {
can_clone = false; can_clone = false;
break; break;
...@@ -2062,14 +1859,13 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, ...@@ -2062,14 +1859,13 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
/* try and find a 1024x768 mode on each connector */ /* try and find a 1024x768 mode on each connector */
can_clone = true; can_clone = true;
dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false); dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
if (!enabled[i]) if (!enabled[i])
continue; continue;
fb_helper_conn = fb_helper->connector_info[i]; list_for_each_entry(mode, &connectors[i]->modes, head) {
list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
if (drm_mode_match(mode, dmt_mode, if (drm_mode_match(mode, dmt_mode,
DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_TIMINGS |
DRM_MODE_MATCH_CLOCK | DRM_MODE_MATCH_CLOCK |
...@@ -2089,30 +1885,31 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper, ...@@ -2089,30 +1885,31 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
return false; return false;
} }
static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper, static int drm_client_get_tile_offsets(struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes, struct drm_display_mode **modes,
struct drm_fb_offset *offsets, struct drm_fb_offset *offsets,
int idx, int idx,
int h_idx, int v_idx) int h_idx, int v_idx)
{ {
struct drm_fb_helper_connector *fb_helper_conn; struct drm_connector *connector;
int i; int i;
int hoffset = 0, voffset = 0; int hoffset = 0, voffset = 0;
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
fb_helper_conn = fb_helper->connector_info[i]; connector = connectors[i];
if (!fb_helper_conn->connector->has_tile) if (!connector->has_tile)
continue; continue;
if (!modes[i] && (h_idx || v_idx)) { if (!modes[i] && (h_idx || v_idx)) {
DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i,
fb_helper_conn->connector->base.id); connector->base.id);
continue; continue;
} }
if (fb_helper_conn->connector->tile_h_loc < h_idx) if (connector->tile_h_loc < h_idx)
hoffset += modes[i]->hdisplay; hoffset += modes[i]->hdisplay;
if (fb_helper_conn->connector->tile_v_loc < v_idx) if (connector->tile_v_loc < v_idx)
voffset += modes[i]->vdisplay; voffset += modes[i]->vdisplay;
} }
offsets[idx].x = hoffset; offsets[idx].x = hoffset;
...@@ -2121,20 +1918,21 @@ static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper, ...@@ -2121,20 +1918,21 @@ static int drm_get_tile_offsets(struct drm_fb_helper *fb_helper,
return 0; return 0;
} }
static bool drm_target_preferred(struct drm_fb_helper *fb_helper, static bool drm_client_target_preferred(struct drm_connector **connectors,
unsigned int connector_count,
struct drm_display_mode **modes, struct drm_display_mode **modes,
struct drm_fb_offset *offsets, struct drm_fb_offset *offsets,
bool *enabled, int width, int height) bool *enabled, int width, int height)
{ {
struct drm_fb_helper_connector *fb_helper_conn; const u64 mask = BIT_ULL(connector_count) - 1;
const u64 mask = BIT_ULL(fb_helper->connector_count) - 1; struct drm_connector *connector;
u64 conn_configured = 0; u64 conn_configured = 0;
int tile_pass = 0; int tile_pass = 0;
int i; int i;
retry: retry:
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
fb_helper_conn = fb_helper->connector_info[i]; connector = connectors[i];
if (conn_configured & BIT_ULL(i)) if (conn_configured & BIT_ULL(i))
continue; continue;
...@@ -2145,17 +1943,17 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper, ...@@ -2145,17 +1943,17 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
} }
/* first pass over all the untiled connectors */ /* first pass over all the untiled connectors */
if (tile_pass == 0 && fb_helper_conn->connector->has_tile) if (tile_pass == 0 && connector->has_tile)
continue; continue;
if (tile_pass == 1) { if (tile_pass == 1) {
if (fb_helper_conn->connector->tile_h_loc != 0 || if (connector->tile_h_loc != 0 ||
fb_helper_conn->connector->tile_v_loc != 0) connector->tile_v_loc != 0)
continue; continue;
} else { } else {
if (fb_helper_conn->connector->tile_h_loc != tile_pass - 1 && if (connector->tile_h_loc != tile_pass - 1 &&
fb_helper_conn->connector->tile_v_loc != tile_pass - 1) connector->tile_v_loc != tile_pass - 1)
/* if this tile_pass doesn't cover any of the tiles - keep going */ /* if this tile_pass doesn't cover any of the tiles - keep going */
continue; continue;
...@@ -2163,22 +1961,22 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper, ...@@ -2163,22 +1961,22 @@ static bool drm_target_preferred(struct drm_fb_helper *fb_helper,
* find the tile offsets for this pass - need to find * find the tile offsets for this pass - need to find
* all tiles left and above * all tiles left and above
*/ */
drm_get_tile_offsets(fb_helper, modes, offsets, drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i,
i, fb_helper_conn->connector->tile_h_loc, fb_helper_conn->connector->tile_v_loc); connector->tile_h_loc, connector->tile_v_loc);
} }
DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
fb_helper_conn->connector->base.id); connector->base.id);
/* got for command line mode first */ /* got for command line mode first */
modes[i] = drm_pick_cmdline_mode(fb_helper_conn); modes[i] = drm_connector_pick_cmdline_mode(connector);
if (!modes[i]) { if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n",
fb_helper_conn->connector->base.id, fb_helper_conn->connector->tile_group ? fb_helper_conn->connector->tile_group->id : 0); connector->base.id, connector->tile_group ? connector->tile_group->id : 0);
modes[i] = drm_has_preferred_mode(fb_helper_conn, width, height); modes[i] = drm_connector_has_preferred_mode(connector, width, height);
} }
/* No preferred modes, pick one off the list */ /* No preferred modes, pick one off the list */
if (!modes[i] && !list_empty(&fb_helper_conn->connector->modes)) { if (!modes[i] && !list_empty(&connector->modes)) {
list_for_each_entry(modes[i], &fb_helper_conn->connector->modes, head) list_for_each_entry(modes[i], &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 :
...@@ -2207,40 +2005,41 @@ static bool connector_has_possible_crtc(struct drm_connector *connector, ...@@ -2207,40 +2005,41 @@ static bool connector_has_possible_crtc(struct drm_connector *connector,
return false; return false;
} }
static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, static int drm_client_pick_crtcs(struct drm_client_dev *client,
struct drm_connector **connectors,
unsigned int connector_count,
struct drm_crtc **best_crtcs, struct drm_crtc **best_crtcs,
struct drm_display_mode **modes, struct drm_display_mode **modes,
int n, int width, int height) int n, int width, int height)
{ {
struct drm_client_dev *client = &fb_helper->client; struct drm_device *dev = client->dev;
struct drm_connector *connector; struct drm_connector *connector;
int my_score, best_score, score; int my_score, best_score, score;
struct drm_crtc **crtcs, *crtc; struct drm_crtc **crtcs, *crtc;
struct drm_mode_set *modeset; struct drm_mode_set *modeset;
struct drm_fb_helper_connector *fb_helper_conn;
int o; int o;
if (n == fb_helper->connector_count) if (n == connector_count)
return 0; return 0;
fb_helper_conn = fb_helper->connector_info[n]; connector = connectors[n];
connector = fb_helper_conn->connector;
best_crtcs[n] = NULL; best_crtcs[n] = NULL;
best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height); best_score = drm_client_pick_crtcs(client, connectors, connector_count,
best_crtcs, modes, n + 1, width, height);
if (modes[n] == NULL) if (modes[n] == NULL)
return best_score; return best_score;
crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL); crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
if (!crtcs) if (!crtcs)
return best_score; return best_score;
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(fb_helper_conn)) if (connector->cmdline_mode.specified)
my_score++; my_score++;
if (drm_has_preferred_mode(fb_helper_conn, width, height)) if (drm_connector_has_preferred_mode(connector, width, height))
my_score++; my_score++;
/* /*
...@@ -2259,7 +2058,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2259,7 +2058,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
if (o < n) { if (o < n) {
/* ignore cloning unless only a single crtc */ /* ignore cloning unless only a single crtc */
if (fb_helper->dev->mode_config.num_crtc > 1) if (dev->mode_config.num_crtc > 1)
continue; continue;
if (!drm_mode_equal(modes[o], modes[n])) if (!drm_mode_equal(modes[o], modes[n]))
...@@ -2268,12 +2067,11 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2268,12 +2067,11 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
crtcs[n] = crtc; crtcs[n] = crtc;
memcpy(crtcs, best_crtcs, n * sizeof(*crtcs)); memcpy(crtcs, best_crtcs, n * sizeof(*crtcs));
score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1, score = my_score + drm_client_pick_crtcs(client, connectors, connector_count,
width, height); crtcs, modes, n + 1, width, height);
if (score > best_score) { if (score > best_score) {
best_score = score; best_score = score;
memcpy(best_crtcs, crtcs, memcpy(best_crtcs, crtcs, connector_count * sizeof(*crtcs));
fb_helper->connector_count * sizeof(*crtcs));
} }
} }
...@@ -2282,15 +2080,17 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2282,15 +2080,17 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
} }
/* Try to read the BIOS display configuration and use it for the initial config */ /* Try to read the BIOS display configuration and use it for the initial config */
static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, static bool drm_client_firmware_config(struct drm_client_dev *client,
struct drm_connector **connectors,
unsigned int connector_count,
struct drm_crtc **crtcs, struct drm_crtc **crtcs,
struct drm_display_mode **modes, struct drm_display_mode **modes,
struct drm_fb_offset *offsets, struct drm_fb_offset *offsets,
bool *enabled, int width, int height) bool *enabled, int width, int height)
{ {
struct drm_device *dev = fb_helper->dev; unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG);
unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
unsigned long conn_configured, conn_seq, mask; unsigned long conn_configured, conn_seq, mask;
struct drm_device *dev = client->dev;
int i, j; int i, j;
bool *save_enabled; bool *save_enabled;
bool fallback = true, ret = true; bool fallback = true, ret = true;
...@@ -2316,13 +2116,11 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, ...@@ -2316,13 +2116,11 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
retry: retry:
conn_seq = conn_configured; conn_seq = conn_configured;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
struct drm_fb_helper_connector *fb_conn;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_crtc *new_crtc; struct drm_crtc *new_crtc;
fb_conn = fb_helper->connector_info[i]; connector = connectors[i];
connector = fb_conn->connector;
if (conn_configured & BIT(i)) if (conn_configured & BIT(i))
continue; continue;
...@@ -2379,14 +2177,13 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, ...@@ -2379,14 +2177,13 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
connector->name); connector->name);
/* go for command line mode first */ /* go for command line mode first */
modes[i] = drm_pick_cmdline_mode(fb_conn); modes[i] = drm_connector_pick_cmdline_mode(connector);
/* try for preferred next */ /* try for preferred next */
if (!modes[i]) { if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n",
connector->name, connector->has_tile); connector->name, connector->has_tile);
modes[i] = drm_has_preferred_mode(fb_conn, width, modes[i] = drm_connector_has_preferred_mode(connector, width, height);
height);
} }
/* No preferred mode marked by the EDID? Are there any modes? */ /* No preferred mode marked by the EDID? Are there any modes? */
...@@ -2461,8 +2258,12 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper, ...@@ -2461,8 +2258,12 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
u32 width, u32 height) u32 width, u32 height)
{ {
struct drm_connector *connector, **connectors = NULL;
struct drm_client_dev *client = &fb_helper->client; struct drm_client_dev *client = &fb_helper->client;
struct drm_connector_list_iter conn_iter;
struct drm_device *dev = fb_helper->dev; struct drm_device *dev = fb_helper->dev;
unsigned int total_modes_count = 0;
unsigned int connector_count = 0;
struct drm_display_mode **modes; struct drm_display_mode **modes;
struct drm_fb_offset *offsets; struct drm_fb_offset *offsets;
struct drm_crtc **crtcs; struct drm_crtc **crtcs;
...@@ -2470,16 +2271,28 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2470,16 +2271,28 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
int i; int i;
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
/* prevent concurrent modification of connector_count by hotplug */
lockdep_assert_held(&fb_helper->lock); drm_connector_list_iter_begin(dev, &conn_iter);
drm_client_for_each_connector_iter(connector, &conn_iter) {
crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL); struct drm_connector **tmp;
modes = kcalloc(fb_helper->connector_count,
sizeof(struct drm_display_mode *), GFP_KERNEL); tmp = krealloc(connectors, (connector_count + 1) * sizeof(*connectors), GFP_KERNEL);
offsets = kcalloc(fb_helper->connector_count, if (!tmp)
sizeof(struct drm_fb_offset), GFP_KERNEL); goto free_connectors;
enabled = kcalloc(fb_helper->connector_count,
sizeof(bool), GFP_KERNEL); connectors = tmp;
drm_connector_get(connector);
connectors[connector_count++] = connector;
}
drm_connector_list_iter_end(&conn_iter);
if (!connector_count)
return;
crtcs = kcalloc(connector_count, sizeof(*crtcs), GFP_KERNEL);
modes = kcalloc(connector_count, sizeof(*modes), GFP_KERNEL);
offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL);
enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL);
if (!crtcs || !modes || !enabled || !offsets) { if (!crtcs || !modes || !enabled || !offsets) {
DRM_ERROR("Memory allocation failed\n"); DRM_ERROR("Memory allocation failed\n");
goto out; goto out;
...@@ -2488,40 +2301,42 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2488,40 +2301,42 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
mutex_lock(&client->modeset_mutex); mutex_lock(&client->modeset_mutex);
mutex_lock(&fb_helper->dev->mode_config.mutex); mutex_lock(&fb_helper->dev->mode_config.mutex);
if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0) for (i = 0; i < connector_count; i++)
total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height);
if (!total_modes_count)
DRM_DEBUG_KMS("No connectors reported connected with modes\n"); DRM_DEBUG_KMS("No connectors reported connected with modes\n");
drm_enable_connectors(fb_helper, enabled); drm_client_connectors_enabled(connectors, connector_count, enabled);
if (!drm_fb_helper_firmware_config(fb_helper, crtcs, modes, offsets, if (!drm_client_firmware_config(client, connectors, connector_count, crtcs,
enabled, width, height)) { modes, offsets, enabled, width, height)) {
memset(modes, 0, fb_helper->connector_count*sizeof(modes[0])); memset(modes, 0, connector_count * sizeof(*modes));
memset(crtcs, 0, fb_helper->connector_count*sizeof(crtcs[0])); memset(crtcs, 0, connector_count * sizeof(*crtcs));
memset(offsets, 0, fb_helper->connector_count*sizeof(offsets[0])); memset(offsets, 0, connector_count * sizeof(*offsets));
if (!drm_target_cloned(fb_helper, modes, offsets, if (!drm_client_target_cloned(dev, connectors, connector_count, modes,
enabled, width, height) && offsets, enabled, width, height) &&
!drm_target_preferred(fb_helper, modes, offsets, !drm_client_target_preferred(connectors, connector_count, modes,
enabled, width, height)) offsets, enabled, width, height))
DRM_ERROR("Unable to find initial modes\n"); DRM_ERROR("Unable to find initial modes\n");
DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
width, height); width, height);
drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); drm_client_pick_crtcs(client, connectors, connector_count,
crtcs, modes, 0, width, height);
} }
mutex_unlock(&fb_helper->dev->mode_config.mutex); mutex_unlock(&fb_helper->dev->mode_config.mutex);
drm_client_modeset_release(client); drm_client_modeset_release(client);
drm_fb_helper_for_each_connector(fb_helper, i) { for (i = 0; i < connector_count; i++) {
struct drm_display_mode *mode = modes[i]; struct drm_display_mode *mode = modes[i];
struct drm_crtc *crtc = crtcs[i]; struct drm_crtc *crtc = crtcs[i];
struct drm_fb_offset *offset = &offsets[i]; struct drm_fb_offset *offset = &offsets[i];
if (mode && crtc) { if (mode && crtc) {
struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc); struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc);
struct drm_connector *connector = struct drm_connector *connector = connectors[i];
fb_helper->connector_info[i]->connector;
DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
mode->name, crtc->base.id, offset->x, offset->y); mode->name, crtc->base.id, offset->x, offset->y);
...@@ -2544,6 +2359,10 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2544,6 +2359,10 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
kfree(modes); kfree(modes);
kfree(offsets); kfree(offsets);
kfree(enabled); kfree(enabled);
free_connectors:
for (i = 0; i < connector_count; i++)
drm_connector_put(connectors[i]);
kfree(connectors);
} }
/* /*
...@@ -2556,10 +2375,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper, ...@@ -2556,10 +2375,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
{ {
struct drm_client_dev *client = &fb_helper->client; struct drm_client_dev *client = &fb_helper->client;
struct drm_connector_list_iter conn_iter;
struct fb_info *info = fb_helper->fbdev; struct fb_info *info = fb_helper->fbdev;
unsigned int rotation, sw_rotations = 0; unsigned int rotation, sw_rotations = 0;
struct drm_connector *connector;
struct drm_mode_set *modeset; struct drm_mode_set *modeset;
int i;
mutex_lock(&client->modeset_mutex); mutex_lock(&client->modeset_mutex);
drm_client_for_each_modeset(modeset, client) { drm_client_for_each_modeset(modeset, client) {
...@@ -2576,10 +2396,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) ...@@ -2576,10 +2396,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
} }
mutex_unlock(&client->modeset_mutex); mutex_unlock(&client->modeset_mutex);
mutex_lock(&fb_helper->dev->mode_config.mutex); drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
drm_fb_helper_for_each_connector(fb_helper, i) { drm_client_for_each_connector_iter(connector, &conn_iter) {
struct drm_connector *connector =
fb_helper->connector_info[i]->connector;
/* use first connected connector for the physical dimensions */ /* use first connected connector for the physical dimensions */
if (connector->status == connector_status_connected) { if (connector->status == connector_status_connected) {
...@@ -2588,7 +2406,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper) ...@@ -2588,7 +2406,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
break; break;
} }
} }
mutex_unlock(&fb_helper->dev->mode_config.mutex); drm_connector_list_iter_end(&conn_iter);
switch (sw_rotations) { switch (sw_rotations) {
case DRM_MODE_ROTATE_0: case DRM_MODE_ROTATE_0:
...@@ -2826,12 +2644,6 @@ int drm_fb_helper_fbdev_setup(struct drm_device *dev, ...@@ -2826,12 +2644,6 @@ int drm_fb_helper_fbdev_setup(struct drm_device *dev,
return ret; return ret;
} }
ret = drm_fb_helper_single_add_all_connectors(fb_helper);
if (ret < 0) {
DRM_DEV_ERROR(dev->dev, "fbdev: Failed to add connectors (ret=%d)\n", ret);
goto err_drm_fb_helper_fini;
}
if (!drm_drv_uses_atomic_modeset(dev)) if (!drm_drv_uses_atomic_modeset(dev))
drm_helper_disable_unused_functions(dev); drm_helper_disable_unused_functions(dev);
...@@ -3137,10 +2949,6 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client) ...@@ -3137,10 +2949,6 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
if (ret) if (ret)
goto err; goto err;
ret = drm_fb_helper_single_add_all_connectors(fb_helper);
if (ret)
goto err_cleanup;
if (!drm_drv_uses_atomic_modeset(dev)) if (!drm_drv_uses_atomic_modeset(dev))
drm_helper_disable_unused_functions(dev); drm_helper_disable_unused_functions(dev);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/types.h> #include <linux/types.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
struct drm_client_dev; struct drm_client_dev;
...@@ -169,6 +170,20 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode); ...@@ -169,6 +170,20 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode);
for (({ lockdep_assert_held(&(client)->modeset_mutex); }), \ for (({ lockdep_assert_held(&(client)->modeset_mutex); }), \
modeset = (client)->modesets; modeset->crtc; modeset++) modeset = (client)->modesets; modeset->crtc; modeset++)
/**
* drm_client_for_each_connector_iter - connector_list iterator macro
* @connector: &struct drm_connector pointer used as cursor
* @iter: &struct drm_connector_list_iter
*
* This iterates the connectors that are useable for internal clients (excludes
* writeback connectors).
*
* For more info see drm_for_each_connector_iter().
*/
#define drm_client_for_each_connector_iter(connector, iter) \
drm_for_each_connector_iter(connector, iter) \
if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
int drm_client_debugfs_init(struct drm_minor *minor); int drm_client_debugfs_init(struct drm_minor *minor);
#endif #endif
...@@ -97,16 +97,10 @@ struct drm_fb_helper_funcs { ...@@ -97,16 +97,10 @@ struct drm_fb_helper_funcs {
struct drm_fb_helper_surface_size *sizes); struct drm_fb_helper_surface_size *sizes);
}; };
struct drm_fb_helper_connector {
struct drm_connector *connector;
};
/** /**
* struct drm_fb_helper - main structure to emulate fbdev on top of KMS * struct drm_fb_helper - main structure to emulate fbdev on top of KMS
* @fb: Scanout framebuffer object * @fb: Scanout framebuffer object
* @dev: DRM device * @dev: DRM device
* @connector_count: number of connected connectors
* @connector_info_alloc_count: size of connector_info
* @funcs: driver callbacks for fb helper * @funcs: driver callbacks for fb helper
* @fbdev: emulated fbdev device info struct * @fbdev: emulated fbdev device info struct
* @pseudo_palette: fake palette of 16 colors * @pseudo_palette: fake palette of 16 colors
...@@ -138,15 +132,6 @@ struct drm_fb_helper { ...@@ -138,15 +132,6 @@ struct drm_fb_helper {
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_device *dev; struct drm_device *dev;
int connector_count;
int connector_info_alloc_count;
/**
* @connector_info:
*
* Array of per-connector information. Do not iterate directly, but use
* drm_fb_helper_for_each_connector.
*/
struct drm_fb_helper_connector **connector_info;
const struct drm_fb_helper_funcs *funcs; const struct drm_fb_helper_funcs *funcs;
struct fb_info *fbdev; struct fb_info *fbdev;
u32 pseudo_palette[17]; u32 pseudo_palette[17];
...@@ -286,18 +271,8 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, ...@@ -286,18 +271,8 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); int 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);
int drm_fb_helper_debug_enter(struct fb_info *info); int drm_fb_helper_debug_enter(struct fb_info *info);
int drm_fb_helper_debug_leave(struct fb_info *info); int drm_fb_helper_debug_leave(struct fb_info *info);
struct drm_display_mode *
drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
int width, int height);
struct drm_display_mode *
drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn);
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector);
int drm_fb_helper_fbdev_setup(struct drm_device *dev, int drm_fb_helper_fbdev_setup(struct drm_device *dev,
struct drm_fb_helper *fb_helper, struct drm_fb_helper *fb_helper,
...@@ -472,12 +447,6 @@ static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, ...@@ -472,12 +447,6 @@ static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper,
return 0; return 0;
} }
static inline int
drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
{
return 0;
}
static inline int drm_fb_helper_debug_enter(struct fb_info *info) static inline int drm_fb_helper_debug_enter(struct fb_info *info)
{ {
return 0; return 0;
...@@ -488,34 +457,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_info *info) ...@@ -488,34 +457,6 @@ static inline int drm_fb_helper_debug_leave(struct fb_info *info)
return 0; return 0;
} }
static inline struct drm_display_mode *
drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector,
int width, int height)
{
return NULL;
}
static inline struct drm_display_mode *
drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
int width, int height)
{
return NULL;
}
static inline int
drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
return 0;
}
static inline int
drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
return 0;
}
static inline int static inline int
drm_fb_helper_fbdev_setup(struct drm_device *dev, drm_fb_helper_fbdev_setup(struct drm_device *dev,
struct drm_fb_helper *fb_helper, struct drm_fb_helper *fb_helper,
...@@ -557,6 +498,27 @@ drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp) ...@@ -557,6 +498,27 @@ drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
#endif #endif
/* TODO: There's a todo entry to remove these three */
static inline int
drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
{
return 0;
}
static inline int
drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
return 0;
}
static inline int
drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
struct drm_connector *connector)
{
return 0;
}
/** /**
* drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers * drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
* @a: memory range, users of which are to be removed * @a: memory range, users of which are to be removed
......
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