Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1178 → Rev 1179

/drivers/video/drm/drm_crtc_helper.c
33,15 → 33,6
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
 
/*
* Detailed mode info for 800x600@60Hz
*/
static struct drm_display_mode std_modes[] = {
{ DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
};
 
static void drm_mode_validate_flag(struct drm_connector *connector,
int flags)
{
94,7 → 85,7
int count = 0;
int mode_flags = 0;
 
DRM_DEBUG("%s\n", drm_get_connector_name(connector));
DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
/* set all modes to the unverified state */
list_for_each_entry_safe(mode, t, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
102,15 → 93,17
connector->status = connector->funcs->detect(connector);
 
if (connector->status == connector_status_disconnected) {
DRM_DEBUG("%s is disconnected\n",
DRM_DEBUG_KMS("%s is disconnected\n",
drm_get_connector_name(connector));
/* TODO set EDID to NULL */
return 0;
goto prune;
}
 
count = (*connector_funcs->get_modes)(connector);
if (!count) {
count = drm_add_modes_noedid(connector, 800, 600);
if (!count)
return 0;
}
 
drm_mode_connector_list_update(connector);
 
130,7 → 123,7
mode);
}
 
 
prune:
drm_mode_prune_invalid(dev, &connector->modes, true);
 
if (list_empty(&connector->modes))
138,7 → 131,8
 
drm_mode_sort(&connector->modes);
 
DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
DRM_DEBUG_KMS("Probed modes for %s\n",
drm_get_connector_name(connector));
list_for_each_entry_safe(mode, t, &connector->modes, head) {
mode->vrefresh = drm_mode_vrefresh(mode);
 
165,39 → 159,6
}
EXPORT_SYMBOL(drm_helper_probe_connector_modes);
 
static void drm_helper_add_std_modes(struct drm_device *dev,
struct drm_connector *connector)
{
struct drm_display_mode *mode, *t;
int i;
 
for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
struct drm_display_mode *stdmode;
 
/*
* When no valid EDID modes are available we end up
* here and bailed in the past, now we add some standard
* modes and move on.
*/
stdmode = drm_mode_duplicate(dev, &std_modes[i]);
drm_mode_probed_add(connector, stdmode);
drm_mode_list_concat(&connector->probed_modes,
&connector->modes);
 
DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
drm_get_connector_name(connector));
}
drm_mode_sort(&connector->modes);
 
DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
list_for_each_entry_safe(mode, t, &connector->modes, head) {
mode->vrefresh = drm_mode_vrefresh(mode);
 
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
drm_mode_debug_printmodeline(mode);
}
}
 
/**
* drm_helper_encoder_in_use - check if a given encoder is in use
* @encoder: encoder to check
258,14 → 219,28
void drm_helper_disable_unused_functions(struct drm_device *dev)
{
struct drm_encoder *encoder;
struct drm_connector *connector;
struct drm_encoder_helper_funcs *encoder_funcs;
struct drm_crtc *crtc;
 
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->encoder)
continue;
if (connector->status == connector_status_disconnected)
connector->encoder = NULL;
}
 
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder_funcs = encoder->helper_private;
if (!drm_helper_encoder_in_use(encoder))
if (!drm_helper_encoder_in_use(encoder)) {
if (encoder_funcs->disable)
(*encoder_funcs->disable)(encoder);
else
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
/* disconnector encoder from any connector */
encoder->crtc = NULL;
}
}
 
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
282,8 → 257,6
{
struct drm_display_mode *mode;
 
ENTRY();
 
list_for_each_entry(mode, &connector->modes, head) {
if (drm_mode_width(mode) > width ||
drm_mode_height(mode) > height)
314,7 → 287,7
 
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
enabled[i] = drm_connector_enabled(connector, true);
DRM_DEBUG("connector %d enabled ? %s\n", connector->base.id,
DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
enabled[i] ? "yes" : "no");
any_enabled |= enabled[i];
i++;
344,7 → 317,7
continue;
}
 
DRM_DEBUG("looking for preferred mode on connector %d\n",
DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
connector->base.id);
 
modes[i] = drm_has_preferred_mode(connector, width, height);
353,7 → 326,7
list_for_each_entry(modes[i], &connector->modes, head)
break;
}
DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
"none");
i++;
}
382,8 → 355,6
c++;
}
 
