forked from Minki/linux
Merge tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel into drm-next
So small drm stuff all over for 3.18. Biggest one is the cmdline parsing from Chris with a few fixes from me to make it work for stupid kernel configs. Plus the atomic prep series. Tested for more than a week in -nightly and Ville/Imre indeed discovered some fun which is now fixed (and i915 vblank patches postponed since the fixups need this branch plus drm-intel-next merged together). * tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel: drm: Use the type of the array element when reallocating drm: Don't return 0 for a value used as a denominator drm: Docbook fixes drm/irq: Implement a generic vblank_wait function drm: Add a plane->reset hook drm: trylock modest locking for fbdev panics drm: Move ->old_fb from crtc to plane drm: Handle legacy per-crtc locking with full acquire ctx drm: Move modeset_lock_all helpers to drm_modeset_lock.[hc] drm: Add drm_plane/connector_index drm: idiot-proof vblank drm: Warn when leaking flip events on close drm: Perform cmdline mode parsing during connector initialisation video/fbdev: Always built-in video= cmdline parsing drm: Don't grab an fb reference for the idr
This commit is contained in:
commit
c0ee755fc5
@ -8,6 +8,7 @@ menuconfig DRM
|
|||||||
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
|
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
|
||||||
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
|
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU && HAS_DMA
|
||||||
select HDMI
|
select HDMI
|
||||||
|
select FB_CMDLINE
|
||||||
select I2C
|
select I2C
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
select DMA_SHARED_BUFFER
|
select DMA_SHARED_BUFFER
|
||||||
|
@ -45,101 +45,6 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev,
|
|||||||
struct drm_mode_fb_cmd2 *r,
|
struct drm_mode_fb_cmd2 *r,
|
||||||
struct drm_file *file_priv);
|
struct drm_file *file_priv);
|
||||||
|
|
||||||
/**
|
|
||||||
* drm_modeset_lock_all - take all modeset locks
|
|
||||||
* @dev: drm device
|
|
||||||
*
|
|
||||||
* This function takes all modeset locks, suitable where a more fine-grained
|
|
||||||
* scheme isn't (yet) implemented. Locks must be dropped with
|
|
||||||
* drm_modeset_unlock_all.
|
|
||||||
*/
|
|
||||||
void drm_modeset_lock_all(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
struct drm_mode_config *config = &dev->mode_config;
|
|
||||||
struct drm_modeset_acquire_ctx *ctx;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
|
||||||
if (WARN_ON(!ctx))
|
|
||||||
return;
|
|
||||||
|
|
||||||
mutex_lock(&config->mutex);
|
|
||||||
|
|
||||||
drm_modeset_acquire_init(ctx, 0);
|
|
||||||
|
|
||||||
retry:
|
|
||||||
ret = drm_modeset_lock(&config->connection_mutex, ctx);
|
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
ret = drm_modeset_lock_all_crtcs(dev, ctx);
|
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
WARN_ON(config->acquire_ctx);
|
|
||||||
|
|
||||||
/* now we hold the locks, so now that it is safe, stash the
|
|
||||||
* ctx for drm_modeset_unlock_all():
|
|
||||||
*/
|
|
||||||
config->acquire_ctx = ctx;
|
|
||||||
|
|
||||||
drm_warn_on_modeset_not_all_locked(dev);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (ret == -EDEADLK) {
|
|
||||||
drm_modeset_backoff(ctx);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_modeset_lock_all);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* drm_modeset_unlock_all - drop all modeset locks
|
|
||||||
* @dev: device
|
|
||||||
*
|
|
||||||
* This function drop all modeset locks taken by drm_modeset_lock_all.
|
|
||||||
*/
|
|
||||||
void drm_modeset_unlock_all(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
struct drm_mode_config *config = &dev->mode_config;
|
|
||||||
struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
|
|
||||||
|
|
||||||
if (WARN_ON(!ctx))
|
|
||||||
return;
|
|
||||||
|
|
||||||
config->acquire_ctx = NULL;
|
|
||||||
drm_modeset_drop_locks(ctx);
|
|
||||||
drm_modeset_acquire_fini(ctx);
|
|
||||||
|
|
||||||
kfree(ctx);
|
|
||||||
|
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_modeset_unlock_all);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
|
|
||||||
* @dev: device
|
|
||||||
*
|
|
||||||
* Useful as a debug assert.
|
|
||||||
*/
|
|
||||||
void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
|
|
||||||
/* Locking is currently fubar in the panic handler. */
|
|
||||||
if (oops_in_progress)
|
|
||||||
return;
|
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
|
||||||
WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
|
|
||||||
|
|
||||||
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
|
||||||
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
|
|
||||||
|
|
||||||
/* Avoid boilerplate. I'm tired of typing. */
|
/* Avoid boilerplate. I'm tired of typing. */
|
||||||
#define DRM_ENUM_NAME_FN(fnname, list) \
|
#define DRM_ENUM_NAME_FN(fnname, list) \
|
||||||
const char *fnname(int val) \
|
const char *fnname(int val) \
|
||||||
@ -515,9 +420,6 @@ int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Grab the idr reference. */
|
|
||||||
drm_framebuffer_reference(fb);
|
|
||||||
|
|
||||||
dev->mode_config.num_fb++;
|
dev->mode_config.num_fb++;
|
||||||
list_add(&fb->head, &dev->mode_config.fb_list);
|
list_add(&fb->head, &dev->mode_config.fb_list);
|
||||||
out:
|
out:
|
||||||
@ -527,10 +429,34 @@ out:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_framebuffer_init);
|
EXPORT_SYMBOL(drm_framebuffer_init);
|
||||||
|
|
||||||
|
/* dev->mode_config.fb_lock must be held! */
|
||||||
|
static void __drm_framebuffer_unregister(struct drm_device *dev,
|
||||||
|
struct drm_framebuffer *fb)
|
||||||
|
{
|
||||||
|
mutex_lock(&dev->mode_config.idr_mutex);
|
||||||
|
idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
|
||||||
|
mutex_unlock(&dev->mode_config.idr_mutex);
|
||||||
|
|
||||||
|
fb->base.id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void drm_framebuffer_free(struct kref *kref)
|
static void drm_framebuffer_free(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct drm_framebuffer *fb =
|
struct drm_framebuffer *fb =
|
||||||
container_of(kref, struct drm_framebuffer, refcount);
|
container_of(kref, struct drm_framebuffer, refcount);
|
||||||
|
struct drm_device *dev = fb->dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The lookup idr holds a weak reference, which has not necessarily been
|
||||||
|
* removed at this point. Check for that.
|
||||||
|
*/
|
||||||
|
mutex_lock(&dev->mode_config.fb_lock);
|
||||||
|
if (fb->base.id) {
|
||||||
|
/* Mark fb as reaped and drop idr ref. */
|
||||||
|
__drm_framebuffer_unregister(dev, fb);
|
||||||
|
}
|
||||||
|
mutex_unlock(&dev->mode_config.fb_lock);
|
||||||
|
|
||||||
fb->funcs->destroy(fb);
|
fb->funcs->destroy(fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,8 +493,10 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
|
|||||||
|
|
||||||
mutex_lock(&dev->mode_config.fb_lock);
|
mutex_lock(&dev->mode_config.fb_lock);
|
||||||
fb = __drm_framebuffer_lookup(dev, id);
|
fb = __drm_framebuffer_lookup(dev, id);
|
||||||
if (fb)
|
if (fb) {
|
||||||
drm_framebuffer_reference(fb);
|
if (!kref_get_unless_zero(&fb->refcount))
|
||||||
|
fb = NULL;
|
||||||
|
}
|
||||||
mutex_unlock(&dev->mode_config.fb_lock);
|
mutex_unlock(&dev->mode_config.fb_lock);
|
||||||
|
|
||||||
return fb;
|
return fb;
|
||||||
@ -612,19 +540,6 @@ static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
|
|||||||
kref_put(&fb->refcount, drm_framebuffer_free_bug);
|
kref_put(&fb->refcount, drm_framebuffer_free_bug);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dev->mode_config.fb_lock must be held! */
|
|
||||||
static void __drm_framebuffer_unregister(struct drm_device *dev,
|
|
||||||
struct drm_framebuffer *fb)
|
|
||||||
{
|
|
||||||
mutex_lock(&dev->mode_config.idr_mutex);
|
|
||||||
idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
|
|
||||||
mutex_unlock(&dev->mode_config.idr_mutex);
|
|
||||||
|
|
||||||
fb->base.id = 0;
|
|
||||||
|
|
||||||
__drm_framebuffer_unreference(fb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
|
* drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
|
||||||
* @fb: fb to unregister
|
* @fb: fb to unregister
|
||||||
@ -852,6 +767,59 @@ static void drm_mode_remove(struct drm_connector *connector,
|
|||||||
drm_mode_destroy(connector->dev, mode);
|
drm_mode_destroy(connector->dev, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_connector_get_cmdline_mode - reads the user's cmdline mode
|
||||||
|
* @connector: connector to quwery
|
||||||
|
* @mode: returned mode
|
||||||
|
*
|
||||||
|
* The kernel supports per-connector configration of its consoles through
|
||||||
|
* use of the video= parameter. This function parses that option and
|
||||||
|
* extracts the user's specified mode (or enable/disable status) for a
|
||||||
|
* particular connector. This is typically only used during the early fbdev
|
||||||
|
* setup.
|
||||||
|
*/
|
||||||
|
static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_cmdline_mode *mode = &connector->cmdline_mode;
|
||||||
|
char *option = NULL;
|
||||||
|
|
||||||
|
if (fb_get_options(connector->name, &option))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!drm_mode_parse_command_line_for_connector(option,
|
||||||
|
connector,
|
||||||
|
mode))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mode->force) {
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
switch (mode->force) {
|
||||||
|
case DRM_FORCE_OFF:
|
||||||
|
s = "OFF";
|
||||||
|
break;
|
||||||
|
case DRM_FORCE_ON_DIGITAL:
|
||||||
|
s = "ON - dig";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case DRM_FORCE_ON:
|
||||||
|
s = "ON";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_INFO("forcing %s connector %s\n", connector->name, s);
|
||||||
|
connector->force = mode->force;
|
||||||
|
}
|
||||||
|
|
||||||
|
DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
|
||||||
|
connector->name,
|
||||||
|
mode->xres, mode->yres,
|
||||||
|
mode->refresh_specified ? mode->refresh : 60,
|
||||||
|
mode->rb ? " reduced blanking" : "",
|
||||||
|
mode->margins ? " with margins" : "",
|
||||||
|
mode->interlace ? " interlaced" : "");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_connector_init - Init a preallocated connector
|
* drm_connector_init - Init a preallocated connector
|
||||||
* @dev: DRM device
|
* @dev: DRM device
|
||||||
@ -904,6 +872,8 @@ int drm_connector_init(struct drm_device *dev,
|
|||||||
connector->edid_blob_ptr = NULL;
|
connector->edid_blob_ptr = NULL;
|
||||||
connector->status = connector_status_unknown;
|
connector->status = connector_status_unknown;
|
||||||
|
|
||||||
|
drm_connector_get_cmdline_mode(connector);
|
||||||
|
|
||||||
list_add_tail(&connector->head, &dev->mode_config.connector_list);
|
list_add_tail(&connector->head, &dev->mode_config.connector_list);
|
||||||
dev->mode_config.num_connector++;
|
dev->mode_config.num_connector++;
|
||||||
|
|
||||||
@ -956,6 +926,29 @@ void drm_connector_cleanup(struct drm_connector *connector)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_connector_cleanup);
|
EXPORT_SYMBOL(drm_connector_cleanup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_connector_index - find the index of a registered connector
|
||||||
|
* @connector: connector to find index for
|
||||||
|
*
|
||||||
|
* Given a registered connector, return the index of that connector within a DRM
|
||||||
|
* device's list of connectors.
|
||||||
|
*/
|
||||||
|
unsigned int drm_connector_index(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
unsigned int index = 0;
|
||||||
|
struct drm_connector *tmp;
|
||||||
|
|
||||||
|
list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
|
||||||
|
if (tmp == connector)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_connector_index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_connector_register - register a connector
|
* drm_connector_register - register a connector
|
||||||
* @connector: the connector to register
|
* @connector: the connector to register
|
||||||
@ -1260,6 +1253,29 @@ void drm_plane_cleanup(struct drm_plane *plane)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_plane_cleanup);
|
EXPORT_SYMBOL(drm_plane_cleanup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_plane_index - find the index of a registered plane
|
||||||
|
* @plane: plane to find index for
|
||||||
|
*
|
||||||
|
* Given a registered plane, return the index of that CRTC within a DRM
|
||||||
|
* device's list of planes.
|
||||||
|
*/
|
||||||
|
unsigned int drm_plane_index(struct drm_plane *plane)
|
||||||
|
{
|
||||||
|
unsigned int index = 0;
|
||||||
|
struct drm_plane *tmp;
|
||||||
|
|
||||||
|
list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
|
||||||
|
if (tmp == plane)
|
||||||
|
return index;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_plane_index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_plane_force_disable - Forcibly disable a plane
|
* drm_plane_force_disable - Forcibly disable a plane
|
||||||
* @plane: plane to disable
|
* @plane: plane to disable
|
||||||
@ -1271,19 +1287,21 @@ EXPORT_SYMBOL(drm_plane_cleanup);
|
|||||||
*/
|
*/
|
||||||
void drm_plane_force_disable(struct drm_plane *plane)
|
void drm_plane_force_disable(struct drm_plane *plane)
|
||||||
{
|
{
|
||||||
struct drm_framebuffer *old_fb = plane->fb;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!old_fb)
|
if (!plane->fb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
plane->old_fb = plane->fb;
|
||||||
ret = plane->funcs->disable_plane(plane);
|
ret = plane->funcs->disable_plane(plane);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("failed to disable plane with busy fb\n");
|
DRM_ERROR("failed to disable plane with busy fb\n");
|
||||||
|
plane->old_fb = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* disconnect the plane from the fb and crtc: */
|
/* disconnect the plane from the fb and crtc: */
|
||||||
__drm_framebuffer_unreference(old_fb);
|
__drm_framebuffer_unreference(plane->old_fb);
|
||||||
|
plane->old_fb = NULL;
|
||||||
plane->fb = NULL;
|
plane->fb = NULL;
|
||||||
plane->crtc = NULL;
|
plane->crtc = NULL;
|
||||||
}
|
}
|
||||||
@ -2259,23 +2277,21 @@ static int setplane_internal(struct drm_plane *plane,
|
|||||||
uint32_t src_w, uint32_t src_h)
|
uint32_t src_w, uint32_t src_h)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = plane->dev;
|
struct drm_device *dev = plane->dev;
|
||||||
struct drm_framebuffer *old_fb = NULL;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned int fb_width, fb_height;
|
unsigned int fb_width, fb_height;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
drm_modeset_lock_all(dev);
|
||||||
/* No fb means shut it down */
|
/* No fb means shut it down */
|
||||||
if (!fb) {
|
if (!fb) {
|
||||||
drm_modeset_lock_all(dev);
|
plane->old_fb = plane->fb;
|
||||||
old_fb = plane->fb;
|
|
||||||
ret = plane->funcs->disable_plane(plane);
|
ret = plane->funcs->disable_plane(plane);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
plane->crtc = NULL;
|
plane->crtc = NULL;
|
||||||
plane->fb = NULL;
|
plane->fb = NULL;
|
||||||
} else {
|
} else {
|
||||||
old_fb = NULL;
|
plane->old_fb = NULL;
|
||||||
}
|
}
|
||||||
drm_modeset_unlock_all(dev);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2315,8 +2331,7 @@ static int setplane_internal(struct drm_plane *plane,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_modeset_lock_all(dev);
|
plane->old_fb = plane->fb;
|
||||||
old_fb = plane->fb;
|
|
||||||
ret = plane->funcs->update_plane(plane, crtc, fb,
|
ret = plane->funcs->update_plane(plane, crtc, fb,
|
||||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||||
src_x, src_y, src_w, src_h);
|
src_x, src_y, src_w, src_h);
|
||||||
@ -2325,15 +2340,16 @@ static int setplane_internal(struct drm_plane *plane,
|
|||||||
plane->fb = fb;
|
plane->fb = fb;
|
||||||
fb = NULL;
|
fb = NULL;
|
||||||
} else {
|
} else {
|
||||||
old_fb = NULL;
|
plane->old_fb = NULL;
|
||||||
}
|
}
|
||||||
drm_modeset_unlock_all(dev);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (fb)
|
if (fb)
|
||||||
drm_framebuffer_unreference(fb);
|
drm_framebuffer_unreference(fb);
|
||||||
if (old_fb)
|
if (plane->old_fb)
|
||||||
drm_framebuffer_unreference(old_fb);
|
drm_framebuffer_unreference(plane->old_fb);
|
||||||
|
plane->old_fb = NULL;
|
||||||
|
drm_modeset_unlock_all(dev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -2440,7 +2456,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
|
|||||||
* crtcs. Atomic modeset will have saner semantics ...
|
* crtcs. Atomic modeset will have saner semantics ...
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
|
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
|
||||||
tmp->old_fb = tmp->primary->fb;
|
tmp->primary->old_fb = tmp->primary->fb;
|
||||||
|
|
||||||
fb = set->fb;
|
fb = set->fb;
|
||||||
|
|
||||||
@ -2453,8 +2469,9 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
|
|||||||
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
|
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
|
||||||
if (tmp->primary->fb)
|
if (tmp->primary->fb)
|
||||||
drm_framebuffer_reference(tmp->primary->fb);
|
drm_framebuffer_reference(tmp->primary->fb);
|
||||||
if (tmp->old_fb)
|
if (tmp->primary->old_fb)
|
||||||
drm_framebuffer_unreference(tmp->old_fb);
|
drm_framebuffer_unreference(tmp->primary->old_fb);
|
||||||
|
tmp->primary->old_fb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -2785,7 +2802,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
|
|||||||
if (crtc->cursor)
|
if (crtc->cursor)
|
||||||
return drm_mode_cursor_universal(crtc, req, file_priv);
|
return drm_mode_cursor_universal(crtc, req, file_priv);
|
||||||
|
|
||||||
drm_modeset_lock(&crtc->mutex, NULL);
|
drm_modeset_lock_crtc(crtc);
|
||||||
if (req->flags & DRM_MODE_CURSOR_BO) {
|
if (req->flags & DRM_MODE_CURSOR_BO) {
|
||||||
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
|
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
@ -2809,7 +2826,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
drm_modeset_unlock(&crtc->mutex);
|
drm_modeset_unlock_crtc(crtc);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -3495,9 +3512,10 @@ EXPORT_SYMBOL(drm_property_create_enum);
|
|||||||
* @flags: flags specifying the property type
|
* @flags: flags specifying the property type
|
||||||
* @name: name of the property
|
* @name: name of the property
|
||||||
* @props: enumeration lists with property bitflags
|
* @props: enumeration lists with property bitflags
|
||||||
* @num_values: number of pre-defined values
|
* @num_props: size of the @props array
|
||||||
|
* @supported_bits: bitmask of all supported enumeration values
|
||||||
*
|
*
|
||||||
* This creates a new generic drm property which can then be attached to a drm
|
* This creates a new bitmask drm property which can then be attached to a drm
|
||||||
* object with drm_object_attach_property. The returned property object must be
|
* object with drm_object_attach_property. The returned property object must be
|
||||||
* freed with drm_property_destroy.
|
* freed with drm_property_destroy.
|
||||||
*
|
*
|
||||||
@ -4529,7 +4547,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||||||
{
|
{
|
||||||
struct drm_mode_crtc_page_flip *page_flip = data;
|
struct drm_mode_crtc_page_flip *page_flip = data;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct drm_framebuffer *fb = NULL, *old_fb = NULL;
|
struct drm_framebuffer *fb = NULL;
|
||||||
struct drm_pending_vblank_event *e = NULL;
|
struct drm_pending_vblank_event *e = NULL;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
@ -4545,7 +4563,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||||||
if (!crtc)
|
if (!crtc)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
drm_modeset_lock(&crtc->mutex, NULL);
|
drm_modeset_lock_crtc(crtc);
|
||||||
if (crtc->primary->fb == NULL) {
|
if (crtc->primary->fb == NULL) {
|
||||||
/* The framebuffer is currently unbound, presumably
|
/* The framebuffer is currently unbound, presumably
|
||||||
* due to a hotplug event, that userspace has not
|
* due to a hotplug event, that userspace has not
|
||||||
@ -4601,7 +4619,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||||||
(void (*) (struct drm_pending_event *)) kfree;
|
(void (*) (struct drm_pending_event *)) kfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_fb = crtc->primary->fb;
|
crtc->primary->old_fb = crtc->primary->fb;
|
||||||
ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
|
ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
||||||
@ -4611,7 +4629,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||||||
kfree(e);
|
kfree(e);
|
||||||
}
|
}
|
||||||
/* Keep the old fb, don't unref it. */
|
/* Keep the old fb, don't unref it. */
|
||||||
old_fb = NULL;
|
crtc->primary->old_fb = NULL;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Warn if the driver hasn't properly updated the crtc->fb
|
* Warn if the driver hasn't properly updated the crtc->fb
|
||||||
@ -4627,9 +4645,10 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||||||
out:
|
out:
|
||||||
if (fb)
|
if (fb)
|
||||||
drm_framebuffer_unreference(fb);
|
drm_framebuffer_unreference(fb);
|
||||||
if (old_fb)
|
if (crtc->primary->old_fb)
|
||||||
drm_framebuffer_unreference(old_fb);
|
drm_framebuffer_unreference(crtc->primary->old_fb);
|
||||||
drm_modeset_unlock(&crtc->mutex);
|
crtc->primary->old_fb = NULL;
|
||||||
|
drm_modeset_unlock_crtc(crtc);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -4645,9 +4664,14 @@ out:
|
|||||||
void drm_mode_config_reset(struct drm_device *dev)
|
void drm_mode_config_reset(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
struct drm_plane *plane;
|
||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
|
||||||
|
list_for_each_entry(plane, &dev->mode_config.plane_list, head)
|
||||||
|
if (plane->funcs->reset)
|
||||||
|
plane->funcs->reset(plane);
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||||
if (crtc->funcs->reset)
|
if (crtc->funcs->reset)
|
||||||
crtc->funcs->reset(crtc);
|
crtc->funcs->reset(crtc);
|
||||||
|
@ -1772,7 +1772,7 @@ static int drm_dp_get_vc_payload_bw(int dp_link_bw, int dp_link_count)
|
|||||||
case DP_LINK_BW_5_4:
|
case DP_LINK_BW_5_4:
|
||||||
return 10 * dp_link_count;
|
return 10 * dp_link_count;
|
||||||
}
|
}
|
||||||
return 0;
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2071,6 +2071,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
|
|||||||
* drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
|
* drm_dp_mst_hpd_irq() - MST hotplug IRQ notify
|
||||||
* @mgr: manager to notify irq for.
|
* @mgr: manager to notify irq for.
|
||||||
* @esi: 4 bytes from SINK_COUNT_ESI
|
* @esi: 4 bytes from SINK_COUNT_ESI
|
||||||
|
* @handled: whether the hpd interrupt was consumed or not
|
||||||
*
|
*
|
||||||
* This should be called from the driver when it detects a short IRQ,
|
* This should be called from the driver when it detects a short IRQ,
|
||||||
* along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
|
* along with the value of the DEVICE_SERVICE_IRQ_VECTOR_ESI0. The
|
||||||
|
@ -3433,10 +3433,10 @@ EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
|
|||||||
/**
|
/**
|
||||||
* drm_assign_hdmi_deep_color_info - detect whether monitor supports
|
* drm_assign_hdmi_deep_color_info - detect whether monitor supports
|
||||||
* hdmi deep color modes and update drm_display_info if so.
|
* hdmi deep color modes and update drm_display_info if so.
|
||||||
*
|
|
||||||
* @edid: monitor EDID information
|
* @edid: monitor EDID information
|
||||||
* @info: Updated with maximum supported deep color bpc and color format
|
* @info: Updated with maximum supported deep color bpc and color format
|
||||||
* if deep color supported.
|
* if deep color supported.
|
||||||
|
* @connector: DRM connector, used only for debug output
|
||||||
*
|
*
|
||||||
* Parse the CEA extension according to CEA-861-B.
|
* Parse the CEA extension according to CEA-861-B.
|
||||||
* Return true if HDMI deep color supported, false if not or unknown.
|
* Return true if HDMI deep color supported, false if not or unknown.
|
||||||
|
@ -126,7 +126,7 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
|
|||||||
|
|
||||||
WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
|
WARN_ON(!mutex_is_locked(&fb_helper->dev->mode_config.mutex));
|
||||||
if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
|
if (fb_helper->connector_count + 1 > fb_helper->connector_info_alloc_count) {
|
||||||
temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector) * (fb_helper->connector_count + 1), GFP_KERNEL);
|
temp = krealloc(fb_helper->connector_info, sizeof(struct drm_fb_helper_connector *) * (fb_helper->connector_count + 1), GFP_KERNEL);
|
||||||
if (!temp)
|
if (!temp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -171,60 +171,6 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
|
EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
|
||||||
|
|
||||||
static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
|
|
||||||
{
|
|
||||||
struct drm_fb_helper_connector *fb_helper_conn;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < fb_helper->connector_count; i++) {
|
|
||||||
struct drm_cmdline_mode *mode;
|
|
||||||
struct drm_connector *connector;
|
|
||||||
char *option = NULL;
|
|
||||||
|
|
||||||
fb_helper_conn = fb_helper->connector_info[i];
|
|
||||||
connector = fb_helper_conn->connector;
|
|
||||||
mode = &fb_helper_conn->cmdline_mode;
|
|
||||||
|
|
||||||
/* do something on return - turn off connector maybe */
|
|
||||||
if (fb_get_options(connector->name, &option))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (drm_mode_parse_command_line_for_connector(option,
|
|
||||||
connector,
|
|
||||||
mode)) {
|
|
||||||
if (mode->force) {
|
|
||||||
const char *s;
|
|
||||||
switch (mode->force) {
|
|
||||||
case DRM_FORCE_OFF:
|
|
||||||
s = "OFF";
|
|
||||||
break;
|
|
||||||
case DRM_FORCE_ON_DIGITAL:
|
|
||||||
s = "ON - dig";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case DRM_FORCE_ON:
|
|
||||||
s = "ON";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_INFO("forcing %s connector %s\n",
|
|
||||||
connector->name, s);
|
|
||||||
connector->force = mode->force;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
|
|
||||||
connector->name,
|
|
||||||
mode->xres, mode->yres,
|
|
||||||
mode->refresh_specified ? mode->refresh : 60,
|
|
||||||
mode->rb ? " reduced blanking" : "",
|
|
||||||
mode->margins ? " with margins" : "",
|
|
||||||
mode->interlace ? " interlaced" : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
|
static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_helper *helper)
|
||||||
{
|
{
|
||||||
uint16_t *r_base, *g_base, *b_base;
|
uint16_t *r_base, *g_base, *b_base;
|
||||||
@ -419,11 +365,11 @@ static bool drm_fb_helper_force_kernel_mode(void)
|
|||||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* NOTE: we use lockless flag below to avoid grabbing other
|
/*
|
||||||
* modeset locks. So just trylock the underlying mutex
|
* NOTE: Use trylock mode to avoid deadlocks and sleeping in
|
||||||
* directly:
|
* panic context.
|
||||||
*/
|
*/
|
||||||
if (!mutex_trylock(&dev->mode_config.mutex)) {
|
if (__drm_modeset_lock_all(dev, true) != 0) {
|
||||||
error = true;
|
error = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -432,7 +378,7 @@ static bool drm_fb_helper_force_kernel_mode(void)
|
|||||||
if (ret)
|
if (ret)
|
||||||
error = true;
|
error = true;
|
||||||
|
|
||||||
mutex_unlock(&dev->mode_config.mutex);
|
drm_modeset_unlock_all(dev);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -1013,7 +959,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
|||||||
struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
|
struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
|
||||||
struct drm_cmdline_mode *cmdline_mode;
|
struct drm_cmdline_mode *cmdline_mode;
|
||||||
|
|
||||||
cmdline_mode = &fb_helper_conn->cmdline_mode;
|
cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
|
||||||
|
|
||||||
if (cmdline_mode->bpp_specified) {
|
if (cmdline_mode->bpp_specified) {
|
||||||
switch (cmdline_mode->bpp) {
|
switch (cmdline_mode->bpp) {
|
||||||
@ -1260,9 +1206,7 @@ EXPORT_SYMBOL(drm_has_preferred_mode);
|
|||||||
|
|
||||||
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
|
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
|
||||||
{
|
{
|
||||||
struct drm_cmdline_mode *cmdline_mode;
|
return fb_connector->connector->cmdline_mode.specified;
|
||||||
cmdline_mode = &fb_connector->cmdline_mode;
|
|
||||||
return cmdline_mode->specified;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
|
struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
|
||||||
@ -1272,7 +1216,7 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
|
|||||||
struct drm_display_mode *mode = NULL;
|
struct drm_display_mode *mode = NULL;
|
||||||
bool prefer_non_interlace;
|
bool prefer_non_interlace;
|
||||||
|
|
||||||
cmdline_mode = &fb_helper_conn->cmdline_mode;
|
cmdline_mode = &fb_helper_conn->connector->cmdline_mode;
|
||||||
if (cmdline_mode->specified == false)
|
if (cmdline_mode->specified == false)
|
||||||
return mode;
|
return mode;
|
||||||
|
|
||||||
@ -1657,8 +1601,6 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
|
|||||||
struct drm_device *dev = fb_helper->dev;
|
struct drm_device *dev = fb_helper->dev;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
drm_fb_helper_parse_command_line(fb_helper);
|
|
||||||
|
|
||||||
mutex_lock(&dev->mode_config.mutex);
|
mutex_lock(&dev->mode_config.mutex);
|
||||||
count = drm_fb_helper_probe_connector_modes(fb_helper,
|
count = drm_fb_helper_probe_connector_modes(fb_helper,
|
||||||
dev->mode_config.max_width,
|
dev->mode_config.max_width,
|
||||||
|
@ -464,6 +464,8 @@ int drm_release(struct inode *inode, struct file *filp)
|
|||||||
if (drm_core_check_feature(dev, DRIVER_PRIME))
|
if (drm_core_check_feature(dev, DRIVER_PRIME))
|
||||||
drm_prime_destroy_file_private(&file_priv->prime);
|
drm_prime_destroy_file_private(&file_priv->prime);
|
||||||
|
|
||||||
|
WARN_ON(!list_empty(&file_priv->event_list));
|
||||||
|
|
||||||
put_pid(file_priv->pid);
|
put_pid(file_priv->pid);
|
||||||
kfree(file_priv);
|
kfree(file_priv);
|
||||||
|
|
||||||
|
@ -720,6 +720,8 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
|
|||||||
*/
|
*/
|
||||||
u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
||||||
{
|
{
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return 0;
|
||||||
return atomic_read(&dev->vblank[crtc].count);
|
return atomic_read(&dev->vblank[crtc].count);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_count);
|
EXPORT_SYMBOL(drm_vblank_count);
|
||||||
@ -742,6 +744,9 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
|
|||||||
{
|
{
|
||||||
u32 cur_vblank;
|
u32 cur_vblank;
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Read timestamp from slot of _vblank_time ringbuffer
|
/* Read timestamp from slot of _vblank_time ringbuffer
|
||||||
* that corresponds to current vblank count. Retry if
|
* that corresponds to current vblank count. Retry if
|
||||||
* count has incremented during readout. This works like
|
* count has incremented during readout. This works like
|
||||||
@ -917,6 +922,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
|
|||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||||
/* Going from 0->1 means we have to enable interrupts again */
|
/* Going from 0->1 means we have to enable interrupts again */
|
||||||
if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
|
if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
|
||||||
@ -965,6 +973,9 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
|
|||||||
{
|
{
|
||||||
BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
|
BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Last user schedules interrupt disable */
|
/* Last user schedules interrupt disable */
|
||||||
if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
|
if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
|
||||||
(drm_vblank_offdelay > 0))
|
(drm_vblank_offdelay > 0))
|
||||||
@ -988,6 +999,50 @@ void drm_crtc_vblank_put(struct drm_crtc *crtc)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_crtc_vblank_put);
|
EXPORT_SYMBOL(drm_crtc_vblank_put);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_wait_one_vblank - wait for one vblank
|
||||||
|
* @dev: DRM device
|
||||||
|
* @crtc: crtc index
|
||||||
|
*
|
||||||
|
* This waits for one vblank to pass on @crtc, using the irq driver interfaces.
|
||||||
|
* It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
|
||||||
|
* due to lack of driver support or because the crtc is off.
|
||||||
|
*/
|
||||||
|
void drm_wait_one_vblank(struct drm_device *dev, int crtc)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 last;
|
||||||
|
|
||||||
|
ret = drm_vblank_get(dev, crtc);
|
||||||
|
if (WARN_ON(ret))
|
||||||
|
return;
|
||||||
|
|
||||||
|
last = drm_vblank_count(dev, crtc);
|
||||||
|
|
||||||
|
ret = wait_event_timeout(dev->vblank[crtc].queue,
|
||||||
|
last != drm_vblank_count(dev, crtc),
|
||||||
|
msecs_to_jiffies(100));
|
||||||
|
|
||||||
|
WARN_ON(ret == 0);
|
||||||
|
|
||||||
|
drm_vblank_put(dev, crtc);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_wait_one_vblank);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_crtc_wait_one_vblank - wait for one vblank
|
||||||
|
* @crtc: DRM crtc
|
||||||
|
*
|
||||||
|
* This waits for one vblank to pass on @crtc, using the irq driver interfaces.
|
||||||
|
* It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
|
||||||
|
* due to lack of driver support or because the crtc is off.
|
||||||
|
*/
|
||||||
|
void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_vblank_off - disable vblank events on a CRTC
|
* drm_vblank_off - disable vblank events on a CRTC
|
||||||
* @dev: DRM device
|
* @dev: DRM device
|
||||||
@ -1009,6 +1064,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
|
|||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||||
vblank_disable_and_save(dev, crtc);
|
vblank_disable_and_save(dev, crtc);
|
||||||
wake_up(&dev->vblank[crtc].queue);
|
wake_up(&dev->vblank[crtc].queue);
|
||||||
@ -1068,6 +1126,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
|
|||||||
{
|
{
|
||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||||
/* re-enable interrupts if there's are users left */
|
/* re-enable interrupts if there's are users left */
|
||||||
if (atomic_read(&dev->vblank[crtc].refcount) != 0)
|
if (atomic_read(&dev->vblank[crtc].refcount) != 0)
|
||||||
@ -1121,6 +1182,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
|
|||||||
/* vblank is not initialized (IRQ not installed ?), or has been freed */
|
/* vblank is not initialized (IRQ not installed ?), or has been freed */
|
||||||
if (!dev->num_crtcs)
|
if (!dev->num_crtcs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To avoid all the problems that might happen if interrupts
|
* To avoid all the problems that might happen if interrupts
|
||||||
* were enabled/disabled around or between these calls, we just
|
* were enabled/disabled around or between these calls, we just
|
||||||
@ -1429,6 +1494,9 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
|
|||||||
if (!dev->num_crtcs)
|
if (!dev->num_crtcs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (WARN_ON(crtc >= dev->num_crtcs))
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Need timestamp lock to prevent concurrent execution with
|
/* Need timestamp lock to prevent concurrent execution with
|
||||||
* vblank enable/disable, as this would cause inconsistent
|
* vblank enable/disable, as this would cause inconsistent
|
||||||
* or corrupted timestamps and vblank counts.
|
* or corrupted timestamps and vblank counts.
|
||||||
|
@ -1259,6 +1259,7 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
|
|||||||
if (!mode)
|
if (!mode)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
mode->type |= DRM_MODE_TYPE_USERDEF;
|
||||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,212 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_modeset_lock_all - internal helper to grab all modeset locks
|
||||||
|
* @dev: DRM device
|
||||||
|
* @trylock: trylock mode for atomic contexts
|
||||||
|
*
|
||||||
|
* This is a special version of drm_modeset_lock_all() which can also be used in
|
||||||
|
* atomic contexts. Then @trylock must be set to true.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success or negative error code on failure.
|
||||||
|
*/
|
||||||
|
int __drm_modeset_lock_all(struct drm_device *dev,
|
||||||
|
bool trylock)
|
||||||
|
{
|
||||||
|
struct drm_mode_config *config = &dev->mode_config;
|
||||||
|
struct drm_modeset_acquire_ctx *ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ctx = kzalloc(sizeof(*ctx),
|
||||||
|
trylock ? GFP_ATOMIC : GFP_KERNEL);
|
||||||
|
if (!ctx)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (trylock) {
|
||||||
|
if (!mutex_trylock(&config->mutex))
|
||||||
|
return -EBUSY;
|
||||||
|
} else {
|
||||||
|
mutex_lock(&config->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_modeset_acquire_init(ctx, 0);
|
||||||
|
ctx->trylock_only = trylock;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = drm_modeset_lock(&config->connection_mutex, ctx);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
ret = drm_modeset_lock_all_crtcs(dev, ctx);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
WARN_ON(config->acquire_ctx);
|
||||||
|
|
||||||
|
/* now we hold the locks, so now that it is safe, stash the
|
||||||
|
* ctx for drm_modeset_unlock_all():
|
||||||
|
*/
|
||||||
|
config->acquire_ctx = ctx;
|
||||||
|
|
||||||
|
drm_warn_on_modeset_not_all_locked(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (ret == -EDEADLK) {
|
||||||
|
drm_modeset_backoff(ctx);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_modeset_lock_all);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_modeset_lock_all - take all modeset locks
|
||||||
|
* @dev: drm device
|
||||||
|
*
|
||||||
|
* This function takes all modeset locks, suitable where a more fine-grained
|
||||||
|
* scheme isn't (yet) implemented. Locks must be dropped with
|
||||||
|
* drm_modeset_unlock_all.
|
||||||
|
*/
|
||||||
|
void drm_modeset_lock_all(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
WARN_ON(__drm_modeset_lock_all(dev, false) != 0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_modeset_lock_all);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_modeset_unlock_all - drop all modeset locks
|
||||||
|
* @dev: device
|
||||||
|
*
|
||||||
|
* This function drop all modeset locks taken by drm_modeset_lock_all.
|
||||||
|
*/
|
||||||
|
void drm_modeset_unlock_all(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct drm_mode_config *config = &dev->mode_config;
|
||||||
|
struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
|
||||||
|
|
||||||
|
if (WARN_ON(!ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
config->acquire_ctx = NULL;
|
||||||
|
drm_modeset_drop_locks(ctx);
|
||||||
|
drm_modeset_acquire_fini(ctx);
|
||||||
|
|
||||||
|
kfree(ctx);
|
||||||
|
|
||||||
|
mutex_unlock(&dev->mode_config.mutex);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_modeset_unlock_all);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_modeset_lock_crtc - lock crtc with hidden acquire ctx
|
||||||
|
* @crtc: drm crtc
|
||||||
|
*
|
||||||
|
* This function locks the given crtc using a hidden acquire context. This is
|
||||||
|
* necessary so that drivers internally using the atomic interfaces can grab
|
||||||
|
* further locks with the lock acquire context.
|
||||||
|
*/
|
||||||
|
void drm_modeset_lock_crtc(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_modeset_acquire_ctx *ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||||
|
if (WARN_ON(!ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
drm_modeset_acquire_init(ctx, 0);
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = drm_modeset_lock(&crtc->mutex, ctx);
|
||||||
|
if (ret)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
WARN_ON(crtc->acquire_ctx);
|
||||||
|
|
||||||
|
/* now we hold the locks, so now that it is safe, stash the
|
||||||
|
* ctx for drm_modeset_unlock_crtc():
|
||||||
|
*/
|
||||||
|
crtc->acquire_ctx = ctx;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (ret == -EDEADLK) {
|
||||||
|
drm_modeset_backoff(ctx);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_modeset_lock_crtc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_modeset_legacy_acquire_ctx - find acquire ctx for legacy ioctls
|
||||||
|
* @crtc: drm crtc
|
||||||
|
*
|
||||||
|
* Legacy ioctl operations like cursor updates or page flips only have per-crtc
|
||||||
|
* locking, and store the acquire ctx in the corresponding crtc. All other
|
||||||
|
* legacy operations take all locks and use a global acquire context. This
|
||||||
|
* function grabs the right one.
|
||||||
|
*/
|
||||||
|
struct drm_modeset_acquire_ctx *
|
||||||
|
drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
if (crtc->acquire_ctx)
|
||||||
|
return crtc->acquire_ctx;
|
||||||
|
|
||||||
|
WARN_ON(!crtc->dev->mode_config.acquire_ctx);
|
||||||
|
|
||||||
|
return crtc->dev->mode_config.acquire_ctx;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_modeset_legacy_acquire_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_modeset_unlock_crtc - drop crtc lock
|
||||||
|
* @crtc: drm crtc
|
||||||
|
*
|
||||||
|
* This drops the crtc lock acquire with drm_modeset_lock_crtc() and all other
|
||||||
|
* locks acquired through the hidden context.
|
||||||
|
*/
|
||||||
|
void drm_modeset_unlock_crtc(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_modeset_acquire_ctx *ctx = crtc->acquire_ctx;
|
||||||
|
|
||||||
|
if (WARN_ON(!ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
crtc->acquire_ctx = NULL;
|
||||||
|
drm_modeset_drop_locks(ctx);
|
||||||
|
drm_modeset_acquire_fini(ctx);
|
||||||
|
|
||||||
|
kfree(ctx);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_modeset_unlock_crtc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
|
||||||
|
* @dev: device
|
||||||
|
*
|
||||||
|
* Useful as a debug assert.
|
||||||
|
*/
|
||||||
|
void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct drm_crtc *crtc;
|
||||||
|
|
||||||
|
/* Locking is currently fubar in the panic handler. */
|
||||||
|
if (oops_in_progress)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||||
|
WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
|
||||||
|
|
||||||
|
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
||||||
|
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_modeset_acquire_init - initialize acquire context
|
* drm_modeset_acquire_init - initialize acquire context
|
||||||
* @ctx: the acquire context
|
* @ctx: the acquire context
|
||||||
@ -108,7 +314,12 @@ static inline int modeset_lock(struct drm_modeset_lock *lock,
|
|||||||
|
|
||||||
WARN_ON(ctx->contended);
|
WARN_ON(ctx->contended);
|
||||||
|
|
||||||
if (interruptible && slow) {
|
if (ctx->trylock_only) {
|
||||||
|
if (!ww_mutex_trylock(&lock->mutex))
|
||||||
|
return -EBUSY;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
} else if (interruptible && slow) {
|
||||||
ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx);
|
ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx);
|
||||||
} else if (interruptible) {
|
} else if (interruptible) {
|
||||||
ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx);
|
ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx);
|
||||||
|
@ -82,6 +82,22 @@ static void drm_mode_validate_flag(struct drm_connector *connector,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct drm_display_mode *mode;
|
||||||
|
|
||||||
|
if (!connector->cmdline_mode.specified)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mode = drm_mode_create_from_cmdline_mode(connector->dev,
|
||||||
|
&connector->cmdline_mode);
|
||||||
|
if (mode == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
drm_mode_probed_add(connector, mode);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
|
static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
|
||||||
uint32_t maxX, uint32_t maxY, bool merge_type_bits)
|
uint32_t maxX, uint32_t maxY, bool merge_type_bits)
|
||||||
{
|
{
|
||||||
@ -141,6 +157,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||||||
|
|
||||||
if (count == 0 && connector->status == connector_status_connected)
|
if (count == 0 && connector->status == connector_status_connected)
|
||||||
count = drm_add_modes_noedid(connector, 1024, 768);
|
count = drm_add_modes_noedid(connector, 1024, 768);
|
||||||
|
count += drm_helper_probe_add_cmdline_mode(connector);
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
goto prune;
|
goto prune;
|
||||||
|
|
||||||
|
@ -1483,11 +1483,7 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
|
|||||||
{
|
{
|
||||||
struct drm_device *dev = connector->dev;
|
struct drm_device *dev = connector->dev;
|
||||||
struct mga_device *mdev = (struct mga_device*)dev->dev_private;
|
struct mga_device *mdev = (struct mga_device*)dev->dev_private;
|
||||||
struct mga_fbdev *mfbdev = mdev->mfbdev;
|
|
||||||
struct drm_fb_helper *fb_helper = &mfbdev->helper;
|
|
||||||
struct drm_fb_helper_connector *fb_helper_conn = NULL;
|
|
||||||
int bpp = 32;
|
int bpp = 32;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (IS_G200_SE(mdev)) {
|
if (IS_G200_SE(mdev)) {
|
||||||
if (mdev->unique_rev_id == 0x01) {
|
if (mdev->unique_rev_id == 0x01) {
|
||||||
@ -1537,21 +1533,14 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Validate the mode input by the user */
|
/* Validate the mode input by the user */
|
||||||
for (i = 0; i < fb_helper->connector_count; i++) {
|
if (connector->cmdline_mode.specified) {
|
||||||
if (fb_helper->connector_info[i]->connector == connector) {
|
if (connector->cmdline_mode.bpp_specified)
|
||||||
/* Found the helper for this connector */
|
bpp = connector->cmdline_mode.bpp;
|
||||||
fb_helper_conn = fb_helper->connector_info[i];
|
|
||||||
if (fb_helper_conn->cmdline_mode.specified) {
|
|
||||||
if (fb_helper_conn->cmdline_mode.bpp_specified) {
|
|
||||||
bpp = fb_helper_conn->cmdline_mode.bpp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
|
if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
|
||||||
if (fb_helper_conn)
|
if (connector->cmdline_mode.specified)
|
||||||
fb_helper_conn->cmdline_mode.specified = false;
|
connector->cmdline_mode.specified = false;
|
||||||
return MODE_BAD;
|
return MODE_BAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
menuconfig FB
|
menuconfig FB
|
||||||
tristate "Support for frame buffer devices"
|
tristate "Support for frame buffer devices"
|
||||||
|
select FB_CMDLINE
|
||||||
---help---
|
---help---
|
||||||
The frame buffer device provides an abstraction for the graphics
|
The frame buffer device provides an abstraction for the graphics
|
||||||
hardware. It represents the frame buffer of some video hardware and
|
hardware. It represents the frame buffer of some video hardware and
|
||||||
@ -52,6 +53,9 @@ config FIRMWARE_EDID
|
|||||||
combination with certain motherboards and monitors are known to
|
combination with certain motherboards and monitors are known to
|
||||||
suffer from this problem.
|
suffer from this problem.
|
||||||
|
|
||||||
|
config FB_CMDLINE
|
||||||
|
bool
|
||||||
|
|
||||||
config FB_DDC
|
config FB_DDC
|
||||||
tristate
|
tristate
|
||||||
depends on FB
|
depends on FB
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
obj-y += fb_notify.o
|
obj-y += fb_notify.o
|
||||||
|
obj-$(CONFIG_FB_CMDLINE) += fb_cmdline.o
|
||||||
obj-$(CONFIG_FB) += fb.o
|
obj-$(CONFIG_FB) += fb.o
|
||||||
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
|
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
|
||||||
modedb.o fbcvt.o
|
modedb.o fbcvt.o
|
||||||
|
110
drivers/video/fbdev/core/fb_cmdline.c
Normal file
110
drivers/video/fbdev/core/fb_cmdline.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* linux/drivers/video/fb_cmdline.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Intel Corp
|
||||||
|
* Copyright (C) 1994 Martin Schaller
|
||||||
|
*
|
||||||
|
* 2001 - Documented with DocBook
|
||||||
|
* - Brad Douglas <brad@neruo.com>
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file COPYING in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Vetter <danie.vetter@ffwll.ch>
|
||||||
|
*/
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
|
||||||
|
static char *video_options[FB_MAX] __read_mostly;
|
||||||
|
static int ofonly __read_mostly;
|
||||||
|
|
||||||
|
const char *fb_mode_option;
|
||||||
|
EXPORT_SYMBOL_GPL(fb_mode_option);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fb_get_options - get kernel boot parameters
|
||||||
|
* @name: framebuffer name as it would appear in
|
||||||
|
* the boot parameter line
|
||||||
|
* (video=<name>:<options>)
|
||||||
|
* @option: the option will be stored here
|
||||||
|
*
|
||||||
|
* NOTE: Needed to maintain backwards compatibility
|
||||||
|
*/
|
||||||
|
int fb_get_options(const char *name, char **option)
|
||||||
|
{
|
||||||
|
char *opt, *options = NULL;
|
||||||
|
int retval = 0;
|
||||||
|
int name_len = strlen(name), i;
|
||||||
|
|
||||||
|
if (name_len && ofonly && strncmp(name, "offb", 4))
|
||||||
|
retval = 1;
|
||||||
|
|
||||||
|
if (name_len && !retval) {
|
||||||
|
for (i = 0; i < FB_MAX; i++) {
|
||||||
|
if (video_options[i] == NULL)
|
||||||
|
continue;
|
||||||
|
if (!video_options[i][0])
|
||||||
|
continue;
|
||||||
|
opt = video_options[i];
|
||||||
|
if (!strncmp(name, opt, name_len) &&
|
||||||
|
opt[name_len] == ':')
|
||||||
|
options = opt + name_len + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* No match, pass global option */
|
||||||
|
if (!options && option && fb_mode_option)
|
||||||
|
options = kstrdup(fb_mode_option, GFP_KERNEL);
|
||||||
|
if (options && !strncmp(options, "off", 3))
|
||||||
|
retval = 1;
|
||||||
|
|
||||||
|
if (option)
|
||||||
|
*option = options;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(fb_get_options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* video_setup - process command line options
|
||||||
|
* @options: string of options
|
||||||
|
*
|
||||||
|
* Process command line options for frame buffer subsystem.
|
||||||
|
*
|
||||||
|
* NOTE: This function is a __setup and __init function.
|
||||||
|
* It only stores the options. Drivers have to call
|
||||||
|
* fb_get_options() as necessary.
|
||||||
|
*
|
||||||
|
* Returns zero.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int __init video_setup(char *options)
|
||||||
|
{
|
||||||
|
int i, global = 0;
|
||||||
|
|
||||||
|
if (!options || !*options)
|
||||||
|
global = 1;
|
||||||
|
|
||||||
|
if (!global && !strncmp(options, "ofonly", 6)) {
|
||||||
|
ofonly = 1;
|
||||||
|
global = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global && !strchr(options, ':')) {
|
||||||
|
fb_mode_option = options;
|
||||||
|
global = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global) {
|
||||||
|
for (i = 0; i < FB_MAX; i++) {
|
||||||
|
if (video_options[i] == NULL) {
|
||||||
|
video_options[i] = options;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("video=", video_setup);
|
@ -1908,96 +1908,4 @@ int fb_new_modelist(struct fb_info *info)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *video_options[FB_MAX] __read_mostly;
|
|
||||||
static int ofonly __read_mostly;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fb_get_options - get kernel boot parameters
|
|
||||||
* @name: framebuffer name as it would appear in
|
|
||||||
* the boot parameter line
|
|
||||||
* (video=<name>:<options>)
|
|
||||||
* @option: the option will be stored here
|
|
||||||
*
|
|
||||||
* NOTE: Needed to maintain backwards compatibility
|
|
||||||
*/
|
|
||||||
int fb_get_options(const char *name, char **option)
|
|
||||||
{
|
|
||||||
char *opt, *options = NULL;
|
|
||||||
int retval = 0;
|
|
||||||
int name_len = strlen(name), i;
|
|
||||||
|
|
||||||
if (name_len && ofonly && strncmp(name, "offb", 4))
|
|
||||||
retval = 1;
|
|
||||||
|
|
||||||
if (name_len && !retval) {
|
|
||||||
for (i = 0; i < FB_MAX; i++) {
|
|
||||||
if (video_options[i] == NULL)
|
|
||||||
continue;
|
|
||||||
if (!video_options[i][0])
|
|
||||||
continue;
|
|
||||||
opt = video_options[i];
|
|
||||||
if (!strncmp(name, opt, name_len) &&
|
|
||||||
opt[name_len] == ':')
|
|
||||||
options = opt + name_len + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* No match, pass global option */
|
|
||||||
if (!options && option && fb_mode_option)
|
|
||||||
options = kstrdup(fb_mode_option, GFP_KERNEL);
|
|
||||||
if (options && !strncmp(options, "off", 3))
|
|
||||||
retval = 1;
|
|
||||||
|
|
||||||
if (option)
|
|
||||||
*option = options;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(fb_get_options);
|
|
||||||
|
|
||||||
#ifndef MODULE
|
|
||||||
/**
|
|
||||||
* video_setup - process command line options
|
|
||||||
* @options: string of options
|
|
||||||
*
|
|
||||||
* Process command line options for frame buffer subsystem.
|
|
||||||
*
|
|
||||||
* NOTE: This function is a __setup and __init function.
|
|
||||||
* It only stores the options. Drivers have to call
|
|
||||||
* fb_get_options() as necessary.
|
|
||||||
*
|
|
||||||
* Returns zero.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int __init video_setup(char *options)
|
|
||||||
{
|
|
||||||
int i, global = 0;
|
|
||||||
|
|
||||||
if (!options || !*options)
|
|
||||||
global = 1;
|
|
||||||
|
|
||||||
if (!global && !strncmp(options, "ofonly", 6)) {
|
|
||||||
ofonly = 1;
|
|
||||||
global = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!global && !strchr(options, ':')) {
|
|
||||||
fb_mode_option = options;
|
|
||||||
global = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!global) {
|
|
||||||
for (i = 0; i < FB_MAX; i++) {
|
|
||||||
if (video_options[i] == NULL) {
|
|
||||||
video_options[i] = options;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("video=", video_setup);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -29,9 +29,6 @@
|
|||||||
#define DPRINTK(fmt, args...)
|
#define DPRINTK(fmt, args...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char *fb_mode_option;
|
|
||||||
EXPORT_SYMBOL_GPL(fb_mode_option);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Standard video mode definitions (taken from XFree86)
|
* Standard video mode definitions (taken from XFree86)
|
||||||
*/
|
*/
|
||||||
|
@ -1294,6 +1294,8 @@ extern int drm_vblank_get(struct drm_device *dev, int crtc);
|
|||||||
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
||||||
extern int drm_crtc_vblank_get(struct drm_crtc *crtc);
|
extern int drm_crtc_vblank_get(struct drm_crtc *crtc);
|
||||||
extern void drm_crtc_vblank_put(struct drm_crtc *crtc);
|
extern void drm_crtc_vblank_put(struct drm_crtc *crtc);
|
||||||
|
extern void drm_wait_one_vblank(struct drm_device *dev, int crtc);
|
||||||
|
extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
|
||||||
extern void drm_vblank_off(struct drm_device *dev, int crtc);
|
extern void drm_vblank_off(struct drm_device *dev, int crtc);
|
||||||
extern void drm_vblank_on(struct drm_device *dev, int crtc);
|
extern void drm_vblank_on(struct drm_device *dev, int crtc);
|
||||||
extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
|
extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
|
||||||
|
@ -218,10 +218,6 @@ struct drm_property {
|
|||||||
struct list_head enum_blob_list;
|
struct list_head enum_blob_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
void drm_modeset_lock_all(struct drm_device *dev);
|
|
||||||
void drm_modeset_unlock_all(struct drm_device *dev);
|
|
||||||
void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
|
|
||||||
|
|
||||||
struct drm_crtc;
|
struct drm_crtc;
|
||||||
struct drm_connector;
|
struct drm_connector;
|
||||||
struct drm_encoder;
|
struct drm_encoder;
|
||||||
@ -345,10 +341,6 @@ struct drm_crtc {
|
|||||||
int cursor_x;
|
int cursor_x;
|
||||||
int cursor_y;
|
int cursor_y;
|
||||||
|
|
||||||
/* Temporary tracking of the old fb while a modeset is ongoing. Used
|
|
||||||
* by drm_mode_set_config_internal to implement correct refcounting. */
|
|
||||||
struct drm_framebuffer *old_fb;
|
|
||||||
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
/* Requested mode from modesetting. */
|
/* Requested mode from modesetting. */
|
||||||
@ -375,6 +367,12 @@ struct drm_crtc {
|
|||||||
void *helper_private;
|
void *helper_private;
|
||||||
|
|
||||||
struct drm_object_properties properties;
|
struct drm_object_properties properties;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For legacy crtc ioctls so that atomic drivers can get at the locking
|
||||||
|
* acquire context.
|
||||||
|
*/
|
||||||
|
struct drm_modeset_acquire_ctx *acquire_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -548,6 +546,7 @@ struct drm_connector {
|
|||||||
void *helper_private;
|
void *helper_private;
|
||||||
|
|
||||||
/* forced on connector */
|
/* forced on connector */
|
||||||
|
struct drm_cmdline_mode cmdline_mode;
|
||||||
enum drm_connector_force force;
|
enum drm_connector_force force;
|
||||||
bool override_edid;
|
bool override_edid;
|
||||||
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
|
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
|
||||||
@ -582,6 +581,7 @@ struct drm_plane_funcs {
|
|||||||
uint32_t src_w, uint32_t src_h);
|
uint32_t src_w, uint32_t src_h);
|
||||||
int (*disable_plane)(struct drm_plane *plane);
|
int (*disable_plane)(struct drm_plane *plane);
|
||||||
void (*destroy)(struct drm_plane *plane);
|
void (*destroy)(struct drm_plane *plane);
|
||||||
|
void (*reset)(struct drm_plane *plane);
|
||||||
|
|
||||||
int (*set_property)(struct drm_plane *plane,
|
int (*set_property)(struct drm_plane *plane,
|
||||||
struct drm_property *property, uint64_t val);
|
struct drm_property *property, uint64_t val);
|
||||||
@ -620,6 +620,10 @@ struct drm_plane {
|
|||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct drm_framebuffer *fb;
|
struct drm_framebuffer *fb;
|
||||||
|
|
||||||
|
/* Temporary tracking of the old fb while a modeset is ongoing. Used
|
||||||
|
* by drm_mode_set_config_internal to implement correct refcounting. */
|
||||||
|
struct drm_framebuffer *old_fb;
|
||||||
|
|
||||||
const struct drm_plane_funcs *funcs;
|
const struct drm_plane_funcs *funcs;
|
||||||
|
|
||||||
struct drm_object_properties properties;
|
struct drm_object_properties properties;
|
||||||
@ -903,6 +907,7 @@ int drm_connector_register(struct drm_connector *connector);
|
|||||||
void drm_connector_unregister(struct drm_connector *connector);
|
void drm_connector_unregister(struct drm_connector *connector);
|
||||||
|
|
||||||
extern void drm_connector_cleanup(struct drm_connector *connector);
|
extern void drm_connector_cleanup(struct drm_connector *connector);
|
||||||
|
extern unsigned int drm_connector_index(struct drm_connector *connector);
|
||||||
/* helper to unplug all connectors from sysfs for device */
|
/* helper to unplug all connectors from sysfs for device */
|
||||||
extern void drm_connector_unplug_all(struct drm_device *dev);
|
extern void drm_connector_unplug_all(struct drm_device *dev);
|
||||||
|
|
||||||
@ -942,6 +947,7 @@ extern int drm_plane_init(struct drm_device *dev,
|
|||||||
const uint32_t *formats, uint32_t format_count,
|
const uint32_t *formats, uint32_t format_count,
|
||||||
bool is_primary);
|
bool is_primary);
|
||||||
extern void drm_plane_cleanup(struct drm_plane *plane);
|
extern void drm_plane_cleanup(struct drm_plane *plane);
|
||||||
|
extern unsigned int drm_plane_index(struct drm_plane *plane);
|
||||||
extern void drm_plane_force_disable(struct drm_plane *plane);
|
extern void drm_plane_force_disable(struct drm_plane *plane);
|
||||||
extern int drm_crtc_check_viewport(const struct drm_crtc *crtc,
|
extern int drm_crtc_check_viewport(const struct drm_crtc *crtc,
|
||||||
int x, int y,
|
int x, int y,
|
||||||
|
@ -77,7 +77,6 @@ struct drm_fb_helper_funcs {
|
|||||||
|
|
||||||
struct drm_fb_helper_connector {
|
struct drm_fb_helper_connector {
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
struct drm_cmdline_mode cmdline_mode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_fb_helper {
|
struct drm_fb_helper {
|
||||||
|
@ -53,6 +53,11 @@ struct drm_modeset_acquire_ctx {
|
|||||||
* list of held locks (drm_modeset_lock)
|
* list of held locks (drm_modeset_lock)
|
||||||
*/
|
*/
|
||||||
struct list_head locked;
|
struct list_head locked;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trylock mode, use only for panic handlers!
|
||||||
|
*/
|
||||||
|
bool trylock_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,6 +125,17 @@ int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock,
|
|||||||
void drm_modeset_unlock(struct drm_modeset_lock *lock);
|
void drm_modeset_unlock(struct drm_modeset_lock *lock);
|
||||||
|
|
||||||
struct drm_device;
|
struct drm_device;
|
||||||
|
struct drm_crtc;
|
||||||
|
|
||||||
|
void drm_modeset_lock_all(struct drm_device *dev);
|
||||||
|
int __drm_modeset_lock_all(struct drm_device *dev, bool trylock);
|
||||||
|
void drm_modeset_unlock_all(struct drm_device *dev);
|
||||||
|
void drm_modeset_lock_crtc(struct drm_crtc *crtc);
|
||||||
|
void drm_modeset_unlock_crtc(struct drm_crtc *crtc);
|
||||||
|
void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
|
||||||
|
struct drm_modeset_acquire_ctx *
|
||||||
|
drm_modeset_legacy_acquire_ctx(struct drm_crtc *crtc);
|
||||||
|
|
||||||
int drm_modeset_lock_all_crtcs(struct drm_device *dev,
|
int drm_modeset_lock_all_crtcs(struct drm_device *dev,
|
||||||
struct drm_modeset_acquire_ctx *ctx);
|
struct drm_modeset_acquire_ctx *ctx);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user