30,9 → 30,11 |
* Jesse Barnes <jesse.barnes@intel.com> |
*/ |
#include <linux/list.h> |
#include <linux/slab.h> |
#include "drm.h" |
#include "drmP.h" |
#include "drm_crtc.h" |
#include "drm_edid.h" |
|
struct drm_prop_enum_list { |
int type; |
78,6 → 80,7 |
{ |
{ DRM_MODE_DITHERING_OFF, "Off" }, |
{ DRM_MODE_DITHERING_ON, "On" }, |
{ DRM_MODE_DITHERING_AUTO, "Automatic" }, |
}; |
|
/* |
153,12 → 156,12 |
{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, |
{ DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, |
{ DRM_MODE_CONNECTOR_Component, "Component", 0 }, |
{ DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 }, |
{ DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 }, |
{ DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, |
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, |
{ DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 }, |
{ DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 }, |
{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 }, |
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, |
{ DRM_MODE_CONNECTOR_TV, "TV", 0 }, |
{ DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 }, |
{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, |
}; |
|
static struct drm_prop_enum_list drm_encoder_enum_list[] = |
493,7 → 496,6 |
list_for_each_entry_safe(mode, t, &connector->user_modes, head) |
drm_mode_remove(connector, mode); |
|
kfree(connector->fb_helper_private); |
mutex_lock(&dev->mode_config.mutex); |
drm_mode_object_put(dev, &connector->base); |
list_del(&connector->head); |
857,7 → 859,6 |
mutex_init(&dev->mode_config.mutex); |
mutex_init(&dev->mode_config.idr_mutex); |
INIT_LIST_HEAD(&dev->mode_config.fb_list); |
INIT_LIST_HEAD(&dev->mode_config.fb_kernel_list); |
INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
INIT_LIST_HEAD(&dev->mode_config.connector_list); |
INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
1074,6 → 1075,9 |
uint32_t __user *encoder_id; |
struct drm_mode_group *mode_group; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
|
/* |
1111,7 → 1115,7 |
if (card_res->count_fbs >= fb_count) { |
copied = 0; |
fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; |
list_for_each_entry(fb, &file_priv->fbs, head) { |
list_for_each_entry(fb, &file_priv->fbs, filp_head) { |
if (put_user(fb->base.id, fb_id + copied)) { |
ret = -EFAULT; |
goto out; |
1128,7 → 1132,7 |
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, |
head) { |
DRM_DEBUG_KMS("CRTC ID is %d\n", crtc->base.id); |
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
if (put_user(crtc->base.id, crtc_id + copied)) { |
ret = -EFAULT; |
goto out; |
1156,8 → 1160,8 |
list_for_each_entry(encoder, |
&dev->mode_config.encoder_list, |
head) { |
DRM_DEBUG_KMS("ENCODER ID is %d\n", |
encoder->base.id); |
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, |
drm_get_encoder_name(encoder)); |
if (put_user(encoder->base.id, encoder_id + |
copied)) { |
ret = -EFAULT; |
1187,8 → 1191,9 |
list_for_each_entry(connector, |
&dev->mode_config.connector_list, |
head) { |
DRM_DEBUG_KMS("CONNECTOR ID is %d\n", |
connector->base.id); |
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
connector->base.id, |
drm_get_connector_name(connector)); |
if (put_user(connector->base.id, |
connector_id + copied)) { |
ret = -EFAULT; |
1211,7 → 1216,7 |
} |
card_res->count_connectors = connector_count; |
|
DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs, |
DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs, |
card_res->count_connectors, card_res->count_encoders); |
|
out: |
1244,6 → 1249,9 |
struct drm_mode_object *obj; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
|
obj = drm_mode_object_find(dev, crtc_resp->crtc_id, |
1312,9 → 1320,12 |
uint64_t __user *prop_values; |
uint32_t __user *encoder_ptr; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); |
|
DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id); |
DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); |
|
mutex_lock(&dev->mode_config.mutex); |
|
1431,6 → 1442,9 |
struct drm_encoder *encoder; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, enc_resp->encoder_id, |
DRM_MODE_OBJECT_ENCODER); |
1486,6 → 1500,9 |
int ret = 0; |
int i; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, crtc_req->crtc_id, |
DRM_MODE_OBJECT_CRTC); |
1495,6 → 1512,7 |
goto out; |
} |
crtc = obj_to_crtc(obj); |
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
|
if (crtc_req->mode_valid) { |
/* If we have a mode we need a framebuffer. */ |
1571,6 → 1589,9 |
goto out; |
} |
connector = obj_to_connector(obj); |
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
connector->base.id, |
drm_get_connector_name(connector)); |
|
connector_set[i] = connector; |
} |
1599,6 → 1620,9 |
struct drm_crtc *crtc; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
if (!req->flags) { |
DRM_ERROR("no operation set\n"); |
return -EINVAL; |
1663,6 → 1687,9 |
struct drm_framebuffer *fb; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
if ((config->min_width > r->width) || (r->width > config->max_width)) { |
DRM_ERROR("mode new framebuffer width not within limits\n"); |
return -EINVAL; |
1674,18 → 1701,19 |
|
mutex_lock(&dev->mode_config.mutex); |
|
/* TODO check buffer is sufficently large */ |
/* TODO check buffer is sufficiently large */ |
/* TODO setup destructor callback */ |
|
fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
if (!fb) { |
if (IS_ERR(fb)) { |
DRM_ERROR("could not create framebuffer\n"); |
ret = -EINVAL; |
ret = PTR_ERR(fb); |
goto out; |
} |
|
r->fb_id = fb->base.id; |
list_add(&fb->filp_head, &file_priv->fbs); |
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
|
out: |
mutex_unlock(&dev->mode_config.mutex); |
1719,9 → 1747,12 |
int ret = 0; |
int found = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); |
/* TODO check that we realy get a framebuffer back. */ |
/* TODO check that we really get a framebuffer back. */ |
if (!obj) { |
DRM_ERROR("mode invalid framebuffer id\n"); |
ret = -EINVAL; |
1775,6 → 1806,9 |
struct drm_framebuffer *fb; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
if (!obj) { |
1808,6 → 1842,9 |
int num_clips; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); |
if (!obj) { |
1842,12 → 1879,15 |
|
ret = copy_from_user(clips, clips_ptr, |
num_clips * sizeof(*clips)); |
if (ret) |
if (ret) { |
ret = -EFAULT; |
goto out_err2; |
} |
} |
|
if (fb->funcs->dirty) { |
ret = fb->funcs->dirty(fb, flags, r->color, clips, num_clips); |
ret = fb->funcs->dirty(fb, file_priv, flags, r->color, |
clips, num_clips); |
} else { |
ret = -ENOSYS; |
goto out_err2; |
1991,6 → 2031,9 |
struct drm_mode_modeinfo *umode = &mode_cmd->mode; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
|
obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
2037,6 → 2080,9 |
struct drm_mode_modeinfo *umode = &mode_cmd->mode; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
|
obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
2208,6 → 2254,9 |
uint64_t __user *values_ptr; |
uint32_t __user *blob_length_ptr; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); |
if (!obj) { |
2332,6 → 2381,9 |
int ret = 0; |
void *blob_ptr; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); |
if (!obj) { |
2359,7 → 2411,7 |
struct edid *edid) |
{ |
struct drm_device *dev = connector->dev; |
int ret = 0; |
int ret = 0, size; |
|
if (connector->edid_blob_ptr) |
drm_property_destroy_blob(dev, connector->edid_blob_ptr); |
2371,7 → 2423,9 |
return ret; |
} |
|
connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); |
size = EDID_LENGTH * (1 + edid->extensions); |
connector->edid_blob_ptr = drm_property_create_blob(connector->dev, |
size, edid); |
|
ret = drm_connector_property_set_value(connector, |
dev->mode_config.edid_property, |
2392,6 → 2446,9 |
int ret = -EINVAL; |
int i; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
|
obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
2510,6 → 2567,9 |
int size; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
2543,7 → 2603,7 |
goto out; |
} |
|
crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); |
crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); |
|
out: |
mutex_unlock(&dev->mode_config.mutex); |
2561,6 → 2621,9 |
int size; |
int ret = 0; |
|
if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
return -EINVAL; |
|
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
2601,3 → 2664,22 |
#endif |
|
|
void drm_mode_config_reset(struct drm_device *dev) |
{ |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
struct drm_connector *connector; |
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
if (crtc->funcs->reset) |
crtc->funcs->reset(crtc); |
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) |
if (encoder->funcs->reset) |
encoder->funcs->reset(encoder); |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
if (connector->funcs->reset) |
connector->funcs->reset(connector); |
} |
EXPORT_SYMBOL(drm_mode_config_reset); |