dbgprintf("n= %d\n", n);
 
best_crtcs[n] = NULL;
best_crtc = NULL;
best_score = drm_pick_crtcs(dev, best_crtcs, modes, n+1, width, height);
395,8 → 366,6
if (!crtcs)
return best_score;
 
dbgprintf("crtcs = %x\n", crtcs);
 
my_score = 1;
if (connector->status == connector_status_connected)
my_score++;
405,9 → 374,6
 
connector_funcs = connector->helper_private;
encoder = connector_funcs->best_encoder(connector);
 
dbgprintf("encoder = %x\n", encoder);
 
if (!encoder)
goto out;
 
418,7 → 384,7
c = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 
if ((connector->encoder->possible_crtcs & (1 << c)) == 0) {
if ((encoder->possible_crtcs & (1 << c)) == 0) {
c++;
continue;
}
448,11 → 414,6
}
out:
kfree(crtcs);
 
dbgprintf("best_score= %x\n", best_score);
 
LEAVE();
 
return best_score;
}
 
466,7 → 427,7
int width, height;
int i, ret;
 
DRM_DEBUG("\n");
DRM_DEBUG_KMS("\n");
 
width = 1280; //dev->mode_config.max_width;
height = 1024; //dev->mode_config.max_height;
489,7 → 450,7
if (!ret)
DRM_ERROR("Unable to find initial modes\n");
 
DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
 
drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
 
504,14 → 465,15
}
 
if (mode && crtc) {
DRM_DEBUG("desired mode %s set on crtc %d\n",
DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
mode->name, crtc->base.id);
crtc->desired_mode = mode;
// crtc->mode = *mode;
crtc->enabled = true;
connector->encoder->crtc = crtc;
} else
} else {
connector->encoder->crtc = NULL;
connector->encoder = NULL;
}
i++;
}
 
518,8 → 480,6
kfree(crtcs);
kfree(modes);
kfree(enabled);
 
LEAVE();
}
 
/**
603,8 → 563,6
struct drm_encoder *encoder;
bool ret = true;
 
ENTRY();
 
adjusted_mode = drm_mode_duplicate(dev, mode);
 
crtc->enabled = drm_helper_crtc_in_use(crtc);
696,7 → 654,7
crtc->x = saved_x;
crtc->y = saved_y;
}
LEAVE();
 
return ret;
}
EXPORT_SYMBOL(drm_crtc_helper_set_mode);
722,18 → 680,17
int drm_crtc_helper_set_config(struct drm_mode_set *set)
{
struct drm_device *dev;
struct drm_crtc **save_crtcs, *new_crtc;
struct drm_encoder **save_encoders, *new_encoder;
struct drm_crtc *save_crtcs, *new_crtc, *crtc;
struct drm_encoder *save_encoders, *new_encoder, *encoder;
struct drm_framebuffer *old_fb = NULL;
bool save_enabled;
bool mode_changed = false;
bool fb_changed = false;
struct drm_connector *connector;
bool mode_changed = false; /* if true do a full mode set */
bool fb_changed = false; /* if true and !mode_changed just do a flip */
struct drm_connector *save_connectors, *connector;
int count = 0, ro, fail = 0;
struct drm_crtc_helper_funcs *crtc_funcs;
int ret = 0;
 
DRM_DEBUG("\n");
DRM_DEBUG_KMS("\n");
 
if (!set)
return -EINVAL;
746,38 → 703,63
 
crtc_funcs = set->crtc->helper_private;
 
DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n",
DRM_DEBUG_KMS("crtc: %p %d fb: %p connectors: %p num_connectors:"
" %d (x, y) (%i, %i)\n",
set->crtc, set->crtc->base.id, set->fb, set->connectors,
(int)set->num_connectors, set->x, set->y);
 
dev = set->crtc->dev;
 
/* save previous config */
save_enabled = set->crtc->enabled;
 
