29,6 → 29,7 |
* Dave Airlie <airlied@linux.ie> |
* Jesse Barnes <jesse.barnes@intel.com> |
*/ |
#include <linux/ctype.h> |
#include <linux/list.h> |
#include <linux/slab.h> |
#include <linux/export.h> |
87,7 → 88,7 |
|
/* Avoid boilerplate. I'm tired of typing. */ |
#define DRM_ENUM_NAME_FN(fnname, list) \ |
char *fnname(int val) \ |
const char *fnname(int val) \ |
{ \ |
int i; \ |
for (i = 0; i < ARRAY_SIZE(list); i++) { \ |
100,7 → 101,7 |
/* |
* Global properties |
*/ |
static struct drm_prop_enum_list drm_dpms_enum_list[] = |
static const struct drm_prop_enum_list drm_dpms_enum_list[] = |
{ { DRM_MODE_DPMS_ON, "On" }, |
{ DRM_MODE_DPMS_STANDBY, "Standby" }, |
{ DRM_MODE_DPMS_SUSPEND, "Suspend" }, |
112,7 → 113,7 |
/* |
* Optional properties |
*/ |
static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = |
static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = |
{ |
{ DRM_MODE_SCALE_NONE, "None" }, |
{ DRM_MODE_SCALE_FULLSCREEN, "Full" }, |
120,7 → 121,7 |
{ DRM_MODE_SCALE_ASPECT, "Full aspect" }, |
}; |
|
static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = |
static const struct drm_prop_enum_list drm_dithering_mode_enum_list[] = |
{ |
{ DRM_MODE_DITHERING_OFF, "Off" }, |
{ DRM_MODE_DITHERING_ON, "On" }, |
130,7 → 131,7 |
/* |
* Non-global properties, but "required" for certain connectors. |
*/ |
static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = |
static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = |
{ |
{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
{ DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
139,7 → 140,7 |
|
DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) |
|
static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = |
static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = |
{ |
{ DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
{ DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
149,7 → 150,7 |
DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, |
drm_dvi_i_subconnector_enum_list) |
|
static struct drm_prop_enum_list drm_tv_select_enum_list[] = |
static const struct drm_prop_enum_list drm_tv_select_enum_list[] = |
{ |
{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
160,7 → 161,7 |
|
DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
|
static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = |
static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = |
{ |
{ DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
172,18 → 173,15 |
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, |
drm_tv_subconnector_enum_list) |
|
static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { |
static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = { |
{ DRM_MODE_DIRTY_OFF, "Off" }, |
{ DRM_MODE_DIRTY_ON, "On" }, |
{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, |
}; |
|
DRM_ENUM_NAME_FN(drm_get_dirty_info_name, |
drm_dirty_info_enum_list) |
|
struct drm_conn_prop_enum_list { |
int type; |
char *name; |
const char *name; |
int count; |
}; |
|
209,7 → 207,7 |
{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0}, |
}; |
|
static struct drm_prop_enum_list drm_encoder_enum_list[] = |
static const struct drm_prop_enum_list drm_encoder_enum_list[] = |
{ { DRM_MODE_ENCODER_NONE, "None" }, |
{ DRM_MODE_ENCODER_DAC, "DAC" }, |
{ DRM_MODE_ENCODER_TMDS, "TMDS" }, |
218,7 → 216,7 |
{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, |
}; |
|
char *drm_get_encoder_name(struct drm_encoder *encoder) |
const char *drm_get_encoder_name(const struct drm_encoder *encoder) |
{ |
static char buf[32]; |
|
229,7 → 227,7 |
} |
EXPORT_SYMBOL(drm_get_encoder_name); |
|
char *drm_get_connector_name(struct drm_connector *connector) |
const char *drm_get_connector_name(const struct drm_connector *connector) |
{ |
static char buf[32]; |
|
240,7 → 238,7 |
} |
EXPORT_SYMBOL(drm_get_connector_name); |
|
char *drm_get_connector_status_name(enum drm_connector_status status) |
const char *drm_get_connector_status_name(enum drm_connector_status status) |
{ |
if (status == connector_status_connected) |
return "connected"; |
251,6 → 249,28 |
} |
EXPORT_SYMBOL(drm_get_connector_status_name); |
|
static char printable_char(int c) |
{ |
return isascii(c) && isprint(c) ? c : '?'; |
} |
|
const char *drm_get_format_name(uint32_t format) |
{ |
static char buf[32]; |
|
snprintf(buf, sizeof(buf), |
"%c%c%c%c %s-endian (0x%08x)", |
printable_char(format & 0xff), |
printable_char((format >> 8) & 0xff), |
printable_char((format >> 16) & 0xff), |
printable_char((format >> 24) & 0x7f), |
format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", |
format); |
|
return buf; |
} |
EXPORT_SYMBOL(drm_get_format_name); |
|
/** |
* drm_mode_object_get - allocate a new modeset identifier |
* @dev: DRM device |
413,7 → 433,7 |
mutex_lock(&dev->mode_config.fb_lock); |
fb = __drm_framebuffer_lookup(dev, id); |
if (fb) |
kref_get(&fb->refcount); |
drm_framebuffer_reference(fb); |
mutex_unlock(&dev->mode_config.fb_lock); |
|
return fb; |
568,17 → 588,9 |
} |
|
list_for_each_entry(plane, &dev->mode_config.plane_list, head) { |
if (plane->fb == fb) { |
/* should turn off the crtc */ |
ret = plane->funcs->disable_plane(plane); |
if (ret) |
DRM_ERROR("failed to disable plane with busy fb\n"); |
/* disconnect the plane from the fb and crtc: */ |
__drm_framebuffer_unreference(plane->fb); |
plane->fb = NULL; |
plane->crtc = NULL; |
if (plane->fb == fb) |
drm_plane_force_disable(plane); |
} |
} |
drm_modeset_unlock_all(dev); |
} |
|
592,7 → 604,7 |
* @crtc: CRTC object to init |
* @funcs: callbacks for the new CRTC |
* |
* Inits a new object created as base part of an driver crtc object. |
* Inits a new object created as base part of a driver crtc object. |
* |
* RETURNS: |
* Zero on success, error code on failure. |
627,11 → 639,12 |
EXPORT_SYMBOL(drm_crtc_init); |
|
/** |
* drm_crtc_cleanup - Cleans up the core crtc usage. |
* drm_crtc_cleanup - Clean up the core crtc usage |
* @crtc: CRTC to cleanup |
* |
* Cleanup @crtc. Removes from drm modesetting space |
* does NOT free object, caller does that. |
* This function cleans up @crtc and removes it from the DRM mode setting |
* core. Note that the function does *not* free the crtc structure itself, |
* this is the responsibility of the caller. |
*/ |
void drm_crtc_cleanup(struct drm_crtc *crtc) |
{ |
656,7 → 669,7 |
void drm_mode_probed_add(struct drm_connector *connector, |
struct drm_display_mode *mode) |
{ |
list_add(&mode->head, &connector->probed_modes); |
list_add_tail(&mode->head, &connector->probed_modes); |
} |
EXPORT_SYMBOL(drm_mode_probed_add); |
|
802,6 → 815,21 |
} |
EXPORT_SYMBOL(drm_encoder_cleanup); |
|
/** |
* drm_plane_init - Initialise a new plane object |
* @dev: DRM device |
* @plane: plane object to init |
* @possible_crtcs: bitmask of possible CRTCs |
* @funcs: callbacks for the new plane |
* @formats: array of supported formats (%DRM_FORMAT_*) |
* @format_count: number of elements in @formats |
* @priv: plane is private (hidden from userspace)? |
* |
* Inits a new object created as base part of a driver plane object. |
* |
* RETURNS: |
* Zero on success, error code on failure. |
*/ |
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, |
unsigned long possible_crtcs, |
const struct drm_plane_funcs *funcs, |
850,6 → 878,14 |
} |
EXPORT_SYMBOL(drm_plane_init); |
|
/** |
* drm_plane_cleanup - Clean up the core plane usage |
* @plane: plane to cleanup |
* |
* This function cleans up @plane and removes it from the DRM mode setting |
* core. Note that the function does *not* free the plane structure itself, |
* this is the responsibility of the caller. |
*/ |
void drm_plane_cleanup(struct drm_plane *plane) |
{ |
struct drm_device *dev = plane->dev; |
867,6 → 903,32 |
EXPORT_SYMBOL(drm_plane_cleanup); |
|
/** |
* drm_plane_force_disable - Forcibly disable a plane |
* @plane: plane to disable |
* |
* Forces the plane to be disabled. |
* |
* Used when the plane's current framebuffer is destroyed, |
* and when restoring fbdev mode. |
*/ |
void drm_plane_force_disable(struct drm_plane *plane) |
{ |
int ret; |
|
if (!plane->fb) |
return; |
|
ret = plane->funcs->disable_plane(plane); |
if (ret) |
DRM_ERROR("failed to disable plane with busy fb\n"); |
/* disconnect the plane from the fb and crtc: */ |
__drm_framebuffer_unreference(plane->fb); |
plane->fb = NULL; |
plane->crtc = NULL; |
} |
EXPORT_SYMBOL(drm_plane_force_disable); |
|
/** |
* drm_mode_create - create a new display mode |
* @dev: DRM device |
* |
1741,7 → 1803,7 |
|
plane_resp->plane_id = plane->base.id; |
plane_resp->possible_crtcs = plane->possible_crtcs; |
plane_resp->gamma_size = plane->gamma_size; |
plane_resp->gamma_size = 0; |
|
/* |
* This ioctl is called twice, once to determine how much space is |
1835,7 → 1897,8 |
if (fb->pixel_format == plane->format_types[i]) |
break; |
if (i == plane->format_count) { |
DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); |
DRM_DEBUG_KMS("Invalid pixel format %s\n", |
drm_get_format_name(fb->pixel_format)); |
ret = -EINVAL; |
goto out; |
} |
1908,20 → 1971,33 |
int drm_mode_set_config_internal(struct drm_mode_set *set) |
{ |
struct drm_crtc *crtc = set->crtc; |
struct drm_framebuffer *fb, *old_fb; |
struct drm_framebuffer *fb; |
struct drm_crtc *tmp; |
int ret; |
|
old_fb = crtc->fb; |
/* |
* NOTE: ->set_config can also disable other crtcs (if we steal all |
* connectors from it), hence we need to refcount the fbs across all |
* crtcs. Atomic modeset will have saner semantics ... |
*/ |
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) |
tmp->old_fb = tmp->fb; |
|
fb = set->fb; |
|
ret = crtc->funcs->set_config(set); |
if (ret == 0) { |
if (old_fb) |
drm_framebuffer_unreference(old_fb); |
if (fb) |
drm_framebuffer_reference(fb); |
/* crtc->fb must be updated by ->set_config, enforces this. */ |
WARN_ON(fb != crtc->fb); |
} |
|
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { |
if (tmp->fb) |
drm_framebuffer_reference(tmp->fb); |
// if (tmp->old_fb) |
// drm_framebuffer_unreference(tmp->old_fb); |
} |
|
return ret; |
} |
EXPORT_SYMBOL(drm_mode_set_config_internal); |
2102,10 → 2178,10 |
return ret; |
} |
|
int drm_mode_cursor_ioctl(struct drm_device *dev, |
void *data, struct drm_file *file_priv) |
static int drm_mode_cursor_common(struct drm_device *dev, |
struct drm_mode_cursor2 *req, |
struct drm_file *file_priv) |
{ |
struct drm_mode_cursor *req = data; |
struct drm_mode_object *obj; |
struct drm_crtc *crtc; |
int ret = 0; |
2125,11 → 2201,15 |
|
mutex_lock(&crtc->mutex); |
if (req->flags & DRM_MODE_CURSOR_BO) { |
if (!crtc->funcs->cursor_set) { |
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { |
ret = -ENXIO; |
goto out; |
} |
/* Turns off the cursor if handle is 0 */ |
if (crtc->funcs->cursor_set2) |
ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle, |
req->width, req->height, req->hot_x, req->hot_y); |
else |
ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, |
req->width, req->height); |
} |
2146,7 → 2226,26 |
mutex_unlock(&crtc->mutex); |
|
return ret; |
|
} |
int drm_mode_cursor_ioctl(struct drm_device *dev, |
void *data, struct drm_file *file_priv) |
{ |
struct drm_mode_cursor *req = data; |
struct drm_mode_cursor2 new_req; |
|
memcpy(&new_req, req, sizeof(struct drm_mode_cursor)); |
new_req.hot_x = new_req.hot_y = 0; |
|
return drm_mode_cursor_common(dev, &new_req, file_priv); |
} |
|
int drm_mode_cursor2_ioctl(struct drm_device *dev, |
void *data, struct drm_file *file_priv) |
{ |
struct drm_mode_cursor2 *req = data; |
return drm_mode_cursor_common(dev, req, file_priv); |
} |
#endif |
/* Original addfb only supported RGB formats, so figure out which one */ |
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) |
2315,7 → 2414,8 |
|
ret = format_check(r); |
if (ret) { |
DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format); |
DRM_DEBUG_KMS("bad framebuffer format %s\n", |
drm_get_format_name(r->pixel_format)); |
return ret; |
} |
|