/*
* We do mode_config.num_connectors here since we'll look at the
* CRTC and encoder associated with each connector later.
*/
save_crtcs = kzalloc(dev->mode_config.num_connector *
sizeof(struct drm_crtc *), GFP_KERNEL);
/* Allocate space for the backup of all (non-pointer) crtc, encoder and
* connector data. */
save_crtcs = kzalloc(dev->mode_config.num_crtc *
sizeof(struct drm_crtc), GFP_KERNEL);
if (!save_crtcs)
return -ENOMEM;
 
save_encoders = kzalloc(dev->mode_config.num_connector *
sizeof(struct drm_encoders *), GFP_KERNEL);
save_encoders = kzalloc(dev->mode_config.num_encoder *
sizeof(struct drm_encoder), GFP_KERNEL);
if (!save_encoders) {
kfree(save_crtcs);
return -ENOMEM;
}
 
save_connectors = kzalloc(dev->mode_config.num_connector *
sizeof(struct drm_connector), GFP_KERNEL);
if (!save_connectors) {
kfree(save_crtcs);
kfree(save_encoders);
return -ENOMEM;
}
 
/* Copy data. Note that driver private data is not affected.
* Should anything bad happen only the expected state is
* restored, not the drivers personal bookkeeping.
*/
count = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
save_crtcs[count++] = *crtc;
}
 
count = 0;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
save_encoders[count++] = *encoder;
}
 
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
save_connectors[count++] = *connector;
}
 
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
if (set->crtc->fb != set->fb) {
/* If we have no fb then treat it as a full mode set */
if (set->crtc->fb == NULL) {
DRM_DEBUG("crtc has no fb, full mode set\n");
DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
mode_changed = true;
} else if (set->fb == NULL) {
mode_changed = true;
} else if ((set->fb->bits_per_pixel !=
set->crtc->fb->bits_per_pixel) ||
set->fb->depth != set->crtc->fb->depth)
790,7 → 772,7
fb_changed = true;
 
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
DRM_DEBUG("modes are different, full mode set\n");
DRM_DEBUG_KMS("modes are different, full mode set\n");
drm_mode_debug_printmodeline(&set->crtc->mode);
drm_mode_debug_printmodeline(set->mode);
mode_changed = true;
801,7 → 783,6
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct drm_connector_helper_funcs *connector_funcs =
connector->helper_private;
save_encoders[count++] = connector->encoder;
new_encoder = connector->encoder;
for (ro = 0; ro < set->num_connectors; ro++) {
if (set->connectors[ro] == connector) {
816,8 → 797,13
}
 
if (new_encoder != connector->encoder) {
DRM_DEBUG("encoder changed, full mode switch\n");
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
mode_changed = true;
/* If the encoder is reused for another connector, then
* the appropriate crtc will be set later.
*/
if (connector->encoder)
connector->encoder->crtc = NULL;
connector->encoder = new_encoder;
}
}
824,7 → 810,7
 
if (fail) {
ret = -EINVAL;
goto fail_no_encoder;
goto fail;
}
 
count = 0;
832,8 → 818,6
if (!connector->encoder)
continue;
 
save_crtcs[count++] = connector->encoder->crtc;
 
if (connector->encoder->crtc == set->crtc)
new_crtc = NULL;
else
848,14 → 832,14
if (new_crtc &&
!drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
ret = -EINVAL;
goto fail_set_mode;
goto fail;
}
if (new_crtc != connector->encoder->crtc) {
DRM_DEBUG("crtc changed, full mode switch\n");
DRM_DEBUG_KMS("crtc changed, full mode switch\n");
mode_changed = true;
connector->encoder->crtc = new_crtc;
}
DRM_DEBUG("setting connector %d crtc to %p\n",
DRM_DEBUG_KMS("setting connector %d crtc to %p\n",
connector->base.id, new_crtc);
}
 
868,7 → 852,8
set->crtc->fb = set->fb;
set->crtc->enabled = (set->mode != NULL);
if (set->mode != NULL) {
DRM_DEBUG("attempting to set mode from userspace\n");
DRM_DEBUG_KMS("attempting to set mode from"
" userspace\n");
drm_mode_debug_printmodeline(set->mode);
if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y,
876,7 → 861,7
DRM_ERROR("failed to set mode on crtc %p\n",
set->crtc);
ret = -EINVAL;
goto fail_set_mode;
goto fail;
}
/* TODO are these needed? */
set->crtc->desired_x = set->x;
885,6 → 870,9
}
drm_helper_disable_unused_functions(dev);
} else if (fb_changed) {
set->crtc->x = set->x;
set->crtc->y = set->y;
 
old_fb = set->crtc->fb;
if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb;
891,30 → 879,34
ret = crtc_funcs->mode_set_base(set->crtc,
set->x, set->y, old_fb);
if (ret != 0)
goto fail_set_mode;
goto fail;
}
 
kfree(save_connectors);
kfree(save_encoders);
kfree(save_crtcs);
return 0;
 
fail_set_mode:
set->crtc->enabled = save_enabled;
set->crtc->fb = old_fb;
fail:
/* Restore all previous data. */
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->encoder)
continue;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
*crtc = save_crtcs[count++];
}
 
connector->encoder->crtc = save_crtcs[count++];
count = 0;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
*encoder = save_encoders[count++];
}
fail_no_encoder:
kfree(save_crtcs);
 
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
connector->encoder = save_encoders[count++];
*connector = save_connectors[count++];
}
 
kfree(save_connectors);
kfree(save_encoders);
kfree(save_crtcs);
return ret;
}
EXPORT_SYMBOL(drm_crtc_helper_set_config);
921,7 → 913,7
 
bool drm_helper_plugged_event(struct drm_device *dev)
{
DRM_DEBUG("\n");
DRM_DEBUG_KMS("\n");
 
drm_helper_probe_connector_modes(dev, dev->mode_config.max_width,
dev->mode_config.max_height);
950,36 → 942,22
*/
bool drm_helper_initial_config(struct drm_device *dev)
{
struct drm_connector *connector;
int count = 0;
 
ENTRY();
 
count = drm_helper_probe_connector_modes(dev,
dev->mode_config.max_width,
dev->mode_config.max_height);
 
/*
* None of the available connectors had any modes, so add some
* and try to light them up anyway
* we shouldn't end up with no modes here.
*/
if (!count) {
DRM_ERROR("connectors have no modes, using standard modes\n");
list_for_each_entry(connector,
&dev->mode_config.connector_list,
head)
drm_helper_add_std_modes(dev, connector);
}
// WARN(!count, "Connected connector with 0 modes\n");
 
drm_setup_crtcs(dev);
 
radeonfb_create(dev->dev_private, 1280, 1024, 1280, 1024, NULL);
 
// /* alert the driver fb layer */
/* alert the driver fb layer */
dev->mode_config.funcs->fb_changed(dev);
 
LEAVE();
 
return 0;
}
EXPORT_SYMBOL(drm_helper_initial_config);
1100,15 → 1078,13
}
EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
 
void sysSetScreen(int width, int height)
void sysSetScreen(int width, int height, int pitch)
{
asm __volatile__
(
"decl %%eax \n\t"
"dec %%edx \n\t"
"call *__imp__SetScreen"
:
:"a" (width),"d"(height)
:"a" (width-1),"d"(height-1), "c"(pitch)
:"memory","cc"
);
}
1117,33 → 1093,21
int drm_helper_resume_force_mode(struct drm_device *dev)
{
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
 
int ret;
 
ENTRY();
 
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 
if (!crtc->enabled)
continue;
dbgprintf("mode %x x %x y %x fb %x\n",
crtc->x, crtc->y, crtc->fb, crtc->mode);
 
fb = list_first_entry(&dev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head);
 
crtc->fb = fb;
 
ret = drm_crtc_helper_set_mode(crtc, crtc->desired_mode,
ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y, crtc->fb);
 
if (ret == false)
DRM_ERROR("failed to set mode on crtc %p\n", crtc);
 
sysSetScreen(1280,1024);
 
}
LEAVE();
/* disable the unused connectors while restoring the modesetting */
drm_helper_disable_unused_functions(dev);
return 0;
}
EXPORT_SYMBOL(drm_helper_resume_force_mode);