/drivers/video/drm/drm_crtc.c |
---|
29,7 → 29,7 |
* Dave Airlie <airlied@linux.ie> |
* Jesse Barnes <jesse.barnes@intel.com> |
*/ |
#include <list.h> |
#include <linux/list.h> |
#include "drm.h" |
#include "drmP.h" |
#include "drm_crtc.h" |
68,10 → 68,10 |
*/ |
static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = |
{ |
{ DRM_MODE_SCALE_NON_GPU, "Non-GPU" }, |
{ DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" }, |
{ DRM_MODE_SCALE_NO_SCALE, "No scale" }, |
{ DRM_MODE_SCALE_ASPECT, "Aspect" }, |
{ DRM_MODE_SCALE_NONE, "None" }, |
{ DRM_MODE_SCALE_FULLSCREEN, "Full" }, |
{ DRM_MODE_SCALE_CENTER, "Center" }, |
{ DRM_MODE_SCALE_ASPECT, "Full aspect" }, |
}; |
static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = |
108,6 → 108,7 |
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
{ DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
{ DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ |
}; |
DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
118,6 → 119,7 |
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
{ DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
{ DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ |
}; |
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, |
146,6 → 148,7 |
{ 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_TV, "TV", 0 }, |
}; |
static struct drm_prop_enum_list drm_encoder_enum_list[] = |
165,6 → 168,7 |
encoder->base.id); |
return buf; |
} |
EXPORT_SYMBOL(drm_get_encoder_name); |
char *drm_get_connector_name(struct drm_connector *connector) |
{ |
214,15 → 218,14 |
return -EINVAL; |
} |
// mutex_lock(&dev->mode_config.idr_mutex); |
mutex_lock(&dev->mode_config.idr_mutex); |
ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id); |
// mutex_unlock(&dev->mode_config.idr_mutex); |
mutex_unlock(&dev->mode_config.idr_mutex); |
if (ret == -EAGAIN) |
goto again; |
obj->id = new_id; |
obj->type = obj_type; |
return 0; |
} |
239,9 → 242,9 |
static void drm_mode_object_put(struct drm_device *dev, |
struct drm_mode_object *object) |
{ |
// mutex_lock(&dev->mode_config.idr_mutex); |
mutex_lock(&dev->mode_config.idr_mutex); |
idr_remove(&dev->mode_config.crtc_idr, object->id); |
// mutex_unlock(&dev->mode_config.idr_mutex); |
mutex_unlock(&dev->mode_config.idr_mutex); |
} |
void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) |
248,43 → 251,17 |
{ |
struct drm_mode_object *obj = NULL; |
// mutex_lock(&dev->mode_config.idr_mutex); |
mutex_lock(&dev->mode_config.idr_mutex); |
obj = idr_find(&dev->mode_config.crtc_idr, id); |
if (!obj || (obj->type != type) || (obj->id != id)) |
obj = NULL; |
// mutex_unlock(&dev->mode_config.idr_mutex); |
mutex_unlock(&dev->mode_config.idr_mutex); |
return obj; |
} |
EXPORT_SYMBOL(drm_mode_object_find); |
/** |
* drm_crtc_from_fb - find the CRTC structure associated with an fb |
* @dev: DRM device |
* @fb: framebuffer in question |
* |
* LOCKING: |
* Caller must hold mode_config lock. |
* |
* Find CRTC in the mode_config structure that matches @fb. |
* |
* RETURNS: |
* Pointer to the CRTC or NULL if it wasn't found. |
*/ |
struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, |
struct drm_framebuffer *fb) |
{ |
struct drm_crtc *crtc; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
if (crtc->fb == fb) |
return crtc; |
} |
return NULL; |
} |
/** |
* drm_framebuffer_init - initialize a framebuffer |
* @dev: DRM device |
* |
330,12 → 307,21 |
{ |
struct drm_device *dev = fb->dev; |
struct drm_crtc *crtc; |
struct drm_mode_set set; |
int ret; |
/* remove from any CRTC */ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
if (crtc->fb == fb) |
crtc->fb = NULL; |
if (crtc->fb == fb) { |
/* should turn off the crtc */ |
memset(&set, 0, sizeof(struct drm_mode_set)); |
set.crtc = crtc; |
set.fb = NULL; |
ret = crtc->funcs->set_config(&set); |
if (ret) |
DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); |
} |
} |
drm_mode_object_put(dev, &fb->base); |
list_del(&fb->head); |
343,7 → 329,6 |
} |
EXPORT_SYMBOL(drm_framebuffer_cleanup); |
/** |
* drm_crtc_init - Initialise a new CRTC object |
* @dev: DRM device |
358,20 → 343,15 |
void drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, |
const struct drm_crtc_funcs *funcs) |
{ |
ENTRY(); |
crtc->dev = dev; |
crtc->funcs = funcs; |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
list_add_tail(&crtc->head, &dev->mode_config.crtc_list); |
dev->mode_config.num_crtc++; |
// mutex_unlock(&dev->mode_config.mutex); |
LEAVE(); |
mutex_unlock(&dev->mode_config.mutex); |
} |
EXPORT_SYMBOL(drm_crtc_init); |
453,7 → 433,7 |
const struct drm_connector_funcs *funcs, |
int connector_type) |
{ |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
connector->dev = dev; |
connector->funcs = funcs; |
475,7 → 455,7 |
drm_connector_attach_property(connector, |
dev->mode_config.dpms_property, 0); |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
} |
EXPORT_SYMBOL(drm_connector_init); |
502,10 → 482,10 |
list_for_each_entry_safe(mode, t, &connector->user_modes, head) |
drm_mode_remove(connector, mode); |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
drm_mode_object_put(dev, &connector->base); |
list_del(&connector->head); |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
} |
EXPORT_SYMBOL(drm_connector_cleanup); |
514,7 → 494,7 |
const struct drm_encoder_funcs *funcs, |
int encoder_type) |
{ |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
encoder->dev = dev; |
525,7 → 505,7 |
list_add_tail(&encoder->head, &dev->mode_config.encoder_list); |
dev->mode_config.num_encoder++; |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
} |
EXPORT_SYMBOL(drm_encoder_init); |
532,10 → 512,10 |
void drm_encoder_cleanup(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
drm_mode_object_put(dev, &encoder->base); |
list_del(&encoder->head); |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
} |
EXPORT_SYMBOL(drm_encoder_cleanup); |
588,7 → 568,6 |
struct drm_property *dpms; |
int i; |
ENTRY(); |
/* |
* Standard properties (apply to all connectors) |
*/ |
604,7 → 583,6 |
drm_dpms_enum_list[i].name); |
dev->mode_config.dpms_property = dpms; |
LEAVE(); |
return 0; |
} |
725,6 → 703,42 |
drm_property_add_enum(dev->mode_config.tv_mode_property, i, |
i, modes[i]); |
dev->mode_config.tv_brightness_property = |
drm_property_create(dev, DRM_MODE_PROP_RANGE, |
"brightness", 2); |
dev->mode_config.tv_brightness_property->values[0] = 0; |
dev->mode_config.tv_brightness_property->values[1] = 100; |
dev->mode_config.tv_contrast_property = |
drm_property_create(dev, DRM_MODE_PROP_RANGE, |
"contrast", 2); |
dev->mode_config.tv_contrast_property->values[0] = 0; |
dev->mode_config.tv_contrast_property->values[1] = 100; |
dev->mode_config.tv_flicker_reduction_property = |
drm_property_create(dev, DRM_MODE_PROP_RANGE, |
"flicker reduction", 2); |
dev->mode_config.tv_flicker_reduction_property->values[0] = 0; |
dev->mode_config.tv_flicker_reduction_property->values[1] = 100; |
dev->mode_config.tv_overscan_property = |
drm_property_create(dev, DRM_MODE_PROP_RANGE, |
"overscan", 2); |
dev->mode_config.tv_overscan_property->values[0] = 0; |
dev->mode_config.tv_overscan_property->values[1] = 100; |
dev->mode_config.tv_saturation_property = |
drm_property_create(dev, DRM_MODE_PROP_RANGE, |
"saturation", 2); |
dev->mode_config.tv_saturation_property->values[0] = 0; |
dev->mode_config.tv_saturation_property->values[1] = 100; |
dev->mode_config.tv_hue_property = |
drm_property_create(dev, DRM_MODE_PROP_RANGE, |
"hue", 2); |
dev->mode_config.tv_hue_property->values[0] = 0; |
dev->mode_config.tv_hue_property->values[1] = 100; |
return 0; |
} |
EXPORT_SYMBOL(drm_mode_create_tv_properties); |
798,8 → 812,6 |
*/ |
void drm_mode_config_init(struct drm_device *dev) |
{ |
ENTRY(); |
// mutex_init(&dev->mode_config.mutex); |
// mutex_init(&dev->mode_config.idr_mutex); |
INIT_LIST_HEAD(&dev->mode_config.fb_list); |
809,12 → 821,11 |
INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
INIT_LIST_HEAD(&dev->mode_config.property_list); |
INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
idr_init(&dev->mode_config.crtc_idr); |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
drm_mode_create_standard_connector_properties(dev); |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
/* Just to be sure */ |
dev->mode_config.num_fb = 0; |
821,9 → 832,6 |
dev->mode_config.num_connector = 0; |
dev->mode_config.num_crtc = 0; |
dev->mode_config.num_encoder = 0; |
LEAVE(); |
} |
EXPORT_SYMBOL(drm_mode_config_init); |
1078,7 → 1086,7 |
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, |
head) { |
DRM_DEBUG("CRTC ID is %d\n", crtc->base.id); |
DRM_DEBUG_KMS("CRTC ID is %d\n", crtc->base.id); |
if (put_user(crtc->base.id, crtc_id + copied)) { |
ret = -EFAULT; |
goto out; |
1106,7 → 1114,7 |
list_for_each_entry(encoder, |
&dev->mode_config.encoder_list, |
head) { |
DRM_DEBUG("ENCODER ID is %d\n", |
DRM_DEBUG_KMS("ENCODER ID is %d\n", |
encoder->base.id); |
if (put_user(encoder->base.id, encoder_id + |
copied)) { |
1137,7 → 1145,7 |
list_for_each_entry(connector, |
&dev->mode_config.connector_list, |
head) { |
DRM_DEBUG("CONNECTOR ID is %d\n", |
DRM_DEBUG_KMS("CONNECTOR ID is %d\n", |
connector->base.id); |
if (put_user(connector->base.id, |
connector_id + copied)) { |
1161,7 → 1169,7 |
} |
card_res->count_connectors = connector_count; |
DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs, |
DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs, |
card_res->count_connectors, card_res->count_encoders); |
out: |
1265,7 → 1273,7 |
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); |
DRM_DEBUG("connector id %d:\n", out_resp->connector_id); |
DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id); |
mutex_lock(&dev->mode_config.mutex); |
1441,7 → 1449,7 |
obj = drm_mode_object_find(dev, crtc_req->crtc_id, |
DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id); |
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); |
ret = -EINVAL; |
goto out; |
} |
1454,7 → 1462,8 |
list_for_each_entry(crtcfb, |
&dev->mode_config.crtc_list, head) { |
if (crtcfb == crtc) { |
DRM_DEBUG("Using current fb for setmode\n"); |
DRM_DEBUG_KMS("Using current fb for " |
"setmode\n"); |
fb = crtc->fb; |
} |
} |
1462,7 → 1471,8 |
obj = drm_mode_object_find(dev, crtc_req->fb_id, |
DRM_MODE_OBJECT_FB); |
if (!obj) { |
DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id); |
DRM_DEBUG_KMS("Unknown FB ID%d\n", |
crtc_req->fb_id); |
ret = -EINVAL; |
goto out; |
} |
1475,13 → 1485,13 |
} |
if (crtc_req->count_connectors == 0 && mode) { |
DRM_DEBUG("Count connectors is 0 but mode set\n"); |
DRM_DEBUG_KMS("Count connectors is 0 but mode set\n"); |
ret = -EINVAL; |
goto out; |
} |
if (crtc_req->count_connectors > 0 && !mode && !fb) { |
DRM_DEBUG("Count connectors is %d but no mode or fb set\n", |
if (crtc_req->count_connectors > 0 && (!mode || !fb)) { |
DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n", |
crtc_req->count_connectors); |
ret = -EINVAL; |
goto out; |
1514,7 → 1524,8 |
obj = drm_mode_object_find(dev, out_id, |
DRM_MODE_OBJECT_CONNECTOR); |
if (!obj) { |
DRM_DEBUG("Connector id %d unknown\n", out_id); |
DRM_DEBUG_KMS("Connector id %d unknown\n", |
out_id); |
ret = -EINVAL; |
goto out; |
} |
1547,7 → 1558,7 |
struct drm_crtc *crtc; |
int ret = 0; |
DRM_DEBUG("\n"); |
DRM_DEBUG_KMS("\n"); |
if (!req->flags) { |
DRM_ERROR("no operation set\n"); |
1557,7 → 1568,7 |
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc_id); |
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); |
ret = -EINVAL; |
goto out; |
} |
1774,7 → 1785,6 |
} |
#endif |
/** |
* drm_mode_attachmode - add a mode to the user mode list |
* @dev: DRM device |
1956,7 → 1966,6 |
} |
drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); |
property->flags = flags; |
property->num_values = num_values; |
INIT_LIST_HEAD(&property->enum_blob_list); |
1964,7 → 1973,6 |
if (name) |
strncpy(property->name, name, DRM_PROP_NAME_LEN); |
list_add_tail(&property->head, &dev->mode_config.property_list); |
dbgprintf("%s %x name %s\n", __FUNCTION__, property, name); |
2099,7 → 2107,7 |
uint64_t __user *values_ptr; |
uint32_t __user *blob_length_ptr; |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); |
if (!obj) { |
ret = -EINVAL; |
2177,7 → 2185,7 |
out_resp->count_enum_blobs = blob_count; |
} |
done: |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
return ret; |
} |
#endif |
2283,7 → 2291,7 |
int ret = -EINVAL; |
int i; |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); |
if (!obj) { |
2340,7 → 2348,7 |
if (!ret) |
drm_connector_property_set_value(connector, property, out_resp->value); |
out: |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
return ret; |
} |
#endif |
2401,7 → 2409,7 |
int size; |
int ret = 0; |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
ret = -EINVAL; |
2437,7 → 2445,7 |
crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size); |
out: |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
return ret; |
} |
2452,7 → 2460,7 |
int size; |
int ret = 0; |
// mutex_lock(&dev->mode_config.mutex); |
mutex_lock(&dev->mode_config.mutex); |
obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
ret = -EINVAL; |
2485,8 → 2493,10 |
goto out; |
} |
out: |
// mutex_unlock(&dev->mode_config.mutex); |
mutex_unlock(&dev->mode_config.mutex); |
return ret; |
} |
#endif |
/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); |
/drivers/video/drm/drm_edid.c |
---|
30,15 → 30,11 |
#include <types.h> |
#include <list.h> |
#include <linux/idr.h> |
#include <linux/i2c.h> |
#include <linux/i2c-algo-bit.h> |
#include "drmP.h" |
#include "drm_edid.h" |
/* |
* TODO: |
* - support EDID 1.4 (incl. CE blocks) |
67,7 → 63,13 |
#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) |
/* use +hsync +vsync for detailed mode */ |
#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
/* define the number of Extension EDID block */ |
#define MAX_EDID_EXT_NUM 4 |
#define LEVEL_DMT 0 |
#define LEVEL_GTF 1 |
#define LEVEL_CVT 2 |
static struct edid_quirk { |
char *vendor; |
int product_id; |
244,6 → 246,263 |
preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
} |
/* |
* Add the Autogenerated from the DMT spec. |
* This table is copied from xfree86/modes/xf86EdidModes.c. |
* But the mode with Reduced blank feature is deleted. |
*/ |
static struct drm_display_mode drm_dmt_modes[] = { |
/* 640x350@85Hz */ |
{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, |
736, 832, 0, 350, 382, 385, 445, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 640x400@85Hz */ |
{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, |
736, 832, 0, 400, 401, 404, 445, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 720x400@85Hz */ |
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756, |
828, 936, 0, 400, 401, 404, 446, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 640x480@60Hz */ |
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, |
752, 800, 0, 480, 489, 492, 525, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 640x480@72Hz */ |
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, |
704, 832, 0, 480, 489, 492, 520, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 640x480@75Hz */ |
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, |
720, 840, 0, 480, 481, 484, 500, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 640x480@85Hz */ |
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696, |
752, 832, 0, 480, 481, 484, 509, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 800x600@56Hz */ |
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, |
896, 1024, 0, 600, 601, 603, 625, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 800x600@60Hz */ |
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, |
968, 1056, 0, 600, 601, 605, 628, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 800x600@72Hz */ |
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, |
976, 1040, 0, 600, 637, 643, 666, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 800x600@75Hz */ |
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, |
896, 1056, 0, 600, 601, 604, 625, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 800x600@85Hz */ |
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832, |
896, 1048, 0, 600, 601, 604, 631, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 848x480@60Hz */ |
{ DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864, |
976, 1088, 0, 480, 486, 494, 517, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1024x768@43Hz, interlace */ |
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032, |
1208, 1264, 0, 768, 768, 772, 817, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | |
DRM_MODE_FLAG_INTERLACE) }, |
/* 1024x768@60Hz */ |
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, |
1184, 1344, 0, 768, 771, 777, 806, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 1024x768@70Hz */ |
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, |
1184, 1328, 0, 768, 771, 777, 806, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 1024x768@75Hz */ |
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040, |
1136, 1312, 0, 768, 769, 772, 800, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1024x768@85Hz */ |
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072, |
1072, 1376, 0, 768, 769, 772, 808, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1152x864@75Hz */ |
{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, |
1344, 1600, 0, 864, 865, 868, 900, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x768@60Hz */ |
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, |
1472, 1664, 0, 768, 771, 778, 798, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x768@75Hz */ |
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360, |
1488, 1696, 0, 768, 771, 778, 805, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 1280x768@85Hz */ |
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360, |
1496, 1712, 0, 768, 771, 778, 809, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x800@60Hz */ |
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, |
1480, 1680, 0, 800, 803, 809, 831, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, |
/* 1280x800@75Hz */ |
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360, |
1488, 1696, 0, 800, 803, 809, 838, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x800@85Hz */ |
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360, |
1496, 1712, 0, 800, 803, 809, 843, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x960@60Hz */ |
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, |
1488, 1800, 0, 960, 961, 964, 1000, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x960@85Hz */ |
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344, |
1504, 1728, 0, 960, 961, 964, 1011, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x1024@60Hz */ |
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, |
1440, 1688, 0, 1024, 1025, 1028, 1066, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x1024@75Hz */ |
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, |
1440, 1688, 0, 1024, 1025, 1028, 1066, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1280x1024@85Hz */ |
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344, |
1504, 1728, 0, 1024, 1025, 1028, 1072, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1360x768@60Hz */ |
{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, |
1536, 1792, 0, 768, 771, 777, 795, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1440x1050@60Hz */ |
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, |
1632, 1864, 0, 1050, 1053, 1057, 1089, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1440x1050@75Hz */ |
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504, |
1648, 1896, 0, 1050, 1053, 1057, 1099, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1440x1050@85Hz */ |
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504, |
1656, 1912, 0, 1050, 1053, 1057, 1105, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1440x900@60Hz */ |
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, |
1672, 1904, 0, 900, 903, 909, 934, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1440x900@75Hz */ |
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536, |
1688, 1936, 0, 900, 903, 909, 942, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1440x900@85Hz */ |
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544, |
1696, 1952, 0, 900, 903, 909, 948, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1600x1200@60Hz */ |
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, |
1856, 2160, 0, 1200, 1201, 1204, 1250, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1600x1200@65Hz */ |
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664, |
1856, 2160, 0, 1200, 1201, 1204, 1250, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1600x1200@70Hz */ |
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664, |
1856, 2160, 0, 1200, 1201, 1204, 1250, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1600x1200@75Hz */ |
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 2025000, 1600, 1664, |
1856, 2160, 0, 1200, 1201, 1204, 1250, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1600x1200@85Hz */ |
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664, |
1856, 2160, 0, 1200, 1201, 1204, 1250, 0, |
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1680x1050@60Hz */ |
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, |
1960, 2240, 0, 1050, 1053, 1059, 1089, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1680x1050@75Hz */ |
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800, |
1976, 2272, 0, 1050, 1053, 1059, 1099, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1680x1050@85Hz */ |
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808, |
1984, 2288, 0, 1050, 1053, 1059, 1105, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1792x1344@60Hz */ |
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, |
2120, 2448, 0, 1344, 1345, 1348, 1394, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1729x1344@75Hz */ |
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888, |
2104, 2456, 0, 1344, 1345, 1348, 1417, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1853x1392@60Hz */ |
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, |
2176, 2528, 0, 1392, 1393, 1396, 1439, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1856x1392@75Hz */ |
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984, |
2208, 2560, 0, 1392, 1395, 1399, 1500, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1920x1200@60Hz */ |
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, |
2256, 2592, 0, 1200, 1203, 1209, 1245, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1920x1200@75Hz */ |
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056, |
2264, 2608, 0, 1200, 1203, 1209, 1255, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1920x1200@85Hz */ |
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064, |
2272, 2624, 0, 1200, 1203, 1209, 1262, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1920x1440@60Hz */ |
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, |
2256, 2600, 0, 1440, 1441, 1444, 1500, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 1920x1440@75Hz */ |
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064, |
2288, 2640, 0, 1440, 1441, 1444, 1500, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 2560x1600@60Hz */ |
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, |
3032, 3504, 0, 1600, 1603, 1609, 1658, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 2560x1600@75HZ */ |
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768, |
3048, 3536, 0, 1600, 1603, 1609, 1672, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
/* 2560x1600@85HZ */ |
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, |
3048, 3536, 0, 1600, 1603, 1609, 1682, 0, |
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
}; |
static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, |
int hsize, int vsize, int fresh) |
{ |
int i, count; |
struct drm_display_mode *ptr, *mode; |
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
mode = NULL; |
for (i = 0; i < count; i++) { |
ptr = &drm_dmt_modes[i]; |
if (hsize == ptr->hdisplay && |
vsize == ptr->vdisplay && |
fresh == drm_mode_vrefresh(ptr)) { |
/* get the expected default mode */ |
mode = drm_mode_duplicate(dev, ptr); |
break; |
} |
} |
return mode; |
} |
/** |
* drm_mode_std - convert standard mode info (width, height, refresh) into mode |
* @t: standard timing params |
255,16 → 514,22 |
* generation code. |
*/ |
struct drm_display_mode *drm_mode_std(struct drm_device *dev, |
struct std_timing *t) |
struct std_timing *t, |
int timing_level) |
{ |
struct drm_display_mode *mode; |
int hsize = t->hsize * 8 + 248, vsize; |
int hsize, vsize; |
int vrefresh_rate; |
unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK) |
>> EDID_TIMING_ASPECT_SHIFT; |
unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK) |
>> EDID_TIMING_VFREQ_SHIFT; |
mode = drm_mode_create(dev); |
if (!mode) |
return NULL; |
/* According to the EDID spec, the hdisplay = hsize * 8 + 248 */ |
hsize = t->hsize * 8 + 248; |
/* vrefresh_rate = vfreq + 60 */ |
vrefresh_rate = vfreq + 60; |
/* the vdisplay is calculated based on the aspect ratio */ |
if (aspect_ratio == 0) |
vsize = (hsize * 10) / 16; |
274,9 → 539,30 |
vsize = (hsize * 4) / 5; |
else |
vsize = (hsize * 9) / 16; |
/* HDTV hack */ |
if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) { |
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
mode->hdisplay = 1366; |
mode->vsync_start = mode->vsync_start - 1; |
mode->vsync_end = mode->vsync_end - 1; |
return mode; |
} |
mode = NULL; |
/* check whether it can be found in default mode table */ |
mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate); |
if (mode) |
return mode; |
drm_mode_set_name(mode); |
switch (timing_level) { |
case LEVEL_DMT: |
break; |
case LEVEL_GTF: |
mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
break; |
case LEVEL_CVT: |
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); |
break; |
} |
return mode; |
} |
458,6 → 744,19 |
return modes; |
} |
/** |
* stanard_timing_level - get std. timing level(CVT/GTF/DMT) |
* @edid: EDID block to scan |
*/ |
static int standard_timing_level(struct edid *edid) |
{ |
if (edid->revision >= 2) { |
if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)) |
return LEVEL_CVT; |
return LEVEL_GTF; |
} |
return LEVEL_DMT; |
} |
/** |
* add_standard_modes - get std. modes from EDID and add them |
470,7 → 769,10 |
{ |
struct drm_device *dev = connector->dev; |
int i, modes = 0; |
int timing_level; |
timing_level = standard_timing_level(edid); |
for (i = 0; i < EDID_STD_TIMINGS; i++) { |
struct std_timing *t = &edid->standard_timings[i]; |
struct drm_display_mode *newmode; |
479,7 → 781,8 |
if (t->hsize == 1 && t->vfreq_aspect == 1) |
continue; |
newmode = drm_mode_std(dev, &edid->standard_timings[i]); |
newmode = drm_mode_std(dev, &edid->standard_timings[i], |
timing_level); |
if (newmode) { |
drm_mode_probed_add(connector, newmode); |
modes++; |
503,18 → 806,50 |
{ |
struct drm_device *dev = connector->dev; |
int i, j, modes = 0; |
int timing_level; |
timing_level = standard_timing_level(edid); |
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { |
struct detailed_timing *timing = &edid->detailed_timings[i]; |
struct detailed_non_pixel *data = &timing->data.other_data; |
struct drm_display_mode *newmode; |
/* EDID up to and including 1.2 may put monitor info here */ |
if (edid->version == 1 && edid->revision < 3) |
continue; |
/* X server check is version 1.1 or higher */ |
if (edid->version == 1 && edid->revision >= 1 && |
!timing->pixel_clock) { |
/* Other timing or info */ |
switch (data->type) { |
case EDID_DETAIL_MONITOR_SERIAL: |
break; |
case EDID_DETAIL_MONITOR_STRING: |
break; |
case EDID_DETAIL_MONITOR_RANGE: |
/* Get monitor range data */ |
break; |
case EDID_DETAIL_MONITOR_NAME: |
break; |
case EDID_DETAIL_MONITOR_CPDATA: |
break; |
case EDID_DETAIL_STD_MODES: |
/* Five modes per detailed section */ |
for (j = 0; j < 5; i++) { |
struct std_timing *std; |
struct drm_display_mode *newmode; |
/* Detailed mode timing */ |
if (timing->pixel_clock) { |
std = &data->data.timings[j]; |
newmode = drm_mode_std(dev, std, |
timing_level); |
if (newmode) { |
drm_mode_probed_add(connector, newmode); |
modes++; |
} |
} |
break; |
default: |
break; |
} |
} else { |
newmode = drm_mode_detailed(dev, edid, timing, quirks); |
if (!newmode) |
continue; |
525,7 → 860,91 |
drm_mode_probed_add(connector, newmode); |
modes++; |
} |
} |
return modes; |
} |
/** |
* add_detailed_mode_eedid - get detailed mode info from addtional timing |
* EDID block |
* @connector: attached connector |
* @edid: EDID block to scan(It is only to get addtional timing EDID block) |
* @quirks: quirks to apply |
* |
* Some of the detailed timing sections may contain mode information. Grab |
* it and add it to the list. |
*/ |
static int add_detailed_info_eedid(struct drm_connector *connector, |
struct edid *edid, u32 quirks) |
{ |
struct drm_device *dev = connector->dev; |
int i, j, modes = 0; |
char *edid_ext = NULL; |
struct detailed_timing *timing; |
struct detailed_non_pixel *data; |
struct drm_display_mode *newmode; |
int edid_ext_num; |
int start_offset, end_offset; |
int timing_level; |
if (edid->version == 1 && edid->revision < 3) { |
/* If the EDID version is less than 1.3, there is no |
* extension EDID. |
*/ |
return 0; |
} |
if (!edid->extensions) { |
/* if there is no extension EDID, it is unnecessary to |
* parse the E-EDID to get detailed info |
*/ |
return 0; |
} |
/* Chose real EDID extension number */ |
edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? |
MAX_EDID_EXT_NUM : edid->extensions; |
/* Find CEA extension */ |
for (i = 0; i < edid_ext_num; i++) { |
edid_ext = (char *)edid + EDID_LENGTH * (i + 1); |
/* This block is CEA extension */ |
if (edid_ext[0] == 0x02) |
break; |
} |
if (i == edid_ext_num) { |
/* if there is no additional timing EDID block, return */ |
return 0; |
} |
/* Get the start offset of detailed timing block */ |
start_offset = edid_ext[2]; |
if (start_offset == 0) { |
/* If the start_offset is zero, it means that neither detailed |
* info nor data block exist. In such case it is also |
* unnecessary to parse the detailed timing info. |
*/ |
return 0; |
} |
timing_level = standard_timing_level(edid); |
end_offset = EDID_LENGTH; |
end_offset -= sizeof(struct detailed_timing); |
for (i = start_offset; i < end_offset; |
i += sizeof(struct detailed_timing)) { |
timing = (struct detailed_timing *)(edid_ext + i); |
data = &timing->data.other_data; |
/* Detailed mode timing */ |
if (timing->pixel_clock) { |
newmode = drm_mode_detailed(dev, edid, timing, quirks); |
if (!newmode) |
continue; |
drm_mode_probed_add(connector, newmode); |
modes++; |
continue; |
} |
/* Other timing or info */ |
548,7 → 967,7 |
struct drm_display_mode *newmode; |
std = &data->data.timings[j]; |
newmode = drm_mode_std(dev, std); |
newmode = drm_mode_std(dev, std, timing_level); |
if (newmode) { |
drm_mode_probed_add(connector, newmode); |
modes++; |
608,8 → 1027,6 |
ret = drm_do_probe_ddc_edid(adapter, buf, len); |
if (ret != 0) { |
// dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n", |
// drm_get_connector_name(connector)); |
goto end; |
} |
if (!edid_is_valid((struct edid *)buf)) { |
621,7 → 1038,6 |
return ret; |
} |
#define MAX_EDID_EXT_NUM 4 |
/** |
* drm_get_edid - get EDID data, if available |
* @connector: connector we're probing |
774,6 → 1190,7 |
num_modes += add_established_modes(connector, edid); |
num_modes += add_standard_modes(connector, edid); |
num_modes += add_detailed_info(connector, edid, quirks); |
num_modes += add_detailed_info_eedid(connector, edid, quirks); |
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
edid_fixup_preferred(connector, quirks); |
799,3 → 1216,49 |
return num_modes; |
} |
EXPORT_SYMBOL(drm_add_edid_modes); |
/** |
* drm_add_modes_noedid - add modes for the connectors without EDID |
* @connector: connector we're probing |
* @hdisplay: the horizontal display limit |
* @vdisplay: the vertical display limit |
* |
* Add the specified modes to the connector's mode list. Only when the |
* hdisplay/vdisplay is not beyond the given limit, it will be added. |
* |
* Return number of modes added or 0 if we couldn't find any. |
*/ |
int drm_add_modes_noedid(struct drm_connector *connector, |
int hdisplay, int vdisplay) |
{ |
int i, count, num_modes = 0; |
struct drm_display_mode *mode, *ptr; |
struct drm_device *dev = connector->dev; |
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); |
if (hdisplay < 0) |
hdisplay = 0; |
if (vdisplay < 0) |
vdisplay = 0; |
for (i = 0; i < count; i++) { |
ptr = &drm_dmt_modes[i]; |
if (hdisplay && vdisplay) { |
/* |
* Only when two are valid, they will be used to check |
* whether the mode should be added to the mode list of |
* the connector. |
*/ |
if (ptr->hdisplay > hdisplay || |
ptr->vdisplay > vdisplay) |
continue; |
} |
mode = drm_mode_duplicate(dev, ptr); |
if (mode) { |
drm_mode_probed_add(connector, mode); |
num_modes++; |
} |
} |
return num_modes; |
} |
EXPORT_SYMBOL(drm_add_modes_noedid); |
/drivers/video/drm/drm_fb_helper.c |
---|
0,0 → 1,666 |
/* |
* Copyright (c) 2006-2009 Red Hat Inc. |
* Copyright (c) 2006-2008 Intel Corporation |
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie> |
* |
* DRM framebuffer helper functions |
* |
* Permission to use, copy, modify, distribute, and sell this software and its |
* documentation for any purpose is hereby granted without fee, provided that |
* the above copyright notice appear in all copies and that both that copyright |
* notice and this permission notice appear in supporting documentation, and |
* that the name of the copyright holders not be used in advertising or |
* publicity pertaining to distribution of the software without specific, |
* written prior permission. The copyright holders make no representations |
* about the suitability of this software for any purpose. It is provided "as |
* is" without express or implied warranty. |
* |
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
* OF THIS SOFTWARE. |
* |
* Authors: |
* Dave Airlie <airlied@linux.ie> |
* Jesse Barnes <jesse.barnes@intel.com> |
*/ |
//#include <linux/sysrq.h> |
#include <linux/fb.h> |
#include "drmP.h" |
#include "drm_crtc.h" |
#include "drm_fb_helper.h" |
#include "drm_crtc_helper.h" |
//MODULE_AUTHOR("David Airlie, Jesse Barnes"); |
//MODULE_DESCRIPTION("DRM KMS helper"); |
//MODULE_LICENSE("GPL and additional rights"); |
static LIST_HEAD(kernel_fb_helper_list); |
bool drm_fb_helper_force_kernel_mode(void) |
{ |
int i = 0; |
bool ret, error = false; |
struct drm_fb_helper *helper; |
if (list_empty(&kernel_fb_helper_list)) |
return false; |
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) { |
for (i = 0; i < helper->crtc_count; i++) { |
struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set; |
ret = drm_crtc_helper_set_config(mode_set); |
if (ret) |
error = true; |
} |
} |
return error; |
} |
/** |
* drm_fb_helper_restore - restore the framebuffer console (kernel) config |
* |
* Restore's the kernel's fbcon mode, used for lastclose & panic paths. |
*/ |
void drm_fb_helper_restore(void) |
{ |
bool ret; |
ret = drm_fb_helper_force_kernel_mode(); |
if (ret == true) |
DRM_ERROR("Failed to restore crtc configuration\n"); |
} |
EXPORT_SYMBOL(drm_fb_helper_restore); |
static void drm_fb_helper_on(struct fb_info *info) |
{ |
struct drm_fb_helper *fb_helper = info->par; |
struct drm_device *dev = fb_helper->dev; |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
int i; |
/* |
* For each CRTC in this fb, turn the crtc on then, |
* find all associated encoders and turn them on. |
*/ |
for (i = 0; i < fb_helper->crtc_count; i++) { |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = |
crtc->helper_private; |
/* Only mess with CRTCs in this fb */ |
if (crtc->base.id != fb_helper->crtc_info[i].crtc_id || |
!crtc->enabled) |
continue; |
mutex_lock(&dev->mode_config.mutex); |
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); |
mutex_unlock(&dev->mode_config.mutex); |
/* Found a CRTC on this fb, now find encoders */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct drm_encoder_helper_funcs *encoder_funcs; |
encoder_funcs = encoder->helper_private; |
mutex_lock(&dev->mode_config.mutex); |
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
} |
} |
} |
static void drm_fb_helper_off(struct fb_info *info, int dpms_mode) |
{ |
struct drm_fb_helper *fb_helper = info->par; |
struct drm_device *dev = fb_helper->dev; |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
int i; |
/* |
* For each CRTC in this fb, find all associated encoders |
* and turn them off, then turn off the CRTC. |
*/ |
for (i = 0; i < fb_helper->crtc_count; i++) { |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = |
crtc->helper_private; |
/* Only mess with CRTCs in this fb */ |
if (crtc->base.id != fb_helper->crtc_info[i].crtc_id || |
!crtc->enabled) |
continue; |
/* Found a CRTC on this fb, now find encoders */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct drm_encoder_helper_funcs *encoder_funcs; |
encoder_funcs = encoder->helper_private; |
mutex_lock(&dev->mode_config.mutex); |
encoder_funcs->dpms(encoder, dpms_mode); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
if (dpms_mode == DRM_MODE_DPMS_OFF) { |
mutex_lock(&dev->mode_config.mutex); |
crtc_funcs->dpms(crtc, dpms_mode); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
} |
} |
int drm_fb_helper_blank(int blank, struct fb_info *info) |
{ |
switch (blank) { |
case FB_BLANK_UNBLANK: |
drm_fb_helper_on(info); |
break; |
case FB_BLANK_NORMAL: |
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); |
break; |
case FB_BLANK_HSYNC_SUSPEND: |
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); |
break; |
case FB_BLANK_VSYNC_SUSPEND: |
drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND); |
break; |
case FB_BLANK_POWERDOWN: |
drm_fb_helper_off(info, DRM_MODE_DPMS_OFF); |
break; |
} |
return 0; |
} |
EXPORT_SYMBOL(drm_fb_helper_blank); |
static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) |
{ |
int i; |
for (i = 0; i < helper->crtc_count; i++) |
kfree(helper->crtc_info[i].mode_set.connectors); |
kfree(helper->crtc_info); |
} |
int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn_count) |
{ |
struct drm_device *dev = helper->dev; |
struct drm_crtc *crtc; |
int ret = 0; |
int i; |
helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); |
if (!helper->crtc_info) |
return -ENOMEM; |
helper->crtc_count = crtc_count; |
for (i = 0; i < crtc_count; i++) { |
helper->crtc_info[i].mode_set.connectors = |
kcalloc(max_conn_count, |
sizeof(struct drm_connector *), |
GFP_KERNEL); |
if (!helper->crtc_info[i].mode_set.connectors) { |
ret = -ENOMEM; |
goto out_free; |
} |
helper->crtc_info[i].mode_set.num_connectors = 0; |
} |
i = 0; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
helper->crtc_info[i].crtc_id = crtc->base.id; |
helper->crtc_info[i].mode_set.crtc = crtc; |
i++; |
} |
helper->conn_limit = max_conn_count; |
return 0; |
out_free: |
drm_fb_helper_crtc_free(helper); |
return -ENOMEM; |
} |
EXPORT_SYMBOL(drm_fb_helper_init_crtc_count); |
int drm_fb_helper_setcolreg(unsigned regno, |
unsigned red, |
unsigned green, |
unsigned blue, |
unsigned transp, |
struct fb_info *info) |
{ |
struct drm_fb_helper *fb_helper = info->par; |
struct drm_device *dev = fb_helper->dev; |
struct drm_crtc *crtc; |
int i; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_framebuffer *fb = fb_helper->fb; |
for (i = 0; i < fb_helper->crtc_count; i++) { |
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) |
break; |
} |
if (i == fb_helper->crtc_count) |
continue; |
if (regno > 255) |
return 1; |
if (fb->depth == 8) { |
fb_helper->funcs->gamma_set(crtc, red, green, blue, regno); |
return 0; |
} |
if (regno < 16) { |
switch (fb->depth) { |
case 15: |
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | |
((green & 0xf800) >> 6) | |
((blue & 0xf800) >> 11); |
break; |
case 16: |
fb->pseudo_palette[regno] = (red & 0xf800) | |
((green & 0xfc00) >> 5) | |
((blue & 0xf800) >> 11); |
break; |
case 24: |
case 32: |
fb->pseudo_palette[regno] = |
(((red >> 8) & 0xff) << info->var.red.offset) | |
(((green >> 8) & 0xff) << info->var.green.offset) | |
(((blue >> 8) & 0xff) << info->var.blue.offset); |
break; |
} |
} |
} |
return 0; |
} |
EXPORT_SYMBOL(drm_fb_helper_setcolreg); |
int drm_fb_helper_check_var(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct drm_fb_helper *fb_helper = info->par; |
struct drm_framebuffer *fb = fb_helper->fb; |
int depth; |
if (var->pixclock == -1 || !var->pixclock) |
return -EINVAL; |
/* Need to resize the fb object !!! */ |
if (var->xres > fb->width || var->yres > fb->height) { |
DRM_ERROR("Requested width/height is greater than current fb " |
"object %dx%d > %dx%d\n", var->xres, var->yres, |
fb->width, fb->height); |
DRM_ERROR("Need resizing code.\n"); |
return -EINVAL; |
} |
switch (var->bits_per_pixel) { |
case 16: |
depth = (var->green.length == 6) ? 16 : 15; |
break; |
case 32: |
depth = (var->transp.length > 0) ? 32 : 24; |
break; |
default: |
depth = var->bits_per_pixel; |
break; |
} |
switch (depth) { |
case 8: |
var->red.offset = 0; |
var->green.offset = 0; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 15: |
var->red.offset = 10; |
var->green.offset = 5; |
var->blue.offset = 0; |
var->red.length = 5; |
var->green.length = 5; |
var->blue.length = 5; |
var->transp.length = 1; |
var->transp.offset = 15; |
break; |
case 16: |
var->red.offset = 11; |
var->green.offset = 5; |
var->blue.offset = 0; |
var->red.length = 5; |
var->green.length = 6; |
var->blue.length = 5; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 24: |
var->red.offset = 16; |
var->green.offset = 8; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 32: |
var->red.offset = 16; |
var->green.offset = 8; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 8; |
var->transp.offset = 24; |
break; |
default: |
return -EINVAL; |
} |
return 0; |
} |
EXPORT_SYMBOL(drm_fb_helper_check_var); |
/* this will let fbcon do the mode init */ |
int drm_fb_helper_set_par(struct fb_info *info) |
{ |
struct drm_fb_helper *fb_helper = info->par; |
struct drm_device *dev = fb_helper->dev; |
struct fb_var_screeninfo *var = &info->var; |
struct drm_crtc *crtc; |
int ret; |
int i; |
if (var->pixclock != -1) { |
DRM_ERROR("PIXEL CLCOK SET\n"); |
return -EINVAL; |
} |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
for (i = 0; i < fb_helper->crtc_count; i++) { |
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) |
break; |
} |
if (i == fb_helper->crtc_count) |
continue; |
if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) { |
mutex_lock(&dev->mode_config.mutex); |
ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set); |
mutex_unlock(&dev->mode_config.mutex); |
if (ret) |
return ret; |
} |
} |
return 0; |
} |
EXPORT_SYMBOL(drm_fb_helper_set_par); |
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct drm_fb_helper *fb_helper = info->par; |
struct drm_device *dev = fb_helper->dev; |
struct drm_mode_set *modeset; |
struct drm_crtc *crtc; |
int ret = 0; |
int i; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
for (i = 0; i < fb_helper->crtc_count; i++) { |
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id) |
break; |
} |
if (i == fb_helper->crtc_count) |
continue; |
modeset = &fb_helper->crtc_info[i].mode_set; |
modeset->x = var->xoffset; |
modeset->y = var->yoffset; |
if (modeset->num_connectors) { |
mutex_lock(&dev->mode_config.mutex); |
ret = crtc->funcs->set_config(modeset); |
mutex_unlock(&dev->mode_config.mutex); |
if (!ret) { |
info->var.xoffset = var->xoffset; |
info->var.yoffset = var->yoffset; |
} |
} |
} |
return ret; |
} |
EXPORT_SYMBOL(drm_fb_helper_pan_display); |
int drm_fb_helper_single_fb_probe(struct drm_device *dev, |
int (*fb_create)(struct drm_device *dev, |
uint32_t fb_width, |
uint32_t fb_height, |
uint32_t surface_width, |
uint32_t surface_height, |
struct drm_framebuffer **fb_ptr)) |
{ |
struct drm_crtc *crtc; |
struct drm_connector *connector; |
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1; |
unsigned int surface_width = 0, surface_height = 0; |
int new_fb = 0; |
int crtc_count = 0; |
int ret, i, conn_count = 0; |
struct fb_info *info; |
struct drm_framebuffer *fb; |
struct drm_mode_set *modeset = NULL; |
struct drm_fb_helper *fb_helper; |
/* first up get a count of crtcs now in use and new min/maxes width/heights */ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
if (drm_helper_crtc_in_use(crtc)) { |
if (crtc->desired_mode) { |
if (crtc->desired_mode->hdisplay < fb_width) |
fb_width = crtc->desired_mode->hdisplay; |
if (crtc->desired_mode->vdisplay < fb_height) |
fb_height = crtc->desired_mode->vdisplay; |
if (crtc->desired_mode->hdisplay > surface_width) |
surface_width = crtc->desired_mode->hdisplay; |
if (crtc->desired_mode->vdisplay > surface_height) |
surface_height = crtc->desired_mode->vdisplay; |
} |
crtc_count++; |
} |
} |
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) { |
/* hmm everyone went away - assume VGA cable just fell out |
and will come back later. */ |
return 0; |
} |
/* do we have an fb already? */ |
if (list_empty(&dev->mode_config.fb_kernel_list)) { |
ret = (*fb_create)(dev, fb_width, fb_height, surface_width, |
surface_height, &fb); |
if (ret) |
return -EINVAL; |
new_fb = 1; |
} else { |
fb = list_first_entry(&dev->mode_config.fb_kernel_list, |
struct drm_framebuffer, filp_head); |
/* if someone hotplugs something bigger than we have already allocated, we are pwned. |
As really we can't resize an fbdev that is in the wild currently due to fbdev |
not really being designed for the lower layers moving stuff around under it. |
- so in the grand style of things - punt. */ |
if ((fb->width < surface_width) || |
(fb->height < surface_height)) { |
DRM_ERROR("Framebuffer not large enough to scale console onto.\n"); |
return -EINVAL; |
} |
} |
info = fb->fbdev; |
fb_helper = info->par; |
crtc_count = 0; |
/* okay we need to setup new connector sets in the crtcs */ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
modeset = &fb_helper->crtc_info[crtc_count].mode_set; |
modeset->fb = fb; |
conn_count = 0; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
if (connector->encoder) |
if (connector->encoder->crtc == modeset->crtc) { |
modeset->connectors[conn_count] = connector; |
conn_count++; |
if (conn_count > fb_helper->conn_limit) |
BUG(); |
} |
} |
for (i = conn_count; i < fb_helper->conn_limit; i++) |
modeset->connectors[i] = NULL; |
modeset->crtc = crtc; |
crtc_count++; |
modeset->num_connectors = conn_count; |
if (modeset->crtc->desired_mode) { |
if (modeset->mode) |
drm_mode_destroy(dev, modeset->mode); |
modeset->mode = drm_mode_duplicate(dev, |
modeset->crtc->desired_mode); |
} |
} |
fb_helper->crtc_count = crtc_count; |
fb_helper->fb = fb; |
if (new_fb) { |
info->var.pixclock = -1; |
// if (register_framebuffer(info) < 0) |
// return -EINVAL; |
} else { |
drm_fb_helper_set_par(info); |
} |
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
info->fix.id); |
/* Switch back to kernel console on panic */ |
/* multi card linked list maybe */ |
list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); |
return 0; |
} |
EXPORT_SYMBOL(drm_fb_helper_single_fb_probe); |
void drm_fb_helper_free(struct drm_fb_helper *helper) |
{ |
list_del(&helper->kernel_fb_list); |
drm_fb_helper_crtc_free(helper); |
} |
EXPORT_SYMBOL(drm_fb_helper_free); |
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch) |
{ |
info->fix.type = FB_TYPE_PACKED_PIXELS; |
info->fix.visual = FB_VISUAL_TRUECOLOR; |
info->fix.type_aux = 0; |
info->fix.xpanstep = 1; /* doing it in hw */ |
info->fix.ypanstep = 1; /* doing it in hw */ |
info->fix.ywrapstep = 0; |
info->fix.accel = FB_ACCEL_NONE; |
info->fix.type_aux = 0; |
info->fix.line_length = pitch; |
return; |
} |
EXPORT_SYMBOL(drm_fb_helper_fill_fix); |
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb, |
uint32_t fb_width, uint32_t fb_height) |
{ |
info->pseudo_palette = fb->pseudo_palette; |
info->var.xres_virtual = fb->width; |
info->var.yres_virtual = fb->height; |
info->var.bits_per_pixel = fb->bits_per_pixel; |
info->var.xoffset = 0; |
info->var.yoffset = 0; |
info->var.activate = FB_ACTIVATE_NOW; |
info->var.height = -1; |
info->var.width = -1; |
switch (fb->depth) { |
case 8: |
info->var.red.offset = 0; |
info->var.green.offset = 0; |
info->var.blue.offset = 0; |
info->var.red.length = 8; /* 8bit DAC */ |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 0; |
info->var.transp.length = 0; |
break; |
case 15: |
info->var.red.offset = 10; |
info->var.green.offset = 5; |
info->var.blue.offset = 0; |
info->var.red.length = 5; |
info->var.green.length = 5; |
info->var.blue.length = 5; |
info->var.transp.offset = 15; |
info->var.transp.length = 1; |
break; |
case 16: |
info->var.red.offset = 11; |
info->var.green.offset = 5; |
info->var.blue.offset = 0; |
info->var.red.length = 5; |
info->var.green.length = 6; |
info->var.blue.length = 5; |
info->var.transp.offset = 0; |
break; |
case 24: |
info->var.red.offset = 16; |
info->var.green.offset = 8; |
info->var.blue.offset = 0; |
info->var.red.length = 8; |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 0; |
info->var.transp.length = 0; |
break; |
case 32: |
info->var.red.offset = 16; |
info->var.green.offset = 8; |
info->var.blue.offset = 0; |
info->var.red.length = 8; |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 24; |
info->var.transp.length = 8; |
break; |
default: |
break; |
} |
info->var.xres = fb_width; |
info->var.yres = fb_height; |
} |
EXPORT_SYMBOL(drm_fb_helper_fill_var); |
/drivers/video/drm/drm_mm.c |
---|
44,6 → 44,7 |
#include "drmP.h" |
#include "drm_mm.h" |
//#include <linux/slab.h> |
#include <linux/seq_file.h> |
#define MM_UNUSED_TARGET 4 |
/drivers/video/drm/drm_modes.c |
---|
8,6 → 8,8 |
* Copyright © 2007 Dave Airlie |
* Copyright © 2007-2008 Intel Corporation |
* Jesse Barnes <jesse.barnes@intel.com> |
* Copyright 2005-2006 Luc Verhaegen |
* Copyright (c) 2001, Andy Ritger aritger@nvidia.com |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
33,12 → 35,11 |
* authorization from the copyright holder(s) and author(s). |
*/ |
#include <list.h> |
#include <linux/list.h> |
#include "drmP.h" |
#include "drm.h" |
#include "drm_crtc.h" |
#define DRM_MODESET_DEBUG "drm_mode" |
/** |
* drm_mode_debug_printmodeline - debug print a mode |
* @dev: DRM device |
51,8 → 52,8 |
*/ |
void drm_mode_debug_printmodeline(struct drm_display_mode *mode) |
{ |
DRM_DEBUG_MODE(DRM_MODESET_DEBUG, |
"Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n", |
DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d " |
"0x%x 0x%x\n", |
mode->base.id, mode->name, mode->vrefresh, mode->clock, |
mode->hdisplay, mode->hsync_start, |
mode->hsync_end, mode->htotal, |
62,6 → 63,420 |
EXPORT_SYMBOL(drm_mode_debug_printmodeline); |
/** |
* drm_cvt_mode -create a modeline based on CVT algorithm |
* @dev: DRM device |
* @hdisplay: hdisplay size |
* @vdisplay: vdisplay size |
* @vrefresh : vrefresh rate |
* @reduced : Whether the GTF calculation is simplified |
* @interlaced:Whether the interlace is supported |
* |
* LOCKING: |
* none. |
* |
* return the modeline based on CVT algorithm |
* |
* This function is called to generate the modeline based on CVT algorithm |
* according to the hdisplay, vdisplay, vrefresh. |
* It is based from the VESA(TM) Coordinated Video Timing Generator by |
* Graham Loveridge April 9, 2003 available at |
* http://www.vesa.org/public/CVT/CVTd6r1.xls |
* |
* And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. |
* What I have done is to translate it by using integer calculation. |
*/ |
#define HV_FACTOR 1000 |
struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, |
int vdisplay, int vrefresh, |
bool reduced, bool interlaced) |
{ |
/* 1) top/bottom margin size (% of height) - default: 1.8, */ |
#define CVT_MARGIN_PERCENTAGE 18 |
/* 2) character cell horizontal granularity (pixels) - default 8 */ |
#define CVT_H_GRANULARITY 8 |
/* 3) Minimum vertical porch (lines) - default 3 */ |
#define CVT_MIN_V_PORCH 3 |
/* 4) Minimum number of vertical back porch lines - default 6 */ |
#define CVT_MIN_V_BPORCH 6 |
/* Pixel Clock step (kHz) */ |
#define CVT_CLOCK_STEP 250 |
struct drm_display_mode *drm_mode; |
bool margins = false; |
unsigned int vfieldrate, hperiod; |
int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; |
int interlace; |
/* allocate the drm_display_mode structure. If failure, we will |
* return directly |
*/ |
drm_mode = drm_mode_create(dev); |
if (!drm_mode) |
return NULL; |
/* the CVT default refresh rate is 60Hz */ |
if (!vrefresh) |
vrefresh = 60; |
/* the required field fresh rate */ |
if (interlaced) |
vfieldrate = vrefresh * 2; |
else |
vfieldrate = vrefresh; |
/* horizontal pixels */ |
hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY); |
/* determine the left&right borders */ |
hmargin = 0; |
if (margins) { |
hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; |
hmargin -= hmargin % CVT_H_GRANULARITY; |
} |
/* find the total active pixels */ |
drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin; |
/* find the number of lines per field */ |
if (interlaced) |
vdisplay_rnd = vdisplay / 2; |
else |
vdisplay_rnd = vdisplay; |
/* find the top & bottom borders */ |
vmargin = 0; |
if (margins) |
vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; |
drm_mode->vdisplay = vdisplay + 2 * vmargin; |
/* Interlaced */ |
if (interlaced) |
interlace = 1; |
else |
interlace = 0; |
/* Determine VSync Width from aspect ratio */ |
if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay)) |
vsync = 4; |
else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay)) |
vsync = 5; |
else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay)) |
vsync = 6; |
else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay)) |
vsync = 7; |
else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay)) |
vsync = 7; |
else /* custom */ |
vsync = 10; |
if (!reduced) { |
/* simplify the GTF calculation */ |
/* 4) Minimum time of vertical sync + back porch interval (µs) |
* default 550.0 |
*/ |
int tmp1, tmp2; |
#define CVT_MIN_VSYNC_BP 550 |
/* 3) Nominal HSync width (% of line period) - default 8 */ |
#define CVT_HSYNC_PERCENTAGE 8 |
unsigned int hblank_percentage; |
int vsyncandback_porch, vback_porch, hblank; |
/* estimated the horizontal period */ |
tmp1 = HV_FACTOR * 1000000 - |
CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate; |
tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 + |
interlace; |
hperiod = tmp1 * 2 / (tmp2 * vfieldrate); |
tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1; |
/* 9. Find number of lines in sync + backporch */ |
if (tmp1 < (vsync + CVT_MIN_V_PORCH)) |
vsyncandback_porch = vsync + CVT_MIN_V_PORCH; |
else |
vsyncandback_porch = tmp1; |
/* 10. Find number of lines in back porch */ |
vback_porch = vsyncandback_porch - vsync; |
drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + |
vsyncandback_porch + CVT_MIN_V_PORCH; |
/* 5) Definition of Horizontal blanking time limitation */ |
/* Gradient (%/kHz) - default 600 */ |
#define CVT_M_FACTOR 600 |
/* Offset (%) - default 40 */ |
#define CVT_C_FACTOR 40 |
/* Blanking time scaling factor - default 128 */ |
#define CVT_K_FACTOR 128 |
/* Scaling factor weighting - default 20 */ |
#define CVT_J_FACTOR 20 |
#define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256) |
#define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ |
CVT_J_FACTOR) |
/* 12. Find ideal blanking duty cycle from formula */ |
hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME * |
hperiod / 1000; |
/* 13. Blanking time */ |
if (hblank_percentage < 20 * HV_FACTOR) |
hblank_percentage = 20 * HV_FACTOR; |
hblank = drm_mode->hdisplay * hblank_percentage / |
(100 * HV_FACTOR - hblank_percentage); |
hblank -= hblank % (2 * CVT_H_GRANULARITY); |
/* 14. find the total pixes per line */ |
drm_mode->htotal = drm_mode->hdisplay + hblank; |
drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2; |
drm_mode->hsync_start = drm_mode->hsync_end - |
(drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100; |
drm_mode->hsync_start += CVT_H_GRANULARITY - |
drm_mode->hsync_start % CVT_H_GRANULARITY; |
/* fill the Vsync values */ |
drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH; |
drm_mode->vsync_end = drm_mode->vsync_start + vsync; |
} else { |
/* Reduced blanking */ |
/* Minimum vertical blanking interval time (µs)- default 460 */ |
#define CVT_RB_MIN_VBLANK 460 |
/* Fixed number of clocks for horizontal sync */ |
#define CVT_RB_H_SYNC 32 |
/* Fixed number of clocks for horizontal blanking */ |
#define CVT_RB_H_BLANK 160 |
/* Fixed number of lines for vertical front porch - default 3*/ |
#define CVT_RB_VFPORCH 3 |
int vbilines; |
int tmp1, tmp2; |
/* 8. Estimate Horizontal period. */ |
tmp1 = HV_FACTOR * 1000000 - |
CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate; |
tmp2 = vdisplay_rnd + 2 * vmargin; |
hperiod = tmp1 / (tmp2 * vfieldrate); |
/* 9. Find number of lines in vertical blanking */ |
vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1; |
/* 10. Check if vertical blanking is sufficient */ |
if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH)) |
vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH; |
/* 11. Find total number of lines in vertical field */ |
drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines; |
/* 12. Find total number of pixels in a line */ |
drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK; |
/* Fill in HSync values */ |
drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2; |
drm_mode->hsync_start = drm_mode->hsync_end = CVT_RB_H_SYNC; |
} |
/* 15/13. Find pixel clock frequency (kHz for xf86) */ |
drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; |
drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; |
/* 18/16. Find actual vertical frame frequency */ |
/* ignore - just set the mode flag for interlaced */ |
if (interlaced) |
drm_mode->vtotal *= 2; |
/* Fill the mode line name */ |
drm_mode_set_name(drm_mode); |
if (reduced) |
drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC | |
DRM_MODE_FLAG_NVSYNC); |
else |
drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC | |
DRM_MODE_FLAG_NHSYNC); |
if (interlaced) |
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; |
return drm_mode; |
} |
EXPORT_SYMBOL(drm_cvt_mode); |
/** |
* drm_gtf_mode - create the modeline based on GTF algorithm |
* |
* @dev :drm device |
* @hdisplay :hdisplay size |
* @vdisplay :vdisplay size |
* @vrefresh :vrefresh rate. |
* @interlaced :whether the interlace is supported |
* @margins :whether the margin is supported |
* |
* LOCKING. |
* none. |
* |
* return the modeline based on GTF algorithm |
* |
* This function is to create the modeline based on the GTF algorithm. |
* Generalized Timing Formula is derived from: |
* GTF Spreadsheet by Andy Morrish (1/5/97) |
* available at http://www.vesa.org |
* |
* And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c. |
* What I have done is to translate it by using integer calculation. |
* I also refer to the function of fb_get_mode in the file of |
* drivers/video/fbmon.c |
*/ |
struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, |
int vdisplay, int vrefresh, |
bool interlaced, int margins) |
{ |
/* 1) top/bottom margin size (% of height) - default: 1.8, */ |
#define GTF_MARGIN_PERCENTAGE 18 |
/* 2) character cell horizontal granularity (pixels) - default 8 */ |
#define GTF_CELL_GRAN 8 |
/* 3) Minimum vertical porch (lines) - default 3 */ |
#define GTF_MIN_V_PORCH 1 |
/* width of vsync in lines */ |
#define V_SYNC_RQD 3 |
/* width of hsync as % of total line */ |
#define H_SYNC_PERCENT 8 |
/* min time of vsync + back porch (microsec) */ |
#define MIN_VSYNC_PLUS_BP 550 |
/* blanking formula gradient */ |
#define GTF_M 600 |
/* blanking formula offset */ |
#define GTF_C 40 |
/* blanking formula scaling factor */ |
#define GTF_K 128 |
/* blanking formula scaling factor */ |
#define GTF_J 20 |
/* C' and M' are part of the Blanking Duty Cycle computation */ |
#define GTF_C_PRIME (((GTF_C - GTF_J) * GTF_K / 256) + GTF_J) |
#define GTF_M_PRIME (GTF_K * GTF_M / 256) |
struct drm_display_mode *drm_mode; |
unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd; |
int top_margin, bottom_margin; |
int interlace; |
unsigned int hfreq_est; |
int vsync_plus_bp, vback_porch; |
unsigned int vtotal_lines, vfieldrate_est, hperiod; |
unsigned int vfield_rate, vframe_rate; |
int left_margin, right_margin; |
unsigned int total_active_pixels, ideal_duty_cycle; |
unsigned int hblank, total_pixels, pixel_freq; |
int hsync, hfront_porch, vodd_front_porch_lines; |
unsigned int tmp1, tmp2; |
drm_mode = drm_mode_create(dev); |
if (!drm_mode) |
return NULL; |
/* 1. In order to give correct results, the number of horizontal |
* pixels requested is first processed to ensure that it is divisible |
* by the character size, by rounding it to the nearest character |
* cell boundary: |
*/ |
hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; |
hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN; |
/* 2. If interlace is requested, the number of vertical lines assumed |
* by the calculation must be halved, as the computation calculates |
* the number of vertical lines per field. |
*/ |
if (interlaced) |
vdisplay_rnd = vdisplay / 2; |
else |
vdisplay_rnd = vdisplay; |
/* 3. Find the frame rate required: */ |
if (interlaced) |
vfieldrate_rqd = vrefresh * 2; |
else |
vfieldrate_rqd = vrefresh; |
/* 4. Find number of lines in Top margin: */ |
top_margin = 0; |
if (margins) |
top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / |
1000; |
/* 5. Find number of lines in bottom margin: */ |
bottom_margin = top_margin; |
/* 6. If interlace is required, then set variable interlace: */ |
if (interlaced) |
interlace = 1; |
else |
interlace = 0; |
/* 7. Estimate the Horizontal frequency */ |
{ |
tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500; |
tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) * |
2 + interlace; |
hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1; |
} |
/* 8. Find the number of lines in V sync + back porch */ |
/* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */ |
vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000; |
vsync_plus_bp = (vsync_plus_bp + 500) / 1000; |
/* 9. Find the number of lines in V back porch alone: */ |
vback_porch = vsync_plus_bp - V_SYNC_RQD; |
/* 10. Find the total number of lines in Vertical field period: */ |
vtotal_lines = vdisplay_rnd + top_margin + bottom_margin + |
vsync_plus_bp + GTF_MIN_V_PORCH; |
/* 11. Estimate the Vertical field frequency: */ |
vfieldrate_est = hfreq_est / vtotal_lines; |
/* 12. Find the actual horizontal period: */ |
hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines); |
/* 13. Find the actual Vertical field frequency: */ |
vfield_rate = hfreq_est / vtotal_lines; |
/* 14. Find the Vertical frame frequency: */ |
if (interlaced) |
vframe_rate = vfield_rate / 2; |
else |
vframe_rate = vfield_rate; |
/* 15. Find number of pixels in left margin: */ |
if (margins) |
left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / |
1000; |
else |
left_margin = 0; |
/* 16.Find number of pixels in right margin: */ |
right_margin = left_margin; |
/* 17.Find total number of active pixels in image and left and right */ |
total_active_pixels = hdisplay_rnd + left_margin + right_margin; |
/* 18.Find the ideal blanking duty cycle from blanking duty cycle */ |
ideal_duty_cycle = GTF_C_PRIME * 1000 - |
(GTF_M_PRIME * 1000000 / hfreq_est); |
/* 19.Find the number of pixels in the blanking time to the nearest |
* double character cell: */ |
hblank = total_active_pixels * ideal_duty_cycle / |
(100000 - ideal_duty_cycle); |
hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN); |
hblank = hblank * 2 * GTF_CELL_GRAN; |
/* 20.Find total number of pixels: */ |
total_pixels = total_active_pixels + hblank; |
/* 21.Find pixel clock frequency: */ |
pixel_freq = total_pixels * hfreq_est / 1000; |
/* Stage 1 computations are now complete; I should really pass |
* the results to another function and do the Stage 2 computations, |
* but I only need a few more values so I'll just append the |
* computations here for now */ |
/* 17. Find the number of pixels in the horizontal sync period: */ |
hsync = H_SYNC_PERCENT * total_pixels / 100; |
hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; |
hsync = hsync * GTF_CELL_GRAN; |
/* 18. Find the number of pixels in horizontal front porch period */ |
hfront_porch = hblank / 2 - hsync; |
/* 36. Find the number of lines in the odd front porch period: */ |
vodd_front_porch_lines = GTF_MIN_V_PORCH ; |
/* finally, pack the results in the mode struct */ |
drm_mode->hdisplay = hdisplay_rnd; |
drm_mode->hsync_start = hdisplay_rnd + hfront_porch; |
drm_mode->hsync_end = drm_mode->hsync_start + hsync; |
drm_mode->htotal = total_pixels; |
drm_mode->vdisplay = vdisplay_rnd; |
drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines; |
drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD; |
drm_mode->vtotal = vtotal_lines; |
drm_mode->clock = pixel_freq; |
drm_mode_set_name(drm_mode); |
drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC; |
if (interlaced) { |
drm_mode->vtotal *= 2; |
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; |
} |
return drm_mode; |
} |
EXPORT_SYMBOL(drm_gtf_mode); |
/** |
* drm_mode_set_name - set the name on a mode |
* @mode: name will be set in this mode |
* |
151,7 → 566,9 |
* FIXME: why is this needed? shouldn't vrefresh be set already? |
* |
* RETURNS: |
* Vertical refresh rate of @mode x 1000. For precision reasons. |
* Vertical refresh rate. It will be the result of actual value plus 0.5. |
* If it is 70.288, it will return 70Hz. |
* If it is 59.6, it will return 60Hz. |
*/ |
int drm_mode_vrefresh(struct drm_display_mode *mode) |
{ |
161,14 → 578,13 |
if (mode->vrefresh > 0) |
refresh = mode->vrefresh; |
else if (mode->htotal > 0 && mode->vtotal > 0) { |
int vtotal; |
vtotal = mode->vtotal; |
/* work out vrefresh the value will be x1000 */ |
calc_val = (mode->clock * 1000); |
calc_val /= mode->htotal; |
calc_val *= 1000; |
calc_val /= mode->vtotal; |
refresh = (calc_val + vtotal / 2) / vtotal; |
refresh = calc_val; |
if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
refresh *= 2; |
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
403,8 → 819,7 |
list_del(&mode->head); |
if (verbose) { |
drm_mode_debug_printmodeline(mode); |
DRM_DEBUG_MODE(DRM_MODESET_DEBUG, |
"Not using %s mode %d\n", |
DRM_DEBUG_KMS("Not using %s mode %d\n", |
mode->name, mode->status); |
} |
drm_mode_destroy(dev, mode); |
566,6 → 981,8 |
found_it = 1; |
/* if equal delete the probed mode */ |
mode->status = pmode->status; |
/* Merge type bits together */ |
mode->type |= pmode->type; |
list_del(&pmode->head); |
drm_mode_destroy(connector->dev, pmode); |
break; |
/drivers/video/drm/idr.c |
---|
27,6 → 27,10 |
*/ |
#include <linux/idr.h> |
#include <stdlib.h> |
#include "drm.h" |
#include "drmP.h" |
#include "drm_crtc.h" |
#define ADDR "=m" (*(volatile long *) addr) |
418,7 → 422,6 |
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id) |
{ |
int rv; |
rv = idr_get_new_above_int(idp, ptr, starting_id); |
/* |
* This is a cheap hack until the IDR code can be fixed to |
425,7 → 428,10 |
* return proper error values. |
*/ |
if (rv < 0) |
{ |
dbgprintf("fail\n"); |
return _idr_rc_to_errno(rv); |
}; |
*id = rv; |
return 0; |
} |
/drivers/video/drm/include/drmP.h |
---|
File deleted |
/drivers/video/drm/include/types.h |
---|
File deleted |
/drivers/video/drm/include/drm_crtc_helper.h |
---|
File deleted |
/drivers/video/drm/include/list.h |
---|
File deleted |
/drivers/video/drm/include/drm_crtc.h |
---|
File deleted |
/drivers/video/drm/include/drm_mode.h |
---|
File deleted |
/drivers/video/drm/include/drm.h |
---|
36,7 → 36,7 |
#ifndef _DRM_H_ |
#define _DRM_H_ |
#include <types.h> |
#include <linux/types.h> |
#include <errno-base.h> |
//#include <asm/ioctl.h> /* For _IO* macros */ |
741,4 → 741,7 |
typedef struct drm_set_version drm_set_version_t; |
#endif |
#define mutex_lock(x) |
#define mutex_unlock(x) |
#endif |
/drivers/video/drm/include/linux/fb.h |
---|
0,0 → 1,1061 |
#ifndef _LINUX_FB_H |
#define _LINUX_FB_H |
#include <linux/types.h> |
#include <list.h> |
#include <linux/i2c.h> |
struct dentry; |
/* Definitions of frame buffers */ |
#define FB_MAX 32 /* sufficient for now */ |
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ |
#define FB_TYPE_PLANES 1 /* Non interleaved planes */ |
#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ |
#define FB_TYPE_TEXT 3 /* Text/attributes */ |
#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ |
#define FB_AUX_TEXT_MDA 0 /* Monochrome text */ |
#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ |
#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */ |
#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */ |
#define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */ |
#define FB_AUX_TEXT_SVGA_GROUP 8 /* 8-15: SVGA tileblit compatible modes */ |
#define FB_AUX_TEXT_SVGA_MASK 7 /* lower three bits says step */ |
#define FB_AUX_TEXT_SVGA_STEP2 8 /* SVGA text mode: text, attr */ |
#define FB_AUX_TEXT_SVGA_STEP4 9 /* SVGA text mode: text, attr, 2 reserved bytes */ |
#define FB_AUX_TEXT_SVGA_STEP8 10 /* SVGA text mode: text, attr, 6 reserved bytes */ |
#define FB_AUX_TEXT_SVGA_STEP16 11 /* SVGA text mode: text, attr, 14 reserved bytes */ |
#define FB_AUX_TEXT_SVGA_LAST 15 /* reserved up to 15 */ |
#define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */ |
#define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */ |
#define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */ |
#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */ |
#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */ |
#define FB_VISUAL_TRUECOLOR 2 /* True color */ |
#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ |
#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ |
#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ |
#define FB_ACCEL_NONE 0 /* no hardware accelerator */ |
#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ |
#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ |
#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */ |
#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */ |
#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */ |
#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */ |
#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */ |
#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */ |
#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */ |
#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */ |
#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */ |
#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */ |
#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */ |
#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */ |
#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */ |
#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */ |
#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */ |
#define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */ |
#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */ |
#define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */ |
#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */ |
#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */ |
#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */ |
#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */ |
#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */ |
#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ |
#define FB_ACCEL_NV3 27 /* nVidia RIVA 128 */ |
#define FB_ACCEL_NV4 28 /* nVidia RIVA TNT */ |
#define FB_ACCEL_NV5 29 /* nVidia RIVA TNT2 */ |
#define FB_ACCEL_CT_6555x 30 /* C&T 6555x */ |
#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */ |
#define FB_ACCEL_ATI_RAGE128 32 /* ATI Rage128 family */ |
#define FB_ACCEL_IGS_CYBER2000 33 /* CyberPro 2000 */ |
#define FB_ACCEL_IGS_CYBER2010 34 /* CyberPro 2010 */ |
#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */ |
#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */ |
#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */ |
#define FB_ACCEL_ATI_RADEON 38 /* ATI Radeon family */ |
#define FB_ACCEL_I810 39 /* Intel 810/815 */ |
#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */ |
#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */ |
#define FB_ACCEL_I830 42 /* Intel 830M/845G/85x/865G */ |
#define FB_ACCEL_NV_10 43 /* nVidia Arch 10 */ |
#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */ |
#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */ |
#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */ |
#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */ |
#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */ |
#define FB_ACCEL_OMAP1610 49 /* TI OMAP16xx */ |
#define FB_ACCEL_TRIDENT_TGUI 50 /* Trident TGUI */ |
#define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */ |
#define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */ |
#define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */ |
#define FB_ACCEL_CIRRUS_ALPINE 53 /* Cirrus Logic 543x/544x/5480 */ |
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ |
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ |
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ |
#define FB_ACCEL_NEOMAGIC_NM2097 93 /* NeoMagic NM2097 */ |
#define FB_ACCEL_NEOMAGIC_NM2160 94 /* NeoMagic NM2160 */ |
#define FB_ACCEL_NEOMAGIC_NM2200 95 /* NeoMagic NM2200 */ |
#define FB_ACCEL_NEOMAGIC_NM2230 96 /* NeoMagic NM2230 */ |
#define FB_ACCEL_NEOMAGIC_NM2360 97 /* NeoMagic NM2360 */ |
#define FB_ACCEL_NEOMAGIC_NM2380 98 /* NeoMagic NM2380 */ |
#define FB_ACCEL_PXA3XX 99 /* PXA3xx */ |
#define FB_ACCEL_SAVAGE4 0x80 /* S3 Savage4 */ |
#define FB_ACCEL_SAVAGE3D 0x81 /* S3 Savage3D */ |
#define FB_ACCEL_SAVAGE3D_MV 0x82 /* S3 Savage3D-MV */ |
#define FB_ACCEL_SAVAGE2000 0x83 /* S3 Savage2000 */ |
#define FB_ACCEL_SAVAGE_MX_MV 0x84 /* S3 Savage/MX-MV */ |
#define FB_ACCEL_SAVAGE_MX 0x85 /* S3 Savage/MX */ |
#define FB_ACCEL_SAVAGE_IX_MV 0x86 /* S3 Savage/IX-MV */ |
#define FB_ACCEL_SAVAGE_IX 0x87 /* S3 Savage/IX */ |
#define FB_ACCEL_PROSAVAGE_PM 0x88 /* S3 ProSavage PM133 */ |
#define FB_ACCEL_PROSAVAGE_KM 0x89 /* S3 ProSavage KM133 */ |
#define FB_ACCEL_S3TWISTER_P 0x8a /* S3 Twister */ |
#define FB_ACCEL_S3TWISTER_K 0x8b /* S3 TwisterK */ |
#define FB_ACCEL_SUPERSAVAGE 0x8c /* S3 Supersavage */ |
#define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */ |
#define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */ |
struct fb_fix_screeninfo { |
char id[16]; /* identification string eg "TT Builtin" */ |
unsigned long smem_start; /* Start of frame buffer mem */ |
/* (physical address) */ |
__u32 smem_len; /* Length of frame buffer mem */ |
__u32 type; /* see FB_TYPE_* */ |
__u32 type_aux; /* Interleave for interleaved Planes */ |
__u32 visual; /* see FB_VISUAL_* */ |
__u16 xpanstep; /* zero if no hardware panning */ |
__u16 ypanstep; /* zero if no hardware panning */ |
__u16 ywrapstep; /* zero if no hardware ywrap */ |
__u32 line_length; /* length of a line in bytes */ |
unsigned long mmio_start; /* Start of Memory Mapped I/O */ |
/* (physical address) */ |
__u32 mmio_len; /* Length of Memory Mapped I/O */ |
__u32 accel; /* Indicate to driver which */ |
/* specific chip/card we have */ |
__u16 reserved[3]; /* Reserved for future compatibility */ |
}; |
/* Interpretation of offset for color fields: All offsets are from the right, |
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you |
* can use the offset as right argument to <<). A pixel afterwards is a bit |
* stream and is written to video memory as that unmodified. |
* |
* For pseudocolor: offset and length should be the same for all color |
* components. Offset specifies the position of the least significant bit |
* of the pallette index in a pixel value. Length indicates the number |
* of available palette entries (i.e. # of entries = 1 << length). |
*/ |
struct fb_bitfield { |
__u32 offset; /* beginning of bitfield */ |
__u32 length; /* length of bitfield */ |
__u32 msb_right; /* != 0 : Most significant bit is */ |
/* right */ |
}; |
#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */ |
#define FB_NONSTD_REV_PIX_IN_B 2 /* order of pixels in each byte is reversed */ |
#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/ |
#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */ |
#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */ |
#define FB_ACTIVATE_MASK 15 |
/* values */ |
#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */ |
#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */ |
#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */ |
#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/ |
#define FB_ACTIVATE_INV_MODE 256 /* invalidate videomode */ |
#define FB_ACCELF_TEXT 1 /* (OBSOLETE) see fb_info.flags and vc_mode */ |
#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ |
#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ |
#define FB_SYNC_EXT 4 /* external sync */ |
#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ |
#define FB_SYNC_BROADCAST 16 /* broadcast video timings */ |
/* vtotal = 144d/288n/576i => PAL */ |
/* vtotal = 121d/242n/484i => NTSC */ |
#define FB_SYNC_ON_GREEN 32 /* sync on green */ |
#define FB_VMODE_NONINTERLACED 0 /* non interlaced */ |
#define FB_VMODE_INTERLACED 1 /* interlaced */ |
#define FB_VMODE_DOUBLE 2 /* double scan */ |
#define FB_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */ |
#define FB_VMODE_MASK 255 |
#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */ |
#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ |
#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ |
/* |
* Display rotation support |
*/ |
#define FB_ROTATE_UR 0 |
#define FB_ROTATE_CW 1 |
#define FB_ROTATE_UD 2 |
#define FB_ROTATE_CCW 3 |
#define PICOS2KHZ(a) (1000000000UL/(a)) |
#define KHZ2PICOS(a) (1000000000UL/(a)) |
struct fb_var_screeninfo { |
__u32 xres; /* visible resolution */ |
__u32 yres; |
__u32 xres_virtual; /* virtual resolution */ |
__u32 yres_virtual; |
__u32 xoffset; /* offset from virtual to visible */ |
__u32 yoffset; /* resolution */ |
__u32 bits_per_pixel; /* guess what */ |
__u32 grayscale; /* != 0 Graylevels instead of colors */ |
struct fb_bitfield red; /* bitfield in fb mem if true color, */ |
struct fb_bitfield green; /* else only length is significant */ |
struct fb_bitfield blue; |
struct fb_bitfield transp; /* transparency */ |
__u32 nonstd; /* != 0 Non standard pixel format */ |
__u32 activate; /* see FB_ACTIVATE_* */ |
__u32 height; /* height of picture in mm */ |
__u32 width; /* width of picture in mm */ |
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */ |
/* Timing: All values in pixclocks, except pixclock (of course) */ |
__u32 pixclock; /* pixel clock in ps (pico seconds) */ |
__u32 left_margin; /* time from sync to picture */ |
__u32 right_margin; /* time from picture to sync */ |
__u32 upper_margin; /* time from sync to picture */ |
__u32 lower_margin; |
__u32 hsync_len; /* length of horizontal sync */ |
__u32 vsync_len; /* length of vertical sync */ |
__u32 sync; /* see FB_SYNC_* */ |
__u32 vmode; /* see FB_VMODE_* */ |
__u32 rotate; /* angle we rotate counter clockwise */ |
__u32 reserved[5]; /* Reserved for future compatibility */ |
}; |
struct fb_cmap { |
__u32 start; /* First entry */ |
__u32 len; /* Number of entries */ |
__u16 *red; /* Red values */ |
__u16 *green; |
__u16 *blue; |
__u16 *transp; /* transparency, can be NULL */ |
}; |
struct fb_con2fbmap { |
__u32 console; |
__u32 framebuffer; |
}; |
/* VESA Blanking Levels */ |
#define VESA_NO_BLANKING 0 |
#define VESA_VSYNC_SUSPEND 1 |
#define VESA_HSYNC_SUSPEND 2 |
#define VESA_POWERDOWN 3 |
enum { |
/* screen: unblanked, hsync: on, vsync: on */ |
FB_BLANK_UNBLANK = VESA_NO_BLANKING, |
/* screen: blanked, hsync: on, vsync: on */ |
FB_BLANK_NORMAL = VESA_NO_BLANKING + 1, |
/* screen: blanked, hsync: on, vsync: off */ |
FB_BLANK_VSYNC_SUSPEND = VESA_VSYNC_SUSPEND + 1, |
/* screen: blanked, hsync: off, vsync: on */ |
FB_BLANK_HSYNC_SUSPEND = VESA_HSYNC_SUSPEND + 1, |
/* screen: blanked, hsync: off, vsync: off */ |
FB_BLANK_POWERDOWN = VESA_POWERDOWN + 1 |
}; |
#define FB_VBLANK_VBLANKING 0x001 /* currently in a vertical blank */ |
#define FB_VBLANK_HBLANKING 0x002 /* currently in a horizontal blank */ |
#define FB_VBLANK_HAVE_VBLANK 0x004 /* vertical blanks can be detected */ |
#define FB_VBLANK_HAVE_HBLANK 0x008 /* horizontal blanks can be detected */ |
#define FB_VBLANK_HAVE_COUNT 0x010 /* global retrace counter is available */ |
#define FB_VBLANK_HAVE_VCOUNT 0x020 /* the vcount field is valid */ |
#define FB_VBLANK_HAVE_HCOUNT 0x040 /* the hcount field is valid */ |
#define FB_VBLANK_VSYNCING 0x080 /* currently in a vsync */ |
#define FB_VBLANK_HAVE_VSYNC 0x100 /* verical syncs can be detected */ |
struct fb_vblank { |
__u32 flags; /* FB_VBLANK flags */ |
__u32 count; /* counter of retraces since boot */ |
__u32 vcount; /* current scanline position */ |
__u32 hcount; /* current scandot position */ |
__u32 reserved[4]; /* reserved for future compatibility */ |
}; |
/* Internal HW accel */ |
#define ROP_COPY 0 |
#define ROP_XOR 1 |
struct fb_copyarea { |
__u32 dx; |
__u32 dy; |
__u32 width; |
__u32 height; |
__u32 sx; |
__u32 sy; |
}; |
struct fb_fillrect { |
__u32 dx; /* screen-relative */ |
__u32 dy; |
__u32 width; |
__u32 height; |
__u32 color; |
__u32 rop; |
}; |
struct fb_image { |
__u32 dx; /* Where to place image */ |
__u32 dy; |
__u32 width; /* Size of image */ |
__u32 height; |
__u32 fg_color; /* Only used when a mono bitmap */ |
__u32 bg_color; |
__u8 depth; /* Depth of the image */ |
const char *data; /* Pointer to image data */ |
struct fb_cmap cmap; /* color map info */ |
}; |
/* |
* hardware cursor control |
*/ |
#define FB_CUR_SETIMAGE 0x01 |
#define FB_CUR_SETPOS 0x02 |
#define FB_CUR_SETHOT 0x04 |
#define FB_CUR_SETCMAP 0x08 |
#define FB_CUR_SETSHAPE 0x10 |
#define FB_CUR_SETSIZE 0x20 |
#define FB_CUR_SETALL 0xFF |
struct fbcurpos { |
__u16 x, y; |
}; |
struct fb_cursor { |
__u16 set; /* what to set */ |
__u16 enable; /* cursor on/off */ |
__u16 rop; /* bitop operation */ |
const char *mask; /* cursor mask bits */ |
struct fbcurpos hot; /* cursor hot spot */ |
struct fb_image image; /* Cursor image */ |
}; |
#ifdef CONFIG_FB_BACKLIGHT |
/* Settings for the generic backlight code */ |
#define FB_BACKLIGHT_LEVELS 128 |
#define FB_BACKLIGHT_MAX 0xFF |
#endif |
//#ifdef __KERNEL__ |
//#include <linux/fs.h> |
//#include <linux/init.h> |
//#include <linux/device.h> |
//#include <linux/workqueue.h> |
//#include <linux/notifier.h> |
#include <linux/list.h> |
//#include <linux/backlight.h> |
//#include <asm/io.h> |
//struct vm_area_struct; |
//struct fb_info; |
//struct device; |
//struct file; |
/* Definitions below are used in the parsed monitor specs */ |
#define FB_DPMS_ACTIVE_OFF 1 |
#define FB_DPMS_SUSPEND 2 |
#define FB_DPMS_STANDBY 4 |
#define FB_DISP_DDI 1 |
#define FB_DISP_ANA_700_300 2 |
#define FB_DISP_ANA_714_286 4 |
#define FB_DISP_ANA_1000_400 8 |
#define FB_DISP_ANA_700_000 16 |
#define FB_DISP_MONO 32 |
#define FB_DISP_RGB 64 |
#define FB_DISP_MULTI 128 |
#define FB_DISP_UNKNOWN 256 |
#define FB_SIGNAL_NONE 0 |
#define FB_SIGNAL_BLANK_BLANK 1 |
#define FB_SIGNAL_SEPARATE 2 |
#define FB_SIGNAL_COMPOSITE 4 |
#define FB_SIGNAL_SYNC_ON_GREEN 8 |
#define FB_SIGNAL_SERRATION_ON 16 |
#define FB_MISC_PRIM_COLOR 1 |
#define FB_MISC_1ST_DETAIL 2 /* First Detailed Timing is preferred */ |
struct fb_chroma { |
__u32 redx; /* in fraction of 1024 */ |
__u32 greenx; |
__u32 bluex; |
__u32 whitex; |
__u32 redy; |
__u32 greeny; |
__u32 bluey; |
__u32 whitey; |
}; |
struct fb_monspecs { |
struct fb_chroma chroma; |
struct fb_videomode *modedb; /* mode database */ |
__u8 manufacturer[4]; /* Manufacturer */ |
__u8 monitor[14]; /* Monitor String */ |
__u8 serial_no[14]; /* Serial Number */ |
__u8 ascii[14]; /* ? */ |
__u32 modedb_len; /* mode database length */ |
__u32 model; /* Monitor Model */ |
__u32 serial; /* Serial Number - Integer */ |
__u32 year; /* Year manufactured */ |
__u32 week; /* Week Manufactured */ |
__u32 hfmin; /* hfreq lower limit (Hz) */ |
__u32 hfmax; /* hfreq upper limit (Hz) */ |
__u32 dclkmin; /* pixelclock lower limit (Hz) */ |
__u32 dclkmax; /* pixelclock upper limit (Hz) */ |
__u16 input; /* display type - see FB_DISP_* */ |
__u16 dpms; /* DPMS support - see FB_DPMS_ */ |
__u16 signal; /* Signal Type - see FB_SIGNAL_* */ |
__u16 vfmin; /* vfreq lower limit (Hz) */ |
__u16 vfmax; /* vfreq upper limit (Hz) */ |
__u16 gamma; /* Gamma - in fractions of 100 */ |
__u16 gtf : 1; /* supports GTF */ |
__u16 misc; /* Misc flags - see FB_MISC_* */ |
__u8 version; /* EDID version... */ |
__u8 revision; /* ...and revision */ |
__u8 max_x; /* Maximum horizontal size (cm) */ |
__u8 max_y; /* Maximum vertical size (cm) */ |
}; |
struct fb_cmap_user { |
__u32 start; /* First entry */ |
__u32 len; /* Number of entries */ |
__u16 __user *red; /* Red values */ |
__u16 __user *green; |
__u16 __user *blue; |
__u16 __user *transp; /* transparency, can be NULL */ |
}; |
struct fb_image_user { |
__u32 dx; /* Where to place image */ |
__u32 dy; |
__u32 width; /* Size of image */ |
__u32 height; |
__u32 fg_color; /* Only used when a mono bitmap */ |
__u32 bg_color; |
__u8 depth; /* Depth of the image */ |
const char __user *data; /* Pointer to image data */ |
struct fb_cmap_user cmap; /* color map info */ |
}; |
struct fb_cursor_user { |
__u16 set; /* what to set */ |
__u16 enable; /* cursor on/off */ |
__u16 rop; /* bitop operation */ |
const char __user *mask; /* cursor mask bits */ |
struct fbcurpos hot; /* cursor hot spot */ |
struct fb_image_user image; /* Cursor image */ |
}; |
/* |
* Register/unregister for framebuffer events |
*/ |
/* The resolution of the passed in fb_info about to change */ |
#define FB_EVENT_MODE_CHANGE 0x01 |
/* The display on this fb_info is beeing suspended, no access to the |
* framebuffer is allowed any more after that call returns |
*/ |
#define FB_EVENT_SUSPEND 0x02 |
/* The display on this fb_info was resumed, you can restore the display |
* if you own it |
*/ |
#define FB_EVENT_RESUME 0x03 |
/* An entry from the modelist was removed */ |
#define FB_EVENT_MODE_DELETE 0x04 |
/* A driver registered itself */ |
#define FB_EVENT_FB_REGISTERED 0x05 |
/* A driver unregistered itself */ |
#define FB_EVENT_FB_UNREGISTERED 0x06 |
/* CONSOLE-SPECIFIC: get console to framebuffer mapping */ |
#define FB_EVENT_GET_CONSOLE_MAP 0x07 |
/* CONSOLE-SPECIFIC: set console to framebuffer mapping */ |
#define FB_EVENT_SET_CONSOLE_MAP 0x08 |
/* A hardware display blank change occured */ |
#define FB_EVENT_BLANK 0x09 |
/* Private modelist is to be replaced */ |
#define FB_EVENT_NEW_MODELIST 0x0A |
/* The resolution of the passed in fb_info about to change and |
all vc's should be changed */ |
#define FB_EVENT_MODE_CHANGE_ALL 0x0B |
/* A software display blank change occured */ |
#define FB_EVENT_CONBLANK 0x0C |
/* Get drawing requirements */ |
#define FB_EVENT_GET_REQ 0x0D |
/* Unbind from the console if possible */ |
#define FB_EVENT_FB_UNBIND 0x0E |
struct fb_event { |
struct fb_info *info; |
void *data; |
}; |
struct fb_blit_caps { |
u32 x; |
u32 y; |
u32 len; |
u32 flags; |
}; |
/* |
* Pixmap structure definition |
* |
* The purpose of this structure is to translate data |
* from the hardware independent format of fbdev to what |
* format the hardware needs. |
*/ |
#define FB_PIXMAP_DEFAULT 1 /* used internally by fbcon */ |
#define FB_PIXMAP_SYSTEM 2 /* memory is in system RAM */ |
#define FB_PIXMAP_IO 4 /* memory is iomapped */ |
#define FB_PIXMAP_SYNC 256 /* set if GPU can DMA */ |
struct fb_pixmap { |
u8 *addr; /* pointer to memory */ |
u32 size; /* size of buffer in bytes */ |
u32 offset; /* current offset to buffer */ |
u32 buf_align; /* byte alignment of each bitmap */ |
u32 scan_align; /* alignment per scanline */ |
u32 access_align; /* alignment per read/write (bits) */ |
u32 flags; /* see FB_PIXMAP_* */ |
u32 blit_x; /* supported bit block dimensions (1-32)*/ |
u32 blit_y; /* Format: blit_x = 1 << (width - 1) */ |
/* blit_y = 1 << (height - 1) */ |
/* if 0, will be set to 0xffffffff (all)*/ |
/* access methods */ |
void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size); |
void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size); |
}; |
#ifdef CONFIG_FB_DEFERRED_IO |
struct fb_deferred_io { |
/* delay between mkwrite and deferred handler */ |
unsigned long delay; |
struct mutex lock; /* mutex that protects the page list */ |
struct list_head pagelist; /* list of touched pages */ |
/* callback */ |
void (*deferred_io)(struct fb_info *info, struct list_head *pagelist); |
}; |
#endif |
/* |
* Frame buffer operations |
* |
* LOCKING NOTE: those functions must _ALL_ be called with the console |
* semaphore held, this is the only suitable locking mechanism we have |
* in 2.6. Some may be called at interrupt time at this point though. |
*/ |
struct fb_ops { |
/* open/release and usage marking */ |
struct module *owner; |
int (*fb_open)(struct fb_info *info, int user); |
int (*fb_release)(struct fb_info *info, int user); |
/* For framebuffers with strange non linear layouts or that do not |
* work with normal memory mapped access |
*/ |
ssize_t (*fb_read)(struct fb_info *info, char __user *buf, |
size_t count, loff_t *ppos); |
ssize_t (*fb_write)(struct fb_info *info, const char __user *buf, |
size_t count, loff_t *ppos); |
/* checks var and eventually tweaks it to something supported, |
* DO NOT MODIFY PAR */ |
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); |
/* set the video mode according to info->var */ |
int (*fb_set_par)(struct fb_info *info); |
/* set color register */ |
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, |
unsigned blue, unsigned transp, struct fb_info *info); |
/* set color registers in batch */ |
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); |
/* blank display */ |
int (*fb_blank)(int blank, struct fb_info *info); |
/* pan display */ |
int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); |
/* Draws a rectangle */ |
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); |
/* Copy data from area to another */ |
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); |
/* Draws a image to the display */ |
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); |
/* Draws cursor */ |
int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); |
/* Rotates the display */ |
void (*fb_rotate)(struct fb_info *info, int angle); |
/* wait for blit idle, optional */ |
int (*fb_sync)(struct fb_info *info); |
/* perform fb specific ioctl (optional) */ |
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, |
unsigned long arg); |
/* Handle 32bit compat ioctl (optional) */ |
int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd, |
unsigned long arg); |
/* perform fb specific mmap */ |
// int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); |
/* save current hardware state */ |
void (*fb_save_state)(struct fb_info *info); |
/* restore saved state */ |
void (*fb_restore_state)(struct fb_info *info); |
/* get capability given var */ |
void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, |
struct fb_var_screeninfo *var); |
/* teardown any resources to do with this framebuffer */ |
void (*fb_destroy)(struct fb_info *info); |
}; |
#ifdef CONFIG_FB_TILEBLITTING |
#define FB_TILE_CURSOR_NONE 0 |
#define FB_TILE_CURSOR_UNDERLINE 1 |
#define FB_TILE_CURSOR_LOWER_THIRD 2 |
#define FB_TILE_CURSOR_LOWER_HALF 3 |
#define FB_TILE_CURSOR_TWO_THIRDS 4 |
#define FB_TILE_CURSOR_BLOCK 5 |
struct fb_tilemap { |
__u32 width; /* width of each tile in pixels */ |
__u32 height; /* height of each tile in scanlines */ |
__u32 depth; /* color depth of each tile */ |
__u32 length; /* number of tiles in the map */ |
const __u8 *data; /* actual tile map: a bitmap array, packed |
to the nearest byte */ |
}; |
struct fb_tilerect { |
__u32 sx; /* origin in the x-axis */ |
__u32 sy; /* origin in the y-axis */ |
__u32 width; /* number of tiles in the x-axis */ |
__u32 height; /* number of tiles in the y-axis */ |
__u32 index; /* what tile to use: index to tile map */ |
__u32 fg; /* foreground color */ |
__u32 bg; /* background color */ |
__u32 rop; /* raster operation */ |
}; |
struct fb_tilearea { |
__u32 sx; /* source origin in the x-axis */ |
__u32 sy; /* source origin in the y-axis */ |
__u32 dx; /* destination origin in the x-axis */ |
__u32 dy; /* destination origin in the y-axis */ |
__u32 width; /* number of tiles in the x-axis */ |
__u32 height; /* number of tiles in the y-axis */ |
}; |
struct fb_tileblit { |
__u32 sx; /* origin in the x-axis */ |
__u32 sy; /* origin in the y-axis */ |
__u32 width; /* number of tiles in the x-axis */ |
__u32 height; /* number of tiles in the y-axis */ |
__u32 fg; /* foreground color */ |
__u32 bg; /* background color */ |
__u32 length; /* number of tiles to draw */ |
__u32 *indices; /* array of indices to tile map */ |
}; |
struct fb_tilecursor { |
__u32 sx; /* cursor position in the x-axis */ |
__u32 sy; /* cursor position in the y-axis */ |
__u32 mode; /* 0 = erase, 1 = draw */ |
__u32 shape; /* see FB_TILE_CURSOR_* */ |
__u32 fg; /* foreground color */ |
__u32 bg; /* background color */ |
}; |
struct fb_tile_ops { |
/* set tile characteristics */ |
void (*fb_settile)(struct fb_info *info, struct fb_tilemap *map); |
/* all dimensions from hereon are in terms of tiles */ |
/* move a rectangular region of tiles from one area to another*/ |
void (*fb_tilecopy)(struct fb_info *info, struct fb_tilearea *area); |
/* fill a rectangular region with a tile */ |
void (*fb_tilefill)(struct fb_info *info, struct fb_tilerect *rect); |
/* copy an array of tiles */ |
void (*fb_tileblit)(struct fb_info *info, struct fb_tileblit *blit); |
/* cursor */ |
void (*fb_tilecursor)(struct fb_info *info, |
struct fb_tilecursor *cursor); |
/* get maximum length of the tile map */ |
int (*fb_get_tilemax)(struct fb_info *info); |
}; |
#endif /* CONFIG_FB_TILEBLITTING */ |
/* FBINFO_* = fb_info.flags bit flags */ |
#define FBINFO_MODULE 0x0001 /* Low-level driver is a module */ |
#define FBINFO_HWACCEL_DISABLED 0x0002 |
/* When FBINFO_HWACCEL_DISABLED is set: |
* Hardware acceleration is turned off. Software implementations |
* of required functions (copyarea(), fillrect(), and imageblit()) |
* takes over; acceleration engine should be in a quiescent state */ |
/* hints */ |
#define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */ |
#define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */ |
/* hardware supported ops */ |
/* semantics: when a bit is set, it indicates that the operation is |
* accelerated by hardware. |
* required functions will still work even if the bit is not set. |
* optional functions may not even exist if the flag bit is not set. |
*/ |
#define FBINFO_HWACCEL_NONE 0x0000 |
#define FBINFO_HWACCEL_COPYAREA 0x0100 /* required */ |
#define FBINFO_HWACCEL_FILLRECT 0x0200 /* required */ |
#define FBINFO_HWACCEL_IMAGEBLIT 0x0400 /* required */ |
#define FBINFO_HWACCEL_ROTATE 0x0800 /* optional */ |
#define FBINFO_HWACCEL_XPAN 0x1000 /* optional */ |
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */ |
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */ |
#define FBINFO_MISC_USEREVENT 0x10000 /* event request |
from userspace */ |
#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ |
#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware |
inited framebuffer */ |
/* A driver may set this flag to indicate that it does want a set_par to be |
* called every time when fbcon_switch is executed. The advantage is that with |
* this flag set you can really be sure that set_par is always called before |
* any of the functions dependant on the correct hardware state or altering |
* that state, even if you are using some broken X releases. The disadvantage |
* is that it introduces unwanted delays to every console switch if set_par |
* is slow. It is a good idea to try this flag in the drivers initialization |
* code whenever there is a bug report related to switching between X and the |
* framebuffer console. |
*/ |
#define FBINFO_MISC_ALWAYS_SETPAR 0x40000 |
/* |
* Host and GPU endianness differ. |
*/ |
#define FBINFO_FOREIGN_ENDIAN 0x100000 |
/* |
* Big endian math. This is the same flags as above, but with different |
* meaning, it is set by the fb subsystem depending FOREIGN_ENDIAN flag |
* and host endianness. Drivers should not use this flag. |
*/ |
#define FBINFO_BE_MATH 0x100000 |
struct fb_info { |
int node; |
int flags; |
// struct mutex lock; /* Lock for open/release/ioctl funcs */ |
// struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ |
struct fb_var_screeninfo var; /* Current var */ |
struct fb_fix_screeninfo fix; /* Current fix */ |
struct fb_monspecs monspecs; /* Current Monitor specs */ |
// struct work_struct queue; /* Framebuffer event queue */ |
// struct fb_pixmap pixmap; /* Image hardware mapper */ |
// struct fb_pixmap sprite; /* Cursor hardware mapper */ |
// struct fb_cmap cmap; /* Current cmap */ |
struct list_head modelist; /* mode list */ |
struct fb_videomode *mode; /* current mode */ |
#ifdef CONFIG_FB_BACKLIGHT |
/* assigned backlight device */ |
/* set before framebuffer registration, |
remove after unregister */ |
struct backlight_device *bl_dev; |
/* Backlight level curve */ |
struct mutex bl_curve_mutex; |
u8 bl_curve[FB_BACKLIGHT_LEVELS]; |
#endif |
#ifdef CONFIG_FB_DEFERRED_IO |
struct delayed_work deferred_work; |
struct fb_deferred_io *fbdefio; |
#endif |
struct fb_ops *fbops; |
// struct device *device; /* This is the parent */ |
// struct device *dev; /* This is this fb device */ |
int class_flag; /* private sysfs flags */ |
#ifdef CONFIG_FB_TILEBLITTING |
struct fb_tile_ops *tileops; /* Tile Blitting */ |
#endif |
char __iomem *screen_base; /* Virtual address */ |
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ |
void *pseudo_palette; /* Fake palette of 16 colors */ |
#define FBINFO_STATE_RUNNING 0 |
#define FBINFO_STATE_SUSPENDED 1 |
u32 state; /* Hardware state i.e suspend */ |
void *fbcon_par; /* fbcon use-only private area */ |
/* From here on everything is device dependent */ |
void *par; |
/* we need the PCI or similiar aperture base/size not |
smem_start/size as smem_start may just be an object |
allocated inside the aperture so may not actually overlap */ |
resource_size_t aperture_base; |
resource_size_t aperture_size; |
}; |
#ifdef MODULE |
#define FBINFO_DEFAULT FBINFO_MODULE |
#else |
#define FBINFO_DEFAULT 0 |
#endif |
// This will go away |
#define FBINFO_FLAG_MODULE FBINFO_MODULE |
#define FBINFO_FLAG_DEFAULT FBINFO_DEFAULT |
/* This will go away |
* fbset currently hacks in FB_ACCELF_TEXT into var.accel_flags |
* when it wants to turn the acceleration engine on. This is |
* really a separate operation, and should be modified via sysfs. |
* But for now, we leave it broken with the following define |
*/ |
#define STUPID_ACCELF_TEXT_SHIT |
#define fb_readb(addr) (*(volatile u8 *) (addr)) |
#define fb_readw(addr) (*(volatile u16 *) (addr)) |
#define fb_readl(addr) (*(volatile u32 *) (addr)) |
#define fb_readq(addr) (*(volatile u64 *) (addr)) |
#define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b)) |
#define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b)) |
#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b)) |
#define fb_writeq(b,addr) (*(volatile u64 *) (addr) = (b)) |
#define fb_memset memset |
#define FB_LEFT_POS(p, bpp) (fb_be_math(p) ? (32 - (bpp)) : 0) |
#define FB_SHIFT_HIGH(p, val, bits) (fb_be_math(p) ? (val) >> (bits) : \ |
(val) << (bits)) |
#define FB_SHIFT_LOW(p, val, bits) (fb_be_math(p) ? (val) << (bits) : \ |
(val) >> (bits)) |
/* |
* `Generic' versions of the frame buffer device operations |
*/ |
extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); |
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); |
extern int fb_blank(struct fb_info *info, int blank); |
extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); |
extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); |
/* |
* Drawing operations where framebuffer is in system RAM |
*/ |
extern void sys_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
extern void sys_copyarea(struct fb_info *info, const struct fb_copyarea *area); |
extern void sys_imageblit(struct fb_info *info, const struct fb_image *image); |
extern ssize_t fb_sys_read(struct fb_info *info, char __user *buf, |
size_t count, loff_t *ppos); |
extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, |
size_t count, loff_t *ppos); |
/* drivers/video/fbmem.c */ |
extern int register_framebuffer(struct fb_info *fb_info); |
extern int unregister_framebuffer(struct fb_info *fb_info); |
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); |
extern int fb_show_logo(struct fb_info *fb_info, int rotate); |
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); |
extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, |
u32 height, u32 shift_high, u32 shift_low, u32 mod); |
extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height); |
extern void fb_set_suspend(struct fb_info *info, int state); |
extern int fb_get_color_depth(struct fb_var_screeninfo *var, |
struct fb_fix_screeninfo *fix); |
extern int fb_get_options(char *name, char **option); |
extern int fb_new_modelist(struct fb_info *info); |
extern struct fb_info *registered_fb[FB_MAX]; |
extern int num_registered_fb; |
extern struct class *fb_class; |
extern int lock_fb_info(struct fb_info *info); |
static inline void unlock_fb_info(struct fb_info *info) |
{ |
// mutex_unlock(&info->lock); |
} |
static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, |
u8 *src, u32 s_pitch, u32 height) |
{ |
int i, j; |
d_pitch -= s_pitch; |
for (i = height; i--; ) { |
/* s_pitch is a few bytes at the most, memcpy is suboptimal */ |
for (j = 0; j < s_pitch; j++) |
*dst++ = *src++; |
dst += d_pitch; |
} |
} |
/* drivers/video/fb_defio.c */ |
static inline bool fb_be_math(struct fb_info *info) |
{ |
#ifdef CONFIG_FB_FOREIGN_ENDIAN |
#if defined(CONFIG_FB_BOTH_ENDIAN) |
return info->flags & FBINFO_BE_MATH; |
#elif defined(CONFIG_FB_BIG_ENDIAN) |
return true; |
#elif defined(CONFIG_FB_LITTLE_ENDIAN) |
return false; |
#endif /* CONFIG_FB_BOTH_ENDIAN */ |
#else |
#ifdef __BIG_ENDIAN |
return true; |
#else |
return false; |
#endif /* __BIG_ENDIAN */ |
#endif /* CONFIG_FB_FOREIGN_ENDIAN */ |
} |
/* drivers/video/fbsysfs.c */ |
//extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); |
//extern void framebuffer_release(struct fb_info *info); |
//extern int fb_init_device(struct fb_info *fb_info); |
//extern void fb_cleanup_device(struct fb_info *head); |
//extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max); |
/* drivers/video/fbmon.c */ |
#define FB_MAXTIMINGS 0 |
#define FB_VSYNCTIMINGS 1 |
#define FB_HSYNCTIMINGS 2 |
#define FB_DCLKTIMINGS 3 |
#define FB_IGNOREMON 0x100 |
#define FB_MODE_IS_UNKNOWN 0 |
#define FB_MODE_IS_DETAILED 1 |
#define FB_MODE_IS_STANDARD 2 |
#define FB_MODE_IS_VESA 4 |
#define FB_MODE_IS_CALCULATED 8 |
#define FB_MODE_IS_FIRST 16 |
#define FB_MODE_IS_FROM_VAR 32 |
extern int fbmon_dpms(const struct fb_info *fb_info); |
extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, |
struct fb_info *info); |
extern int fb_validate_mode(const struct fb_var_screeninfo *var, |
struct fb_info *info); |
extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var); |
//extern const unsigned char *fb_firmware_edid(struct device *device); |
extern void fb_edid_to_monspecs(unsigned char *edid, |
struct fb_monspecs *specs); |
extern void fb_destroy_modedb(struct fb_videomode *modedb); |
extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb); |
extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter); |
/* drivers/video/modedb.c */ |
#define VESA_MODEDB_SIZE 34 |
extern void fb_var_to_videomode(struct fb_videomode *mode, |
const struct fb_var_screeninfo *var); |
extern void fb_videomode_to_var(struct fb_var_screeninfo *var, |
const struct fb_videomode *mode); |
extern int fb_mode_is_equal(const struct fb_videomode *mode1, |
const struct fb_videomode *mode2); |
extern int fb_add_videomode(const struct fb_videomode *mode, |
struct list_head *head); |
extern void fb_delete_videomode(const struct fb_videomode *mode, |
struct list_head *head); |
extern const struct fb_videomode *fb_match_mode(const struct fb_var_screeninfo *var, |
struct list_head *head); |
extern const struct fb_videomode *fb_find_best_mode(const struct fb_var_screeninfo *var, |
struct list_head *head); |
extern const struct fb_videomode *fb_find_nearest_mode(const struct fb_videomode *mode, |
struct list_head *head); |
extern void fb_destroy_modelist(struct list_head *head); |
extern void fb_videomode_to_modelist(const struct fb_videomode *modedb, int num, |
struct list_head *head); |
extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs *specs, |
struct list_head *head); |
/* drivers/video/fbcmap.c */ |
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); |
extern void fb_dealloc_cmap(struct fb_cmap *cmap); |
extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to); |
extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to); |
extern int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *fb_info); |
extern int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *fb_info); |
extern const struct fb_cmap *fb_default_cmap(int len); |
extern void fb_invert_cmaps(void); |
struct fb_videomode { |
const char *name; /* optional */ |
u32 refresh; /* optional */ |
u32 xres; |
u32 yres; |
u32 pixclock; |
u32 left_margin; |
u32 right_margin; |
u32 upper_margin; |
u32 lower_margin; |
u32 hsync_len; |
u32 vsync_len; |
u32 sync; |
u32 vmode; |
u32 flag; |
}; |
extern const char *fb_mode_option; |
extern const struct fb_videomode vesa_modes[]; |
struct fb_modelist { |
struct list_head list; |
struct fb_videomode mode; |
}; |
extern int fb_find_mode(struct fb_var_screeninfo *var, |
struct fb_info *info, const char *mode_option, |
const struct fb_videomode *db, |
unsigned int dbsize, |
const struct fb_videomode *default_mode, |
unsigned int default_bpp); |
#endif /* _LINUX_FB_H */ |
/drivers/video/drm/include/linux/i2c-id.h |
---|
0,0 → 1,59 |
/* ------------------------------------------------------------------------- */ |
/* */ |
/* i2c-id.h - identifier values for i2c drivers and adapters */ |
/* */ |
/* ------------------------------------------------------------------------- */ |
/* Copyright (C) 1995-1999 Simon G. Vogl |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
/* ------------------------------------------------------------------------- */ |
#ifndef LINUX_I2C_ID_H |
#define LINUX_I2C_ID_H |
/* Please note that I2C driver IDs are optional. They are only needed if a |
legacy chip driver needs to identify a bus or a bus driver needs to |
identify a legacy client. If you don't need them, just don't set them. */ |
/* |
* ---- Adapter types ---------------------------------------------------- |
*/ |
/* --- Bit algorithm adapters */ |
#define I2C_HW_B_BT848 0x010005 /* BT848 video boards */ |
#define I2C_HW_B_RIVA 0x010010 /* Riva based graphics cards */ |
#define I2C_HW_B_ZR36067 0x010019 /* Zoran-36057/36067 based boards */ |
#define I2C_HW_B_CX2388x 0x01001b /* connexant 2388x based tv cards */ |
#define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ |
#define I2C_HW_B_CX2341X 0x010020 /* Conexant CX2341X MPEG encoder cards */ |
#define I2C_HW_B_CX23885 0x010022 /* conexant 23885 based tv cards (bus1) */ |
#define I2C_HW_B_AU0828 0x010023 /* auvitek au0828 usb bridge */ |
#define I2C_HW_B_CX231XX 0x010024 /* Conexant CX231XX USB based cards */ |
#define I2C_HW_B_HDPVR 0x010025 /* Hauppauge HD PVR */ |
/* --- SGI adapters */ |
#define I2C_HW_SGI_VINO 0x160000 |
/* --- SMBus only adapters */ |
#define I2C_HW_SMBUS_W9968CF 0x04000d |
#define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */ |
#define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */ |
#define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */ |
/* --- Miscellaneous adapters */ |
#define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */ |
#define I2C_HW_SAA7134 0x090000 /* SAA7134 video decoder bus */ |
#endif /* LINUX_I2C_ID_H */ |
/drivers/video/drm/include/linux/list.h |
---|
0,0 → 1,703 |
#ifndef _LINUX_LIST_H |
#define _LINUX_LIST_H |
//#include <linux/stddef.h> |
//#include <linux/poison.h> |
//#include <linux/prefetch.h> |
//#include <asm/system.h> |
/* |
* Simple doubly linked list implementation. |
* |
* Some of the internal functions ("__xxx") are useful when |
* manipulating whole lists rather than single entries, as |
* sometimes we already know the next/prev entries and we can |
* generate better code by using them directly rather than |
* using the generic single-entry routines. |
*/ |
#define LIST_POISON1 ((struct list_head*)0xFFFF0100) |
#define LIST_POISON2 ((struct list_head*)0xFFFF0200) |
#define prefetch(x) __builtin_prefetch(x) |
struct list_head { |
struct list_head *next, *prev; |
}; |
#define LIST_HEAD_INIT(name) { &(name), &(name) } |
#define LIST_HEAD(name) \ |
struct list_head name = LIST_HEAD_INIT(name) |
static inline void INIT_LIST_HEAD(struct list_head *list) |
{ |
list->next = list; |
list->prev = list; |
} |
/* |
* Insert a new entry between two known consecutive entries. |
* |
* This is only for internal list manipulation where we know |
* the prev/next entries already! |
*/ |
#ifndef CONFIG_DEBUG_LIST |
static inline void __list_add(struct list_head *new, |
struct list_head *prev, |
struct list_head *next) |
{ |
next->prev = new; |
new->next = next; |
new->prev = prev; |
prev->next = new; |
} |
#else |
extern void __list_add(struct list_head *new, |
struct list_head *prev, |
struct list_head *next); |
#endif |
/** |
* list_add - add a new entry |
* @new: new entry to be added |
* @head: list head to add it after |
* |
* Insert a new entry after the specified head. |
* This is good for implementing stacks. |
*/ |
static inline void list_add(struct list_head *new, struct list_head *head) |
{ |
__list_add(new, head, head->next); |
} |
/** |
* list_add_tail - add a new entry |
* @new: new entry to be added |
* @head: list head to add it before |
* |
* Insert a new entry before the specified head. |
* This is useful for implementing queues. |
*/ |
static inline void list_add_tail(struct list_head *new, struct list_head *head) |
{ |
__list_add(new, head->prev, head); |
} |
/* |
* Delete a list entry by making the prev/next entries |
* point to each other. |
* |
* This is only for internal list manipulation where we know |
* the prev/next entries already! |
*/ |
static inline void __list_del(struct list_head * prev, struct list_head * next) |
{ |
next->prev = prev; |
prev->next = next; |
} |
/** |
* list_del - deletes entry from list. |
* @entry: the element to delete from the list. |
* Note: list_empty() on entry does not return true after this, the entry is |
* in an undefined state. |
*/ |
#ifndef CONFIG_DEBUG_LIST |
static inline void list_del(struct list_head *entry) |
{ |
__list_del(entry->prev, entry->next); |
entry->next = LIST_POISON1; |
entry->prev = LIST_POISON2; |
} |
#else |
extern void list_del(struct list_head *entry); |
#endif |
/** |
* list_replace - replace old entry by new one |
* @old : the element to be replaced |
* @new : the new element to insert |
* |
* If @old was empty, it will be overwritten. |
*/ |
static inline void list_replace(struct list_head *old, |
struct list_head *new) |
{ |
new->next = old->next; |
new->next->prev = new; |
new->prev = old->prev; |
new->prev->next = new; |
} |
static inline void list_replace_init(struct list_head *old, |
struct list_head *new) |
{ |
list_replace(old, new); |
INIT_LIST_HEAD(old); |
} |
/** |
* list_del_init - deletes entry from list and reinitialize it. |
* @entry: the element to delete from the list. |
*/ |
static inline void list_del_init(struct list_head *entry) |
{ |
__list_del(entry->prev, entry->next); |
INIT_LIST_HEAD(entry); |
} |
/** |
* list_move - delete from one list and add as another's head |
* @list: the entry to move |
* @head: the head that will precede our entry |
*/ |
static inline void list_move(struct list_head *list, struct list_head *head) |
{ |
__list_del(list->prev, list->next); |
list_add(list, head); |
} |
/** |
* list_move_tail - delete from one list and add as another's tail |
* @list: the entry to move |
* @head: the head that will follow our entry |
*/ |
static inline void list_move_tail(struct list_head *list, |
struct list_head *head) |
{ |
__list_del(list->prev, list->next); |
list_add_tail(list, head); |
} |
/** |
* list_is_last - tests whether @list is the last entry in list @head |
* @list: the entry to test |
* @head: the head of the list |
*/ |
static inline int list_is_last(const struct list_head *list, |
const struct list_head *head) |
{ |
return list->next == head; |
} |
/** |
* list_empty - tests whether a list is empty |
* @head: the list to test. |
*/ |
static inline int list_empty(const struct list_head *head) |
{ |
return head->next == head; |
} |
/** |
* list_empty_careful - tests whether a list is empty and not being modified |
* @head: the list to test |
* |
* Description: |
* tests whether a list is empty _and_ checks that no other CPU might be |
* in the process of modifying either member (next or prev) |
* |
* NOTE: using list_empty_careful() without synchronization |
* can only be safe if the only activity that can happen |
* to the list entry is list_del_init(). Eg. it cannot be used |
* if another CPU could re-list_add() it. |
*/ |
static inline int list_empty_careful(const struct list_head *head) |
{ |
struct list_head *next = head->next; |
return (next == head) && (next == head->prev); |
} |
/** |
* list_is_singular - tests whether a list has just one entry. |
* @head: the list to test. |
*/ |
static inline int list_is_singular(const struct list_head *head) |
{ |
return !list_empty(head) && (head->next == head->prev); |
} |
static inline void __list_cut_position(struct list_head *list, |
struct list_head *head, struct list_head *entry) |
{ |
struct list_head *new_first = entry->next; |
list->next = head->next; |
list->next->prev = list; |
list->prev = entry; |
entry->next = list; |
head->next = new_first; |
new_first->prev = head; |
} |
/** |
* list_cut_position - cut a list into two |
* @list: a new list to add all removed entries |
* @head: a list with entries |
* @entry: an entry within head, could be the head itself |
* and if so we won't cut the list |
* |
* This helper moves the initial part of @head, up to and |
* including @entry, from @head to @list. You should |
* pass on @entry an element you know is on @head. @list |
* should be an empty list or a list you do not care about |
* losing its data. |
* |
*/ |
static inline void list_cut_position(struct list_head *list, |
struct list_head *head, struct list_head *entry) |
{ |
if (list_empty(head)) |
return; |
if (list_is_singular(head) && |
(head->next != entry && head != entry)) |
return; |
if (entry == head) |
INIT_LIST_HEAD(list); |
else |
__list_cut_position(list, head, entry); |
} |
static inline void __list_splice(const struct list_head *list, |
struct list_head *prev, |
struct list_head *next) |
{ |
struct list_head *first = list->next; |
struct list_head *last = list->prev; |
first->prev = prev; |
prev->next = first; |
last->next = next; |
next->prev = last; |
} |
/** |
* list_splice - join two lists, this is designed for stacks |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
*/ |
static inline void list_splice(const struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) |
__list_splice(list, head, head->next); |
} |
/** |
* list_splice_tail - join two lists, each list being a queue |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
*/ |
static inline void list_splice_tail(struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) |
__list_splice(list, head->prev, head); |
} |
/** |
* list_splice_init - join two lists and reinitialise the emptied list. |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
* |
* The list at @list is reinitialised |
*/ |
static inline void list_splice_init(struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) { |
__list_splice(list, head, head->next); |
INIT_LIST_HEAD(list); |
} |
} |
/** |
* list_splice_tail_init - join two lists and reinitialise the emptied list |
* @list: the new list to add. |
* @head: the place to add it in the first list. |
* |
* Each of the lists is a queue. |
* The list at @list is reinitialised |
*/ |
static inline void list_splice_tail_init(struct list_head *list, |
struct list_head *head) |
{ |
if (!list_empty(list)) { |
__list_splice(list, head->prev, head); |
INIT_LIST_HEAD(list); |
} |
} |
/** |
* list_entry - get the struct for this entry |
* @ptr: the &struct list_head pointer. |
* @type: the type of the struct this is embedded in. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_entry(ptr, type, member) \ |
container_of(ptr, type, member) |
/** |
* list_first_entry - get the first element from a list |
* @ptr: the list head to take the element from. |
* @type: the type of the struct this is embedded in. |
* @member: the name of the list_struct within the struct. |
* |
* Note, that list is expected to be not empty. |
*/ |
#define list_first_entry(ptr, type, member) \ |
list_entry((ptr)->next, type, member) |
/** |
* list_for_each - iterate over a list |
* @pos: the &struct list_head to use as a loop cursor. |
* @head: the head for your list. |
*/ |
#define list_for_each(pos, head) \ |
for (pos = (head)->next; prefetch(pos->next), pos != (head); \ |
pos = pos->next) |
/** |
* __list_for_each - iterate over a list |
* @pos: the &struct list_head to use as a loop cursor. |
* @head: the head for your list. |
* |
* This variant differs from list_for_each() in that it's the |
* simplest possible list iteration code, no prefetching is done. |
* Use this for code that knows the list to be very short (empty |
* or 1 entry) most of the time. |
*/ |
#define __list_for_each(pos, head) \ |
for (pos = (head)->next; pos != (head); pos = pos->next) |
/** |
* list_for_each_prev - iterate over a list backwards |
* @pos: the &struct list_head to use as a loop cursor. |
* @head: the head for your list. |
*/ |
#define list_for_each_prev(pos, head) \ |
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ |
pos = pos->prev) |
/** |
* list_for_each_safe - iterate over a list safe against removal of list entry |
* @pos: the &struct list_head to use as a loop cursor. |
* @n: another &struct list_head to use as temporary storage |
* @head: the head for your list. |
*/ |
#define list_for_each_safe(pos, n, head) \ |
for (pos = (head)->next, n = pos->next; pos != (head); \ |
pos = n, n = pos->next) |
/** |
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry |
* @pos: the &struct list_head to use as a loop cursor. |
* @n: another &struct list_head to use as temporary storage |
* @head: the head for your list. |
*/ |
#define list_for_each_prev_safe(pos, n, head) \ |
for (pos = (head)->prev, n = pos->prev; \ |
prefetch(pos->prev), pos != (head); \ |
pos = n, n = pos->prev) |
/** |
* list_for_each_entry - iterate over list of given type |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_for_each_entry(pos, head, member) \ |
for (pos = list_entry((head)->next, typeof(*pos), member); \ |
prefetch(pos->member.next), &pos->member != (head); \ |
pos = list_entry(pos->member.next, typeof(*pos), member)) |
/** |
* list_for_each_entry_reverse - iterate backwards over list of given type. |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_for_each_entry_reverse(pos, head, member) \ |
for (pos = list_entry((head)->prev, typeof(*pos), member); \ |
prefetch(pos->member.prev), &pos->member != (head); \ |
pos = list_entry(pos->member.prev, typeof(*pos), member)) |
/** |
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() |
* @pos: the type * to use as a start point |
* @head: the head of the list |
* @member: the name of the list_struct within the struct. |
* |
* Prepares a pos entry for use as a start point in list_for_each_entry_continue(). |
*/ |
#define list_prepare_entry(pos, head, member) \ |
((pos) ? : list_entry(head, typeof(*pos), member)) |
/** |
* list_for_each_entry_continue - continue iteration over list of given type |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Continue to iterate over list of given type, continuing after |
* the current position. |
*/ |
#define list_for_each_entry_continue(pos, head, member) \ |
for (pos = list_entry(pos->member.next, typeof(*pos), member); \ |
prefetch(pos->member.next), &pos->member != (head); \ |
pos = list_entry(pos->member.next, typeof(*pos), member)) |
/** |
* list_for_each_entry_continue_reverse - iterate backwards from the given point |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Start to iterate over list of given type backwards, continuing after |
* the current position. |
*/ |
#define list_for_each_entry_continue_reverse(pos, head, member) \ |
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ |
prefetch(pos->member.prev), &pos->member != (head); \ |
pos = list_entry(pos->member.prev, typeof(*pos), member)) |
/** |
* list_for_each_entry_from - iterate over list of given type from the current point |
* @pos: the type * to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate over list of given type, continuing from current position. |
*/ |
#define list_for_each_entry_from(pos, head, member) \ |
for (; prefetch(pos->member.next), &pos->member != (head); \ |
pos = list_entry(pos->member.next, typeof(*pos), member)) |
/** |
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
*/ |
#define list_for_each_entry_safe(pos, n, head, member) \ |
for (pos = list_entry((head)->next, typeof(*pos), member), \ |
n = list_entry(pos->member.next, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
/** |
* list_for_each_entry_safe_continue |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate over list of given type, continuing after current point, |
* safe against removal of list entry. |
*/ |
#define list_for_each_entry_safe_continue(pos, n, head, member) \ |
for (pos = list_entry(pos->member.next, typeof(*pos), member), \ |
n = list_entry(pos->member.next, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
/** |
* list_for_each_entry_safe_from |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate over list of given type from current point, safe against |
* removal of list entry. |
*/ |
#define list_for_each_entry_safe_from(pos, n, head, member) \ |
for (n = list_entry(pos->member.next, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
/** |
* list_for_each_entry_safe_reverse |
* @pos: the type * to use as a loop cursor. |
* @n: another type * to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the list_struct within the struct. |
* |
* Iterate backwards over list of given type, safe against removal |
* of list entry. |
*/ |
#define list_for_each_entry_safe_reverse(pos, n, head, member) \ |
for (pos = list_entry((head)->prev, typeof(*pos), member), \ |
n = list_entry(pos->member.prev, typeof(*pos), member); \ |
&pos->member != (head); \ |
pos = n, n = list_entry(n->member.prev, typeof(*n), member)) |
/* |
* Double linked lists with a single pointer list head. |
* Mostly useful for hash tables where the two pointer list head is |
* too wasteful. |
* You lose the ability to access the tail in O(1). |
*/ |
#if 0 |
struct hlist_head { |
struct hlist_node *first; |
}; |
struct hlist_node { |
struct hlist_node *next, **pprev; |
}; |
#define HLIST_HEAD_INIT { .first = NULL } |
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } |
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) |
static inline void INIT_HLIST_NODE(struct hlist_node *h) |
{ |
h->next = NULL; |
h->pprev = NULL; |
} |
static inline int hlist_unhashed(const struct hlist_node *h) |
{ |
return !h->pprev; |
} |
static inline int hlist_empty(const struct hlist_head *h) |
{ |
return !h->first; |
} |
static inline void __hlist_del(struct hlist_node *n) |
{ |
struct hlist_node *next = n->next; |
struct hlist_node **pprev = n->pprev; |
*pprev = next; |
if (next) |
next->pprev = pprev; |
} |
static inline void hlist_del(struct hlist_node *n) |
{ |
__hlist_del(n); |
n->next = LIST_POISON1; |
n->pprev = LIST_POISON2; |
} |
static inline void hlist_del_init(struct hlist_node *n) |
{ |
if (!hlist_unhashed(n)) { |
__hlist_del(n); |
INIT_HLIST_NODE(n); |
} |
} |
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) |
{ |
struct hlist_node *first = h->first; |
n->next = first; |
if (first) |
first->pprev = &n->next; |
h->first = n; |
n->pprev = &h->first; |
} |
/* next must be != NULL */ |
static inline void hlist_add_before(struct hlist_node *n, |
struct hlist_node *next) |
{ |
n->pprev = next->pprev; |
n->next = next; |
next->pprev = &n->next; |
*(n->pprev) = n; |
} |
static inline void hlist_add_after(struct hlist_node *n, |
struct hlist_node *next) |
{ |
next->next = n->next; |
n->next = next; |
next->pprev = &n->next; |
if(next->next) |
next->next->pprev = &next->next; |
} |
/* |
* Move a list from one list head to another. Fixup the pprev |
* reference of the first entry if it exists. |
*/ |
static inline void hlist_move_list(struct hlist_head *old, |
struct hlist_head *new) |
{ |
new->first = old->first; |
if (new->first) |
new->first->pprev = &new->first; |
old->first = NULL; |
} |
#define hlist_entry(ptr, type, member) container_of(ptr,type,member) |
#define hlist_for_each(pos, head) \ |
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ |
pos = pos->next) |
#define hlist_for_each_safe(pos, n, head) \ |
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ |
pos = n) |
/** |
* hlist_for_each_entry - iterate over list of given type |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @head: the head for your list. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry(tpos, pos, head, member) \ |
for (pos = (head)->first; \ |
pos && ({ prefetch(pos->next); 1;}) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = pos->next) |
/** |
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry_continue(tpos, pos, member) \ |
for (pos = (pos)->next; \ |
pos && ({ prefetch(pos->next); 1;}) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = pos->next) |
/** |
* hlist_for_each_entry_from - iterate over a hlist continuing from current point |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry_from(tpos, pos, member) \ |
for (; pos && ({ prefetch(pos->next); 1;}) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = pos->next) |
/** |
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
* @tpos: the type * to use as a loop cursor. |
* @pos: the &struct hlist_node to use as a loop cursor. |
* @n: another &struct hlist_node to use as temporary storage |
* @head: the head for your list. |
* @member: the name of the hlist_node within the struct. |
*/ |
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ |
for (pos = (head)->first; \ |
pos && ({ n = pos->next; 1; }) && \ |
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ |
pos = n) |
#endif |
#endif |
/drivers/video/drm/include/linux/module.h |
---|
0,0 → 1,5 |
#include <types.h> |
#include <list.h> |
#include <syscall.h> |
/drivers/video/drm/include/linux/sched.h |
---|
0,0 → 1,0 |
/* stub */ |
/drivers/video/drm/include/linux/seq_file.h |
---|
0,0 → 1,0 |
/* stub */ |
/drivers/video/drm/include/linux/types.h |
---|
0,0 → 1,247 |
#ifndef __TYPES_H__ |
#define __TYPES_H__ |
# define __iomem |
# define __force |
# define __user |
# define WARN(condition, format...) |
typedef int bool; |
#define false 0 |
#define true 1 |
typedef int ssize_t; |
typedef long long loff_t; |
typedef unsigned int size_t; |
typedef unsigned int count_t; |
typedef unsigned int addr_t; |
typedef unsigned char u8; |
typedef unsigned short u16; |
typedef unsigned int u32; |
typedef unsigned long long u64; |
typedef unsigned char __u8; |
typedef unsigned short __u16; |
typedef unsigned int __u32; |
typedef unsigned long long __u64; |
typedef signed char __s8; |
typedef signed short __s16; |
typedef signed int __s32; |
typedef signed long long __s64; |
typedef unsigned char uint8_t; |
typedef unsigned short uint16_t; |
typedef unsigned int uint32_t; |
typedef unsigned long long uint64_t; |
typedef unsigned char u8_t; |
typedef unsigned short u16_t; |
typedef unsigned int u32_t; |
typedef unsigned long long u64_t; |
typedef signed char int8_t; |
typedef signed int int32_t; |
typedef signed long long int64_t; |
#define NULL (void*)0 |
typedef uint32_t dma_addr_t; |
typedef uint32_t resource_size_t; |
#define cpu_to_le16(v16) (v16) |
#define cpu_to_le32(v32) (v32) |
#define cpu_to_le64(v64) (v64) |
#define le16_to_cpu(v16) (v16) |
#define le32_to_cpu(v32) (v32) |
#define le64_to_cpu(v64) (v64) |
#define likely(x) __builtin_expect(!!(x), 1) |
#define unlikely(x) __builtin_expect(!!(x), 0) |
#define BITS_PER_LONG 32 |
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) |
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) |
#define DECLARE_BITMAP(name,bits) \ |
unsigned long name[BITS_TO_LONGS(bits)] |
#define KERN_EMERG "<0>" /* system is unusable */ |
#define KERN_ALERT "<1>" /* action must be taken immediately */ |
#define KERN_CRIT "<2>" /* critical conditions */ |
#define KERN_ERR "<3>" /* error conditions */ |
#define KERN_WARNING "<4>" /* warning conditions */ |
#define KERN_NOTICE "<5>" /* normal but significant condition */ |
#define KERN_INFO "<6>" /* informational */ |
#define KERN_DEBUG "<7>" /* debug-level messages */ |
//int printk(const char *fmt, ...); |
#define printk(fmt, arg...) dbgprintf(fmt , ##arg) |
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ |
#define DRM_INFO(fmt, arg...) dbgprintf("DRM: "fmt , ##arg) |
#define DRM_ERROR(fmt, arg...) \ |
printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg) |
#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) |
#define __must_be_array(a) \ |
BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0]))) |
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) |
#ifndef HAVE_ARCH_BUG |
#define BUG() do { \ |
printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \ |
/* panic("BUG!"); */ \ |
} while (0) |
#endif |
#ifndef HAVE_ARCH_BUG_ON |
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0) |
#endif |
#define MTRR_TYPE_UNCACHABLE 0 |
#define MTRR_TYPE_WRCOMB 1 |
#define MTRR_TYPE_WRTHROUGH 4 |
#define MTRR_TYPE_WRPROT 5 |
#define MTRR_TYPE_WRBACK 6 |
#define MTRR_NUM_TYPES 7 |
int dbgprintf(const char* format, ...); |
#define GFP_KERNEL 0 |
//#include <stdio.h> |
int snprintf(char *str, size_t size, const char *format, ...); |
//#include <string.h> |
void* memcpy(void *s1, const void *s2, size_t n); |
void* memset(void *s, int c, size_t n); |
size_t strlen(const char *s); |
char *strcpy(char *s1, const char *s2); |
char *strncpy (char *dst, const char *src, size_t len); |
void *malloc(size_t size); |
#define kmalloc(s,f) malloc((s)) |
#define kfree free |
static inline void *kzalloc(size_t size, u32_t flags) |
{ |
void *ret = malloc(size); |
memset(ret, 0, size); |
return ret; |
} |
struct drm_file; |
#define offsetof(TYPE,MEMBER) __builtin_offsetof(TYPE,MEMBER) |
#define container_of(ptr, type, member) ({ \ |
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ |
(type *)( (char *)__mptr - offsetof(type,member) );}) |
#define DRM_MEMORYBARRIER() __asm__ __volatile__("lock; addl $0,0(%esp)") |
#define mb() __asm__ __volatile__("lock; addl $0,0(%esp)") |
#define PAGE_SHIFT 12 |
#define PAGE_SIZE (1UL << PAGE_SHIFT) |
#define PAGE_MASK (~(PAGE_SIZE-1)) |
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) |
static inline void bitmap_zero(unsigned long *dst, int nbits) |
{ |
if (nbits <= BITS_PER_LONG) |
*dst = 0UL; |
else { |
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); |
memset(dst, 0, len); |
} |
} |
#define EXPORT_SYMBOL(x) |
#define min(x,y) ({ \ |
typeof(x) _x = (x); \ |
typeof(y) _y = (y); \ |
(void) (&_x == &_y); \ |
_x < _y ? _x : _y; }) |
#define max(x,y) ({ \ |
typeof(x) _x = (x); \ |
typeof(y) _y = (y); \ |
(void) (&_x == &_y); \ |
_x > _y ? _x : _y; }) |
extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); |
# define do_div(n,base) ({ \ |
uint32_t __base = (base); \ |
uint32_t __rem; \ |
(void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ |
if (likely(((n) >> 32) == 0)) { \ |
__rem = (uint32_t)(n) % __base; \ |
(n) = (uint32_t)(n) / __base; \ |
} else \ |
__rem = __div64_32(&(n), __base); \ |
__rem; \ |
}) |
#define lower_32_bits(n) ((u32)(n)) |
#define INT_MAX ((int)(~0U>>1)) |
#define INT_MIN (-INT_MAX - 1) |
#define UINT_MAX (~0U) |
#define LONG_MAX ((long)(~0UL>>1)) |
#define LONG_MIN (-LONG_MAX - 1) |
#define ULONG_MAX (~0UL) |
#define LLONG_MAX ((long long)(~0ULL>>1)) |
#define LLONG_MIN (-LLONG_MAX - 1) |
#define ULLONG_MAX (~0ULL) |
static inline void *kcalloc(size_t n, size_t size, u32_t flags) |
{ |
if (n != 0 && size > ULONG_MAX / n) |
return NULL; |
return kzalloc(n * size, 0); |
} |
#define ENTER() dbgprintf("enter %s\n",__FUNCTION__) |
#define LEAVE() dbgprintf("leave %s\n",__FUNCTION__) |
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) |
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) |
#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159 |
#endif //__TYPES_H__ |
/drivers/video/drm/include/syscall.h |
---|
21,7 → 21,7 |
#define ERR_PARAM -1 |
u32_t __stdcall drvEntry(int)__asm__("_drvEntry"); |
u32_t drvEntry(int, char *)__asm__("_drvEntry"); |
/////////////////////////////////////////////////////////////////////////////// |
/drivers/video/drm/radeon/radeon_drm.h |
---|
File deleted |
/drivers/video/drm/radeon/atikms.lds |
---|
20,11 → 20,21 |
*(.data) |
} |
.reloc ALIGN(__section_alignment__) : |
.bss ALIGN(__section_alignment__): |
{ |
*(.reloc) |
*(.bss) |
*(COMMON) |
} |
/DISCARD/ : |
{ |
*(.debug$S) |
*(.debug$T) |
*(.debug$F) |
*(.drectve) |
*(.edata) |
} |
.idata ALIGN(__section_alignment__): |
{ |
SORT(*)(.idata$2) |
37,19 → 47,10 |
SORT(*)(.idata$7) |
} |
.bss ALIGN(__section_alignment__): |
.reloc ALIGN(__section_alignment__) : |
{ |
*(.bss) |
*(COMMON) |
*(.reloc) |
} |
/DISCARD/ : |
{ |
*(.debug$S) |
*(.debug$T) |
*(.debug$F) |
*(.drectve) |
*(.edata) |
} |
} |
/drivers/video/drm/radeon/atom.c |
---|
22,12 → 22,9 |
* Author: Stanislaw Skowronek |
*/ |
//#include <linux/module.h> |
//#include <linux/sched.h> |
#include <linux/module.h> |
#include <linux/sched.h> |
#include <types.h> |
#include <syscall.h> |
#define ATOM_DEBUG |
#include "atom.h" |
1164,9 → 1161,6 |
int atom_asic_init(struct atom_context *ctx) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR); |
uint32_t ps[16]; |
memset(ps, 0, 64); |
/drivers/video/drm/radeon/atom.h |
---|
25,7 → 25,7 |
#ifndef ATOM_H |
#define ATOM_H |
#include <types.h> |
#include <linux/types.h> |
#include "drmP.h" |
#define ATOM_BIOS_MAGIC 0xAA55 |
/drivers/video/drm/radeon/atombios.h |
---|
2374,6 → 2374,17 |
ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING]; |
} ATOM_ANALOG_TV_INFO; |
#define MAX_SUPPORTED_TV_TIMING_V1_2 3 |
typedef struct _ATOM_ANALOG_TV_INFO_V1_2 { |
ATOM_COMMON_TABLE_HEADER sHeader; |
UCHAR ucTV_SupportedStandard; |
UCHAR ucTV_BootUpDefaultStandard; |
UCHAR ucExt_TV_ASIC_ID; |
UCHAR ucExt_TV_ASIC_SlaveAddr; |
ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING]; |
} ATOM_ANALOG_TV_INFO_V1_2; |
/**************************************************************************/ |
/* VRAM usage and their defintions */ |
/drivers/video/drm/radeon/atombios_crtc.c |
---|
23,14 → 23,159 |
* Authors: Dave Airlie |
* Alex Deucher |
*/ |
#include <drmP.h> |
#include <drm_crtc_helper.h> |
#include "radeon_drm.h" |
#include <drm/drmP.h> |
#include <drm/drm_crtc_helper.h> |
#include <drm/radeon_drm.h> |
#include "radeon_fixed.h" |
#include "radeon.h" |
#include "atom.h" |
#include "atom-bits.h" |
/* evil but including atombios.h is much worse */ |
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, |
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, |
int32_t *pixel_clock); |
static void atombios_overscan_setup(struct drm_crtc *crtc, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
SET_CRTC_OVERSCAN_PS_ALLOCATION args; |
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); |
int a1, a2; |
memset(&args, 0, sizeof(args)); |
args.usOverscanRight = 0; |
args.usOverscanLeft = 0; |
args.usOverscanBottom = 0; |
args.usOverscanTop = 0; |
args.ucCRTC = radeon_crtc->crtc_id; |
switch (radeon_crtc->rmx_type) { |
case RMX_CENTER: |
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; |
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; |
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; |
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
break; |
case RMX_ASPECT: |
a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; |
a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; |
if (a1 > a2) { |
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; |
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; |
} else if (a2 > a1) { |
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; |
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; |
} |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
break; |
case RMX_FULL: |
default: |
args.usOverscanRight = 0; |
args.usOverscanLeft = 0; |
args.usOverscanBottom = 0; |
args.usOverscanTop = 0; |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
break; |
} |
} |
static void atombios_scaler_setup(struct drm_crtc *crtc) |
{ |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
ENABLE_SCALER_PS_ALLOCATION args; |
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); |
/* fixme - fill in enc_priv for atom dac */ |
enum radeon_tv_std tv_std = TV_STD_NTSC; |
bool is_tv = false, is_cv = false; |
struct drm_encoder *encoder; |
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) |
return; |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
/* find tv std */ |
if (encoder->crtc == crtc) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { |
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; |
tv_std = tv_dac->tv_std; |
is_tv = true; |
} |
} |
} |
memset(&args, 0, sizeof(args)); |
args.ucScaler = radeon_crtc->crtc_id; |
if (is_tv) { |
switch (tv_std) { |
case TV_STD_NTSC: |
default: |
args.ucTVStandard = ATOM_TV_NTSC; |
break; |
case TV_STD_PAL: |
args.ucTVStandard = ATOM_TV_PAL; |
break; |
case TV_STD_PAL_M: |
args.ucTVStandard = ATOM_TV_PALM; |
break; |
case TV_STD_PAL_60: |
args.ucTVStandard = ATOM_TV_PAL60; |
break; |
case TV_STD_NTSC_J: |
args.ucTVStandard = ATOM_TV_NTSCJ; |
break; |
case TV_STD_SCART_PAL: |
args.ucTVStandard = ATOM_TV_PAL; /* ??? */ |
break; |
case TV_STD_SECAM: |
args.ucTVStandard = ATOM_TV_SECAM; |
break; |
case TV_STD_PAL_CN: |
args.ucTVStandard = ATOM_TV_PALCN; |
break; |
} |
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
} else if (is_cv) { |
args.ucTVStandard = ATOM_TV_CV; |
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
} else { |
switch (radeon_crtc->rmx_type) { |
case RMX_FULL: |
args.ucEnable = ATOM_SCALER_EXPANSION; |
break; |
case RMX_CENTER: |
args.ucEnable = ATOM_SCALER_CENTER; |
break; |
case RMX_ASPECT: |
args.ucEnable = ATOM_SCALER_EXPANSION; |
break; |
default: |
if (ASIC_IS_AVIVO(rdev)) |
args.ucEnable = ATOM_SCALER_DISABLE; |
else |
args.ucEnable = ATOM_SCALER_CENTER; |
break; |
} |
} |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
if ((is_tv || is_cv) |
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) { |
atom_rv515_force_tv_scaler(rdev, radeon_crtc); |
} |
} |
static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
203,6 → 348,12 |
if (ASIC_IS_AVIVO(rdev)) { |
uint32_t ss_cntl; |
if ((rdev->family == CHIP_RS600) || |
(rdev->family == CHIP_RS690) || |
(rdev->family == CHIP_RS740)) |
pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV | |
RADEON_PLL_PREFER_CLOSEST_LOWER); |
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ |
pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
else |
238,6 → 389,7 |
pll_flags |= RADEON_PLL_USE_REF_DIV; |
} |
radeon_encoder = to_radeon_encoder(encoder); |
break; |
} |
} |
321,13 → 473,15 |
struct drm_gem_object *obj; |
struct drm_radeon_gem_object *obj_priv; |
uint64_t fb_location; |
uint32_t fb_format, fb_pitch_pixels; |
uint32_t fb_format, fb_pitch_pixels, tiling_flags; |
ENTRY(); |
if (!crtc->fb) |
return -EINVAL; |
dbgprintf("x = %d y = %d width = %d height = %d\n", |
x, y, crtc->fb->width, crtc->fb->height); |
dbgprintf("hdisplay = %d\n", crtc->mode.hdisplay); |
radeon_fb = to_radeon_framebuffer(crtc->fb); |
obj = radeon_fb->obj; |
340,9 → 494,14 |
fb_location = 0; //rdev->mc.vram_location; |
dbgprintf("fb_location %x\n", fb_location); |
dbgprintf("bpp %x\n", crtc->fb->bits_per_pixel); |
dbgprintf("bpp %d\n", crtc->fb->bits_per_pixel); |
switch (crtc->fb->bits_per_pixel) { |
case 8: |
fb_format = |
AVIVO_D1GRPH_CONTROL_DEPTH_8BPP | |
AVIVO_D1GRPH_CONTROL_8BPP_INDEXED; |
break; |
case 15: |
fb_format = |
AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | |
365,7 → 524,14 |
return -EINVAL; |
} |
/* TODO tiling */ |
// radeon_object_get_tiling_flags(obj->driver_private, |
// &tiling_flags, NULL); |
// if (tiling_flags & RADEON_TILING_MACRO) |
// fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE; |
// if (tiling_flags & RADEON_TILING_MICRO) |
// fb_format |= AVIVO_D1GRPH_TILED; |
if (radeon_crtc->crtc_id == 0) |
WREG32(AVIVO_D1VGA_CONTROL, 0); |
else |
403,10 → 569,9 |
WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); |
if (old_fb && old_fb != crtc->fb) { |
radeon_fb = to_radeon_framebuffer(old_fb); |
// radeon_fb = to_radeon_framebuffer(old_fb); |
// radeon_gem_object_unpin(radeon_fb->obj); |
} |
LEAVE(); |
return 0; |
} |
420,18 → 585,41 |
struct radeon_device *rdev = dev->dev_private; |
struct drm_encoder *encoder; |
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; |
int need_tv_timings = 0; |
bool ret; |
ENTRY(); |
/* TODO color tiling */ |
memset(&crtc_timing, 0, sizeof(crtc_timing)); |
/* TODO tv */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
/* find tv std */ |
if (encoder->crtc == crtc) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { |
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; |
if (tv_dac) { |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M) |
need_tv_timings = 1; |
else |
need_tv_timings = 2; |
break; |
} |
} |
} |
} |
crtc_timing.ucCRTC = radeon_crtc->crtc_id; |
if (need_tv_timings) { |
ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1, |
&crtc_timing, &adjusted_mode->clock); |
if (ret == false) |
need_tv_timings = 0; |
} |
if (!need_tv_timings) { |
crtc_timing.usH_Total = adjusted_mode->crtc_htotal; |
crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay; |
crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start; |
458,6 → 646,7 |
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) |
crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; |
} |
atombios_crtc_set_pll(crtc, adjusted_mode); |
atombios_crtc_set_timing(crtc, &crtc_timing); |
519,8 → 708,9 |
radeon_crtc_set_base(crtc, x, y, old_fb); |
radeon_legacy_atom_set_surface(crtc); |
} |
LEAVE(); |
atombios_overscan_setup(crtc, mode, adjusted_mode); |
atombios_scaler_setup(crtc); |
radeon_bandwidth_update(rdev); |
return 0; |
} |
528,6 → 718,8 |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
return false; |
return true; |
} |
560,150 → 752,3 |
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; |
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); |
} |
void radeon_init_disp_bw_avivo(struct drm_device *dev, |
struct drm_display_mode *mode1, |
uint32_t pixel_bytes1, |
struct drm_display_mode *mode2, |
uint32_t pixel_bytes2) |
{ |
struct radeon_device *rdev = dev->dev_private; |
fixed20_12 min_mem_eff; |
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff; |
fixed20_12 sclk_ff, mclk_ff; |
uint32_t dc_lb_memory_split, temp; |
min_mem_eff.full = rfixed_const_8(0); |
if (rdev->disp_priority == 2) { |
uint32_t mc_init_misc_lat_timer = 0; |
if (rdev->family == CHIP_RV515) |
mc_init_misc_lat_timer = |
RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER); |
else if (rdev->family == CHIP_RS690) |
mc_init_misc_lat_timer = |
RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER); |
mc_init_misc_lat_timer &= |
~(R300_MC_DISP1R_INIT_LAT_MASK << |
R300_MC_DISP1R_INIT_LAT_SHIFT); |
mc_init_misc_lat_timer &= |
~(R300_MC_DISP0R_INIT_LAT_MASK << |
R300_MC_DISP0R_INIT_LAT_SHIFT); |
if (mode2) |
mc_init_misc_lat_timer |= |
(1 << R300_MC_DISP1R_INIT_LAT_SHIFT); |
if (mode1) |
mc_init_misc_lat_timer |= |
(1 << R300_MC_DISP0R_INIT_LAT_SHIFT); |
if (rdev->family == CHIP_RV515) |
WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER, |
mc_init_misc_lat_timer); |
else if (rdev->family == CHIP_RS690) |
WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER, |
mc_init_misc_lat_timer); |
} |
/* |
* determine is there is enough bw for current mode |
*/ |
temp_ff.full = rfixed_const(100); |
mclk_ff.full = rfixed_const(rdev->clock.default_mclk); |
mclk_ff.full = rfixed_div(mclk_ff, temp_ff); |
sclk_ff.full = rfixed_const(rdev->clock.default_sclk); |
sclk_ff.full = rfixed_div(sclk_ff, temp_ff); |
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); |
temp_ff.full = rfixed_const(temp); |
mem_bw.full = rfixed_mul(mclk_ff, temp_ff); |
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); |
pix_clk.full = 0; |
pix_clk2.full = 0; |
peak_disp_bw.full = 0; |
if (mode1) { |
temp_ff.full = rfixed_const(1000); |
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ |
pix_clk.full = rfixed_div(pix_clk, temp_ff); |
temp_ff.full = rfixed_const(pixel_bytes1); |
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); |
} |
if (mode2) { |
temp_ff.full = rfixed_const(1000); |
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ |
pix_clk2.full = rfixed_div(pix_clk2, temp_ff); |
temp_ff.full = rfixed_const(pixel_bytes2); |
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); |
} |
if (peak_disp_bw.full >= mem_bw.full) { |
DRM_ERROR |
("You may not have enough display bandwidth for current mode\n" |
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); |
printk("peak disp bw %d, mem_bw %d\n", |
rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw)); |
} |
/* |
* Line Buffer Setup |
* There is a single line buffer shared by both display controllers. |
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display |
* controllers. The paritioning can either be done manually or via one of four |
* preset allocations specified in bits 1:0: |
* 0 - line buffer is divided in half and shared between each display controller |
* 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 |
* 2 - D1 gets the whole buffer |
* 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 |
* Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode. |
* In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits |
* 14:4; D2 allocation follows D1. |
*/ |
/* is auto or manual better ? */ |
dc_lb_memory_split = |
RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK; |
dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; |
#if 1 |
/* auto */ |
if (mode1 && mode2) { |
if (mode1->hdisplay > mode2->hdisplay) { |
if (mode1->hdisplay > 2560) |
dc_lb_memory_split |= |
AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; |
else |
dc_lb_memory_split |= |
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
} else if (mode2->hdisplay > mode1->hdisplay) { |
if (mode2->hdisplay > 2560) |
dc_lb_memory_split |= |
AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
else |
dc_lb_memory_split |= |
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
} else |
dc_lb_memory_split |= |
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
} else if (mode1) { |
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY; |
} else if (mode2) { |
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
} |
#else |
/* manual */ |
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; |
dc_lb_memory_split &= |
~(AVIVO_DC_LB_DISP1_END_ADR_MASK << |
AVIVO_DC_LB_DISP1_END_ADR_SHIFT); |
if (mode1) { |
dc_lb_memory_split |= |
((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK) |
<< AVIVO_DC_LB_DISP1_END_ADR_SHIFT); |
} else if (mode2) { |
dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); |
} |
#endif |
WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); |
} |
/drivers/video/drm/radeon/avivod.h |
---|
0,0 → 1,69 |
/* |
* Copyright 2009 Advanced Micro Devices, Inc. |
* Copyright 2009 Red Hat Inc. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef AVIVOD_H |
#define AVIVOD_H |
#define D1CRTC_CONTROL 0x6080 |
#define CRTC_EN (1 << 0) |
#define D1CRTC_UPDATE_LOCK 0x60E8 |
#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 |
#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 |
#define D2CRTC_CONTROL 0x6880 |
#define D2CRTC_UPDATE_LOCK 0x68E8 |
#define D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910 |
#define D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918 |
#define D1VGA_CONTROL 0x0330 |
#define DVGA_CONTROL_MODE_ENABLE (1 << 0) |
#define DVGA_CONTROL_TIMING_SELECT (1 << 8) |
#define DVGA_CONTROL_SYNC_POLARITY_SELECT (1 << 9) |
#define DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1 << 10) |
#define DVGA_CONTROL_OVERSCAN_COLOR_EN (1 << 16) |
#define DVGA_CONTROL_ROTATE (1 << 24) |
#define D2VGA_CONTROL 0x0338 |
#define VGA_HDP_CONTROL 0x328 |
#define VGA_MEM_PAGE_SELECT_EN (1 << 0) |
#define VGA_MEMORY_DISABLE (1 << 4) |
#define VGA_RBBM_LOCK_DISABLE (1 << 8) |
#define VGA_SOFT_RESET (1 << 16) |
#define VGA_MEMORY_BASE_ADDRESS 0x0310 |
#define VGA_RENDER_CONTROL 0x0300 |
#define VGA_VSTATUS_CNTL_MASK 0x00030000 |
/* AVIVO disable VGA rendering */ |
static inline void radeon_avivo_vga_render_disable(struct radeon_device *rdev) |
{ |
u32 vga_render; |
vga_render = RREG32(VGA_RENDER_CONTROL); |
vga_render &= ~VGA_VSTATUS_CNTL_MASK; |
WREG32(VGA_RENDER_CONTROL, vga_render); |
} |
#endif |
/drivers/video/drm/radeon/display.h |
---|
0,0 → 1,25 |
typedef struct |
{ |
u32_t width; |
u32_t height; |
u32_t bpp; |
u32_t lfb; |
u32_t pci_fb; |
u32_t gpu_fb; |
u32_t fb_object; |
struct drm_display_mode *mode; |
cursor_t *cursor; |
int (*set_cursor)(); |
int (*show_cursor)(); |
int (*hide_cursor)(); |
int (*move_cursor)(); |
int (*copy)(); |
int (*blit)(); |
}display_t; |
/drivers/video/drm/radeon/makefile |
---|
4,7 → 4,6 |
CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf |
LDFLAGS = -nostdlib -shared -s -Map atikms.map --image-base 0 --file-alignment 512 --section-alignment 4096 |
DRM_TOPDIR = $(CURDIR)/.. |
DRM_INCLUDES = $(DRM_TOPDIR)/include |
14,16 → 13,16 |
NAME:= atikms |
INCLUDES = -I $(DRM_INCLUDES) -I $(DRM_INCLUDES)/ttm |
INCLUDES = -I $(DRM_INCLUDES) -I $(DRM_INCLUDES)/linux -I $(DRM_INCLUDES)/drm |
HFILES:= $(DRM_INCLUDES)/types.h \ |
$(DRM_INCLUDES)/list.h \ |
HFILES:= $(DRM_INCLUDES)/linux/types.h \ |
$(DRM_INCLUDES)/linux/list.h \ |
$(DRM_INCLUDES)/pci.h \ |
$(DRM_INCLUDES)/drm.h \ |
$(DRM_INCLUDES)/drmP.h \ |
$(DRM_INCLUDES)/drm/drmP.h \ |
$(DRM_INCLUDES)/drm_edid.h \ |
$(DRM_INCLUDES)/drm_crtc.h \ |
$(DRM_INCLUDES)/drm_mode.h \ |
$(DRM_INCLUDES)/drm/drm_crtc.h \ |
$(DRM_INCLUDES)/drm/drm_mode.h \ |
$(DRM_INCLUDES)/drm_mm.h \ |
atom.h \ |
radeon.h \ |
36,6 → 35,7 |
$(DRM_TOPDIR)/drm_modes.c \ |
$(DRM_TOPDIR)/drm_crtc.c \ |
$(DRM_TOPDIR)/drm_crtc_helper.c \ |
$(DRM_TOPDIR)/drm_fb_helper.c \ |
$(DRM_TOPDIR)/i2c/i2c-core.c \ |
$(DRM_TOPDIR)/i2c/i2c-algo-bit.c \ |
$(DRM_TOPDIR)/idr.c \ |
52,11 → 52,14 |
radeon_combios.c \ |
radeon_legacy_crtc.c \ |
radeon_legacy_encoders.c \ |
radeon_legacy_tv.c \ |
radeon_display.c \ |
radeon_cursor.c \ |
radeon_object.c \ |
radeon_gart.c \ |
radeon_ring.c \ |
r100.c \ |
r200.c \ |
r300.c \ |
r420.c \ |
rv515.c \ |
71,8 → 74,8 |
SRC_DEP:= |
NAME_OBJS = $(patsubst %.s, %.obj, $(patsubst %.asm, %.obj,\ |
$(patsubst %.c, %.obj, $(NAME_SRC)))) |
NAME_OBJS = $(patsubst %.s, %.o, $(patsubst %.asm, %.o,\ |
$(patsubst %.c, %.o, $(NAME_SRC)))) |
82,5 → 85,5 |
ld -L$(LIBPATH) $(LDFLAGS) -T atikms.lds -o $@ $(NAME_OBJS) vsprintf.obj icompute.obj $(LIBS) |
%.obj : %.c $(HFILES) Makefile |
%.o : %.c $(HFILES) Makefile |
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ -c $< |
/drivers/video/drm/radeon/r100.c |
---|
25,7 → 25,7 |
* Alex Deucher |
* Jerome Glisse |
*/ |
//#include <linux/seq_file.h> |
#include <linux/seq_file.h> |
#include "drmP.h" |
#include "drm.h" |
#include "radeon_drm.h" |
32,12 → 32,16 |
#include "radeon_microcode.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "r100d.h" |
#include "r100_reg_safe.h" |
#include "rn50_reg_safe.h" |
/* This files gather functions specifics to: |
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 |
* |
* Some of these functions might be used by newer ASICs. |
*/ |
int r200_init(struct radeon_device *rdev); |
void r100_hdp_reset(struct radeon_device *rdev); |
void r100_gpu_init(struct radeon_device *rdev); |
int r100_gui_wait_for_idle(struct radeon_device *rdev); |
46,6 → 50,7 |
void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); |
int r100_debugfs_mc_info_init(struct radeon_device *rdev); |
/* |
* PCI GART |
*/ |
57,23 → 62,28 |
* could end up in wrong address. */ |
} |
int r100_pci_gart_enable(struct radeon_device *rdev) |
int r100_pci_gart_init(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
int r; |
if (rdev->gart.table.ram.ptr) { |
WARN(1, "R100 PCI GART already initialized.\n"); |
return 0; |
} |
/* Initialize common gart structure */ |
r = radeon_gart_init(rdev); |
if (r) { |
if (r) |
return r; |
} |
if (rdev->gart.table.ram.ptr == NULL) { |
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
r = radeon_gart_table_ram_alloc(rdev); |
if (r) { |
return r; |
rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; |
rdev->asic->gart_set_page = &r100_pci_gart_set_page; |
return radeon_gart_table_ram_alloc(rdev); |
} |
} |
int r100_pci_gart_enable(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
/* discard memory request outside of configured range */ |
tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; |
WREG32(RADEON_AIC_CNTL, tmp); |
104,24 → 114,21 |
WREG32(RADEON_AIC_HI_ADDR, 0); |
} |
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) |
{ |
if (i < 0 || i > rdev->gart.num_gpu_pages) { |
return -EINVAL; |
} |
rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr); |
rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); |
return 0; |
} |
int r100_gart_enable(struct radeon_device *rdev) |
void r100_pci_gart_fini(struct radeon_device *rdev) |
{ |
if (rdev->flags & RADEON_IS_AGP) { |
r100_pci_gart_disable(rdev); |
return 0; |
radeon_gart_table_ram_free(rdev); |
radeon_gart_fini(rdev); |
} |
return r100_pci_gart_enable(rdev); |
} |
/* |
173,8 → 180,12 |
DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); |
} |
/* Write VRAM size in case we are limiting it */ |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
/* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM, |
* if the aperture is 64MB but we have 32MB VRAM |
* we report only 32MB VRAM but we have to set MC_FB_LOCATION |
* to 64MB, otherwise the gpu accidentially dies */ |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32(RADEON_MC_FB_LOCATION, tmp); |
215,18 → 226,7 |
r100_pci_gart_disable(rdev); |
/* Setup GPU memory space */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
if (rdev->flags & RADEON_IS_AGP) { |
r = radeon_agp_init(rdev); |
if (r) { |
printk(KERN_WARNING "[drm] Disabling AGP\n"); |
rdev->flags &= ~RADEON_IS_AGP; |
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
} else { |
rdev->mc.gtt_location = rdev->mc.agp_base; |
} |
} |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
244,11 → 244,17 |
void r100_mc_fini(struct radeon_device *rdev) |
{ |
r100_pci_gart_disable(rdev); |
// radeon_gart_table_ram_free(rdev); |
// radeon_gart_fini(rdev); |
} |
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) |
{ |
if (crtc == 0) |
return RREG32(RADEON_CRTC_CRNT_FRAME); |
else |
return RREG32(RADEON_CRTC2_CRNT_FRAME); |
} |
/* |
* Fence emission |
*/ |
297,14 → 303,21 |
return r; |
} |
} |
WREG32(0x774, rdev->wb.gpu_addr); |
WREG32(0x70C, rdev->wb.gpu_addr + 1024); |
WREG32(0x770, 0xff); |
WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr); |
WREG32(R_00070C_CP_RB_RPTR_ADDR, |
S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + 1024) >> 2)); |
WREG32(R_000770_SCRATCH_UMSK, 0xff); |
return 0; |
} |
void r100_wb_disable(struct radeon_device *rdev) |
{ |
WREG32(R_000770_SCRATCH_UMSK, 0); |
} |
void r100_wb_fini(struct radeon_device *rdev) |
{ |
r100_wb_disable(rdev); |
if (rdev->wb.wb_obj) { |
// radeon_object_kunmap(rdev->wb.wb_obj); |
// radeon_object_unpin(rdev->wb.wb_obj); |
314,7 → 327,6 |
} |
} |
int r100_copy_blit(struct radeon_device *rdev, |
uint64_t src_offset, |
uint64_t dst_offset, |
393,6 → 405,21 |
/* |
* CP |
*/ |
static int r100_cp_wait_for_idle(struct radeon_device *rdev) |
{ |
unsigned i; |
u32 tmp; |
for (i = 0; i < rdev->usec_timeout; i++) { |
tmp = RREG32(R_000E40_RBBM_STATUS); |
if (!G_000E40_CP_CMDSTRM_BUSY(tmp)) { |
return 0; |
} |
udelay(1); |
} |
return -1; |
} |
void r100_ring_start(struct radeon_device *rdev) |
{ |
int r; |
483,6 → 510,12 |
} |
} |
static int r100_cp_init_microcode(struct radeon_device *rdev) |
{ |
return 0; |
} |
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) |
{ |
unsigned rb_bufsz; |
517,6 → 550,15 |
} else { |
DRM_INFO("radeon: cp idle (0x%08X)\n", tmp); |
} |
if (!rdev->me_fw) { |
r = r100_cp_init_microcode(rdev); |
if (r) { |
DRM_ERROR("Failed to load firmware!\n"); |
return r; |
} |
} |
/* Align ring size */ |
rb_bufsz = drm_order(ring_size / 8); |
ring_size = (1 << (rb_bufsz + 1)) * 4; |
588,12 → 630,13 |
return 0; |
} |
void r100_cp_fini(struct radeon_device *rdev) |
{ |
if (r100_cp_wait_for_idle(rdev)) { |
DRM_ERROR("Wait for CP idle timeout, shutting down CP.\n"); |
} |
/* Disable ring */ |
rdev->cp.ready = false; |
WREG32(RADEON_CP_CSQ_CNTL, 0); |
r100_cp_disable(rdev); |
radeon_ring_fini(rdev); |
DRM_INFO("radeon: cp finalized\n"); |
} |
610,7 → 653,6 |
} |
} |
int r100_cp_reset(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
617,9 → 659,8 |
bool reinit_cp; |
int i; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
reinit_cp = rdev->cp.ready; |
rdev->cp.ready = false; |
WREG32(RADEON_CP_CSQ_MODE, 0); |
647,6 → 688,13 |
return -1; |
} |
void r100_cp_commit(struct radeon_device *rdev) |
{ |
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr); |
(void)RREG32(RADEON_CP_RB_WPTR); |
} |
#if 0 |
/* |
* CS functions |
725,7 → 773,7 |
unsigned idx) |
{ |
struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; |
uint32_t header = ib_chunk->kdata[idx]; |
uint32_t header; |
if (idx >= ib_chunk->length_dw) { |
DRM_ERROR("Can not parse packet at %d after CS end %d !\n", |
732,6 → 780,7 |
idx, ib_chunk->length_dw); |
return -EINVAL; |
} |
header = ib_chunk->kdata[idx]; |
pkt->idx = idx; |
pkt->type = CP_PACKET_GET_TYPE(header); |
pkt->count = CP_PACKET_GET_COUNT(header); |
759,6 → 808,102 |
} |
/** |
* r100_cs_packet_next_vline() - parse userspace VLINE packet |
* @parser: parser structure holding parsing context. |
* |
* Userspace sends a special sequence for VLINE waits. |
* PACKET0 - VLINE_START_END + value |
* PACKET0 - WAIT_UNTIL +_value |
* RELOC (P3) - crtc_id in reloc. |
* |
* This function parses this and relocates the VLINE START END |
* and WAIT UNTIL packets to the correct crtc. |
* It also detects a switched off crtc and nulls out the |
* wait in that case. |
*/ |
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct drm_mode_object *obj; |
struct drm_crtc *crtc; |
struct radeon_crtc *radeon_crtc; |
struct radeon_cs_packet p3reloc, waitreloc; |
int crtc_id; |
int r; |
uint32_t header, h_idx, reg; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
/* parse the wait until */ |
r = r100_cs_packet_parse(p, &waitreloc, p->idx); |
if (r) |
return r; |
/* check its a wait until and only 1 count */ |
if (waitreloc.reg != RADEON_WAIT_UNTIL || |
waitreloc.count != 0) { |
DRM_ERROR("vline wait had illegal wait until segment\n"); |
r = -EINVAL; |
return r; |
} |
if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { |
DRM_ERROR("vline wait had illegal wait until\n"); |
r = -EINVAL; |
return r; |
} |
/* jump over the NOP */ |
r = r100_cs_packet_parse(p, &p3reloc, p->idx); |
if (r) |
return r; |
h_idx = p->idx - 2; |
p->idx += waitreloc.count; |
p->idx += p3reloc.count; |
header = ib_chunk->kdata[h_idx]; |
crtc_id = ib_chunk->kdata[h_idx + 5]; |
reg = ib_chunk->kdata[h_idx] >> 2; |
mutex_lock(&p->rdev->ddev->mode_config.mutex); |
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); |
if (!obj) { |
DRM_ERROR("cannot find crtc %d\n", crtc_id); |
r = -EINVAL; |
goto out; |
} |
crtc = obj_to_crtc(obj); |
radeon_crtc = to_radeon_crtc(crtc); |
crtc_id = radeon_crtc->crtc_id; |
if (!crtc->enabled) { |
/* if the CRTC isn't enabled - we need to nop out the wait until */ |
ib_chunk->kdata[h_idx + 2] = PACKET2(0); |
ib_chunk->kdata[h_idx + 3] = PACKET2(0); |
} else if (crtc_id == 1) { |
switch (reg) { |
case AVIVO_D1MODE_VLINE_START_END: |
header &= R300_CP_PACKET0_REG_MASK; |
header |= AVIVO_D2MODE_VLINE_START_END >> 2; |
break; |
case RADEON_CRTC_GUI_TRIG_VLINE: |
header &= R300_CP_PACKET0_REG_MASK; |
header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; |
break; |
default: |
DRM_ERROR("unknown crtc reloc\n"); |
r = -EINVAL; |
goto out; |
} |
ib_chunk->kdata[h_idx] = header; |
ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; |
} |
out: |
mutex_unlock(&p->rdev->ddev->mode_config.mutex); |
return r; |
} |
/** |
* r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 |
* @parser: parser structure holding parsing context. |
* @data: pointer to relocation data |
808,33 → 953,95 |
return 0; |
} |
static int r100_get_vtx_size(uint32_t vtx_fmt) |
{ |
int vtx_size; |
vtx_size = 2; |
/* ordered according to bits in spec */ |
if (vtx_fmt & RADEON_SE_VTX_FMT_W0) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_FPCOLOR) |
vtx_size += 3; |
if (vtx_fmt & RADEON_SE_VTX_FMT_FPALPHA) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_PKCOLOR) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_FPSPEC) |
vtx_size += 3; |
if (vtx_fmt & RADEON_SE_VTX_FMT_FPFOG) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_PKSPEC) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_ST0) |
vtx_size += 2; |
if (vtx_fmt & RADEON_SE_VTX_FMT_ST1) |
vtx_size += 2; |
if (vtx_fmt & RADEON_SE_VTX_FMT_Q1) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_ST2) |
vtx_size += 2; |
if (vtx_fmt & RADEON_SE_VTX_FMT_Q2) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_ST3) |
vtx_size += 2; |
if (vtx_fmt & RADEON_SE_VTX_FMT_Q3) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_Q0) |
vtx_size++; |
/* blend weight */ |
if (vtx_fmt & (0x7 << 15)) |
vtx_size += (vtx_fmt >> 15) & 0x7; |
if (vtx_fmt & RADEON_SE_VTX_FMT_N0) |
vtx_size += 3; |
if (vtx_fmt & RADEON_SE_VTX_FMT_XY1) |
vtx_size += 2; |
if (vtx_fmt & RADEON_SE_VTX_FMT_Z1) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_W1) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_N1) |
vtx_size++; |
if (vtx_fmt & RADEON_SE_VTX_FMT_Z) |
vtx_size++; |
return vtx_size; |
} |
static int r100_packet0_check(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt) |
struct radeon_cs_packet *pkt, |
unsigned idx, unsigned reg) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r100_cs_track *track; |
volatile uint32_t *ib; |
uint32_t tmp; |
unsigned reg; |
unsigned i; |
unsigned idx; |
bool onereg; |
int r; |
int i, face; |
u32 tile_flags = 0; |
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
idx = pkt->idx + 1; |
reg = pkt->reg; |
onereg = false; |
if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) { |
onereg = true; |
track = (struct r100_cs_track *)p->track; |
switch (reg) { |
case RADEON_CRTC_GUI_TRIG_VLINE: |
r = r100_cs_packet_parse_vline(p); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { |
switch (reg) { |
break; |
/* FIXME: only allow PACKET3 blit? easier to check for out of |
* range access */ |
case RADEON_DST_PITCH_OFFSET: |
case RADEON_SRC_PITCH_OFFSET: |
r = r100_reloc_pitch_offset(p, pkt, idx, reg); |
if (r) |
return r; |
break; |
case RADEON_RB3D_DEPTHOFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
842,39 → 1049,26 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
tmp = ib_chunk->kdata[idx] & 0x003fffff; |
tmp += (((u32)reloc->lobj.gpu_offset) >> 10); |
ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; |
track->zb.robj = reloc->robj; |
track->zb.offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_RB3D_DEPTHOFFSET: |
case RADEON_RB3D_COLOROFFSET: |
case R300_RB3D_COLOROFFSET0: |
case R300_ZB_DEPTHOFFSET: |
case R200_PP_TXOFFSET_0: |
case R200_PP_TXOFFSET_1: |
case R200_PP_TXOFFSET_2: |
case R200_PP_TXOFFSET_3: |
case R200_PP_TXOFFSET_4: |
case R200_PP_TXOFFSET_5: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->cb[0].robj = reloc->robj; |
track->cb[0].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_PP_TXOFFSET_0: |
case RADEON_PP_TXOFFSET_1: |
case RADEON_PP_TXOFFSET_2: |
case R300_TX_OFFSET_0: |
case R300_TX_OFFSET_0+4: |
case R300_TX_OFFSET_0+8: |
case R300_TX_OFFSET_0+12: |
case R300_TX_OFFSET_0+16: |
case R300_TX_OFFSET_0+20: |
case R300_TX_OFFSET_0+24: |
case R300_TX_OFFSET_0+28: |
case R300_TX_OFFSET_0+32: |
case R300_TX_OFFSET_0+36: |
case R300_TX_OFFSET_0+40: |
case R300_TX_OFFSET_0+44: |
case R300_TX_OFFSET_0+48: |
case R300_TX_OFFSET_0+52: |
case R300_TX_OFFSET_0+56: |
case R300_TX_OFFSET_0+60: |
i = (reg - RADEON_PP_TXOFFSET_0) / 24; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
883,16 → 1077,233 |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[i].robj = reloc->robj; |
break; |
case RADEON_PP_CUBIC_OFFSET_T0_0: |
case RADEON_PP_CUBIC_OFFSET_T0_1: |
case RADEON_PP_CUBIC_OFFSET_T0_2: |
case RADEON_PP_CUBIC_OFFSET_T0_3: |
case RADEON_PP_CUBIC_OFFSET_T0_4: |
i = (reg - RADEON_PP_CUBIC_OFFSET_T0_0) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[0].cube_info[i].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[0].cube_info[i].robj = reloc->robj; |
break; |
case RADEON_PP_CUBIC_OFFSET_T1_0: |
case RADEON_PP_CUBIC_OFFSET_T1_1: |
case RADEON_PP_CUBIC_OFFSET_T1_2: |
case RADEON_PP_CUBIC_OFFSET_T1_3: |
case RADEON_PP_CUBIC_OFFSET_T1_4: |
i = (reg - RADEON_PP_CUBIC_OFFSET_T1_0) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[1].cube_info[i].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[1].cube_info[i].robj = reloc->robj; |
break; |
case RADEON_PP_CUBIC_OFFSET_T2_0: |
case RADEON_PP_CUBIC_OFFSET_T2_1: |
case RADEON_PP_CUBIC_OFFSET_T2_2: |
case RADEON_PP_CUBIC_OFFSET_T2_3: |
case RADEON_PP_CUBIC_OFFSET_T2_4: |
i = (reg - RADEON_PP_CUBIC_OFFSET_T2_0) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[2].cube_info[i].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[2].cube_info[i].robj = reloc->robj; |
break; |
case RADEON_RE_WIDTH_HEIGHT: |
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF); |
break; |
case RADEON_RB3D_COLORPITCH: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) |
tile_flags |= RADEON_COLOR_TILE_ENABLE; |
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; |
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); |
tmp |= tile_flags; |
ib[idx] = tmp; |
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK; |
break; |
case RADEON_RB3D_DEPTHPITCH: |
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK; |
break; |
case RADEON_RB3D_CNTL: |
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { |
case 7: |
case 8: |
case 9: |
case 11: |
case 12: |
track->cb[0].cpp = 1; |
break; |
case 3: |
case 4: |
case 15: |
track->cb[0].cpp = 2; |
break; |
case 6: |
track->cb[0].cpp = 4; |
break; |
default: |
/* FIXME: we don't want to allow anyothers packet */ |
DRM_ERROR("Invalid color buffer format (%d) !\n", |
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); |
return -EINVAL; |
} |
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE); |
break; |
case RADEON_RB3D_ZSTENCILCNTL: |
switch (ib_chunk->kdata[idx] & 0xf) { |
case 0: |
track->zb.cpp = 2; |
break; |
case 2: |
case 3: |
case 4: |
case 5: |
case 9: |
case 11: |
track->zb.cpp = 4; |
break; |
default: |
break; |
} |
if (onereg) { |
/* FIXME: forbid onereg write to register on relocate */ |
break; |
case RADEON_RB3D_ZPASS_ADDR: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_PP_CNTL: |
{ |
uint32_t temp = ib_chunk->kdata[idx] >> 4; |
for (i = 0; i < track->num_texture; i++) |
track->textures[i].enabled = !!(temp & (1 << i)); |
} |
break; |
case RADEON_SE_VF_CNTL: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
break; |
case RADEON_SE_VTX_FMT: |
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx]); |
break; |
case RADEON_PP_TEX_SIZE_0: |
case RADEON_PP_TEX_SIZE_1: |
case RADEON_PP_TEX_SIZE_2: |
i = (reg - RADEON_PP_TEX_SIZE_0) / 8; |
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1; |
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; |
break; |
case RADEON_PP_TEX_PITCH_0: |
case RADEON_PP_TEX_PITCH_1: |
case RADEON_PP_TEX_PITCH_2: |
i = (reg - RADEON_PP_TEX_PITCH_0) / 8; |
track->textures[i].pitch = ib_chunk->kdata[idx] + 32; |
break; |
case RADEON_PP_TXFILTER_0: |
case RADEON_PP_TXFILTER_1: |
case RADEON_PP_TXFILTER_2: |
i = (reg - RADEON_PP_TXFILTER_0) / 24; |
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & RADEON_MAX_MIP_LEVEL_MASK) |
>> RADEON_MAX_MIP_LEVEL_SHIFT); |
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7; |
if (tmp == 2 || tmp == 6) |
track->textures[i].roundup_w = false; |
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7; |
if (tmp == 2 || tmp == 6) |
track->textures[i].roundup_h = false; |
break; |
case RADEON_PP_TXFORMAT_0: |
case RADEON_PP_TXFORMAT_1: |
case RADEON_PP_TXFORMAT_2: |
i = (reg - RADEON_PP_TXFORMAT_0) / 24; |
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_NON_POWER2) { |
track->textures[i].use_pitch = 1; |
} else { |
track->textures[i].use_pitch = 0; |
track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); |
track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); |
} |
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) |
track->textures[i].tex_coord_type = 2; |
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) { |
case RADEON_TXFORMAT_I8: |
case RADEON_TXFORMAT_RGB332: |
case RADEON_TXFORMAT_Y8: |
track->textures[i].cpp = 1; |
break; |
case RADEON_TXFORMAT_AI88: |
case RADEON_TXFORMAT_ARGB1555: |
case RADEON_TXFORMAT_RGB565: |
case RADEON_TXFORMAT_ARGB4444: |
case RADEON_TXFORMAT_VYUY422: |
case RADEON_TXFORMAT_YVYU422: |
case RADEON_TXFORMAT_DXT1: |
case RADEON_TXFORMAT_SHADOW16: |
case RADEON_TXFORMAT_LDUDV655: |
case RADEON_TXFORMAT_DUDV88: |
track->textures[i].cpp = 2; |
break; |
case RADEON_TXFORMAT_ARGB8888: |
case RADEON_TXFORMAT_RGBA8888: |
case RADEON_TXFORMAT_DXT23: |
case RADEON_TXFORMAT_DXT45: |
case RADEON_TXFORMAT_SHADOW32: |
case RADEON_TXFORMAT_LDUDUV8888: |
track->textures[i].cpp = 4; |
break; |
} |
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf); |
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf); |
break; |
case RADEON_PP_CUBIC_FACES_0: |
case RADEON_PP_CUBIC_FACES_1: |
case RADEON_PP_CUBIC_FACES_2: |
tmp = ib_chunk->kdata[idx]; |
i = (reg - RADEON_PP_CUBIC_FACES_0) / 4; |
for (face = 0; face < 4; face++) { |
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); |
track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf); |
} |
break; |
default: |
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", |
reg, idx); |
return -EINVAL; |
} |
return 0; |
} |
920,6 → 1331,7 |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r100_cs_track *track; |
unsigned idx; |
unsigned i, c; |
volatile uint32_t *ib; |
928,9 → 1340,11 |
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
idx = pkt->idx + 1; |
track = (struct r100_cs_track *)p->track; |
switch (pkt->opcode) { |
case PACKET3_3D_LOAD_VBPNTR: |
c = ib_chunk->kdata[idx++]; |
track->num_arrays = c; |
for (i = 0; i < (c - 1); i += 2, idx += 3) { |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
940,6 → 1354,9 |
return r; |
} |
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); |
track->arrays[i + 0].robj = reloc->robj; |
track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8; |
track->arrays[i + 0].esize &= 0x7F; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for packet3 %d\n", |
948,6 → 1365,9 |
return r; |
} |
ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); |
track->arrays[i + 1].robj = reloc->robj; |
track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24; |
track->arrays[i + 1].esize &= 0x7F; |
} |
if (c & 1) { |
r = r100_cs_packet_next_reloc(p, &reloc); |
958,6 → 1378,9 |
return r; |
} |
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); |
track->arrays[i + 0].robj = reloc->robj; |
track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8; |
track->arrays[i + 0].esize &= 0x7F; |
} |
break; |
case PACKET3_INDX_BUFFER: |
974,7 → 1397,6 |
} |
break; |
case 0x23: |
/* FIXME: cleanup */ |
/* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
983,18 → 1405,71 |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->num_arrays = 1; |
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx+2]); |
track->arrays[0].robj = reloc->robj; |
track->arrays[0].esize = track->vtx_size; |
track->max_indx = ib_chunk->kdata[idx+1]; |
track->vap_vf_cntl = ib_chunk->kdata[idx+3]; |
track->immd_dwords = pkt->count - 1; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
case PACKET3_3D_DRAW_IMMD: |
if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) { |
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); |
return -EINVAL; |
} |
track->vap_vf_cntl = ib_chunk->kdata[idx+1]; |
track->immd_dwords = pkt->count - 1; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
/* triggers drawing using in-packet vertex data */ |
case PACKET3_3D_DRAW_IMMD_2: |
if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) { |
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); |
return -EINVAL; |
} |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
track->immd_dwords = pkt->count; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
/* triggers drawing using in-packet vertex data */ |
case PACKET3_3D_DRAW_VBUF_2: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
/* triggers drawing of vertex buffers setup elsewhere */ |
case PACKET3_3D_DRAW_INDX_2: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
/* triggers drawing using indices to vertex buffer */ |
case PACKET3_3D_DRAW_VBUF: |
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
/* triggers drawing of vertex buffers setup elsewhere */ |
case PACKET3_3D_DRAW_INDX: |
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; |
r = r100_cs_track_check(p->rdev, track); |
if (r) |
return r; |
break; |
/* triggers drawing using indices to vertex buffer */ |
case PACKET3_NOP: |
break; |
1008,8 → 1483,12 |
int r100_cs_parse(struct radeon_cs_parser *p) |
{ |
struct radeon_cs_packet pkt; |
struct r100_cs_track *track; |
int r; |
track = kzalloc(sizeof(*track), GFP_KERNEL); |
r100_cs_track_clear(p->rdev, track); |
p->track = track; |
do { |
r = r100_cs_packet_parse(p, &pkt, p->idx); |
if (r) { |
1018,7 → 1497,16 |
p->idx += pkt.count + 2; |
switch (pkt.type) { |
case PACKET_TYPE0: |
r = r100_packet0_check(p, &pkt); |
if (p->rdev->family >= CHIP_R200) |
r = r100_cs_parse_packet0(p, &pkt, |
p->rdev->config.r100.reg_safe_bm, |
p->rdev->config.r100.reg_safe_bm_size, |
&r200_packet0_check); |
else |
r = r100_cs_parse_packet0(p, &pkt, |
p->rdev->config.r100.reg_safe_bm, |
p->rdev->config.r100.reg_safe_bm_size, |
&r100_packet0_check); |
break; |
case PACKET_TYPE2: |
break; |
1057,8 → 1545,6 |
} |
} |
/* Wait for vertical sync on primary CRTC */ |
void r100_gpu_wait_for_vsync(struct radeon_device *rdev) |
{ |
1163,7 → 1649,7 |
{ |
uint32_t tmp; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; |
tmp |= (7 << 28); |
1180,7 → 1666,7 |
uint32_t tmp; |
int i; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2); |
(void)RREG32(RADEON_RBBM_SOFT_RESET); |
1269,31 → 1755,117 |
} |
} |
void r100_vram_info(struct radeon_device *rdev) |
static u32 r100_get_accessible_vram(struct radeon_device *rdev) |
{ |
r100_vram_get_type(rdev); |
u32 aper_size; |
u8 byte; |
aper_size = RREG32(RADEON_CONFIG_APER_SIZE); |
/* Set HDP_APER_CNTL only on cards that are known not to be broken, |
* that is has the 2nd generation multifunction PCI interface |
*/ |
if (rdev->family == CHIP_RV280 || |
rdev->family >= CHIP_RV350) { |
WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, |
~RADEON_HDP_APER_CNTL); |
DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); |
return aper_size * 2; |
} |
/* Older cards have all sorts of funny issues to deal with. First |
* check if it's a multifunction card by reading the PCI config |
* header type... Limit those to one aperture size |
*/ |
// pci_read_config_byte(rdev->pdev, 0xe, &byte); |
// if (byte & 0x80) { |
// DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); |
// DRM_INFO("Limiting VRAM to one aperture\n"); |
// return aper_size; |
// } |
/* Single function older card. We read HDP_APER_CNTL to see how the BIOS |
* have set it up. We don't write this as it's broken on some ASICs but |
* we expect the BIOS to have done the right thing (might be too optimistic...) |
*/ |
if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) |
return aper_size * 2; |
return aper_size; |
} |
void r100_vram_init_sizes(struct radeon_device *rdev) |
{ |
u64 config_aper_size; |
u32 accessible; |
config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); |
if (rdev->flags & RADEON_IS_IGP) { |
uint32_t tom; |
/* read NB_TOM to get the amount of ram stolen for the GPU */ |
tom = RREG32(RADEON_NB_TOM); |
rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); |
rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); |
/* for IGPs we need to keep VRAM where it was put by the BIOS */ |
rdev->mc.vram_location = (tom & 0xffff) << 16; |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
rdev->mc.mc_vram_size = rdev->mc.real_vram_size; |
} else { |
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
/* Some production boards of m6 will report 0 |
* if it's 8 MB |
*/ |
if (rdev->mc.vram_size == 0) { |
rdev->mc.vram_size = 8192 * 1024; |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); |
if (rdev->mc.real_vram_size == 0) { |
rdev->mc.real_vram_size = 8192 * 1024; |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
} |
/* let driver place VRAM */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - |
* Novell bug 204882 + along with lots of ubuntu ones */ |
if (config_aper_size > rdev->mc.real_vram_size) |
rdev->mc.mc_vram_size = config_aper_size; |
else |
rdev->mc.mc_vram_size = rdev->mc.real_vram_size; |
} |
/* work out accessible VRAM */ |
accessible = r100_get_accessible_vram(rdev); |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
if (accessible > rdev->mc.aper_size) |
accessible = rdev->mc.aper_size; |
if (rdev->mc.mc_vram_size > rdev->mc.aper_size) |
rdev->mc.mc_vram_size = rdev->mc.aper_size; |
if (rdev->mc.real_vram_size > rdev->mc.aper_size) |
rdev->mc.real_vram_size = rdev->mc.aper_size; |
} |
void r100_vga_set_state(struct radeon_device *rdev, bool state) |
{ |
uint32_t temp; |
temp = RREG32(RADEON_CONFIG_CNTL); |
if (state == false) { |
temp &= ~(1<<8); |
temp |= (1<<9); |
} else { |
temp &= ~(1<<9); |
} |
WREG32(RADEON_CONFIG_CNTL, temp); |
} |
void r100_vram_info(struct radeon_device *rdev) |
{ |
r100_vram_get_type(rdev); |
r100_vram_init_sizes(rdev); |
} |
/* |
* Indirect registers accessor |
*/ |
1350,28 → 1922,17 |
r100_pll_errata_after_data(rdev); |
} |
uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) |
int r100_init(struct radeon_device *rdev) |
{ |
if (reg < 0x10000) |
return readl(((void __iomem *)rdev->rmmio) + reg); |
else { |
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); |
if (ASIC_IS_RN50(rdev)) { |
rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm; |
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(rn50_reg_safe_bm); |
} else if (rdev->family < CHIP_R200) { |
rdev->config.r100.reg_safe_bm = r100_reg_safe_bm; |
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r100_reg_safe_bm); |
} else { |
return r200_init(rdev); |
} |
} |
void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
{ |
if (reg < 0x10000) |
writel(v, ((void __iomem *)rdev->rmmio) + reg); |
else { |
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); |
} |
} |
int r100_init(struct radeon_device *rdev) |
{ |
return 0; |
} |
1545,3 → 2106,611 |
return 0; |
#endif |
} |
int r100_set_surface_reg(struct radeon_device *rdev, int reg, |
uint32_t tiling_flags, uint32_t pitch, |
uint32_t offset, uint32_t obj_size) |
{ |
int surf_index = reg * 16; |
int flags = 0; |
/* r100/r200 divide by 16 */ |
if (rdev->family < CHIP_R300) |
flags = pitch / 16; |
else |
flags = pitch / 8; |
if (rdev->family <= CHIP_RS200) { |
if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) |
== (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) |
flags |= RADEON_SURF_TILE_COLOR_BOTH; |
if (tiling_flags & RADEON_TILING_MACRO) |
flags |= RADEON_SURF_TILE_COLOR_MACRO; |
} else if (rdev->family <= CHIP_RV280) { |
if (tiling_flags & (RADEON_TILING_MACRO)) |
flags |= R200_SURF_TILE_COLOR_MACRO; |
if (tiling_flags & RADEON_TILING_MICRO) |
flags |= R200_SURF_TILE_COLOR_MICRO; |
} else { |
if (tiling_flags & RADEON_TILING_MACRO) |
flags |= R300_SURF_TILE_MACRO; |
if (tiling_flags & RADEON_TILING_MICRO) |
flags |= R300_SURF_TILE_MICRO; |
} |
if (tiling_flags & RADEON_TILING_SWAP_16BIT) |
flags |= RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; |
if (tiling_flags & RADEON_TILING_SWAP_32BIT) |
flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; |
DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); |
WREG32(RADEON_SURFACE0_INFO + surf_index, flags); |
WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); |
WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); |
return 0; |
} |
void r100_clear_surface_reg(struct radeon_device *rdev, int reg) |
{ |
int surf_index = reg * 16; |
WREG32(RADEON_SURFACE0_INFO + surf_index, 0); |
} |
void r100_bandwidth_update(struct radeon_device *rdev) |
{ |
fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; |
fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; |
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; |
uint32_t temp, data, mem_trcd, mem_trp, mem_tras; |
fixed20_12 memtcas_ff[8] = { |
fixed_init(1), |
fixed_init(2), |
fixed_init(3), |
fixed_init(0), |
fixed_init_half(1), |
fixed_init_half(2), |
fixed_init(0), |
}; |
fixed20_12 memtcas_rs480_ff[8] = { |
fixed_init(0), |
fixed_init(1), |
fixed_init(2), |
fixed_init(3), |
fixed_init(0), |
fixed_init_half(1), |
fixed_init_half(2), |
fixed_init_half(3), |
}; |
fixed20_12 memtcas2_ff[8] = { |
fixed_init(0), |
fixed_init(1), |
fixed_init(2), |
fixed_init(3), |
fixed_init(4), |
fixed_init(5), |
fixed_init(6), |
fixed_init(7), |
}; |
fixed20_12 memtrbs[8] = { |
fixed_init(1), |
fixed_init_half(1), |
fixed_init(2), |
fixed_init_half(2), |
fixed_init(3), |
fixed_init_half(3), |
fixed_init(4), |
fixed_init_half(4) |
}; |
fixed20_12 memtrbs_r4xx[8] = { |
fixed_init(4), |
fixed_init(5), |
fixed_init(6), |
fixed_init(7), |
fixed_init(8), |
fixed_init(9), |
fixed_init(10), |
fixed_init(11) |
}; |
fixed20_12 min_mem_eff; |
fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; |
fixed20_12 cur_latency_mclk, cur_latency_sclk; |
fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, |
disp_drain_rate2, read_return_rate; |
fixed20_12 time_disp1_drop_priority; |
int c; |
int cur_size = 16; /* in octawords */ |
int critical_point = 0, critical_point2; |
/* uint32_t read_return_rate, time_disp1_drop_priority; */ |
int stop_req, max_stop_req; |
struct drm_display_mode *mode1 = NULL; |
struct drm_display_mode *mode2 = NULL; |
uint32_t pixel_bytes1 = 0; |
uint32_t pixel_bytes2 = 0; |
if (rdev->mode_info.crtcs[0]->base.enabled) { |
mode1 = &rdev->mode_info.crtcs[0]->base.mode; |
pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; |
} |
if (rdev->mode_info.crtcs[1]->base.enabled) { |
mode2 = &rdev->mode_info.crtcs[1]->base.mode; |
pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; |
} |
min_mem_eff.full = rfixed_const_8(0); |
/* get modes */ |
if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { |
uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); |
mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); |
mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); |
/* check crtc enables */ |
if (mode2) |
mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); |
if (mode1) |
mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); |
WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); |
} |
/* |
* determine is there is enough bw for current mode |
*/ |
mclk_ff.full = rfixed_const(rdev->clock.default_mclk); |
temp_ff.full = rfixed_const(100); |
mclk_ff.full = rfixed_div(mclk_ff, temp_ff); |
sclk_ff.full = rfixed_const(rdev->clock.default_sclk); |
sclk_ff.full = rfixed_div(sclk_ff, temp_ff); |
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); |
temp_ff.full = rfixed_const(temp); |
mem_bw.full = rfixed_mul(mclk_ff, temp_ff); |
pix_clk.full = 0; |
pix_clk2.full = 0; |
peak_disp_bw.full = 0; |
if (mode1) { |
temp_ff.full = rfixed_const(1000); |
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ |
pix_clk.full = rfixed_div(pix_clk, temp_ff); |
temp_ff.full = rfixed_const(pixel_bytes1); |
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); |
} |
if (mode2) { |
temp_ff.full = rfixed_const(1000); |
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ |
pix_clk2.full = rfixed_div(pix_clk2, temp_ff); |
temp_ff.full = rfixed_const(pixel_bytes2); |
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); |
} |
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); |
if (peak_disp_bw.full >= mem_bw.full) { |
DRM_ERROR("You may not have enough display bandwidth for current mode\n" |
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); |
} |
/* Get values from the EXT_MEM_CNTL register...converting its contents. */ |
temp = RREG32(RADEON_MEM_TIMING_CNTL); |
if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ |
mem_trcd = ((temp >> 2) & 0x3) + 1; |
mem_trp = ((temp & 0x3)) + 1; |
mem_tras = ((temp & 0x70) >> 4) + 1; |
} else if (rdev->family == CHIP_R300 || |
rdev->family == CHIP_R350) { /* r300, r350 */ |
mem_trcd = (temp & 0x7) + 1; |
mem_trp = ((temp >> 8) & 0x7) + 1; |
mem_tras = ((temp >> 11) & 0xf) + 4; |
} else if (rdev->family == CHIP_RV350 || |
rdev->family <= CHIP_RV380) { |
/* rv3x0 */ |
mem_trcd = (temp & 0x7) + 3; |
mem_trp = ((temp >> 8) & 0x7) + 3; |
mem_tras = ((temp >> 11) & 0xf) + 6; |
} else if (rdev->family == CHIP_R420 || |
rdev->family == CHIP_R423 || |
rdev->family == CHIP_RV410) { |
/* r4xx */ |
mem_trcd = (temp & 0xf) + 3; |
if (mem_trcd > 15) |
mem_trcd = 15; |
mem_trp = ((temp >> 8) & 0xf) + 3; |
if (mem_trp > 15) |
mem_trp = 15; |
mem_tras = ((temp >> 12) & 0x1f) + 6; |
if (mem_tras > 31) |
mem_tras = 31; |
} else { /* RV200, R200 */ |
mem_trcd = (temp & 0x7) + 1; |
mem_trp = ((temp >> 8) & 0x7) + 1; |
mem_tras = ((temp >> 12) & 0xf) + 4; |
} |
/* convert to FF */ |
trcd_ff.full = rfixed_const(mem_trcd); |
trp_ff.full = rfixed_const(mem_trp); |
tras_ff.full = rfixed_const(mem_tras); |
/* Get values from the MEM_SDRAM_MODE_REG register...converting its */ |
temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); |
data = (temp & (7 << 20)) >> 20; |
if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { |
if (rdev->family == CHIP_RS480) /* don't think rs400 */ |
tcas_ff = memtcas_rs480_ff[data]; |
else |
tcas_ff = memtcas_ff[data]; |
} else |
tcas_ff = memtcas2_ff[data]; |
if (rdev->family == CHIP_RS400 || |
rdev->family == CHIP_RS480) { |
/* extra cas latency stored in bits 23-25 0-4 clocks */ |
data = (temp >> 23) & 0x7; |
if (data < 5) |
tcas_ff.full += rfixed_const(data); |
} |
if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { |
/* on the R300, Tcas is included in Trbs. |
*/ |
temp = RREG32(RADEON_MEM_CNTL); |
data = (R300_MEM_NUM_CHANNELS_MASK & temp); |
if (data == 1) { |
if (R300_MEM_USE_CD_CH_ONLY & temp) { |
temp = RREG32(R300_MC_IND_INDEX); |
temp &= ~R300_MC_IND_ADDR_MASK; |
temp |= R300_MC_READ_CNTL_CD_mcind; |
WREG32(R300_MC_IND_INDEX, temp); |
temp = RREG32(R300_MC_IND_DATA); |
data = (R300_MEM_RBS_POSITION_C_MASK & temp); |
} else { |
temp = RREG32(R300_MC_READ_CNTL_AB); |
data = (R300_MEM_RBS_POSITION_A_MASK & temp); |
} |
} else { |
temp = RREG32(R300_MC_READ_CNTL_AB); |
data = (R300_MEM_RBS_POSITION_A_MASK & temp); |
} |
if (rdev->family == CHIP_RV410 || |
rdev->family == CHIP_R420 || |
rdev->family == CHIP_R423) |
trbs_ff = memtrbs_r4xx[data]; |
else |
trbs_ff = memtrbs[data]; |
tcas_ff.full += trbs_ff.full; |
} |
sclk_eff_ff.full = sclk_ff.full; |
if (rdev->flags & RADEON_IS_AGP) { |
fixed20_12 agpmode_ff; |
agpmode_ff.full = rfixed_const(radeon_agpmode); |
temp_ff.full = rfixed_const_666(16); |
sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); |
} |
/* TODO PCIE lanes may affect this - agpmode == 16?? */ |
if (ASIC_IS_R300(rdev)) { |
sclk_delay_ff.full = rfixed_const(250); |
} else { |
if ((rdev->family == CHIP_RV100) || |
rdev->flags & RADEON_IS_IGP) { |
if (rdev->mc.vram_is_ddr) |
sclk_delay_ff.full = rfixed_const(41); |
else |
sclk_delay_ff.full = rfixed_const(33); |
} else { |
if (rdev->mc.vram_width == 128) |
sclk_delay_ff.full = rfixed_const(57); |
else |
sclk_delay_ff.full = rfixed_const(41); |
} |
} |
mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); |
if (rdev->mc.vram_is_ddr) { |
if (rdev->mc.vram_width == 32) { |
k1.full = rfixed_const(40); |
c = 3; |
} else { |
k1.full = rfixed_const(20); |
c = 1; |
} |
} else { |
k1.full = rfixed_const(40); |
c = 3; |
} |
temp_ff.full = rfixed_const(2); |
mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); |
temp_ff.full = rfixed_const(c); |
mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); |
temp_ff.full = rfixed_const(4); |
mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); |
mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); |
mc_latency_mclk.full += k1.full; |
mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); |
mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); |
/* |
HW cursor time assuming worst case of full size colour cursor. |
*/ |
temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); |
temp_ff.full += trcd_ff.full; |
if (temp_ff.full < tras_ff.full) |
temp_ff.full = tras_ff.full; |
cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); |
temp_ff.full = rfixed_const(cur_size); |
cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); |
/* |
Find the total latency for the display data. |
*/ |
disp_latency_overhead.full = rfixed_const(80); |
disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); |
mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; |
mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; |
if (mc_latency_mclk.full > mc_latency_sclk.full) |
disp_latency.full = mc_latency_mclk.full; |
else |
disp_latency.full = mc_latency_sclk.full; |
/* setup Max GRPH_STOP_REQ default value */ |
if (ASIC_IS_RV100(rdev)) |
max_stop_req = 0x5c; |
else |
max_stop_req = 0x7c; |
if (mode1) { |
/* CRTC1 |
Set GRPH_BUFFER_CNTL register using h/w defined optimal values. |
GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] |
*/ |
stop_req = mode1->hdisplay * pixel_bytes1 / 16; |
if (stop_req > max_stop_req) |
stop_req = max_stop_req; |
/* |
Find the drain rate of the display buffer. |
*/ |
temp_ff.full = rfixed_const((16/pixel_bytes1)); |
disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); |
/* |
Find the critical point of the display buffer. |
*/ |
crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); |
crit_point_ff.full += rfixed_const_half(0); |
critical_point = rfixed_trunc(crit_point_ff); |
if (rdev->disp_priority == 2) { |
critical_point = 0; |
} |
/* |
The critical point should never be above max_stop_req-4. Setting |
GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. |
*/ |
if (max_stop_req - critical_point < 4) |
critical_point = 0; |
if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { |
/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ |
critical_point = 0x10; |
} |
temp = RREG32(RADEON_GRPH_BUFFER_CNTL); |
temp &= ~(RADEON_GRPH_STOP_REQ_MASK); |
temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); |
temp &= ~(RADEON_GRPH_START_REQ_MASK); |
if ((rdev->family == CHIP_R350) && |
(stop_req > 0x15)) { |
stop_req -= 0x10; |
} |
temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); |
temp |= RADEON_GRPH_BUFFER_SIZE; |
temp &= ~(RADEON_GRPH_CRITICAL_CNTL | |
RADEON_GRPH_CRITICAL_AT_SOF | |
RADEON_GRPH_STOP_CNTL); |
/* |
Write the result into the register. |
*/ |
WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | |
(critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); |
#if 0 |
if ((rdev->family == CHIP_RS400) || |
(rdev->family == CHIP_RS480)) { |
/* attempt to program RS400 disp regs correctly ??? */ |
temp = RREG32(RS400_DISP1_REG_CNTL); |
temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | |
RS400_DISP1_STOP_REQ_LEVEL_MASK); |
WREG32(RS400_DISP1_REQ_CNTL1, (temp | |
(critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | |
(critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); |
temp = RREG32(RS400_DMIF_MEM_CNTL1); |
temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | |
RS400_DISP1_CRITICAL_POINT_STOP_MASK); |
WREG32(RS400_DMIF_MEM_CNTL1, (temp | |
(critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | |
(critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); |
} |
#endif |
DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", |
/* (unsigned int)info->SavedReg->grph_buffer_cntl, */ |
(unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); |
} |
if (mode2) { |
u32 grph2_cntl; |
stop_req = mode2->hdisplay * pixel_bytes2 / 16; |
if (stop_req > max_stop_req) |
stop_req = max_stop_req; |
/* |
Find the drain rate of the display buffer. |
*/ |
temp_ff.full = rfixed_const((16/pixel_bytes2)); |
disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); |
grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); |
grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); |
grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); |
grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); |
if ((rdev->family == CHIP_R350) && |
(stop_req > 0x15)) { |
stop_req -= 0x10; |
} |
grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); |
grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; |
grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | |
RADEON_GRPH_CRITICAL_AT_SOF | |
RADEON_GRPH_STOP_CNTL); |
if ((rdev->family == CHIP_RS100) || |
(rdev->family == CHIP_RS200)) |
critical_point2 = 0; |
else { |
temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; |
temp_ff.full = rfixed_const(temp); |
temp_ff.full = rfixed_mul(mclk_ff, temp_ff); |
if (sclk_ff.full < temp_ff.full) |
temp_ff.full = sclk_ff.full; |
read_return_rate.full = temp_ff.full; |
if (mode1) { |
temp_ff.full = read_return_rate.full - disp_drain_rate.full; |
time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); |
} else { |
time_disp1_drop_priority.full = 0; |
} |
crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; |
crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); |
crit_point_ff.full += rfixed_const_half(0); |
critical_point2 = rfixed_trunc(crit_point_ff); |
if (rdev->disp_priority == 2) { |
critical_point2 = 0; |
} |
if (max_stop_req - critical_point2 < 4) |
critical_point2 = 0; |
} |
if (critical_point2 == 0 && rdev->family == CHIP_R300) { |
/* some R300 cards have problem with this set to 0 */ |
critical_point2 = 0x10; |
} |
WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | |
(critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); |
if ((rdev->family == CHIP_RS400) || |
(rdev->family == CHIP_RS480)) { |
#if 0 |
/* attempt to program RS400 disp2 regs correctly ??? */ |
temp = RREG32(RS400_DISP2_REQ_CNTL1); |
temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | |
RS400_DISP2_STOP_REQ_LEVEL_MASK); |
WREG32(RS400_DISP2_REQ_CNTL1, (temp | |
(critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | |
(critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); |
temp = RREG32(RS400_DISP2_REQ_CNTL2); |
temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | |
RS400_DISP2_CRITICAL_POINT_STOP_MASK); |
WREG32(RS400_DISP2_REQ_CNTL2, (temp | |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); |
#endif |
WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); |
WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); |
WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); |
WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); |
} |
DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", |
(unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); |
} |
} |
void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) |
{ |
/* Shutdown CP we shouldn't need to do that but better be safe than |
* sorry |
*/ |
rdev->cp.ready = false; |
WREG32(R_000740_CP_CSQ_CNTL, 0); |
/* Save few CRTC registers */ |
save->GENMO_WT = RREG32(R_0003C0_GENMO_WT); |
save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL); |
save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL); |
save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET); |
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
save->CRTC2_GEN_CNTL = RREG32(R_0003F8_CRTC2_GEN_CNTL); |
save->CUR2_OFFSET = RREG32(R_000360_CUR2_OFFSET); |
} |
/* Disable VGA aperture access */ |
WREG32(R_0003C0_GENMO_WT, C_0003C0_VGA_RAM_EN & save->GENMO_WT); |
/* Disable cursor, overlay, crtc */ |
WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1)); |
WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL | |
S_000054_CRTC_DISPLAY_DIS(1)); |
WREG32(R_000050_CRTC_GEN_CNTL, |
(C_000050_CRTC_CUR_EN & save->CRTC_GEN_CNTL) | |
S_000050_CRTC_DISP_REQ_EN_B(1)); |
WREG32(R_000420_OV0_SCALE_CNTL, |
C_000420_OV0_OVERLAY_EN & RREG32(R_000420_OV0_SCALE_CNTL)); |
WREG32(R_000260_CUR_OFFSET, C_000260_CUR_LOCK & save->CUR_OFFSET); |
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
WREG32(R_000360_CUR2_OFFSET, save->CUR2_OFFSET | |
S_000360_CUR2_LOCK(1)); |
WREG32(R_0003F8_CRTC2_GEN_CNTL, |
(C_0003F8_CRTC2_CUR_EN & save->CRTC2_GEN_CNTL) | |
S_0003F8_CRTC2_DISPLAY_DIS(1) | |
S_0003F8_CRTC2_DISP_REQ_EN_B(1)); |
WREG32(R_000360_CUR2_OFFSET, |
C_000360_CUR2_LOCK & save->CUR2_OFFSET); |
} |
} |
void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save) |
{ |
/* Update base address for crtc */ |
WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location); |
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, |
rdev->mc.vram_location); |
} |
/* Restore CRTC registers */ |
WREG32(R_0003C0_GENMO_WT, save->GENMO_WT); |
WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL); |
WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL); |
if (!(rdev->flags & RADEON_SINGLE_CRTC)) { |
WREG32(R_0003F8_CRTC2_GEN_CNTL, save->CRTC2_GEN_CNTL); |
} |
} |
int drm_order(unsigned long size) |
{ |
int order; |
unsigned long tmp; |
for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ; |
if (size & (size - 1)) |
++order; |
return order; |
} |
/drivers/video/drm/radeon/r100_reg_safe.h |
---|
0,0 → 1,28 |
static const unsigned r100_reg_safe_bm[102] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFCF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFF9F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x38E7FE1F, 0xFFC3FF8E, 0x7FF8FFFF, 0xFFFF803C, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFEFFFF, 0xFFFFFFFF, |
0x00000000, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFCFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFEF, |
}; |
/drivers/video/drm/radeon/r100d.h |
---|
0,0 → 1,607 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef __R100D_H__ |
#define __R100D_H__ |
#define CP_PACKET0 0x00000000 |
#define PACKET0_BASE_INDEX_SHIFT 0 |
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) |
#define PACKET0_COUNT_SHIFT 16 |
#define PACKET0_COUNT_MASK (0x3fff << 16) |
#define CP_PACKET1 0x40000000 |
#define CP_PACKET2 0x80000000 |
#define PACKET2_PAD_SHIFT 0 |
#define PACKET2_PAD_MASK (0x3fffffff << 0) |
#define CP_PACKET3 0xC0000000 |
#define PACKET3_IT_OPCODE_SHIFT 8 |
#define PACKET3_IT_OPCODE_MASK (0xff << 8) |
#define PACKET3_COUNT_SHIFT 16 |
#define PACKET3_COUNT_MASK (0x3fff << 16) |
/* PACKET3 op code */ |
#define PACKET3_NOP 0x10 |
#define PACKET3_3D_DRAW_VBUF 0x28 |
#define PACKET3_3D_DRAW_IMMD 0x29 |
#define PACKET3_3D_DRAW_INDX 0x2A |
#define PACKET3_3D_LOAD_VBPNTR 0x2F |
#define PACKET3_INDX_BUFFER 0x33 |
#define PACKET3_3D_DRAW_VBUF_2 0x34 |
#define PACKET3_3D_DRAW_IMMD_2 0x35 |
#define PACKET3_3D_DRAW_INDX_2 0x36 |
#define PACKET3_BITBLT_MULTI 0x9B |
#define PACKET0(reg, n) (CP_PACKET0 | \ |
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ |
REG_SET(PACKET0_COUNT, (n))) |
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) |
#define PACKET3(op, n) (CP_PACKET3 | \ |
REG_SET(PACKET3_IT_OPCODE, (op)) | \ |
REG_SET(PACKET3_COUNT, (n))) |
#define PACKET_TYPE0 0 |
#define PACKET_TYPE1 1 |
#define PACKET_TYPE2 2 |
#define PACKET_TYPE3 3 |
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) |
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) |
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) |
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) |
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) |
/* Registers */ |
#define R_000040_GEN_INT_CNTL 0x000040 |
#define S_000040_CRTC_VBLANK(x) (((x) & 0x1) << 0) |
#define G_000040_CRTC_VBLANK(x) (((x) >> 0) & 0x1) |
#define C_000040_CRTC_VBLANK 0xFFFFFFFE |
#define S_000040_CRTC_VLINE(x) (((x) & 0x1) << 1) |
#define G_000040_CRTC_VLINE(x) (((x) >> 1) & 0x1) |
#define C_000040_CRTC_VLINE 0xFFFFFFFD |
#define S_000040_CRTC_VSYNC(x) (((x) & 0x1) << 2) |
#define G_000040_CRTC_VSYNC(x) (((x) >> 2) & 0x1) |
#define C_000040_CRTC_VSYNC 0xFFFFFFFB |
#define S_000040_SNAPSHOT(x) (((x) & 0x1) << 3) |
#define G_000040_SNAPSHOT(x) (((x) >> 3) & 0x1) |
#define C_000040_SNAPSHOT 0xFFFFFFF7 |
#define S_000040_FP_DETECT(x) (((x) & 0x1) << 4) |
#define G_000040_FP_DETECT(x) (((x) >> 4) & 0x1) |
#define C_000040_FP_DETECT 0xFFFFFFEF |
#define S_000040_CRTC2_VLINE(x) (((x) & 0x1) << 5) |
#define G_000040_CRTC2_VLINE(x) (((x) >> 5) & 0x1) |
#define C_000040_CRTC2_VLINE 0xFFFFFFDF |
#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12) |
#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1) |
#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF |
#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6) |
#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1) |
#define C_000040_CRTC2_VSYNC 0xFFFFFFBF |
#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7) |
#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1) |
#define C_000040_SNAPSHOT2 0xFFFFFF7F |
#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9) |
#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1) |
#define C_000040_CRTC2_VBLANK 0xFFFFFDFF |
#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10) |
#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1) |
#define C_000040_FP2_DETECT 0xFFFFFBFF |
#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11) |
#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1) |
#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF |
#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13) |
#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1) |
#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF |
#define S_000040_DMA_VIPH2_INT_EN(x) (((x) & 0x1) << 14) |
#define G_000040_DMA_VIPH2_INT_EN(x) (((x) >> 14) & 0x1) |
#define C_000040_DMA_VIPH2_INT_EN 0xFFFFBFFF |
#define S_000040_DMA_VIPH3_INT_EN(x) (((x) & 0x1) << 15) |
#define G_000040_DMA_VIPH3_INT_EN(x) (((x) >> 15) & 0x1) |
#define C_000040_DMA_VIPH3_INT_EN 0xFFFF7FFF |
#define S_000040_I2C_INT_EN(x) (((x) & 0x1) << 17) |
#define G_000040_I2C_INT_EN(x) (((x) >> 17) & 0x1) |
#define C_000040_I2C_INT_EN 0xFFFDFFFF |
#define S_000040_GUI_IDLE(x) (((x) & 0x1) << 19) |
#define G_000040_GUI_IDLE(x) (((x) >> 19) & 0x1) |
#define C_000040_GUI_IDLE 0xFFF7FFFF |
#define S_000040_VIPH_INT_EN(x) (((x) & 0x1) << 24) |
#define G_000040_VIPH_INT_EN(x) (((x) >> 24) & 0x1) |
#define C_000040_VIPH_INT_EN 0xFEFFFFFF |
#define S_000040_SW_INT_EN(x) (((x) & 0x1) << 25) |
#define G_000040_SW_INT_EN(x) (((x) >> 25) & 0x1) |
#define C_000040_SW_INT_EN 0xFDFFFFFF |
#define S_000040_GEYSERVILLE(x) (((x) & 0x1) << 27) |
#define G_000040_GEYSERVILLE(x) (((x) >> 27) & 0x1) |
#define C_000040_GEYSERVILLE 0xF7FFFFFF |
#define S_000040_HDCP_AUTHORIZED_INT(x) (((x) & 0x1) << 28) |
#define G_000040_HDCP_AUTHORIZED_INT(x) (((x) >> 28) & 0x1) |
#define C_000040_HDCP_AUTHORIZED_INT 0xEFFFFFFF |
#define S_000040_DVI_I2C_INT(x) (((x) & 0x1) << 29) |
#define G_000040_DVI_I2C_INT(x) (((x) >> 29) & 0x1) |
#define C_000040_DVI_I2C_INT 0xDFFFFFFF |
#define S_000040_GUIDMA(x) (((x) & 0x1) << 30) |
#define G_000040_GUIDMA(x) (((x) >> 30) & 0x1) |
#define C_000040_GUIDMA 0xBFFFFFFF |
#define S_000040_VIDDMA(x) (((x) & 0x1) << 31) |
#define G_000040_VIDDMA(x) (((x) >> 31) & 0x1) |
#define C_000040_VIDDMA 0x7FFFFFFF |
#define R_000044_GEN_INT_STATUS 0x000044 |
#define S_000044_CRTC_VBLANK_STAT(x) (((x) & 0x1) << 0) |
#define G_000044_CRTC_VBLANK_STAT(x) (((x) >> 0) & 0x1) |
#define C_000044_CRTC_VBLANK_STAT 0xFFFFFFFE |
#define S_000044_CRTC_VBLANK_STAT_AK(x) (((x) & 0x1) << 0) |
#define G_000044_CRTC_VBLANK_STAT_AK(x) (((x) >> 0) & 0x1) |
#define C_000044_CRTC_VBLANK_STAT_AK 0xFFFFFFFE |
#define S_000044_CRTC_VLINE_STAT(x) (((x) & 0x1) << 1) |
#define G_000044_CRTC_VLINE_STAT(x) (((x) >> 1) & 0x1) |
#define C_000044_CRTC_VLINE_STAT 0xFFFFFFFD |
#define S_000044_CRTC_VLINE_STAT_AK(x) (((x) & 0x1) << 1) |
#define G_000044_CRTC_VLINE_STAT_AK(x) (((x) >> 1) & 0x1) |
#define C_000044_CRTC_VLINE_STAT_AK 0xFFFFFFFD |
#define S_000044_CRTC_VSYNC_STAT(x) (((x) & 0x1) << 2) |
#define G_000044_CRTC_VSYNC_STAT(x) (((x) >> 2) & 0x1) |
#define C_000044_CRTC_VSYNC_STAT 0xFFFFFFFB |
#define S_000044_CRTC_VSYNC_STAT_AK(x) (((x) & 0x1) << 2) |
#define G_000044_CRTC_VSYNC_STAT_AK(x) (((x) >> 2) & 0x1) |
#define C_000044_CRTC_VSYNC_STAT_AK 0xFFFFFFFB |
#define S_000044_SNAPSHOT_STAT(x) (((x) & 0x1) << 3) |
#define G_000044_SNAPSHOT_STAT(x) (((x) >> 3) & 0x1) |
#define C_000044_SNAPSHOT_STAT 0xFFFFFFF7 |
#define S_000044_SNAPSHOT_STAT_AK(x) (((x) & 0x1) << 3) |
#define G_000044_SNAPSHOT_STAT_AK(x) (((x) >> 3) & 0x1) |
#define C_000044_SNAPSHOT_STAT_AK 0xFFFFFFF7 |
#define S_000044_FP_DETECT_STAT(x) (((x) & 0x1) << 4) |
#define G_000044_FP_DETECT_STAT(x) (((x) >> 4) & 0x1) |
#define C_000044_FP_DETECT_STAT 0xFFFFFFEF |
#define S_000044_FP_DETECT_STAT_AK(x) (((x) & 0x1) << 4) |
#define G_000044_FP_DETECT_STAT_AK(x) (((x) >> 4) & 0x1) |
#define C_000044_FP_DETECT_STAT_AK 0xFFFFFFEF |
#define S_000044_CRTC2_VLINE_STAT(x) (((x) & 0x1) << 5) |
#define G_000044_CRTC2_VLINE_STAT(x) (((x) >> 5) & 0x1) |
#define C_000044_CRTC2_VLINE_STAT 0xFFFFFFDF |
#define S_000044_CRTC2_VLINE_STAT_AK(x) (((x) & 0x1) << 5) |
#define G_000044_CRTC2_VLINE_STAT_AK(x) (((x) >> 5) & 0x1) |
#define C_000044_CRTC2_VLINE_STAT_AK 0xFFFFFFDF |
#define S_000044_CRTC2_VSYNC_STAT(x) (((x) & 0x1) << 6) |
#define G_000044_CRTC2_VSYNC_STAT(x) (((x) >> 6) & 0x1) |
#define C_000044_CRTC2_VSYNC_STAT 0xFFFFFFBF |
#define S_000044_CRTC2_VSYNC_STAT_AK(x) (((x) & 0x1) << 6) |
#define G_000044_CRTC2_VSYNC_STAT_AK(x) (((x) >> 6) & 0x1) |
#define C_000044_CRTC2_VSYNC_STAT_AK 0xFFFFFFBF |
#define S_000044_SNAPSHOT2_STAT(x) (((x) & 0x1) << 7) |
#define G_000044_SNAPSHOT2_STAT(x) (((x) >> 7) & 0x1) |
#define C_000044_SNAPSHOT2_STAT 0xFFFFFF7F |
#define S_000044_SNAPSHOT2_STAT_AK(x) (((x) & 0x1) << 7) |
#define G_000044_SNAPSHOT2_STAT_AK(x) (((x) >> 7) & 0x1) |
#define C_000044_SNAPSHOT2_STAT_AK 0xFFFFFF7F |
#define S_000044_CAP0_INT_ACTIVE(x) (((x) & 0x1) << 8) |
#define G_000044_CAP0_INT_ACTIVE(x) (((x) >> 8) & 0x1) |
#define C_000044_CAP0_INT_ACTIVE 0xFFFFFEFF |
#define S_000044_CRTC2_VBLANK_STAT(x) (((x) & 0x1) << 9) |
#define G_000044_CRTC2_VBLANK_STAT(x) (((x) >> 9) & 0x1) |
#define C_000044_CRTC2_VBLANK_STAT 0xFFFFFDFF |
#define S_000044_CRTC2_VBLANK_STAT_AK(x) (((x) & 0x1) << 9) |
#define G_000044_CRTC2_VBLANK_STAT_AK(x) (((x) >> 9) & 0x1) |
#define C_000044_CRTC2_VBLANK_STAT_AK 0xFFFFFDFF |
#define S_000044_FP2_DETECT_STAT(x) (((x) & 0x1) << 10) |
#define G_000044_FP2_DETECT_STAT(x) (((x) >> 10) & 0x1) |
#define C_000044_FP2_DETECT_STAT 0xFFFFFBFF |
#define S_000044_FP2_DETECT_STAT_AK(x) (((x) & 0x1) << 10) |
#define G_000044_FP2_DETECT_STAT_AK(x) (((x) >> 10) & 0x1) |
#define C_000044_FP2_DETECT_STAT_AK 0xFFFFFBFF |
#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) & 0x1) << 11) |
#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) >> 11) & 0x1) |
#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT 0xFFFFF7FF |
#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) & 0x1) << 11) |
#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) >> 11) & 0x1) |
#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK 0xFFFFF7FF |
#define S_000044_DMA_VIPH0_INT(x) (((x) & 0x1) << 12) |
#define G_000044_DMA_VIPH0_INT(x) (((x) >> 12) & 0x1) |
#define C_000044_DMA_VIPH0_INT 0xFFFFEFFF |
#define S_000044_DMA_VIPH0_INT_AK(x) (((x) & 0x1) << 12) |
#define G_000044_DMA_VIPH0_INT_AK(x) (((x) >> 12) & 0x1) |
#define C_000044_DMA_VIPH0_INT_AK 0xFFFFEFFF |
#define S_000044_DMA_VIPH1_INT(x) (((x) & 0x1) << 13) |
#define G_000044_DMA_VIPH1_INT(x) (((x) >> 13) & 0x1) |
#define C_000044_DMA_VIPH1_INT 0xFFFFDFFF |
#define S_000044_DMA_VIPH1_INT_AK(x) (((x) & 0x1) << 13) |
#define G_000044_DMA_VIPH1_INT_AK(x) (((x) >> 13) & 0x1) |
#define C_000044_DMA_VIPH1_INT_AK 0xFFFFDFFF |
#define S_000044_DMA_VIPH2_INT(x) (((x) & 0x1) << 14) |
#define G_000044_DMA_VIPH2_INT(x) (((x) >> 14) & 0x1) |
#define C_000044_DMA_VIPH2_INT 0xFFFFBFFF |
#define S_000044_DMA_VIPH2_INT_AK(x) (((x) & 0x1) << 14) |
#define G_000044_DMA_VIPH2_INT_AK(x) (((x) >> 14) & 0x1) |
#define C_000044_DMA_VIPH2_INT_AK 0xFFFFBFFF |
#define S_000044_DMA_VIPH3_INT(x) (((x) & 0x1) << 15) |
#define G_000044_DMA_VIPH3_INT(x) (((x) >> 15) & 0x1) |
#define C_000044_DMA_VIPH3_INT 0xFFFF7FFF |
#define S_000044_DMA_VIPH3_INT_AK(x) (((x) & 0x1) << 15) |
#define G_000044_DMA_VIPH3_INT_AK(x) (((x) >> 15) & 0x1) |
#define C_000044_DMA_VIPH3_INT_AK 0xFFFF7FFF |
#define S_000044_I2C_INT(x) (((x) & 0x1) << 17) |
#define G_000044_I2C_INT(x) (((x) >> 17) & 0x1) |
#define C_000044_I2C_INT 0xFFFDFFFF |
#define S_000044_I2C_INT_AK(x) (((x) & 0x1) << 17) |
#define G_000044_I2C_INT_AK(x) (((x) >> 17) & 0x1) |
#define C_000044_I2C_INT_AK 0xFFFDFFFF |
#define S_000044_GUI_IDLE_STAT(x) (((x) & 0x1) << 19) |
#define G_000044_GUI_IDLE_STAT(x) (((x) >> 19) & 0x1) |
#define C_000044_GUI_IDLE_STAT 0xFFF7FFFF |
#define S_000044_GUI_IDLE_STAT_AK(x) (((x) & 0x1) << 19) |
#define G_000044_GUI_IDLE_STAT_AK(x) (((x) >> 19) & 0x1) |
#define C_000044_GUI_IDLE_STAT_AK 0xFFF7FFFF |
#define S_000044_VIPH_INT(x) (((x) & 0x1) << 24) |
#define G_000044_VIPH_INT(x) (((x) >> 24) & 0x1) |
#define C_000044_VIPH_INT 0xFEFFFFFF |
#define S_000044_SW_INT(x) (((x) & 0x1) << 25) |
#define G_000044_SW_INT(x) (((x) >> 25) & 0x1) |
#define C_000044_SW_INT 0xFDFFFFFF |
#define S_000044_SW_INT_AK(x) (((x) & 0x1) << 25) |
#define G_000044_SW_INT_AK(x) (((x) >> 25) & 0x1) |
#define C_000044_SW_INT_AK 0xFDFFFFFF |
#define S_000044_SW_INT_SET(x) (((x) & 0x1) << 26) |
#define G_000044_SW_INT_SET(x) (((x) >> 26) & 0x1) |
#define C_000044_SW_INT_SET 0xFBFFFFFF |
#define S_000044_GEYSERVILLE_STAT(x) (((x) & 0x1) << 27) |
#define G_000044_GEYSERVILLE_STAT(x) (((x) >> 27) & 0x1) |
#define C_000044_GEYSERVILLE_STAT 0xF7FFFFFF |
#define S_000044_GEYSERVILLE_STAT_AK(x) (((x) & 0x1) << 27) |
#define G_000044_GEYSERVILLE_STAT_AK(x) (((x) >> 27) & 0x1) |
#define C_000044_GEYSERVILLE_STAT_AK 0xF7FFFFFF |
#define S_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) & 0x1) << 28) |
#define G_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) >> 28) & 0x1) |
#define C_000044_HDCP_AUTHORIZED_INT_STAT 0xEFFFFFFF |
#define S_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) & 0x1) << 28) |
#define G_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) >> 28) & 0x1) |
#define C_000044_HDCP_AUTHORIZED_INT_AK 0xEFFFFFFF |
#define S_000044_DVI_I2C_INT_STAT(x) (((x) & 0x1) << 29) |
#define G_000044_DVI_I2C_INT_STAT(x) (((x) >> 29) & 0x1) |
#define C_000044_DVI_I2C_INT_STAT 0xDFFFFFFF |
#define S_000044_DVI_I2C_INT_AK(x) (((x) & 0x1) << 29) |
#define G_000044_DVI_I2C_INT_AK(x) (((x) >> 29) & 0x1) |
#define C_000044_DVI_I2C_INT_AK 0xDFFFFFFF |
#define S_000044_GUIDMA_STAT(x) (((x) & 0x1) << 30) |
#define G_000044_GUIDMA_STAT(x) (((x) >> 30) & 0x1) |
#define C_000044_GUIDMA_STAT 0xBFFFFFFF |
#define S_000044_GUIDMA_AK(x) (((x) & 0x1) << 30) |
#define G_000044_GUIDMA_AK(x) (((x) >> 30) & 0x1) |
#define C_000044_GUIDMA_AK 0xBFFFFFFF |
#define S_000044_VIDDMA_STAT(x) (((x) & 0x1) << 31) |
#define G_000044_VIDDMA_STAT(x) (((x) >> 31) & 0x1) |
#define C_000044_VIDDMA_STAT 0x7FFFFFFF |
#define S_000044_VIDDMA_AK(x) (((x) & 0x1) << 31) |
#define G_000044_VIDDMA_AK(x) (((x) >> 31) & 0x1) |
#define C_000044_VIDDMA_AK 0x7FFFFFFF |
#define R_000050_CRTC_GEN_CNTL 0x000050 |
#define S_000050_CRTC_DBL_SCAN_EN(x) (((x) & 0x1) << 0) |
#define G_000050_CRTC_DBL_SCAN_EN(x) (((x) >> 0) & 0x1) |
#define C_000050_CRTC_DBL_SCAN_EN 0xFFFFFFFE |
#define S_000050_CRTC_INTERLACE_EN(x) (((x) & 0x1) << 1) |
#define G_000050_CRTC_INTERLACE_EN(x) (((x) >> 1) & 0x1) |
#define C_000050_CRTC_INTERLACE_EN 0xFFFFFFFD |
#define S_000050_CRTC_C_SYNC_EN(x) (((x) & 0x1) << 4) |
#define G_000050_CRTC_C_SYNC_EN(x) (((x) >> 4) & 0x1) |
#define C_000050_CRTC_C_SYNC_EN 0xFFFFFFEF |
#define S_000050_CRTC_PIX_WIDTH(x) (((x) & 0xF) << 8) |
#define G_000050_CRTC_PIX_WIDTH(x) (((x) >> 8) & 0xF) |
#define C_000050_CRTC_PIX_WIDTH 0xFFFFF0FF |
#define S_000050_CRTC_ICON_EN(x) (((x) & 0x1) << 15) |
#define G_000050_CRTC_ICON_EN(x) (((x) >> 15) & 0x1) |
#define C_000050_CRTC_ICON_EN 0xFFFF7FFF |
#define S_000050_CRTC_CUR_EN(x) (((x) & 0x1) << 16) |
#define G_000050_CRTC_CUR_EN(x) (((x) >> 16) & 0x1) |
#define C_000050_CRTC_CUR_EN 0xFFFEFFFF |
#define S_000050_CRTC_VSTAT_MODE(x) (((x) & 0x3) << 17) |
#define G_000050_CRTC_VSTAT_MODE(x) (((x) >> 17) & 0x3) |
#define C_000050_CRTC_VSTAT_MODE 0xFFF9FFFF |
#define S_000050_CRTC_CUR_MODE(x) (((x) & 0x7) << 20) |
#define G_000050_CRTC_CUR_MODE(x) (((x) >> 20) & 0x7) |
#define C_000050_CRTC_CUR_MODE 0xFF8FFFFF |
#define S_000050_CRTC_EXT_DISP_EN(x) (((x) & 0x1) << 24) |
#define G_000050_CRTC_EXT_DISP_EN(x) (((x) >> 24) & 0x1) |
#define C_000050_CRTC_EXT_DISP_EN 0xFEFFFFFF |
#define S_000050_CRTC_EN(x) (((x) & 0x1) << 25) |
#define G_000050_CRTC_EN(x) (((x) >> 25) & 0x1) |
#define C_000050_CRTC_EN 0xFDFFFFFF |
#define S_000050_CRTC_DISP_REQ_EN_B(x) (((x) & 0x1) << 26) |
#define G_000050_CRTC_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1) |
#define C_000050_CRTC_DISP_REQ_EN_B 0xFBFFFFFF |
#define R_000054_CRTC_EXT_CNTL 0x000054 |
#define S_000054_CRTC_VGA_XOVERSCAN(x) (((x) & 0x1) << 0) |
#define G_000054_CRTC_VGA_XOVERSCAN(x) (((x) >> 0) & 0x1) |
#define C_000054_CRTC_VGA_XOVERSCAN 0xFFFFFFFE |
#define S_000054_VGA_BLINK_RATE(x) (((x) & 0x3) << 1) |
#define G_000054_VGA_BLINK_RATE(x) (((x) >> 1) & 0x3) |
#define C_000054_VGA_BLINK_RATE 0xFFFFFFF9 |
#define S_000054_VGA_ATI_LINEAR(x) (((x) & 0x1) << 3) |
#define G_000054_VGA_ATI_LINEAR(x) (((x) >> 3) & 0x1) |
#define C_000054_VGA_ATI_LINEAR 0xFFFFFFF7 |
#define S_000054_VGA_128KAP_PAGING(x) (((x) & 0x1) << 4) |
#define G_000054_VGA_128KAP_PAGING(x) (((x) >> 4) & 0x1) |
#define C_000054_VGA_128KAP_PAGING 0xFFFFFFEF |
#define S_000054_VGA_TEXT_132(x) (((x) & 0x1) << 5) |
#define G_000054_VGA_TEXT_132(x) (((x) >> 5) & 0x1) |
#define C_000054_VGA_TEXT_132 0xFFFFFFDF |
#define S_000054_VGA_XCRT_CNT_EN(x) (((x) & 0x1) << 6) |
#define G_000054_VGA_XCRT_CNT_EN(x) (((x) >> 6) & 0x1) |
#define C_000054_VGA_XCRT_CNT_EN 0xFFFFFFBF |
#define S_000054_CRTC_HSYNC_DIS(x) (((x) & 0x1) << 8) |
#define G_000054_CRTC_HSYNC_DIS(x) (((x) >> 8) & 0x1) |
#define C_000054_CRTC_HSYNC_DIS 0xFFFFFEFF |
#define S_000054_CRTC_VSYNC_DIS(x) (((x) & 0x1) << 9) |
#define G_000054_CRTC_VSYNC_DIS(x) (((x) >> 9) & 0x1) |
#define C_000054_CRTC_VSYNC_DIS 0xFFFFFDFF |
#define S_000054_CRTC_DISPLAY_DIS(x) (((x) & 0x1) << 10) |
#define G_000054_CRTC_DISPLAY_DIS(x) (((x) >> 10) & 0x1) |
#define C_000054_CRTC_DISPLAY_DIS 0xFFFFFBFF |
#define S_000054_CRTC_SYNC_TRISTATE(x) (((x) & 0x1) << 11) |
#define G_000054_CRTC_SYNC_TRISTATE(x) (((x) >> 11) & 0x1) |
#define C_000054_CRTC_SYNC_TRISTATE 0xFFFFF7FF |
#define S_000054_CRTC_HSYNC_TRISTATE(x) (((x) & 0x1) << 12) |
#define G_000054_CRTC_HSYNC_TRISTATE(x) (((x) >> 12) & 0x1) |
#define C_000054_CRTC_HSYNC_TRISTATE 0xFFFFEFFF |
#define S_000054_CRTC_VSYNC_TRISTATE(x) (((x) & 0x1) << 13) |
#define G_000054_CRTC_VSYNC_TRISTATE(x) (((x) >> 13) & 0x1) |
#define C_000054_CRTC_VSYNC_TRISTATE 0xFFFFDFFF |
#define S_000054_CRT_ON(x) (((x) & 0x1) << 15) |
#define G_000054_CRT_ON(x) (((x) >> 15) & 0x1) |
#define C_000054_CRT_ON 0xFFFF7FFF |
#define S_000054_VGA_CUR_B_TEST(x) (((x) & 0x1) << 17) |
#define G_000054_VGA_CUR_B_TEST(x) (((x) >> 17) & 0x1) |
#define C_000054_VGA_CUR_B_TEST 0xFFFDFFFF |
#define S_000054_VGA_PACK_DIS(x) (((x) & 0x1) << 18) |
#define G_000054_VGA_PACK_DIS(x) (((x) >> 18) & 0x1) |
#define C_000054_VGA_PACK_DIS 0xFFFBFFFF |
#define S_000054_VGA_MEM_PS_EN(x) (((x) & 0x1) << 19) |
#define G_000054_VGA_MEM_PS_EN(x) (((x) >> 19) & 0x1) |
#define C_000054_VGA_MEM_PS_EN 0xFFF7FFFF |
#define S_000054_VCRTC_IDX_MASTER(x) (((x) & 0x7F) << 24) |
#define G_000054_VCRTC_IDX_MASTER(x) (((x) >> 24) & 0x7F) |
#define C_000054_VCRTC_IDX_MASTER 0x80FFFFFF |
#define R_00023C_DISPLAY_BASE_ADDR 0x00023C |
#define S_00023C_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) |
#define G_00023C_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) |
#define C_00023C_DISPLAY_BASE_ADDR 0x00000000 |
#define R_000260_CUR_OFFSET 0x000260 |
#define S_000260_CUR_OFFSET(x) (((x) & 0x7FFFFFF) << 0) |
#define G_000260_CUR_OFFSET(x) (((x) >> 0) & 0x7FFFFFF) |
#define C_000260_CUR_OFFSET 0xF8000000 |
#define S_000260_CUR_LOCK(x) (((x) & 0x1) << 31) |
#define G_000260_CUR_LOCK(x) (((x) >> 31) & 0x1) |
#define C_000260_CUR_LOCK 0x7FFFFFFF |
#define R_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00033C |
#define S_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) |
#define G_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) |
#define C_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00000000 |
#define R_000360_CUR2_OFFSET 0x000360 |
#define S_000360_CUR2_OFFSET(x) (((x) & 0x7FFFFFF) << 0) |
#define G_000360_CUR2_OFFSET(x) (((x) >> 0) & 0x7FFFFFF) |
#define C_000360_CUR2_OFFSET 0xF8000000 |
#define S_000360_CUR2_LOCK(x) (((x) & 0x1) << 31) |
#define G_000360_CUR2_LOCK(x) (((x) >> 31) & 0x1) |
#define C_000360_CUR2_LOCK 0x7FFFFFFF |
#define R_0003C0_GENMO_WT 0x0003C0 |
#define S_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) & 0x1) << 0) |
#define G_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) >> 0) & 0x1) |
#define C_0003C0_GENMO_MONO_ADDRESS_B 0xFFFFFFFE |
#define S_0003C0_VGA_RAM_EN(x) (((x) & 0x1) << 1) |
#define G_0003C0_VGA_RAM_EN(x) (((x) >> 1) & 0x1) |
#define C_0003C0_VGA_RAM_EN 0xFFFFFFFD |
#define S_0003C0_VGA_CKSEL(x) (((x) & 0x3) << 2) |
#define G_0003C0_VGA_CKSEL(x) (((x) >> 2) & 0x3) |
#define C_0003C0_VGA_CKSEL 0xFFFFFFF3 |
#define S_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) & 0x1) << 5) |
#define G_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) >> 5) & 0x1) |
#define C_0003C0_ODD_EVEN_MD_PGSEL 0xFFFFFFDF |
#define S_0003C0_VGA_HSYNC_POL(x) (((x) & 0x1) << 6) |
#define G_0003C0_VGA_HSYNC_POL(x) (((x) >> 6) & 0x1) |
#define C_0003C0_VGA_HSYNC_POL 0xFFFFFFBF |
#define S_0003C0_VGA_VSYNC_POL(x) (((x) & 0x1) << 7) |
#define G_0003C0_VGA_VSYNC_POL(x) (((x) >> 7) & 0x1) |
#define C_0003C0_VGA_VSYNC_POL 0xFFFFFF7F |
#define R_0003F8_CRTC2_GEN_CNTL 0x0003F8 |
#define S_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) & 0x1) << 0) |
#define G_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) >> 0) & 0x1) |
#define C_0003F8_CRTC2_DBL_SCAN_EN 0xFFFFFFFE |
#define S_0003F8_CRTC2_INTERLACE_EN(x) (((x) & 0x1) << 1) |
#define G_0003F8_CRTC2_INTERLACE_EN(x) (((x) >> 1) & 0x1) |
#define C_0003F8_CRTC2_INTERLACE_EN 0xFFFFFFFD |
#define S_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) & 0x1) << 4) |
#define G_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) >> 4) & 0x1) |
#define C_0003F8_CRTC2_SYNC_TRISTATE 0xFFFFFFEF |
#define S_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) & 0x1) << 5) |
#define G_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) >> 5) & 0x1) |
#define C_0003F8_CRTC2_HSYNC_TRISTATE 0xFFFFFFDF |
#define S_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) & 0x1) << 6) |
#define G_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) >> 6) & 0x1) |
#define C_0003F8_CRTC2_VSYNC_TRISTATE 0xFFFFFFBF |
#define S_0003F8_CRT2_ON(x) (((x) & 0x1) << 7) |
#define G_0003F8_CRT2_ON(x) (((x) >> 7) & 0x1) |
#define C_0003F8_CRT2_ON 0xFFFFFF7F |
#define S_0003F8_CRTC2_PIX_WIDTH(x) (((x) & 0xF) << 8) |
#define G_0003F8_CRTC2_PIX_WIDTH(x) (((x) >> 8) & 0xF) |
#define C_0003F8_CRTC2_PIX_WIDTH 0xFFFFF0FF |
#define S_0003F8_CRTC2_ICON_EN(x) (((x) & 0x1) << 15) |
#define G_0003F8_CRTC2_ICON_EN(x) (((x) >> 15) & 0x1) |
#define C_0003F8_CRTC2_ICON_EN 0xFFFF7FFF |
#define S_0003F8_CRTC2_CUR_EN(x) (((x) & 0x1) << 16) |
#define G_0003F8_CRTC2_CUR_EN(x) (((x) >> 16) & 0x1) |
#define C_0003F8_CRTC2_CUR_EN 0xFFFEFFFF |
#define S_0003F8_CRTC2_CUR_MODE(x) (((x) & 0x7) << 20) |
#define G_0003F8_CRTC2_CUR_MODE(x) (((x) >> 20) & 0x7) |
#define C_0003F8_CRTC2_CUR_MODE 0xFF8FFFFF |
#define S_0003F8_CRTC2_DISPLAY_DIS(x) (((x) & 0x1) << 23) |
#define G_0003F8_CRTC2_DISPLAY_DIS(x) (((x) >> 23) & 0x1) |
#define C_0003F8_CRTC2_DISPLAY_DIS 0xFF7FFFFF |
#define S_0003F8_CRTC2_EN(x) (((x) & 0x1) << 25) |
#define G_0003F8_CRTC2_EN(x) (((x) >> 25) & 0x1) |
#define C_0003F8_CRTC2_EN 0xFDFFFFFF |
#define S_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) & 0x1) << 26) |
#define G_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1) |
#define C_0003F8_CRTC2_DISP_REQ_EN_B 0xFBFFFFFF |
#define S_0003F8_CRTC2_C_SYNC_EN(x) (((x) & 0x1) << 27) |
#define G_0003F8_CRTC2_C_SYNC_EN(x) (((x) >> 27) & 0x1) |
#define C_0003F8_CRTC2_C_SYNC_EN 0xF7FFFFFF |
#define S_0003F8_CRTC2_HSYNC_DIS(x) (((x) & 0x1) << 28) |
#define G_0003F8_CRTC2_HSYNC_DIS(x) (((x) >> 28) & 0x1) |
#define C_0003F8_CRTC2_HSYNC_DIS 0xEFFFFFFF |
#define S_0003F8_CRTC2_VSYNC_DIS(x) (((x) & 0x1) << 29) |
#define G_0003F8_CRTC2_VSYNC_DIS(x) (((x) >> 29) & 0x1) |
#define C_0003F8_CRTC2_VSYNC_DIS 0xDFFFFFFF |
#define R_000420_OV0_SCALE_CNTL 0x000420 |
#define S_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) & 0x1) << 1) |
#define G_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) >> 1) & 0x1) |
#define C_000420_OV0_NO_READ_BEHIND_SCAN 0xFFFFFFFD |
#define S_000420_OV0_HORZ_PICK_NEAREST(x) (((x) & 0x1) << 2) |
#define G_000420_OV0_HORZ_PICK_NEAREST(x) (((x) >> 2) & 0x1) |
#define C_000420_OV0_HORZ_PICK_NEAREST 0xFFFFFFFB |
#define S_000420_OV0_VERT_PICK_NEAREST(x) (((x) & 0x1) << 3) |
#define G_000420_OV0_VERT_PICK_NEAREST(x) (((x) >> 3) & 0x1) |
#define C_000420_OV0_VERT_PICK_NEAREST 0xFFFFFFF7 |
#define S_000420_OV0_SIGNED_UV(x) (((x) & 0x1) << 4) |
#define G_000420_OV0_SIGNED_UV(x) (((x) >> 4) & 0x1) |
#define C_000420_OV0_SIGNED_UV 0xFFFFFFEF |
#define S_000420_OV0_GAMMA_SEL(x) (((x) & 0x7) << 5) |
#define G_000420_OV0_GAMMA_SEL(x) (((x) >> 5) & 0x7) |
#define C_000420_OV0_GAMMA_SEL 0xFFFFFF1F |
#define S_000420_OV0_SURFACE_FORMAT(x) (((x) & 0xF) << 8) |
#define G_000420_OV0_SURFACE_FORMAT(x) (((x) >> 8) & 0xF) |
#define C_000420_OV0_SURFACE_FORMAT 0xFFFFF0FF |
#define S_000420_OV0_ADAPTIVE_DEINT(x) (((x) & 0x1) << 12) |
#define G_000420_OV0_ADAPTIVE_DEINT(x) (((x) >> 12) & 0x1) |
#define C_000420_OV0_ADAPTIVE_DEINT 0xFFFFEFFF |
#define S_000420_OV0_CRTC_SEL(x) (((x) & 0x1) << 14) |
#define G_000420_OV0_CRTC_SEL(x) (((x) >> 14) & 0x1) |
#define C_000420_OV0_CRTC_SEL 0xFFFFBFFF |
#define S_000420_OV0_BURST_PER_PLANE(x) (((x) & 0x7F) << 16) |
#define G_000420_OV0_BURST_PER_PLANE(x) (((x) >> 16) & 0x7F) |
#define C_000420_OV0_BURST_PER_PLANE 0xFF80FFFF |
#define S_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) & 0x1) << 24) |
#define G_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) >> 24) & 0x1) |
#define C_000420_OV0_DOUBLE_BUFFER_REGS 0xFEFFFFFF |
#define S_000420_OV0_BANDWIDTH(x) (((x) & 0x1) << 26) |
#define G_000420_OV0_BANDWIDTH(x) (((x) >> 26) & 0x1) |
#define C_000420_OV0_BANDWIDTH 0xFBFFFFFF |
#define S_000420_OV0_LIN_TRANS_BYPASS(x) (((x) & 0x1) << 28) |
#define G_000420_OV0_LIN_TRANS_BYPASS(x) (((x) >> 28) & 0x1) |
#define C_000420_OV0_LIN_TRANS_BYPASS 0xEFFFFFFF |
#define S_000420_OV0_INT_EMU(x) (((x) & 0x1) << 29) |
#define G_000420_OV0_INT_EMU(x) (((x) >> 29) & 0x1) |
#define C_000420_OV0_INT_EMU 0xDFFFFFFF |
#define S_000420_OV0_OVERLAY_EN(x) (((x) & 0x1) << 30) |
#define G_000420_OV0_OVERLAY_EN(x) (((x) >> 30) & 0x1) |
#define C_000420_OV0_OVERLAY_EN 0xBFFFFFFF |
#define S_000420_OV0_SOFT_RESET(x) (((x) & 0x1) << 31) |
#define G_000420_OV0_SOFT_RESET(x) (((x) >> 31) & 0x1) |
#define C_000420_OV0_SOFT_RESET 0x7FFFFFFF |
#define R_00070C_CP_RB_RPTR_ADDR 0x00070C |
#define S_00070C_RB_RPTR_SWAP(x) (((x) & 0x3) << 0) |
#define G_00070C_RB_RPTR_SWAP(x) (((x) >> 0) & 0x3) |
#define C_00070C_RB_RPTR_SWAP 0xFFFFFFFC |
#define S_00070C_RB_RPTR_ADDR(x) (((x) & 0x3FFFFFFF) << 2) |
#define G_00070C_RB_RPTR_ADDR(x) (((x) >> 2) & 0x3FFFFFFF) |
#define C_00070C_RB_RPTR_ADDR 0x00000003 |
#define R_000740_CP_CSQ_CNTL 0x000740 |
#define S_000740_CSQ_CNT_PRIMARY(x) (((x) & 0xFF) << 0) |
#define G_000740_CSQ_CNT_PRIMARY(x) (((x) >> 0) & 0xFF) |
#define C_000740_CSQ_CNT_PRIMARY 0xFFFFFF00 |
#define S_000740_CSQ_CNT_INDIRECT(x) (((x) & 0xFF) << 8) |
#define G_000740_CSQ_CNT_INDIRECT(x) (((x) >> 8) & 0xFF) |
#define C_000740_CSQ_CNT_INDIRECT 0xFFFF00FF |
#define S_000740_CSQ_MODE(x) (((x) & 0xF) << 28) |
#define G_000740_CSQ_MODE(x) (((x) >> 28) & 0xF) |
#define C_000740_CSQ_MODE 0x0FFFFFFF |
#define R_000770_SCRATCH_UMSK 0x000770 |
#define S_000770_SCRATCH_UMSK(x) (((x) & 0x3F) << 0) |
#define G_000770_SCRATCH_UMSK(x) (((x) >> 0) & 0x3F) |
#define C_000770_SCRATCH_UMSK 0xFFFFFFC0 |
#define S_000770_SCRATCH_SWAP(x) (((x) & 0x3) << 16) |
#define G_000770_SCRATCH_SWAP(x) (((x) >> 16) & 0x3) |
#define C_000770_SCRATCH_SWAP 0xFFFCFFFF |
#define R_000774_SCRATCH_ADDR 0x000774 |
#define S_000774_SCRATCH_ADDR(x) (((x) & 0x7FFFFFF) << 5) |
#define G_000774_SCRATCH_ADDR(x) (((x) >> 5) & 0x7FFFFFF) |
#define C_000774_SCRATCH_ADDR 0x0000001F |
#define R_000E40_RBBM_STATUS 0x000E40 |
#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) |
#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) |
#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 |
#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) |
#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) |
#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF |
#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) |
#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) |
#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF |
#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) |
#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) |
#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF |
#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) |
#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) |
#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF |
#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) |
#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) |
#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF |
#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) |
#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) |
#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF |
#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) |
#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) |
#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF |
#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) |
#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) |
#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF |
#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) |
#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) |
#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF |
#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) |
#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) |
#define C_000E40_E2_BUSY 0xFFFDFFFF |
#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) |
#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) |
#define C_000E40_RB2D_BUSY 0xFFFBFFFF |
#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) |
#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) |
#define C_000E40_RB3D_BUSY 0xFFF7FFFF |
#define S_000E40_SE_BUSY(x) (((x) & 0x1) << 20) |
#define G_000E40_SE_BUSY(x) (((x) >> 20) & 0x1) |
#define C_000E40_SE_BUSY 0xFFEFFFFF |
#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) |
#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) |
#define C_000E40_RE_BUSY 0xFFDFFFFF |
#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) |
#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) |
#define C_000E40_TAM_BUSY 0xFFBFFFFF |
#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) |
#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) |
#define C_000E40_TDM_BUSY 0xFF7FFFFF |
#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) |
#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) |
#define C_000E40_PB_BUSY 0xFEFFFFFF |
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) |
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) |
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF |
#endif |
/drivers/video/drm/radeon/r200.c |
---|
0,0 → 1,458 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#include "drmP.h" |
#include "drm.h" |
#include "radeon_drm.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "r200_reg_safe.h" |
//#include "r100_track.h" |
#if 0 |
static int r200_get_vtx_size_0(uint32_t vtx_fmt_0) |
{ |
int vtx_size, i; |
vtx_size = 2; |
if (vtx_fmt_0 & R200_VTX_Z0) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_W0) |
vtx_size++; |
/* blend weight */ |
if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT)) |
vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7; |
if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_N0) |
vtx_size += 3; |
if (vtx_fmt_0 & R200_VTX_POINT_SIZE) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_SHININESS_0) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_SHININESS_1) |
vtx_size++; |
for (i = 0; i < 8; i++) { |
int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3; |
switch (color_size) { |
case 0: break; |
case 1: vtx_size++; break; |
case 2: vtx_size += 3; break; |
case 3: vtx_size += 4; break; |
} |
} |
if (vtx_fmt_0 & R200_VTX_XY1) |
vtx_size += 2; |
if (vtx_fmt_0 & R200_VTX_Z1) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_W1) |
vtx_size++; |
if (vtx_fmt_0 & R200_VTX_N1) |
vtx_size += 3; |
return vtx_size; |
} |
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1) |
{ |
int vtx_size, i, tex_size; |
vtx_size = 0; |
for (i = 0; i < 6; i++) { |
tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7; |
if (tex_size > 4) |
continue; |
vtx_size += tex_size; |
} |
return vtx_size; |
} |
int r200_packet0_check(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt, |
unsigned idx, unsigned reg) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r100_cs_track *track; |
volatile uint32_t *ib; |
uint32_t tmp; |
int r; |
int i; |
int face; |
u32 tile_flags = 0; |
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
track = (struct r100_cs_track *)p->track; |
switch (reg) { |
case RADEON_CRTC_GUI_TRIG_VLINE: |
r = r100_cs_packet_parse_vline(p); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
break; |
/* FIXME: only allow PACKET3 blit? easier to check for out of |
* range access */ |
case RADEON_DST_PITCH_OFFSET: |
case RADEON_SRC_PITCH_OFFSET: |
r = r100_reloc_pitch_offset(p, pkt, idx, reg); |
if (r) |
return r; |
break; |
case RADEON_RB3D_DEPTHOFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->zb.robj = reloc->robj; |
track->zb.offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_RB3D_COLOROFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->cb[0].robj = reloc->robj; |
track->cb[0].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case R200_PP_TXOFFSET_0: |
case R200_PP_TXOFFSET_1: |
case R200_PP_TXOFFSET_2: |
case R200_PP_TXOFFSET_3: |
case R200_PP_TXOFFSET_4: |
case R200_PP_TXOFFSET_5: |
i = (reg - R200_PP_TXOFFSET_0) / 24; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[i].robj = reloc->robj; |
break; |
case R200_PP_CUBIC_OFFSET_F1_0: |
case R200_PP_CUBIC_OFFSET_F2_0: |
case R200_PP_CUBIC_OFFSET_F3_0: |
case R200_PP_CUBIC_OFFSET_F4_0: |
case R200_PP_CUBIC_OFFSET_F5_0: |
case R200_PP_CUBIC_OFFSET_F1_1: |
case R200_PP_CUBIC_OFFSET_F2_1: |
case R200_PP_CUBIC_OFFSET_F3_1: |
case R200_PP_CUBIC_OFFSET_F4_1: |
case R200_PP_CUBIC_OFFSET_F5_1: |
case R200_PP_CUBIC_OFFSET_F1_2: |
case R200_PP_CUBIC_OFFSET_F2_2: |
case R200_PP_CUBIC_OFFSET_F3_2: |
case R200_PP_CUBIC_OFFSET_F4_2: |
case R200_PP_CUBIC_OFFSET_F5_2: |
case R200_PP_CUBIC_OFFSET_F1_3: |
case R200_PP_CUBIC_OFFSET_F2_3: |
case R200_PP_CUBIC_OFFSET_F3_3: |
case R200_PP_CUBIC_OFFSET_F4_3: |
case R200_PP_CUBIC_OFFSET_F5_3: |
case R200_PP_CUBIC_OFFSET_F1_4: |
case R200_PP_CUBIC_OFFSET_F2_4: |
case R200_PP_CUBIC_OFFSET_F3_4: |
case R200_PP_CUBIC_OFFSET_F4_4: |
case R200_PP_CUBIC_OFFSET_F5_4: |
case R200_PP_CUBIC_OFFSET_F1_5: |
case R200_PP_CUBIC_OFFSET_F2_5: |
case R200_PP_CUBIC_OFFSET_F3_5: |
case R200_PP_CUBIC_OFFSET_F4_5: |
case R200_PP_CUBIC_OFFSET_F5_5: |
i = (reg - R200_PP_TXOFFSET_0) / 24; |
face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4; |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
track->textures[i].cube_info[face - 1].offset = ib_chunk->kdata[idx]; |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
track->textures[i].cube_info[face - 1].robj = reloc->robj; |
break; |
case RADEON_RE_WIDTH_HEIGHT: |
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF); |
break; |
case RADEON_RB3D_COLORPITCH: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) |
tile_flags |= RADEON_COLOR_TILE_ENABLE; |
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; |
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); |
tmp |= tile_flags; |
ib[idx] = tmp; |
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK; |
break; |
case RADEON_RB3D_DEPTHPITCH: |
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK; |
break; |
case RADEON_RB3D_CNTL: |
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { |
case 7: |
case 8: |
case 9: |
case 11: |
case 12: |
track->cb[0].cpp = 1; |
break; |
case 3: |
case 4: |
case 15: |
track->cb[0].cpp = 2; |
break; |
case 6: |
track->cb[0].cpp = 4; |
break; |
default: |
DRM_ERROR("Invalid color buffer format (%d) !\n", |
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); |
return -EINVAL; |
} |
if (ib_chunk->kdata[idx] & RADEON_DEPTHXY_OFFSET_ENABLE) { |
DRM_ERROR("No support for depth xy offset in kms\n"); |
return -EINVAL; |
} |
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE); |
break; |
case RADEON_RB3D_ZSTENCILCNTL: |
switch (ib_chunk->kdata[idx] & 0xf) { |
case 0: |
track->zb.cpp = 2; |
break; |
case 2: |
case 3: |
case 4: |
case 5: |
case 9: |
case 11: |
track->zb.cpp = 4; |
break; |
default: |
break; |
} |
break; |
case RADEON_RB3D_ZPASS_ADDR: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case RADEON_PP_CNTL: |
{ |
uint32_t temp = ib_chunk->kdata[idx] >> 4; |
for (i = 0; i < track->num_texture; i++) |
track->textures[i].enabled = !!(temp & (1 << i)); |
} |
break; |
case RADEON_SE_VF_CNTL: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
break; |
case 0x210c: |
/* VAP_VF_MAX_VTX_INDX */ |
track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL; |
break; |
case R200_SE_VTX_FMT_0: |
track->vtx_size = r200_get_vtx_size_0(ib_chunk->kdata[idx]); |
break; |
case R200_SE_VTX_FMT_1: |
track->vtx_size += r200_get_vtx_size_1(ib_chunk->kdata[idx]); |
break; |
case R200_PP_TXSIZE_0: |
case R200_PP_TXSIZE_1: |
case R200_PP_TXSIZE_2: |
case R200_PP_TXSIZE_3: |
case R200_PP_TXSIZE_4: |
case R200_PP_TXSIZE_5: |
i = (reg - R200_PP_TXSIZE_0) / 32; |
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1; |
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; |
break; |
case R200_PP_TXPITCH_0: |
case R200_PP_TXPITCH_1: |
case R200_PP_TXPITCH_2: |
case R200_PP_TXPITCH_3: |
case R200_PP_TXPITCH_4: |
case R200_PP_TXPITCH_5: |
i = (reg - R200_PP_TXPITCH_0) / 32; |
track->textures[i].pitch = ib_chunk->kdata[idx] + 32; |
break; |
case R200_PP_TXFILTER_0: |
case R200_PP_TXFILTER_1: |
case R200_PP_TXFILTER_2: |
case R200_PP_TXFILTER_3: |
case R200_PP_TXFILTER_4: |
case R200_PP_TXFILTER_5: |
i = (reg - R200_PP_TXFILTER_0) / 32; |
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & R200_MAX_MIP_LEVEL_MASK) |
>> R200_MAX_MIP_LEVEL_SHIFT); |
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7; |
if (tmp == 2 || tmp == 6) |
track->textures[i].roundup_w = false; |
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7; |
if (tmp == 2 || tmp == 6) |
track->textures[i].roundup_h = false; |
break; |
case R200_PP_TXMULTI_CTL_0: |
case R200_PP_TXMULTI_CTL_1: |
case R200_PP_TXMULTI_CTL_2: |
case R200_PP_TXMULTI_CTL_3: |
case R200_PP_TXMULTI_CTL_4: |
case R200_PP_TXMULTI_CTL_5: |
i = (reg - R200_PP_TXMULTI_CTL_0) / 32; |
break; |
case R200_PP_TXFORMAT_X_0: |
case R200_PP_TXFORMAT_X_1: |
case R200_PP_TXFORMAT_X_2: |
case R200_PP_TXFORMAT_X_3: |
case R200_PP_TXFORMAT_X_4: |
case R200_PP_TXFORMAT_X_5: |
i = (reg - R200_PP_TXFORMAT_X_0) / 32; |
track->textures[i].txdepth = ib_chunk->kdata[idx] & 0x7; |
tmp = (ib_chunk->kdata[idx] >> 16) & 0x3; |
/* 2D, 3D, CUBE */ |
switch (tmp) { |
case 0: |
case 5: |
case 6: |
case 7: |
track->textures[i].tex_coord_type = 0; |
break; |
case 1: |
track->textures[i].tex_coord_type = 1; |
break; |
case 2: |
track->textures[i].tex_coord_type = 2; |
break; |
} |
break; |
case R200_PP_TXFORMAT_0: |
case R200_PP_TXFORMAT_1: |
case R200_PP_TXFORMAT_2: |
case R200_PP_TXFORMAT_3: |
case R200_PP_TXFORMAT_4: |
case R200_PP_TXFORMAT_5: |
i = (reg - R200_PP_TXFORMAT_0) / 32; |
if (ib_chunk->kdata[idx] & R200_TXFORMAT_NON_POWER2) { |
track->textures[i].use_pitch = 1; |
} else { |
track->textures[i].use_pitch = 0; |
track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); |
track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); |
} |
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) { |
case R200_TXFORMAT_I8: |
case R200_TXFORMAT_RGB332: |
case R200_TXFORMAT_Y8: |
track->textures[i].cpp = 1; |
break; |
case R200_TXFORMAT_DXT1: |
case R200_TXFORMAT_AI88: |
case R200_TXFORMAT_ARGB1555: |
case R200_TXFORMAT_RGB565: |
case R200_TXFORMAT_ARGB4444: |
case R200_TXFORMAT_VYUY422: |
case R200_TXFORMAT_YVYU422: |
case R200_TXFORMAT_LDVDU655: |
case R200_TXFORMAT_DVDU88: |
case R200_TXFORMAT_AVYU4444: |
track->textures[i].cpp = 2; |
break; |
case R200_TXFORMAT_ARGB8888: |
case R200_TXFORMAT_RGBA8888: |
case R200_TXFORMAT_ABGR8888: |
case R200_TXFORMAT_BGR111110: |
case R200_TXFORMAT_LDVDU8888: |
case R200_TXFORMAT_DXT23: |
case R200_TXFORMAT_DXT45: |
track->textures[i].cpp = 4; |
break; |
} |
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf); |
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf); |
break; |
case R200_PP_CUBIC_FACES_0: |
case R200_PP_CUBIC_FACES_1: |
case R200_PP_CUBIC_FACES_2: |
case R200_PP_CUBIC_FACES_3: |
case R200_PP_CUBIC_FACES_4: |
case R200_PP_CUBIC_FACES_5: |
tmp = ib_chunk->kdata[idx]; |
i = (reg - R200_PP_CUBIC_FACES_0) / 32; |
for (face = 0; face < 4; face++) { |
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); |
track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf); |
} |
break; |
default: |
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", |
reg, idx); |
return -EINVAL; |
} |
return 0; |
} |
#endif |
int r200_init(struct radeon_device *rdev) |
{ |
rdev->config.r100.reg_safe_bm = r200_reg_safe_bm; |
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm); |
return 0; |
} |
/drivers/video/drm/radeon/r200_reg_safe.h |
---|
0,0 → 1,28 |
static const unsigned r200_reg_safe_bm[102] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFE7FE1F, 0xF003FFFF, 0x7EFFFFFF, 0xFFFF803C, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFEFCE, 0xFFFEFFFF, 0xFFFFFFFE, |
0x020E0FF0, 0xFFFC83FD, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFBFFFF, 0xEFFCFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xDFDFDFDF, 0x3FFDDFDF, 0xFFFFFFFF, 0xFFFFFF7F, |
0xFFFFFFFF, 0x00FFFFFF, 0x00000000, 0x00000000, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFE3F, 0xFFFFFFEF, |
}; |
/drivers/video/drm/radeon/r300.c |
---|
25,12 → 25,17 |
* Alex Deucher |
* Jerome Glisse |
*/ |
//#include <linux/seq_file.h> |
#include <linux/seq_file.h> |
#include "drmP.h" |
#include "drm.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "radeon_drm.h" |
#include "r300d.h" |
#include "r300_reg_safe.h" |
/* r300,r350,rv350,rv370,rv380 depends on : */ |
void r100_hdp_reset(struct radeon_device *rdev); |
int r100_cp_reset(struct radeon_device *rdev); |
37,7 → 42,6 |
int r100_rb2d_reset(struct radeon_device *rdev); |
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); |
int r100_pci_gart_enable(struct radeon_device *rdev); |
void r100_pci_gart_disable(struct radeon_device *rdev); |
void r100_mc_setup(struct radeon_device *rdev); |
void r100_mc_disable_clients(struct radeon_device *rdev); |
int r100_gui_wait_for_idle(struct radeon_device *rdev); |
44,14 → 48,11 |
int r100_cs_packet_parse(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt, |
unsigned idx); |
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, |
struct radeon_cs_reloc **cs_reloc); |
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p); |
int r100_cs_parse_packet0(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt, |
const unsigned *auth, unsigned n, |
radeon_packet0_check_t check); |
void r100_cs_dump_packet(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt); |
int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt, |
struct radeon_object *robj); |
80,30 → 81,61 |
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB); |
(void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); |
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); |
} |
mb(); |
} |
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) |
{ |
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; |
if (i < 0 || i > rdev->gart.num_gpu_pages) { |
return -EINVAL; |
} |
addr = (lower_32_bits(addr) >> 8) | |
((upper_32_bits(addr) & 0xff) << 24) | |
0xc; |
/* on x86 we want this to be CPU endian, on powerpc |
* on powerpc without HW swappers, it'll get swapped on way |
* into VRAM - so no need for cpu_to_le32 on VRAM tables */ |
writel(addr, ((void __iomem *)ptr) + (i * 4)); |
return 0; |
} |
int rv370_pcie_gart_enable(struct radeon_device *rdev) |
int rv370_pcie_gart_init(struct radeon_device *rdev) |
{ |
uint32_t table_addr; |
uint32_t tmp; |
int r; |
if (rdev->gart.table.vram.robj) { |
WARN(1, "RV370 PCIE GART already initialized.\n"); |
return 0; |
} |
/* Initialize common gart structure */ |
r = radeon_gart_init(rdev); |
if (r) { |
if (r) |
return r; |
} |
r = rv370_debugfs_pcie_gart_info_init(rdev); |
if (r) { |
if (r) |
DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); |
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; |
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; |
return radeon_gart_table_vram_alloc(rdev); |
} |
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
r = radeon_gart_table_vram_alloc(rdev); |
if (r) { |
int rv370_pcie_gart_enable(struct radeon_device *rdev) |
{ |
uint32_t table_addr; |
uint32_t tmp; |
int r; |
if (rdev->gart.table.vram.robj == NULL) { |
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); |
return -EINVAL; |
} |
r = radeon_gart_table_vram_pin(rdev); |
if (r) |
return r; |
} |
/* discard memory request outside of configured range */ |
tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; |
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); |
125,7 → 157,7 |
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); |
rv370_pcie_gart_tlb_flush(rdev); |
DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n", |
rdev->mc.gtt_size >> 20, table_addr); |
(unsigned)(rdev->mc.gtt_size >> 20), table_addr); |
rdev->gart.ready = true; |
return 0; |
} |
143,40 → 175,13 |
} |
} |
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) |
void rv370_pcie_gart_fini(struct radeon_device *rdev) |
{ |
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; |
if (i < 0 || i > rdev->gart.num_gpu_pages) { |
return -EINVAL; |
} |
addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC; |
writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4)); |
return 0; |
} |
int r300_gart_enable(struct radeon_device *rdev) |
{ |
#if __OS_HAS_AGP |
if (rdev->flags & RADEON_IS_AGP) { |
if (rdev->family > CHIP_RV350) { |
rv370_pcie_gart_disable(rdev); |
} else { |
r100_pci_gart_disable(rdev); |
radeon_gart_table_vram_free(rdev); |
radeon_gart_fini(rdev); |
} |
return 0; |
} |
#endif |
if (rdev->flags & RADEON_IS_PCIE) { |
rdev->asic->gart_disable = &rv370_pcie_gart_disable; |
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; |
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; |
return rv370_pcie_gart_enable(rdev); |
} |
return r100_pci_gart_enable(rdev); |
} |
/* |
* MC |
*/ |
197,16 → 202,6 |
/* Setup GPU memory space */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
if (rdev->flags & RADEON_IS_AGP) { |
r = radeon_agp_init(rdev); |
if (r) { |
printk(KERN_WARNING "[drm] Disabling AGP\n"); |
rdev->flags &= ~RADEON_IS_AGP; |
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
} else { |
rdev->mc.gtt_location = rdev->mc.agp_base; |
} |
} |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
224,15 → 219,7 |
void r300_mc_fini(struct radeon_device *rdev) |
{ |
if (rdev->flags & RADEON_IS_PCIE) { |
rv370_pcie_gart_disable(rdev); |
radeon_gart_table_vram_free(rdev); |
} else { |
r100_pci_gart_disable(rdev); |
radeon_gart_table_ram_free(rdev); |
} |
radeon_gart_fini(rdev); |
} |
/* |
444,6 → 431,7 |
/* rv350,rv370,rv380 */ |
rdev->num_gb_pipes = 1; |
} |
rdev->num_z_pipes = 1; |
gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); |
switch (rdev->num_gb_pipes) { |
case 2: |
482,7 → 470,8 |
printk(KERN_WARNING "Failed to wait MC idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes); |
DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n", |
rdev->num_gb_pipes, rdev->num_z_pipes); |
} |
int r300_ga_reset(struct radeon_device *rdev) |
583,35 → 572,12 |
} else { |
rdev->mc.vram_width = 64; |
} |
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
r100_vram_init_sizes(rdev); |
} |
/* |
* Indirect registers accessor |
*/ |
uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) |
{ |
uint32_t r; |
WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff)); |
(void)RREG32(RADEON_PCIE_INDEX); |
r = RREG32(RADEON_PCIE_DATA); |
return r; |
} |
void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
{ |
WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff)); |
(void)RREG32(RADEON_PCIE_INDEX); |
WREG32(RADEON_PCIE_DATA, (v)); |
(void)RREG32(RADEON_PCIE_DATA); |
} |
/* |
* PCIE Lanes |
*/ |
722,304 → 688,6 |
/* |
* CS functions |
*/ |
struct r300_cs_track_cb { |
struct radeon_object *robj; |
unsigned pitch; |
unsigned cpp; |
unsigned offset; |
}; |
struct r300_cs_track_array { |
struct radeon_object *robj; |
unsigned esize; |
}; |
struct r300_cs_track_texture { |
struct radeon_object *robj; |
unsigned pitch; |
unsigned width; |
unsigned height; |
unsigned num_levels; |
unsigned cpp; |
unsigned tex_coord_type; |
unsigned txdepth; |
unsigned width_11; |
unsigned height_11; |
bool use_pitch; |
bool enabled; |
bool roundup_w; |
bool roundup_h; |
}; |
struct r300_cs_track { |
unsigned num_cb; |
unsigned maxy; |
unsigned vtx_size; |
unsigned vap_vf_cntl; |
unsigned immd_dwords; |
unsigned num_arrays; |
unsigned max_indx; |
struct r300_cs_track_array arrays[11]; |
struct r300_cs_track_cb cb[4]; |
struct r300_cs_track_cb zb; |
struct r300_cs_track_texture textures[16]; |
bool z_enabled; |
}; |
static inline void r300_cs_track_texture_print(struct r300_cs_track_texture *t) |
{ |
DRM_ERROR("pitch %d\n", t->pitch); |
DRM_ERROR("width %d\n", t->width); |
DRM_ERROR("height %d\n", t->height); |
DRM_ERROR("num levels %d\n", t->num_levels); |
DRM_ERROR("depth %d\n", t->txdepth); |
DRM_ERROR("bpp %d\n", t->cpp); |
DRM_ERROR("coordinate type %d\n", t->tex_coord_type); |
DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); |
DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); |
} |
static inline int r300_cs_track_texture_check(struct radeon_device *rdev, |
struct r300_cs_track *track) |
{ |
struct radeon_object *robj; |
unsigned long size; |
unsigned u, i, w, h; |
for (u = 0; u < 16; u++) { |
if (!track->textures[u].enabled) |
continue; |
robj = track->textures[u].robj; |
if (robj == NULL) { |
DRM_ERROR("No texture bound to unit %u\n", u); |
return -EINVAL; |
} |
size = 0; |
for (i = 0; i <= track->textures[u].num_levels; i++) { |
if (track->textures[u].use_pitch) { |
w = track->textures[u].pitch / (1 << i); |
} else { |
w = track->textures[u].width / (1 << i); |
if (rdev->family >= CHIP_RV515) |
w |= track->textures[u].width_11; |
if (track->textures[u].roundup_w) |
w = roundup_pow_of_two(w); |
} |
h = track->textures[u].height / (1 << i); |
if (rdev->family >= CHIP_RV515) |
h |= track->textures[u].height_11; |
if (track->textures[u].roundup_h) |
h = roundup_pow_of_two(h); |
size += w * h; |
} |
size *= track->textures[u].cpp; |
switch (track->textures[u].tex_coord_type) { |
case 0: |
break; |
case 1: |
size *= (1 << track->textures[u].txdepth); |
break; |
case 2: |
size *= 6; |
break; |
default: |
DRM_ERROR("Invalid texture coordinate type %u for unit " |
"%u\n", track->textures[u].tex_coord_type, u); |
return -EINVAL; |
} |
if (size > radeon_object_size(robj)) { |
DRM_ERROR("Texture of unit %u needs %lu bytes but is " |
"%lu\n", u, size, radeon_object_size(robj)); |
r300_cs_track_texture_print(&track->textures[u]); |
return -EINVAL; |
} |
} |
return 0; |
} |
int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track) |
{ |
unsigned i; |
unsigned long size; |
unsigned prim_walk; |
unsigned nverts; |
for (i = 0; i < track->num_cb; i++) { |
if (track->cb[i].robj == NULL) { |
DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); |
return -EINVAL; |
} |
size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; |
size += track->cb[i].offset; |
if (size > radeon_object_size(track->cb[i].robj)) { |
DRM_ERROR("[drm] Buffer too small for color buffer %d " |
"(need %lu have %lu) !\n", i, size, |
radeon_object_size(track->cb[i].robj)); |
DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", |
i, track->cb[i].pitch, track->cb[i].cpp, |
track->cb[i].offset, track->maxy); |
return -EINVAL; |
} |
} |
if (track->z_enabled) { |
if (track->zb.robj == NULL) { |
DRM_ERROR("[drm] No buffer for z buffer !\n"); |
return -EINVAL; |
} |
size = track->zb.pitch * track->zb.cpp * track->maxy; |
size += track->zb.offset; |
if (size > radeon_object_size(track->zb.robj)) { |
DRM_ERROR("[drm] Buffer too small for z buffer " |
"(need %lu have %lu) !\n", size, |
radeon_object_size(track->zb.robj)); |
return -EINVAL; |
} |
} |
prim_walk = (track->vap_vf_cntl >> 4) & 0x3; |
nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; |
switch (prim_walk) { |
case 1: |
for (i = 0; i < track->num_arrays; i++) { |
size = track->arrays[i].esize * track->max_indx * 4; |
if (track->arrays[i].robj == NULL) { |
DRM_ERROR("(PW %u) Vertex array %u no buffer " |
"bound\n", prim_walk, i); |
return -EINVAL; |
} |
if (size > radeon_object_size(track->arrays[i].robj)) { |
DRM_ERROR("(PW %u) Vertex array %u need %lu dwords " |
"have %lu dwords\n", prim_walk, i, |
size >> 2, |
radeon_object_size(track->arrays[i].robj) >> 2); |
DRM_ERROR("Max indices %u\n", track->max_indx); |
return -EINVAL; |
} |
} |
break; |
case 2: |
for (i = 0; i < track->num_arrays; i++) { |
size = track->arrays[i].esize * (nverts - 1) * 4; |
if (track->arrays[i].robj == NULL) { |
DRM_ERROR("(PW %u) Vertex array %u no buffer " |
"bound\n", prim_walk, i); |
return -EINVAL; |
} |
if (size > radeon_object_size(track->arrays[i].robj)) { |
DRM_ERROR("(PW %u) Vertex array %u need %lu dwords " |
"have %lu dwords\n", prim_walk, i, size >> 2, |
radeon_object_size(track->arrays[i].robj) >> 2); |
return -EINVAL; |
} |
} |
break; |
case 3: |
size = track->vtx_size * nverts; |
if (size != track->immd_dwords) { |
DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", |
track->immd_dwords, size); |
DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", |
nverts, track->vtx_size); |
return -EINVAL; |
} |
break; |
default: |
DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", |
prim_walk); |
return -EINVAL; |
} |
return r300_cs_track_texture_check(rdev, track); |
} |
static inline void r300_cs_track_clear(struct r300_cs_track *track) |
{ |
unsigned i; |
track->num_cb = 4; |
track->maxy = 4096; |
for (i = 0; i < track->num_cb; i++) { |
track->cb[i].robj = NULL; |
track->cb[i].pitch = 8192; |
track->cb[i].cpp = 16; |
track->cb[i].offset = 0; |
} |
track->z_enabled = true; |
track->zb.robj = NULL; |
track->zb.pitch = 8192; |
track->zb.cpp = 4; |
track->zb.offset = 0; |
track->vtx_size = 0x7F; |
track->immd_dwords = 0xFFFFFFFFUL; |
track->num_arrays = 11; |
track->max_indx = 0x00FFFFFFUL; |
for (i = 0; i < track->num_arrays; i++) { |
track->arrays[i].robj = NULL; |
track->arrays[i].esize = 0x7F; |
} |
for (i = 0; i < 16; i++) { |
track->textures[i].pitch = 16536; |
track->textures[i].width = 16536; |
track->textures[i].height = 16536; |
track->textures[i].width_11 = 1 << 11; |
track->textures[i].height_11 = 1 << 11; |
track->textures[i].num_levels = 12; |
track->textures[i].txdepth = 16; |
track->textures[i].cpp = 64; |
track->textures[i].tex_coord_type = 1; |
track->textures[i].robj = NULL; |
/* CS IB emission code makes sure texture unit are disabled */ |
track->textures[i].enabled = false; |
track->textures[i].roundup_w = true; |
track->textures[i].roundup_h = true; |
} |
} |
#endif |
static const unsigned r300_reg_safe_bm[159] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, |
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, |
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF, |
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, |
0x00000000, 0x0000C100, 0x00000000, 0x00000000, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x0003FC01, 0xFFFFFFF8, 0xFE800B19, |
}; |
#if 0 |
static int r300_packet0_check(struct radeon_cs_parser *p, |
struct radeon_cs_packet *pkt, |
unsigned idx, unsigned reg) |
1026,19 → 694,19 |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r300_cs_track *track; |
struct r100_cs_track *track; |
volatile uint32_t *ib; |
uint32_t tmp; |
uint32_t tmp, tile_flags = 0; |
unsigned i; |
int r; |
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
track = (struct r300_cs_track*)p->track; |
track = (struct r100_cs_track *)p->track; |
switch(reg) { |
case RADEON_DST_PITCH_OFFSET: |
case RADEON_SRC_PITCH_OFFSET: |
r = r100_cs_packet_next_reloc(p, &reloc); |
case AVIVO_D1MODE_VLINE_START_END: |
case RADEON_CRTC_GUI_TRIG_VLINE: |
r = r100_cs_packet_parse_vline(p); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
1045,10 → 713,13 |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
tmp = ib_chunk->kdata[idx] & 0x003fffff; |
tmp += (((u32)reloc->lobj.gpu_offset) >> 10); |
ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; |
break; |
case RADEON_DST_PITCH_OFFSET: |
case RADEON_SRC_PITCH_OFFSET: |
r = r100_reloc_pitch_offset(p, pkt, idx, reg); |
if (r) |
return r; |
break; |
case R300_RB3D_COLOROFFSET0: |
case R300_RB3D_COLOROFFSET1: |
case R300_RB3D_COLOROFFSET2: |
1136,6 → 807,23 |
/* RB3D_COLORPITCH1 */ |
/* RB3D_COLORPITCH2 */ |
/* RB3D_COLORPITCH3 */ |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) |
tile_flags |= R300_COLOR_TILE_ENABLE; |
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
tile_flags |= R300_COLOR_MICROTILE_ENABLE; |
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); |
tmp |= tile_flags; |
ib[idx] = tmp; |
i = (reg - 0x4E38) >> 2; |
track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; |
switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { |
1191,6 → 879,23 |
break; |
case 0x4F24: |
/* ZB_DEPTHPITCH */ |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) |
tile_flags |= R300_DEPTHMACROTILE_ENABLE; |
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) |
tile_flags |= R300_DEPTHMICROTILE_TILED;; |
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); |
tmp |= tile_flags; |
ib[idx] = tmp; |
track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; |
break; |
case 0x4104: |
1222,42 → 927,41 |
tmp = (ib_chunk->kdata[idx] >> 25) & 0x3; |
track->textures[i].tex_coord_type = tmp; |
switch ((ib_chunk->kdata[idx] & 0x1F)) { |
case 0: |
case 2: |
case 5: |
case 18: |
case 20: |
case 21: |
case R300_TX_FORMAT_X8: |
case R300_TX_FORMAT_Y4X4: |
case R300_TX_FORMAT_Z3Y3X2: |
track->textures[i].cpp = 1; |
break; |
case 1: |
case 3: |
case 6: |
case 7: |
case 10: |
case 11: |
case 19: |
case 22: |
case 24: |
case R300_TX_FORMAT_X16: |
case R300_TX_FORMAT_Y8X8: |
case R300_TX_FORMAT_Z5Y6X5: |
case R300_TX_FORMAT_Z6Y5X5: |
case R300_TX_FORMAT_W4Z4Y4X4: |
case R300_TX_FORMAT_W1Z5Y5X5: |
case R300_TX_FORMAT_DXT1: |
case R300_TX_FORMAT_D3DMFT_CxV8U8: |
case R300_TX_FORMAT_B8G8_B8G8: |
case R300_TX_FORMAT_G8R8_G8B8: |
track->textures[i].cpp = 2; |
break; |
case 4: |
case 8: |
case 9: |
case 12: |
case 13: |
case 23: |
case 25: |
case 27: |
case 30: |
case R300_TX_FORMAT_Y16X16: |
case R300_TX_FORMAT_Z11Y11X10: |
case R300_TX_FORMAT_Z10Y11X11: |
case R300_TX_FORMAT_W8Z8Y8X8: |
case R300_TX_FORMAT_W2Z10Y10X10: |
case 0x17: |
case R300_TX_FORMAT_FL_I32: |
case 0x1e: |
case R300_TX_FORMAT_DXT3: |
case R300_TX_FORMAT_DXT5: |
track->textures[i].cpp = 4; |
break; |
case 14: |
case 26: |
case 28: |
case R300_TX_FORMAT_W16Z16Y16X16: |
case R300_TX_FORMAT_FL_R16G16B16A16: |
case R300_TX_FORMAT_FL_I32A32: |
track->textures[i].cpp = 8; |
break; |
case 29: |
case R300_TX_FORMAT_FL_R32G32B32A32: |
track->textures[i].cpp = 16; |
break; |
default: |
1285,11 → 989,11 |
case 0x443C: |
/* TX_FILTER0_[0-15] */ |
i = (reg - 0x4400) >> 2; |
tmp = ib_chunk->kdata[idx] & 0x7;; |
tmp = ib_chunk->kdata[idx] & 0x7; |
if (tmp == 2 || tmp == 4 || tmp == 6) { |
track->textures[i].roundup_w = false; |
} |
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;; |
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7; |
if (tmp == 2 || tmp == 4 || tmp == 6) { |
track->textures[i].roundup_h = false; |
} |
1350,6 → 1054,21 |
tmp = (ib_chunk->kdata[idx] >> 22) & 0xF; |
track->textures[i].txdepth = tmp; |
break; |
case R300_ZB_ZPASS_ADDR: |
r = r100_cs_packet_next_reloc(p, &reloc); |
if (r) { |
DRM_ERROR("No reloc for ib[%d]=0x%04X\n", |
idx, reg); |
r100_cs_dump_packet(p, pkt); |
return r; |
} |
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); |
break; |
case 0x4be8: |
/* valid register only on RV530 */ |
if (p->rdev->family == CHIP_RV530) |
break; |
/* fallthrough do not move */ |
default: |
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", |
reg, idx); |
1362,8 → 1081,9 |
struct radeon_cs_packet *pkt) |
{ |
struct radeon_cs_chunk *ib_chunk; |
struct radeon_cs_reloc *reloc; |
struct r300_cs_track *track; |
struct r100_cs_track *track; |
volatile uint32_t *ib; |
unsigned idx; |
unsigned i, c; |
1372,7 → 1092,7 |
ib = p->ib->ptr; |
ib_chunk = &p->chunks[p->chunk_ib_idx]; |
idx = pkt->idx + 1; |
track = (struct r300_cs_track*)p->track; |
track = (struct r100_cs_track *)p->track; |
switch(pkt->opcode) { |
case PACKET3_3D_LOAD_VBPNTR: |
c = ib_chunk->kdata[idx++] & 0x1F; |
1439,7 → 1159,7 |
} |
track->vap_vf_cntl = ib_chunk->kdata[idx+1]; |
track->immd_dwords = pkt->count - 1; |
r = r300_cs_track_check(p->rdev, track); |
r = r100_cs_track_check(p->rdev, track); |
if (r) { |
return r; |
} |
1454,7 → 1174,7 |
} |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
track->immd_dwords = pkt->count; |
r = r300_cs_track_check(p->rdev, track); |
r = r100_cs_track_check(p->rdev, track); |
if (r) { |
return r; |
} |
1461,7 → 1181,7 |
break; |
case PACKET3_3D_DRAW_VBUF: |
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; |
r = r300_cs_track_check(p->rdev, track); |
r = r100_cs_track_check(p->rdev, track); |
if (r) { |
return r; |
} |
1468,7 → 1188,7 |
break; |
case PACKET3_3D_DRAW_VBUF_2: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
r = r300_cs_track_check(p->rdev, track); |
r = r100_cs_track_check(p->rdev, track); |
if (r) { |
return r; |
} |
1475,7 → 1195,7 |
break; |
case PACKET3_3D_DRAW_INDX: |
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; |
r = r300_cs_track_check(p->rdev, track); |
r = r100_cs_track_check(p->rdev, track); |
if (r) { |
return r; |
} |
1482,7 → 1202,7 |
break; |
case PACKET3_3D_DRAW_INDX_2: |
track->vap_vf_cntl = ib_chunk->kdata[idx]; |
r = r300_cs_track_check(p->rdev, track); |
r = r100_cs_track_check(p->rdev, track); |
if (r) { |
return r; |
} |
1499,11 → 1219,12 |
int r300_cs_parse(struct radeon_cs_parser *p) |
{ |
struct radeon_cs_packet pkt; |
struct r300_cs_track track; |
struct r100_cs_track *track; |
int r; |
r300_cs_track_clear(&track); |
p->track = &track; |
track = kzalloc(sizeof(*track), GFP_KERNEL); |
r100_cs_track_clear(p->rdev, track); |
p->track = track; |
do { |
r = r100_cs_packet_parse(p, &pkt, p->idx); |
if (r) { |
1532,14 → 1253,51 |
} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); |
return 0; |
} |
#endif |
int r300_init(struct radeon_device *rdev) |
void r300_set_reg_safe(struct radeon_device *rdev) |
{ |
rdev->config.r300.reg_safe_bm = r300_reg_safe_bm; |
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm); |
} |
int r300_init(struct radeon_device *rdev) |
{ |
r300_set_reg_safe(rdev); |
return 0; |
} |
void r300_mc_program(struct radeon_device *rdev) |
{ |
struct r100_mc_save save; |
int r; |
r = r100_debugfs_mc_info_init(rdev); |
if (r) { |
dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n"); |
} |
/* Stops all mc clients */ |
r100_mc_stop(rdev, &save); |
if (rdev->flags & RADEON_IS_AGP) { |
WREG32(R_00014C_MC_AGP_LOCATION, |
S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | |
S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); |
WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); |
WREG32(R_00015C_AGP_BASE_2, |
upper_32_bits(rdev->mc.agp_base) & 0xff); |
} else { |
WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); |
WREG32(R_000170_AGP_BASE, 0); |
WREG32(R_00015C_AGP_BASE_2, 0); |
} |
/* Wait for mc idle */ |
if (r300_mc_wait_for_idle(rdev)) |
DRM_INFO("Failed to wait MC idle before programming MC.\n"); |
/* Program MC, should be a 32bits limited address space */ |
WREG32(R_000148_MC_FB_LOCATION, |
S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | |
S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); |
r100_mc_resume(rdev, &save); |
} |
/drivers/video/drm/radeon/r300_reg.h |
---|
27,9 → 27,11 |
#ifndef _R300_REG_H_ |
#define _R300_REG_H_ |
#define R300_SURF_TILE_MACRO (1<<16) |
#define R300_SURF_TILE_MICRO (2<<16) |
#define R300_SURF_TILE_BOTH (3<<16) |
#define R300_MC_INIT_MISC_LAT_TIMER 0x180 |
# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 |
# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4 |
/drivers/video/drm/radeon/r300_reg_safe.h |
---|
0,0 → 1,42 |
static const unsigned r300_reg_safe_bm[159] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, |
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, |
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF, |
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, |
0x00000000, 0x0000C100, 0x00000000, 0x00000000, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x0003FC01, 0xFFFFFCF8, 0xFF800B19, |
}; |
/drivers/video/drm/radeon/r300d.h |
---|
0,0 → 1,101 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef __R300D_H__ |
#define __R300D_H__ |
#define CP_PACKET0 0x00000000 |
#define PACKET0_BASE_INDEX_SHIFT 0 |
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) |
#define PACKET0_COUNT_SHIFT 16 |
#define PACKET0_COUNT_MASK (0x3fff << 16) |
#define CP_PACKET1 0x40000000 |
#define CP_PACKET2 0x80000000 |
#define PACKET2_PAD_SHIFT 0 |
#define PACKET2_PAD_MASK (0x3fffffff << 0) |
#define CP_PACKET3 0xC0000000 |
#define PACKET3_IT_OPCODE_SHIFT 8 |
#define PACKET3_IT_OPCODE_MASK (0xff << 8) |
#define PACKET3_COUNT_SHIFT 16 |
#define PACKET3_COUNT_MASK (0x3fff << 16) |
/* PACKET3 op code */ |
#define PACKET3_NOP 0x10 |
#define PACKET3_3D_DRAW_VBUF 0x28 |
#define PACKET3_3D_DRAW_IMMD 0x29 |
#define PACKET3_3D_DRAW_INDX 0x2A |
#define PACKET3_3D_LOAD_VBPNTR 0x2F |
#define PACKET3_INDX_BUFFER 0x33 |
#define PACKET3_3D_DRAW_VBUF_2 0x34 |
#define PACKET3_3D_DRAW_IMMD_2 0x35 |
#define PACKET3_3D_DRAW_INDX_2 0x36 |
#define PACKET3_BITBLT_MULTI 0x9B |
#define PACKET0(reg, n) (CP_PACKET0 | \ |
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ |
REG_SET(PACKET0_COUNT, (n))) |
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) |
#define PACKET3(op, n) (CP_PACKET3 | \ |
REG_SET(PACKET3_IT_OPCODE, (op)) | \ |
REG_SET(PACKET3_COUNT, (n))) |
#define PACKET_TYPE0 0 |
#define PACKET_TYPE1 1 |
#define PACKET_TYPE2 2 |
#define PACKET_TYPE3 3 |
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) |
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) |
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) |
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) |
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) |
/* Registers */ |
#define R_000148_MC_FB_LOCATION 0x000148 |
#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0) |
#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF) |
#define C_000148_MC_FB_START 0xFFFF0000 |
#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16) |
#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF) |
#define C_000148_MC_FB_TOP 0x0000FFFF |
#define R_00014C_MC_AGP_LOCATION 0x00014C |
#define S_00014C_MC_AGP_START(x) (((x) & 0xFFFF) << 0) |
#define G_00014C_MC_AGP_START(x) (((x) >> 0) & 0xFFFF) |
#define C_00014C_MC_AGP_START 0xFFFF0000 |
#define S_00014C_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16) |
#define G_00014C_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF) |
#define C_00014C_MC_AGP_TOP 0x0000FFFF |
#define R_00015C_AGP_BASE_2 0x00015C |
#define S_00015C_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0) |
#define G_00015C_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF) |
#define C_00015C_AGP_BASE_ADDR_2 0xFFFFFFF0 |
#define R_000170_AGP_BASE 0x000170 |
#define S_000170_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0) |
#define G_000170_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF) |
#define C_000170_AGP_BASE_ADDR 0x00000000 |
#endif |
/drivers/video/drm/radeon/r420.c |
---|
0,0 → 1,385 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#include <linux/seq_file.h> |
#include "drmP.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "atom.h" |
#include "r420d.h" |
int r420_mc_init(struct radeon_device *rdev) |
{ |
int r; |
/* Setup GPU memory space */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
} |
return 0; |
} |
void r420_pipes_init(struct radeon_device *rdev) |
{ |
unsigned tmp; |
unsigned gb_pipe_select; |
unsigned num_pipes; |
/* GA_ENHANCE workaround TCL deadlock issue */ |
WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); |
/* add idle wait as per freedesktop.org bug 24041 */ |
if (r100_gui_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait GUI idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
/* get max number of pipes */ |
gb_pipe_select = RREG32(0x402C); |
num_pipes = ((gb_pipe_select >> 12) & 3) + 1; |
rdev->num_gb_pipes = num_pipes; |
tmp = 0; |
switch (num_pipes) { |
default: |
/* force to 1 pipe */ |
num_pipes = 1; |
case 1: |
tmp = (0 << 1); |
break; |
case 2: |
tmp = (3 << 1); |
break; |
case 3: |
tmp = (6 << 1); |
break; |
case 4: |
tmp = (7 << 1); |
break; |
} |
WREG32(0x42C8, (1 << num_pipes) - 1); |
/* Sub pixel 1/12 so we can have 4K rendering according to doc */ |
tmp |= (1 << 4) | (1 << 0); |
WREG32(0x4018, tmp); |
if (r100_gui_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait GUI idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
tmp = RREG32(0x170C); |
WREG32(0x170C, tmp | (1 << 31)); |
WREG32(R300_RB2D_DSTCACHE_MODE, |
RREG32(R300_RB2D_DSTCACHE_MODE) | |
R300_DC_AUTOFLUSH_ENABLE | |
R300_DC_DC_DISABLE_IGNORE_PE); |
if (r100_gui_wait_for_idle(rdev)) { |
printk(KERN_WARNING "Failed to wait GUI idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
if (rdev->family == CHIP_RV530) { |
tmp = RREG32(RV530_GB_PIPE_SELECT2); |
if ((tmp & 3) == 3) |
rdev->num_z_pipes = 2; |
else |
rdev->num_z_pipes = 1; |
} else |
rdev->num_z_pipes = 1; |
DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n", |
rdev->num_gb_pipes, rdev->num_z_pipes); |
} |
u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) |
{ |
u32 r; |
WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); |
r = RREG32(R_0001FC_MC_IND_DATA); |
return r; |
} |
void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) |
{ |
WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | |
S_0001F8_MC_IND_WR_EN(1)); |
WREG32(R_0001FC_MC_IND_DATA, v); |
} |
static void r420_debugfs(struct radeon_device *rdev) |
{ |
if (r100_debugfs_rbbm_init(rdev)) { |
DRM_ERROR("Failed to register debugfs file for RBBM !\n"); |
} |
if (r420_debugfs_pipes_info_init(rdev)) { |
DRM_ERROR("Failed to register debugfs file for pipes !\n"); |
} |
} |
static void r420_clock_resume(struct radeon_device *rdev) |
{ |
u32 sclk_cntl; |
sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL); |
sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); |
if (rdev->family == CHIP_R420) |
sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1); |
WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); |
} |
static int r420_startup(struct radeon_device *rdev) |
{ |
int r; |
r300_mc_program(rdev); |
/* Initialize GART (initialize after TTM so we can allocate |
* memory through TTM but finalize after TTM) */ |
if (rdev->flags & RADEON_IS_PCIE) { |
r = rv370_pcie_gart_enable(rdev); |
if (r) |
return r; |
} |
if (rdev->flags & RADEON_IS_PCI) { |
r = r100_pci_gart_enable(rdev); |
if (r) |
return r; |
} |
r420_pipes_init(rdev); |
/* Enable IRQ */ |
// rdev->irq.sw_int = true; |
// r100_irq_set(rdev); |
/* 1M ring buffer */ |
r = r100_cp_init(rdev, 1024 * 1024); |
if (r) { |
dev_err(rdev->dev, "failled initializing CP (%d).\n", r); |
return r; |
} |
// r = r100_wb_init(rdev); |
// if (r) { |
// dev_err(rdev->dev, "failled initializing WB (%d).\n", r); |
// } |
// r = r100_ib_init(rdev); |
// if (r) { |
// dev_err(rdev->dev, "failled initializing IB (%d).\n", r); |
// return r; |
// } |
return 0; |
} |
int r420_resume(struct radeon_device *rdev) |
{ |
/* Make sur GART are not working */ |
if (rdev->flags & RADEON_IS_PCIE) |
rv370_pcie_gart_disable(rdev); |
if (rdev->flags & RADEON_IS_PCI) |
r100_pci_gart_disable(rdev); |
/* Resume clock before doing reset */ |
r420_clock_resume(rdev); |
/* Reset gpu before posting otherwise ATOM will enter infinite loop */ |
if (radeon_gpu_reset(rdev)) { |
dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", |
RREG32(R_000E40_RBBM_STATUS), |
RREG32(R_0007C0_CP_STAT)); |
} |
/* check if cards are posted or not */ |
if (rdev->is_atom_bios) { |
atom_asic_init(rdev->mode_info.atom_context); |
} else { |
radeon_combios_asic_init(rdev->ddev); |
} |
/* Resume clock after posting */ |
r420_clock_resume(rdev); |
return r420_startup(rdev); |
} |
int r420_suspend(struct radeon_device *rdev) |
{ |
r100_cp_disable(rdev); |
// r100_wb_disable(rdev); |
// r100_irq_disable(rdev); |
if (rdev->flags & RADEON_IS_PCIE) |
rv370_pcie_gart_disable(rdev); |
if (rdev->flags & RADEON_IS_PCI) |
r100_pci_gart_disable(rdev); |
return 0; |
} |
void r420_fini(struct radeon_device *rdev) |
{ |
r100_cp_fini(rdev); |
// r100_wb_fini(rdev); |
// r100_ib_fini(rdev); |
radeon_gem_fini(rdev); |
if (rdev->flags & RADEON_IS_PCIE) |
rv370_pcie_gart_fini(rdev); |
if (rdev->flags & RADEON_IS_PCI) |
r100_pci_gart_fini(rdev); |
// radeon_agp_fini(rdev); |
// radeon_irq_kms_fini(rdev); |
// radeon_fence_driver_fini(rdev); |
// radeon_object_fini(rdev); |
if (rdev->is_atom_bios) { |
radeon_atombios_fini(rdev); |
} else { |
radeon_combios_fini(rdev); |
} |
kfree(rdev->bios); |
rdev->bios = NULL; |
} |
int r420_init(struct radeon_device *rdev) |
{ |
int r; |
rdev->new_init_path = true; |
/* Initialize scratch registers */ |
radeon_scratch_init(rdev); |
/* Initialize surface registers */ |
radeon_surface_init(rdev); |
/* TODO: disable VGA need to use VGA request */ |
/* BIOS*/ |
if (!radeon_get_bios(rdev)) { |
if (ASIC_IS_AVIVO(rdev)) |
return -EINVAL; |
} |
if (rdev->is_atom_bios) { |
r = radeon_atombios_init(rdev); |
if (r) { |
return r; |
} |
} else { |
r = radeon_combios_init(rdev); |
if (r) { |
return r; |
} |
} |
/* Reset gpu before posting otherwise ATOM will enter infinite loop */ |
if (radeon_gpu_reset(rdev)) { |
dev_warn(rdev->dev, |
"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", |
RREG32(R_000E40_RBBM_STATUS), |
RREG32(R_0007C0_CP_STAT)); |
} |
/* check if cards are posted or not */ |
if (!radeon_card_posted(rdev) && rdev->bios) { |
DRM_INFO("GPU not posted. posting now...\n"); |
if (rdev->is_atom_bios) { |
atom_asic_init(rdev->mode_info.atom_context); |
} else { |
radeon_combios_asic_init(rdev->ddev); |
} |
} |
/* Initialize clocks */ |
radeon_get_clock_info(rdev->ddev); |
/* Get vram informations */ |
r300_vram_info(rdev); |
/* Initialize memory controller (also test AGP) */ |
r = r420_mc_init(rdev); |
if (r) { |
return r; |
} |
r420_debugfs(rdev); |
/* Fence driver */ |
// r = radeon_fence_driver_init(rdev); |
// if (r) { |
// return r; |
// } |
// r = radeon_irq_kms_init(rdev); |
// if (r) { |
// return r; |
// } |
/* Memory manager */ |
r = radeon_object_init(rdev); |
if (r) { |
return r; |
} |
if (rdev->flags & RADEON_IS_PCIE) { |
r = rv370_pcie_gart_init(rdev); |
if (r) |
return r; |
} |
if (rdev->flags & RADEON_IS_PCI) { |
r = r100_pci_gart_init(rdev); |
if (r) |
return r; |
} |
r300_set_reg_safe(rdev); |
rdev->accel_working = true; |
r = r420_startup(rdev); |
if (r) { |
/* Somethings want wront with the accel init stop accel */ |
dev_err(rdev->dev, "Disabling GPU acceleration\n"); |
r420_suspend(rdev); |
// r100_cp_fini(rdev); |
// r100_wb_fini(rdev); |
// r100_ib_fini(rdev); |
if (rdev->flags & RADEON_IS_PCIE) |
rv370_pcie_gart_fini(rdev); |
if (rdev->flags & RADEON_IS_PCI) |
r100_pci_gart_fini(rdev); |
// radeon_agp_fini(rdev); |
// radeon_irq_kms_fini(rdev); |
rdev->accel_working = false; |
} |
return 0; |
} |
/* |
* Debugfs info |
*/ |
#if defined(CONFIG_DEBUG_FS) |
static int r420_debugfs_pipes_info(struct seq_file *m, void *data) |
{ |
struct drm_info_node *node = (struct drm_info_node *) m->private; |
struct drm_device *dev = node->minor->dev; |
struct radeon_device *rdev = dev->dev_private; |
uint32_t tmp; |
tmp = RREG32(R400_GB_PIPE_SELECT); |
seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); |
tmp = RREG32(R300_GB_TILE_CONFIG); |
seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); |
tmp = RREG32(R300_DST_PIPE_CONFIG); |
seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); |
return 0; |
} |
static struct drm_info_list r420_pipes_info_list[] = { |
{"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL}, |
}; |
#endif |
int r420_debugfs_pipes_info_init(struct radeon_device *rdev) |
{ |
#if defined(CONFIG_DEBUG_FS) |
return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1); |
#else |
return 0; |
#endif |
} |
/drivers/video/drm/radeon/r420d.h |
---|
0,0 → 1,249 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef R420D_H |
#define R420D_H |
#define R_0001F8_MC_IND_INDEX 0x0001F8 |
#define S_0001F8_MC_IND_ADDR(x) (((x) & 0x7F) << 0) |
#define G_0001F8_MC_IND_ADDR(x) (((x) >> 0) & 0x7F) |
#define C_0001F8_MC_IND_ADDR 0xFFFFFF80 |
#define S_0001F8_MC_IND_WR_EN(x) (((x) & 0x1) << 8) |
#define G_0001F8_MC_IND_WR_EN(x) (((x) >> 8) & 0x1) |
#define C_0001F8_MC_IND_WR_EN 0xFFFFFEFF |
#define R_0001FC_MC_IND_DATA 0x0001FC |
#define S_0001FC_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0) |
#define G_0001FC_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF) |
#define C_0001FC_MC_IND_DATA 0x00000000 |
#define R_0007C0_CP_STAT 0x0007C0 |
#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0) |
#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1) |
#define C_0007C0_MRU_BUSY 0xFFFFFFFE |
#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1) |
#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1) |
#define C_0007C0_MWU_BUSY 0xFFFFFFFD |
#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2) |
#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1) |
#define C_0007C0_RSIU_BUSY 0xFFFFFFFB |
#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3) |
#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1) |
#define C_0007C0_RCIU_BUSY 0xFFFFFFF7 |
#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9) |
#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1) |
#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF |
#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10) |
#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1) |
#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF |
#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11) |
#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1) |
#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF |
#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12) |
#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1) |
#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF |
#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13) |
#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1) |
#define C_0007C0_CSI_BUSY 0xFFFFDFFF |
#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14) |
#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1) |
#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF |
#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15) |
#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1) |
#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF |
#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28) |
#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1) |
#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF |
#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29) |
#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1) |
#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF |
#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30) |
#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1) |
#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF |
#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31) |
#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1) |
#define C_0007C0_CP_BUSY 0x7FFFFFFF |
#define R_000E40_RBBM_STATUS 0x000E40 |
#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0) |
#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F) |
#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80 |
#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8) |
#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1) |
#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF |
#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9) |
#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1) |
#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF |
#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10) |
#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1) |
#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF |
#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11) |
#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1) |
#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF |
#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12) |
#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1) |
#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF |
#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13) |
#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1) |
#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF |
#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14) |
#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1) |
#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF |
#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15) |
#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1) |
#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF |
#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16) |
#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1) |
#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF |
#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17) |
#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1) |
#define C_000E40_E2_BUSY 0xFFFDFFFF |
#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18) |
#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1) |
#define C_000E40_RB2D_BUSY 0xFFFBFFFF |
#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19) |
#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1) |
#define C_000E40_RB3D_BUSY 0xFFF7FFFF |
#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20) |
#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1) |
#define C_000E40_VAP_BUSY 0xFFEFFFFF |
#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21) |
#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1) |
#define C_000E40_RE_BUSY 0xFFDFFFFF |
#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22) |
#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1) |
#define C_000E40_TAM_BUSY 0xFFBFFFFF |
#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23) |
#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1) |
#define C_000E40_TDM_BUSY 0xFF7FFFFF |
#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24) |
#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1) |
#define C_000E40_PB_BUSY 0xFEFFFFFF |
#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25) |
#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1) |
#define C_000E40_TIM_BUSY 0xFDFFFFFF |
#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26) |
#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1) |
#define C_000E40_GA_BUSY 0xFBFFFFFF |
#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27) |
#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1) |
#define C_000E40_CBA2D_BUSY 0xF7FFFFFF |
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31) |
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1) |
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF |
/* CLK registers */ |
#define R_00000D_SCLK_CNTL 0x00000D |
#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0) |
#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7) |
#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8 |
#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3) |
#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1) |
#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7 |
#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4) |
#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1) |
#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF |
#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5) |
#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1) |
#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF |
#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6) |
#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1) |
#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF |
#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7) |
#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1) |
#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F |
#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8) |
#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1) |
#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF |
#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9) |
#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1) |
#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF |
#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10) |
#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1) |
#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF |
#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11) |
#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1) |
#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF |
#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12) |
#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1) |
#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF |
#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13) |
#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1) |
#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF |
#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14) |
#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1) |
#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF |
#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15) |
#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1) |
#define C_00000D_FORCE_DISP2 0xFFFF7FFF |
#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16) |
#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1) |
#define C_00000D_FORCE_CP 0xFFFEFFFF |
#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17) |
#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1) |
#define C_00000D_FORCE_HDP 0xFFFDFFFF |
#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18) |
#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1) |
#define C_00000D_FORCE_DISP1 0xFFFBFFFF |
#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19) |
#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1) |
#define C_00000D_FORCE_TOP 0xFFF7FFFF |
#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20) |
#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1) |
#define C_00000D_FORCE_E2 0xFFEFFFFF |
#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21) |
#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1) |
#define C_00000D_FORCE_SE 0xFFDFFFFF |
#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22) |
#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1) |
#define C_00000D_FORCE_IDCT 0xFFBFFFFF |
#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23) |
#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1) |
#define C_00000D_FORCE_VIP 0xFF7FFFFF |
#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24) |
#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1) |
#define C_00000D_FORCE_RE 0xFEFFFFFF |
#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25) |
#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1) |
#define C_00000D_FORCE_PB 0xFDFFFFFF |
#define S_00000D_FORCE_PX(x) (((x) & 0x1) << 26) |
#define G_00000D_FORCE_PX(x) (((x) >> 26) & 0x1) |
#define C_00000D_FORCE_PX 0xFBFFFFFF |
#define S_00000D_FORCE_TX(x) (((x) & 0x1) << 27) |
#define G_00000D_FORCE_TX(x) (((x) >> 27) & 0x1) |
#define C_00000D_FORCE_TX 0xF7FFFFFF |
#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28) |
#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1) |
#define C_00000D_FORCE_RB 0xEFFFFFFF |
#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29) |
#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1) |
#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF |
#define S_00000D_FORCE_SUBPIC(x) (((x) & 0x1) << 30) |
#define G_00000D_FORCE_SUBPIC(x) (((x) >> 30) & 0x1) |
#define C_00000D_FORCE_SUBPIC 0xBFFFFFFF |
#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31) |
#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1) |
#define C_00000D_FORCE_OV0 0x7FFFFFFF |
#endif |
/drivers/video/drm/radeon/r500_reg.h |
---|
350,6 → 350,7 |
#define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 |
#define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 |
#define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c |
#define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 |
#define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 |
/* master controls */ |
438,13 → 439,15 |
# define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4 |
# define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff |
#define R500_DxMODE_INT_MASK 0x6540 |
#define R500_D1MODE_INT_MASK (1<<0) |
#define R500_D2MODE_INT_MASK (1<<8) |
#define AVIVO_D1MODE_DATA_FORMAT 0x6528 |
# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) |
#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C |
#define AVIVO_D1MODE_VBLANK_STATUS 0x6534 |
# define AVIVO_VBLANK_ACK (1 << 4) |
#define AVIVO_D1MODE_VLINE_START_END 0x6538 |
#define AVIVO_DxMODE_INT_MASK 0x6540 |
# define AVIVO_D1MODE_INT_MASK (1 << 0) |
# define AVIVO_D2MODE_INT_MASK (1 << 8) |
#define AVIVO_D1MODE_VIEWPORT_START 0x6580 |
#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 |
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 |
474,6 → 477,7 |
#define AVIVO_D2CRTC_BLANK_CONTROL 0x6884 |
#define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888 |
#define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c |
#define AVIVO_D2CRTC_FRAME_COUNT 0x68a4 |
#define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4 |
#define AVIVO_D2GRPH_ENABLE 0x6900 |
496,6 → 500,8 |
#define AVIVO_D2CUR_SIZE 0x6c10 |
#define AVIVO_D2CUR_POSITION 0x6c14 |
#define AVIVO_D2MODE_VBLANK_STATUS 0x6d34 |
#define AVIVO_D2MODE_VLINE_START_END 0x6d38 |
#define AVIVO_D2MODE_VIEWPORT_START 0x6d80 |
#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 |
#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 |
746,4 → 752,8 |
# define AVIVO_I2C_EN (1 << 0) |
# define AVIVO_I2C_RESET (1 << 8) |
#define AVIVO_DISP_INTERRUPT_STATUS 0x7edc |
# define AVIVO_D1_VBLANK_INTERRUPT (1 << 4) |
# define AVIVO_D2_VBLANK_INTERRUPT (1 << 5) |
#endif |
/drivers/video/drm/radeon/r520.c |
---|
31,8 → 31,6 |
/* r520,rv530,rv560,rv570,r580 depends on : */ |
void r100_hdp_reset(struct radeon_device *rdev); |
int rv370_pcie_gart_enable(struct radeon_device *rdev); |
void rv370_pcie_gart_disable(struct radeon_device *rdev); |
void r420_pipes_init(struct radeon_device *rdev); |
void rs600_mc_disable_clients(struct radeon_device *rdev); |
void rs600_disable_vga(struct radeon_device *rdev); |
47,6 → 45,7 |
void r520_gpu_init(struct radeon_device *rdev); |
int r520_mc_wait_for_idle(struct radeon_device *rdev); |
/* |
* MC |
*/ |
55,7 → 54,7 |
uint32_t tmp; |
int r; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
if (r100_debugfs_rbbm_init(rdev)) { |
DRM_ERROR("Failed to register debugfs file for RBBM !\n"); |
73,16 → 72,6 |
/* Setup GPU memory space */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
if (rdev->flags & RADEON_IS_AGP) { |
r = radeon_agp_init(rdev); |
if (r) { |
printk(KERN_WARNING "[drm] Disabling AGP\n"); |
rdev->flags &= ~RADEON_IS_AGP; |
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
} else { |
rdev->mc.gtt_location = rdev->mc.agp_base; |
} |
} |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
95,8 → 84,8 |
"programming pipes. Bad things might happen.\n"); |
} |
/* Write VRAM size in case we are limiting it */ |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32_MC(R520_MC_FB_LOCATION, tmp); |
115,7 → 104,7 |
WREG32_MC(R520_MC_AGP_BASE_2, 0); |
} |
dbgprintf("done: %s\n",__FUNCTION__); |
LEAVE(); |
return 0; |
} |
122,9 → 111,6 |
void r520_mc_fini(struct radeon_device *rdev) |
{ |
rv370_pcie_gart_disable(rdev); |
radeon_gart_table_vram_free(rdev); |
radeon_gart_fini(rdev); |
} |
155,7 → 141,7 |
void r520_gpu_init(struct radeon_device *rdev) |
{ |
unsigned pipe_select_current, gb_pipe_select, tmp; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
r100_hdp_reset(rdev); |
rs600_disable_vga(rdev); |
181,7 → 167,6 |
*/ |
/* workaround for RV530 */ |
if (rdev->family == CHIP_RV530) { |
WREG32(0x4124, 1); |
WREG32(0x4128, 0xFF); |
} |
r420_pipes_init(rdev); |
204,7 → 189,7 |
static void r520_vram_get_type(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
rdev->mc.vram_width = 128; |
rdev->mc.vram_is_ddr = true; |
232,164 → 217,20 |
void r520_vram_info(struct radeon_device *rdev) |
{ |
fixed20_12 a; |
r520_vram_get_type(rdev); |
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
r100_vram_init_sizes(rdev); |
/* FIXME: we should enforce default clock in case GPU is not in |
* default setup |
*/ |
a.full = rfixed_const(100); |
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); |
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); |
} |
int radeon_agp_init(struct radeon_device *rdev) |
void r520_bandwidth_update(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
#if __OS_HAS_AGP |
struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list; |
struct drm_agp_mode mode; |
struct drm_agp_info info; |
uint32_t agp_status; |
int default_mode; |
bool is_v3; |
int ret; |
/* Acquire AGP. */ |
if (!rdev->ddev->agp->acquired) { |
ret = drm_agp_acquire(rdev->ddev); |
if (ret) { |
DRM_ERROR("Unable to acquire AGP: %d\n", ret); |
return ret; |
rv515_bandwidth_avivo_update(rdev); |
} |
} |
ret = drm_agp_info(rdev->ddev, &info); |
if (ret) { |
DRM_ERROR("Unable to get AGP info: %d\n", ret); |
return ret; |
} |
mode.mode = info.mode; |
agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode; |
is_v3 = !!(agp_status & RADEON_AGPv3_MODE); |
if (is_v3) { |
default_mode = (agp_status & RADEON_AGPv3_8X_MODE) ? 8 : 4; |
} else { |
if (agp_status & RADEON_AGP_4X_MODE) { |
default_mode = 4; |
} else if (agp_status & RADEON_AGP_2X_MODE) { |
default_mode = 2; |
} else { |
default_mode = 1; |
} |
} |
/* Apply AGPMode Quirks */ |
while (p && p->chip_device != 0) { |
if (info.id_vendor == p->hostbridge_vendor && |
info.id_device == p->hostbridge_device && |
rdev->pdev->vendor == p->chip_vendor && |
rdev->pdev->device == p->chip_device && |
rdev->pdev->subsystem_vendor == p->subsys_vendor && |
rdev->pdev->subsystem_device == p->subsys_device) { |
default_mode = p->default_mode; |
} |
++p; |
} |
if (radeon_agpmode > 0) { |
if ((radeon_agpmode < (is_v3 ? 4 : 1)) || |
(radeon_agpmode > (is_v3 ? 8 : 4)) || |
(radeon_agpmode & (radeon_agpmode - 1))) { |
DRM_ERROR("Illegal AGP Mode: %d (valid %s), leaving at %d\n", |
radeon_agpmode, is_v3 ? "4, 8" : "1, 2, 4", |
default_mode); |
radeon_agpmode = default_mode; |
} else { |
DRM_INFO("AGP mode requested: %d\n", radeon_agpmode); |
} |
} else { |
radeon_agpmode = default_mode; |
} |
mode.mode &= ~RADEON_AGP_MODE_MASK; |
if (is_v3) { |
switch (radeon_agpmode) { |
case 8: |
mode.mode |= RADEON_AGPv3_8X_MODE; |
break; |
case 4: |
default: |
mode.mode |= RADEON_AGPv3_4X_MODE; |
break; |
} |
} else { |
switch (radeon_agpmode) { |
case 4: |
mode.mode |= RADEON_AGP_4X_MODE; |
break; |
case 2: |
mode.mode |= RADEON_AGP_2X_MODE; |
break; |
case 1: |
default: |
mode.mode |= RADEON_AGP_1X_MODE; |
break; |
} |
} |
mode.mode &= ~RADEON_AGP_FW_MODE; /* disable fw */ |
ret = drm_agp_enable(rdev->ddev, mode); |
if (ret) { |
DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); |
return ret; |
} |
rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base; |
rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20; |
/* workaround some hw issues */ |
if (rdev->family < CHIP_R200) { |
WREG32(RADEON_AGP_CNTL, RREG32(RADEON_AGP_CNTL) | 0x000e0000); |
} |
return 0; |
#else |
return 0; |
#endif |
} |
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); |
int radeon_fence_driver_init(struct radeon_device *rdev) |
{ |
unsigned long irq_flags; |
int r; |
// write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); |
r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg); |
if (r) { |
DRM_ERROR("Fence failed to get a scratch register."); |
// write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); |
return r; |
} |
WREG32(rdev->fence_drv.scratch_reg, 0); |
// atomic_set(&rdev->fence_drv.seq, 0); |
// INIT_LIST_HEAD(&rdev->fence_drv.created); |
// INIT_LIST_HEAD(&rdev->fence_drv.emited); |
// INIT_LIST_HEAD(&rdev->fence_drv.signaled); |
rdev->fence_drv.count_timeout = 0; |
// init_waitqueue_head(&rdev->fence_drv.queue); |
// write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); |
// if (radeon_debugfs_fence_init(rdev)) { |
// DRM_ERROR("Failed to register debugfs file for fence !\n"); |
// } |
return 0; |
} |
/drivers/video/drm/radeon/r600.c |
---|
67,7 → 67,7 |
"programming pipes. Bad things might happen.\n"); |
} |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24); |
tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24); |
WREG32(R600_MC_VM_FB_LOCATION, tmp); |
140,7 → 140,8 |
void r600_vram_info(struct radeon_device *rdev) |
{ |
r600_vram_get_type(rdev); |
rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE); |
rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE); |
rdev->mc.mc_vram_size = rdev->mc.real_vram_size; |
/* Could aper size report 0 ? */ |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
/drivers/video/drm/radeon/radeon.h |
---|
45,18 → 45,23 |
*/ |
#include <types.h> |
#include <list.h> |
#include <linux/list.h> |
#include <pci.h> |
#include <errno-base.h> |
#include "drm_edid.h" |
#include "radeon_family.h" |
#include "radeon_mode.h" |
#include "radeon_reg.h" |
#include "r300.h" |
#include <syscall.h> |
/* |
* Modules parameters. |
*/ |
extern int radeon_no_wb; |
extern int radeon_modeset; |
extern int radeon_dynclks; |
extern int radeon_r4xx_atom; |
64,8 → 69,62 |
extern int radeon_vram_limit; |
extern int radeon_gart_size; |
extern int radeon_benchmarking; |
extern int radeon_testing; |
extern int radeon_connector_table; |
extern int radeon_tv; |
static inline uint8_t __raw_readb(const volatile void __iomem *addr) |
{ |
return *(const volatile uint8_t __force *) addr; |
} |
static inline uint16_t __raw_readw(const volatile void __iomem *addr) |
{ |
return *(const volatile uint16_t __force *) addr; |
} |
static inline uint32_t __raw_readl(const volatile void __iomem *addr) |
{ |
return *(const volatile uint32_t __force *) addr; |
} |
#define readb __raw_readb |
#define readw __raw_readw |
#define readl __raw_readl |
static inline void __raw_writeb(uint8_t b, volatile void __iomem *addr) |
{ |
*(volatile uint8_t __force *) addr = b; |
} |
static inline void __raw_writew(uint16_t b, volatile void __iomem *addr) |
{ |
*(volatile uint16_t __force *) addr = b; |
} |
static inline void __raw_writel(uint32_t b, volatile void __iomem *addr) |
{ |
*(volatile uint32_t __force *) addr = b; |
} |
static inline void __raw_writeq(__u64 b, volatile void __iomem *addr) |
{ |
*(volatile __u64 *)addr = b; |
} |
#define writeb __raw_writeb |
#define writew __raw_writew |
#define writel __raw_writel |
#define writeq __raw_writeq |
//#define writeb(b,addr) *(volatile uint8_t* ) addr = (uint8_t)b |
//#define writew(b,addr) *(volatile uint16_t*) addr = (uint16_t)b |
//#define writel(b,addr) *(volatile uint32_t*) addr = (uint32_t)b |
/* |
* Copy from radeon_drv.h so we don't have to include both and have conflicting |
* symbol; |
74,63 → 133,8 |
#define RADEON_IB_POOL_SIZE 16 |
#define RADEON_DEBUGFS_MAX_NUM_FILES 32 |
#define RADEONFB_CONN_LIMIT 4 |
#define RADEON_BIOS_NUM_SCRATCH 8 |
enum radeon_family { |
CHIP_R100, |
CHIP_RV100, |
CHIP_RS100, |
CHIP_RV200, |
CHIP_RS200, |
CHIP_R200, |
CHIP_RV250, |
CHIP_RS300, |
CHIP_RV280, |
CHIP_R300, |
CHIP_R350, |
CHIP_RV350, |
CHIP_RV380, |
CHIP_R420, |
CHIP_R423, |
CHIP_RV410, |
CHIP_RS400, |
CHIP_RS480, |
CHIP_RS600, |
CHIP_RS690, |
CHIP_RS740, |
CHIP_RV515, |
CHIP_R520, |
CHIP_RV530, |
CHIP_RV560, |
CHIP_RV570, |
CHIP_R580, |
CHIP_R600, |
CHIP_RV610, |
CHIP_RV630, |
CHIP_RV620, |
CHIP_RV635, |
CHIP_RV670, |
CHIP_RS780, |
CHIP_RV770, |
CHIP_RV730, |
CHIP_RV710, |
CHIP_LAST, |
}; |
enum radeon_chip_flags { |
RADEON_FAMILY_MASK = 0x0000ffffUL, |
RADEON_FLAGS_MASK = 0xffff0000UL, |
RADEON_IS_MOBILITY = 0x00010000UL, |
RADEON_IS_IGP = 0x00020000UL, |
RADEON_SINGLE_CRTC = 0x00040000UL, |
RADEON_IS_AGP = 0x00080000UL, |
RADEON_HAS_HIERZ = 0x00100000UL, |
RADEON_IS_PCIE = 0x00200000UL, |
RADEON_NEW_MEMMAP = 0x00400000UL, |
RADEON_IS_PCI = 0x00800000UL, |
RADEON_IS_IGPGART = 0x01000000UL, |
}; |
/* |
* Errata workarounds. |
*/ |
149,10 → 153,21 |
*/ |
bool radeon_get_bios(struct radeon_device *rdev); |
/* |
* Dummy page |
*/ |
struct radeon_dummy_page { |
struct page *page; |
dma_addr_t addr; |
}; |
int radeon_dummy_page_init(struct radeon_device *rdev); |
void radeon_dummy_page_fini(struct radeon_device *rdev); |
/* |
* Clocks |
*/ |
struct radeon_clock { |
struct radeon_pll p1pll; |
struct radeon_pll p2pll; |
163,6 → 178,7 |
uint32_t default_sclk; |
}; |
/* |
* Fences. |
*/ |
201,7 → 217,15 |
struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); |
void radeon_fence_unref(struct radeon_fence **fence); |
/* |
* Tiling registers |
*/ |
struct radeon_surface_reg { |
struct radeon_object *robj; |
}; |
#define RADEON_GEM_MAX_SURFACES 8 |
/* |
* Radeon buffer. |
*/ |
213,6 → 237,7 |
uint64_t gpu_offset; |
unsigned rdomain; |
unsigned wdomain; |
uint32_t tiling_flags; |
}; |
int radeon_object_init(struct radeon_device *rdev); |
294,11 → 319,18 |
resource_size_t aper_size; |
resource_size_t aper_base; |
resource_size_t agp_base; |
unsigned gtt_location; |
unsigned gtt_size; |
unsigned vram_location; |
unsigned vram_size; |
/* for some chips with <= 32MB we need to lie |
* about vram size near mc fb location */ |
u64 mc_vram_size; |
u64 gtt_location; |
u64 gtt_size; |
u64 gtt_start; |
u64 gtt_end; |
u64 vram_location; |
u64 vram_start; |
u64 vram_end; |
unsigned vram_width; |
u64 real_vram_size; |
int vram_mtrr; |
bool vram_is_ddr; |
}; |
345,6 → 377,10 |
uint32_t length_dw; |
}; |
/* |
* locking - |
* mutex protects scheduled_ibs, ready, alloc_bm |
*/ |
struct radeon_ib_pool { |
// struct mutex mutex; |
struct radeon_object *robj; |
370,6 → 406,16 |
bool ready; |
}; |
struct r600_blit { |
struct radeon_object *shader_obj; |
u64 shader_gpu_addr; |
u32 vs_offset, ps_offset; |
u32 state_offset; |
u32 state_len; |
u32 vb_used, vb_total; |
struct radeon_ib *vb_ib; |
}; |
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib); |
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); |
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); |
422,6 → 468,7 |
int chunk_relocs_idx; |
struct radeon_ib *ib; |
void *track; |
unsigned family; |
}; |
struct radeon_cs_packet { |
456,6 → 503,38 |
uint64_t gpu_addr; |
}; |
/** |
* struct radeon_pm - power management datas |
* @max_bandwidth: maximum bandwidth the gpu has (MByte/s) |
* @igp_sideport_mclk: sideport memory clock Mhz (rs690,rs740,rs780,rs880) |
* @igp_system_mclk: system clock Mhz (rs690,rs740,rs780,rs880) |
* @igp_ht_link_clk: ht link clock Mhz (rs690,rs740,rs780,rs880) |
* @igp_ht_link_width: ht link width in bits (rs690,rs740,rs780,rs880) |
* @k8_bandwidth: k8 bandwidth the gpu has (MByte/s) (IGP) |
* @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP) |
* @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP) |
* @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP) |
* @sclk: GPU clock Mhz (core bandwith depends of this clock) |
* @needed_bandwidth: current bandwidth needs |
* |
* It keeps track of various data needed to take powermanagement decision. |
* Bandwith need is used to determine minimun clock of the GPU and memory. |
* Equation between gpu/memory clock and available bandwidth is hw dependent |
* (type of memory, bus size, efficiency, ...) |
*/ |
struct radeon_pm { |
fixed20_12 max_bandwidth; |
fixed20_12 igp_sideport_mclk; |
fixed20_12 igp_system_mclk; |
fixed20_12 igp_ht_link_clk; |
fixed20_12 igp_ht_link_width; |
fixed20_12 k8_bandwidth; |
fixed20_12 sideport_bandwidth; |
fixed20_12 ht_bandwidth; |
fixed20_12 core_bandwidth; |
fixed20_12 sclk; |
fixed20_12 needed_bandwidth; |
}; |
/* |
* ASIC specific functions. |
462,13 → 541,19 |
*/ |
struct radeon_asic { |
int (*init)(struct radeon_device *rdev); |
void (*fini)(struct radeon_device *rdev); |
int (*resume)(struct radeon_device *rdev); |
int (*suspend)(struct radeon_device *rdev); |
void (*errata)(struct radeon_device *rdev); |
void (*vram_info)(struct radeon_device *rdev); |
void (*vga_set_state)(struct radeon_device *rdev, bool state); |
int (*gpu_reset)(struct radeon_device *rdev); |
int (*mc_init)(struct radeon_device *rdev); |
void (*mc_fini)(struct radeon_device *rdev); |
int (*wb_init)(struct radeon_device *rdev); |
void (*wb_fini)(struct radeon_device *rdev); |
int (*gart_init)(struct radeon_device *rdev); |
void (*gart_fini)(struct radeon_device *rdev); |
int (*gart_enable)(struct radeon_device *rdev); |
void (*gart_disable)(struct radeon_device *rdev); |
void (*gart_tlb_flush)(struct radeon_device *rdev); |
476,9 → 561,14 |
int (*cp_init)(struct radeon_device *rdev, unsigned ring_size); |
void (*cp_fini)(struct radeon_device *rdev); |
void (*cp_disable)(struct radeon_device *rdev); |
void (*cp_commit)(struct radeon_device *rdev); |
void (*ring_start)(struct radeon_device *rdev); |
int (*ring_test)(struct radeon_device *rdev); |
void (*ring_ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib); |
int (*ib_test)(struct radeon_device *rdev); |
int (*irq_set)(struct radeon_device *rdev); |
int (*irq_process)(struct radeon_device *rdev); |
u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc); |
void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence); |
int (*cs_parse)(struct radeon_cs_parser *p); |
int (*copy_blit)(struct radeon_device *rdev, |
500,14 → 590,75 |
void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); |
void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); |
void (*set_clock_gating)(struct radeon_device *rdev, int enable); |
int (*set_surface_reg)(struct radeon_device *rdev, int reg, |
uint32_t tiling_flags, uint32_t pitch, |
uint32_t offset, uint32_t obj_size); |
int (*clear_surface_reg)(struct radeon_device *rdev, int reg); |
void (*bandwidth_update)(struct radeon_device *rdev); |
}; |
/* |
* Asic structures |
*/ |
struct r100_asic { |
const unsigned *reg_safe_bm; |
unsigned reg_safe_bm_size; |
}; |
struct r300_asic { |
const unsigned *reg_safe_bm; |
unsigned reg_safe_bm_size; |
}; |
struct r600_asic { |
unsigned max_pipes; |
unsigned max_tile_pipes; |
unsigned max_simds; |
unsigned max_backends; |
unsigned max_gprs; |
unsigned max_threads; |
unsigned max_stack_entries; |
unsigned max_hw_contexts; |
unsigned max_gs_threads; |
unsigned sx_max_export_size; |
unsigned sx_max_export_pos_size; |
unsigned sx_max_export_smx_size; |
unsigned sq_num_cf_insts; |
}; |
struct rv770_asic { |
unsigned max_pipes; |
unsigned max_tile_pipes; |
unsigned max_simds; |
unsigned max_backends; |
unsigned max_gprs; |
unsigned max_threads; |
unsigned max_stack_entries; |
unsigned max_hw_contexts; |
unsigned max_gs_threads; |
unsigned sx_max_export_size; |
unsigned sx_max_export_pos_size; |
unsigned sx_max_export_smx_size; |
unsigned sq_num_cf_insts; |
unsigned sx_num_of_sets; |
unsigned sc_prim_fifo_size; |
unsigned sc_hiz_tile_fifo_size; |
unsigned sc_earlyz_tile_fifo_fize; |
}; |
union radeon_asic_config { |
struct r300_asic r300; |
struct r100_asic r100; |
struct r600_asic r600; |
struct rv770_asic rv770; |
}; |
/* |
/* |
* Core structure, functions and helpers. |
*/ |
524,6 → 675,7 |
int usec_timeout; |
enum radeon_pll_errata pll_errata; |
int num_gb_pipes; |
int num_z_pipes; |
int disp_priority; |
/* BIOS */ |
uint8_t *bios; |
534,20 → 686,15 |
struct fb_info *fbdev_info; |
struct radeon_object *fbdev_robj; |
struct radeon_framebuffer *fbdev_rfb; |
/* Register mmio */ |
unsigned long rmmio_base; |
unsigned long rmmio_size; |
void *rmmio; |
radeon_rreg_t mm_rreg; |
radeon_wreg_t mm_wreg; |
radeon_rreg_t mc_rreg; |
radeon_wreg_t mc_wreg; |
radeon_rreg_t pll_rreg; |
radeon_wreg_t pll_wreg; |
radeon_rreg_t pcie_rreg; |
radeon_wreg_t pcie_wreg; |
uint32_t pcie_reg_mask; |
radeon_rreg_t pciep_rreg; |
radeon_wreg_t pciep_wreg; |
struct radeon_clock clock; |
562,11 → 709,21 |
// struct radeon_irq irq; |
struct radeon_asic *asic; |
struct radeon_gem gem; |
struct radeon_pm pm; |
uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH]; |
// struct mutex cs_mutex; |
struct radeon_wb wb; |
struct radeon_dummy_page dummy_page; |
bool gpu_lockup; |
bool shutdown; |
bool suspend; |
bool need_dma32; |
bool new_init_path; |
bool accel_working; |
struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES]; |
const struct firmware *me_fw; /* all family ME firmware */ |
const struct firmware *pfp_fw; /* r6/700 PFP firmware */ |
struct r600_blit r600_blit; |
}; |
int radeon_device_init(struct radeon_device *rdev, |
576,70 → 733,41 |
void radeon_device_fini(struct radeon_device *rdev); |
int radeon_gpu_wait_for_idle(struct radeon_device *rdev); |
#define __iomem |
#define __force |
/* r600 blit */ |
int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes); |
void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence); |
void r600_kms_blit_copy(struct radeon_device *rdev, |
u64 src_gpu_addr, u64 dst_gpu_addr, |
int size_bytes); |
static inline uint8_t __raw_readb(const volatile void __iomem *addr) |
static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) |
{ |
return *(const volatile uint8_t __force *) addr; |
if (reg < 0x10000) |
return readl(((void __iomem *)rdev->rmmio) + reg); |
else { |
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); |
} |
static inline uint16_t __raw_readw(const volatile void __iomem *addr) |
{ |
return *(const volatile uint16_t __force *) addr; |
} |
static inline uint32_t __raw_readl(const volatile void __iomem *addr) |
static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
{ |
return *(const volatile uint32_t __force *) addr; |
if (reg < 0x10000) |
writel(v, ((void __iomem *)rdev->rmmio) + reg); |
else { |
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); |
} |
#define readb __raw_readb |
#define readw __raw_readw |
#define readl __raw_readl |
static inline void __raw_writeb(uint8_t b, volatile void __iomem *addr) |
{ |
*(volatile uint8_t __force *) addr = b; |
} |
static inline void __raw_writew(uint16_t b, volatile void __iomem *addr) |
{ |
*(volatile uint16_t __force *) addr = b; |
} |
static inline void __raw_writel(uint32_t b, volatile void __iomem *addr) |
{ |
*(volatile uint32_t __force *) addr = b; |
} |
static inline void __raw_writeq(__u64 b, volatile void __iomem *addr) |
{ |
*(volatile __u64 *)addr = b; |
} |
#define writeb __raw_writeb |
#define writew __raw_writew |
#define writel __raw_writel |
#define writeq __raw_writeq |
//#define writeb(b,addr) *(volatile uint8_t* ) addr = (uint8_t)b |
//#define writew(b,addr) *(volatile uint16_t*) addr = (uint16_t)b |
//#define writel(b,addr) *(volatile uint32_t*) addr = (uint32_t)b |
/* |
* Registers read & write functions. |
*/ |
#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg)) |
#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg)) |
#define RREG32(reg) rdev->mm_rreg(rdev, (reg)) |
#define WREG32(reg, v) rdev->mm_wreg(rdev, (reg), (v)) |
#define RREG32(reg) r100_mm_rreg(rdev, (reg)) |
#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v)) |
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) |
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) |
#define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg)) |
646,8 → 774,8 |
#define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v)) |
#define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg)) |
#define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v)) |
#define RREG32_PCIE(reg) rdev->pcie_rreg(rdev, (reg)) |
#define WREG32_PCIE(reg, v) rdev->pcie_wreg(rdev, (reg), (v)) |
#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg)) |
#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v)) |
#define WREG32_P(reg, val, mask) \ |
do { \ |
uint32_t tmp_ = RREG32(reg); \ |
663,7 → 791,34 |
WREG32_PLL(reg, tmp_); \ |
} while (0) |
/* |
* Indirect registers accessor |
*/ |
static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) |
{ |
uint32_t r; |
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); |
r = RREG32(RADEON_PCIE_DATA); |
return r; |
} |
static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
{ |
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); |
WREG32(RADEON_PCIE_DATA, (v)); |
} |
void r100_pll_errata_after_index(struct radeon_device *rdev); |
#define radeon_PCI_IDS \ |
{0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ |
{0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
1075,6 → 1230,8 |
/* |
* ASICs helpers. |
*/ |
#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \ |
(rdev->pdev->device == 0x5969)) |
#define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \ |
(rdev->family == CHIP_RV200) || \ |
(rdev->family == CHIP_RS100) || \ |
1175,14 → 1332,20 |
* ASICs macro. |
*/ |
#define radeon_init(rdev) (rdev)->asic->init((rdev)) |
#define radeon_fini(rdev) (rdev)->asic->fini((rdev)) |
#define radeon_resume(rdev) (rdev)->asic->resume((rdev)) |
#define radeon_suspend(rdev) (rdev)->asic->suspend((rdev)) |
#define radeon_cs_parse(p) rdev->asic->cs_parse((p)) |
#define radeon_errata(rdev) (rdev)->asic->errata((rdev)) |
#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev)) |
#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) |
#define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev)) |
#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev)) |
#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev)) |
#define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev)) |
#define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev)) |
#define radeon_gpu_gart_init(rdev) (rdev)->asic->gart_init((rdev)) |
#define radeon_gpu_gart_fini(rdev) (rdev)->asic->gart_fini((rdev)) |
#define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev)) |
#define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev)) |
#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev)) |
1190,9 → 1353,14 |
#define radeon_cp_init(rdev,rsize) (rdev)->asic->cp_init((rdev), (rsize)) |
#define radeon_cp_fini(rdev) (rdev)->asic->cp_fini((rdev)) |
#define radeon_cp_disable(rdev) (rdev)->asic->cp_disable((rdev)) |
#define radeon_cp_commit(rdev) (rdev)->asic->cp_commit((rdev)) |
#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev)) |
#define radeon_ring_test(rdev) (rdev)->asic->ring_test((rdev)) |
#define radeon_ring_ib_execute(rdev, ib) (rdev)->asic->ring_ib_execute((rdev), (ib)) |
#define radeon_ib_test(rdev) (rdev)->asic->ib_test((rdev)) |
#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev)) |
#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev)) |
#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc)) |
#define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence)) |
#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f)) |
#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f)) |
1201,8 → 1369,102 |
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) |
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) |
#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) |
#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) |
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) |
#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) |
/* Common functions */ |
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); |
extern int radeon_modeset_init(struct radeon_device *rdev); |
extern void radeon_modeset_fini(struct radeon_device *rdev); |
extern bool radeon_card_posted(struct radeon_device *rdev); |
extern int radeon_clocks_init(struct radeon_device *rdev); |
extern void radeon_clocks_fini(struct radeon_device *rdev); |
extern void radeon_scratch_init(struct radeon_device *rdev); |
extern void radeon_surface_init(struct radeon_device *rdev); |
extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); |
/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ |
struct r100_mc_save { |
u32 GENMO_WT; |
u32 CRTC_EXT_CNTL; |
u32 CRTC_GEN_CNTL; |
u32 CRTC2_GEN_CNTL; |
u32 CUR_OFFSET; |
u32 CUR2_OFFSET; |
}; |
extern void r100_cp_disable(struct radeon_device *rdev); |
extern int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); |
extern void r100_cp_fini(struct radeon_device *rdev); |
extern void r100_pci_gart_tlb_flush(struct radeon_device *rdev); |
extern int r100_pci_gart_init(struct radeon_device *rdev); |
extern void r100_pci_gart_fini(struct radeon_device *rdev); |
extern int r100_pci_gart_enable(struct radeon_device *rdev); |
extern void r100_pci_gart_disable(struct radeon_device *rdev); |
extern int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); |
extern int r100_debugfs_mc_info_init(struct radeon_device *rdev); |
extern int r100_gui_wait_for_idle(struct radeon_device *rdev); |
extern void r100_ib_fini(struct radeon_device *rdev); |
extern int r100_ib_init(struct radeon_device *rdev); |
extern void r100_irq_disable(struct radeon_device *rdev); |
extern int r100_irq_set(struct radeon_device *rdev); |
extern void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save); |
extern void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save); |
extern void r100_vram_init_sizes(struct radeon_device *rdev); |
extern void r100_wb_disable(struct radeon_device *rdev); |
extern void r100_wb_fini(struct radeon_device *rdev); |
extern int r100_wb_init(struct radeon_device *rdev); |
/* r300,r350,rv350,rv370,rv380 */ |
extern void r300_set_reg_safe(struct radeon_device *rdev); |
extern void r300_mc_program(struct radeon_device *rdev); |
extern void r300_vram_info(struct radeon_device *rdev); |
extern int rv370_pcie_gart_init(struct radeon_device *rdev); |
extern void rv370_pcie_gart_fini(struct radeon_device *rdev); |
extern int rv370_pcie_gart_enable(struct radeon_device *rdev); |
extern void rv370_pcie_gart_disable(struct radeon_device *rdev); |
/* r420,r423,rv410 */ |
extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); |
extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v); |
extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev); |
/* rv515 */ |
extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev); |
/* rs690, rs740 */ |
extern void rs690_line_buffer_adjust(struct radeon_device *rdev, |
struct drm_display_mode *mode1, |
struct drm_display_mode *mode2); |
/* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ |
extern bool r600_card_posted(struct radeon_device *rdev); |
extern void r600_cp_stop(struct radeon_device *rdev); |
extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size); |
extern int r600_cp_resume(struct radeon_device *rdev); |
extern int r600_count_pipe_bits(uint32_t val); |
extern int r600_gart_clear_page(struct radeon_device *rdev, int i); |
extern int r600_mc_wait_for_idle(struct radeon_device *rdev); |
extern int r600_pcie_gart_init(struct radeon_device *rdev); |
extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); |
extern int r600_ib_test(struct radeon_device *rdev); |
extern int r600_ring_test(struct radeon_device *rdev); |
extern int r600_wb_init(struct radeon_device *rdev); |
extern void r600_wb_fini(struct radeon_device *rdev); |
extern void r600_scratch_init(struct radeon_device *rdev); |
extern int r600_blit_init(struct radeon_device *rdev); |
extern void r600_blit_fini(struct radeon_device *rdev); |
extern int r600_cp_init_microcode(struct radeon_device *rdev); |
extern int r600_gpu_reset(struct radeon_device *rdev); |
#define DRM_UDELAY(d) udelay(d) |
resource_size_t |
1212,4 → 1474,6 |
bool set_mode(struct drm_device *dev, int width, int height); |
#endif |
/drivers/video/drm/radeon/radeon_asic.h |
---|
42,16 → 42,21 |
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 |
*/ |
int r100_init(struct radeon_device *rdev); |
int r200_init(struct radeon_device *rdev); |
uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg); |
void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
void r100_errata(struct radeon_device *rdev); |
void r100_vram_info(struct radeon_device *rdev); |
void r100_vga_set_state(struct radeon_device *rdev, bool state); |
int r100_gpu_reset(struct radeon_device *rdev); |
int r100_mc_init(struct radeon_device *rdev); |
void r100_mc_fini(struct radeon_device *rdev); |
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); |
int r100_wb_init(struct radeon_device *rdev); |
void r100_wb_fini(struct radeon_device *rdev); |
int r100_gart_enable(struct radeon_device *rdev); |
int r100_pci_gart_init(struct radeon_device *rdev); |
void r100_pci_gart_fini(struct radeon_device *rdev); |
int r100_pci_gart_enable(struct radeon_device *rdev); |
void r100_pci_gart_disable(struct radeon_device *rdev); |
void r100_pci_gart_tlb_flush(struct radeon_device *rdev); |
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); |
58,6 → 63,7 |
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); |
void r100_cp_fini(struct radeon_device *rdev); |
void r100_cp_disable(struct radeon_device *rdev); |
void r100_cp_commit(struct radeon_device *rdev); |
void r100_ring_start(struct radeon_device *rdev); |
int r100_irq_set(struct radeon_device *rdev); |
int r100_irq_process(struct radeon_device *rdev); |
71,8 → 77,15 |
uint64_t dst_offset, |
unsigned num_pages, |
struct radeon_fence *fence); |
int r100_set_surface_reg(struct radeon_device *rdev, int reg, |
uint32_t tiling_flags, uint32_t pitch, |
uint32_t offset, uint32_t obj_size); |
int r100_clear_surface_reg(struct radeon_device *rdev, int reg); |
void r100_bandwidth_update(struct radeon_device *rdev); |
void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); |
int r100_ib_test(struct radeon_device *rdev); |
int r100_ring_test(struct radeon_device *rdev); |
static struct radeon_asic r100_asic = { |
.init = &r100_init, |
.errata = &r100_errata, |
82,7 → 95,7 |
.mc_fini = &r100_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_enable = &r100_gart_enable, |
.gart_enable = &r100_pci_gart_enable, |
.gart_disable = &r100_pci_gart_disable, |
.gart_tlb_flush = &r100_pci_gart_tlb_flush, |
.gart_set_page = &r100_pci_gart_set_page, |
101,6 → 114,9 |
// .set_memory_clock = NULL, |
// .set_pcie_lanes = NULL, |
// .set_clock_gating = &radeon_legacy_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &r100_bandwidth_update, |
}; |
117,7 → 133,9 |
void r300_fence_ring_emit(struct radeon_device *rdev, |
struct radeon_fence *fence); |
int r300_cs_parse(struct radeon_cs_parser *p); |
int r300_gart_enable(struct radeon_device *rdev); |
int rv370_pcie_gart_init(struct radeon_device *rdev); |
void rv370_pcie_gart_fini(struct radeon_device *rdev); |
int rv370_pcie_gart_enable(struct radeon_device *rdev); |
void rv370_pcie_gart_disable(struct radeon_device *rdev); |
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); |
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); |
130,17 → 148,17 |
unsigned num_pages, |
struct radeon_fence *fence); |
static struct radeon_asic r300_asic = { |
.init = &r300_init, |
.errata = &r300_errata, |
.vram_info = &r300_vram_info, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &r300_gpu_reset, |
.mc_init = &r300_mc_init, |
.mc_fini = &r300_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_enable = &r300_gart_enable, |
.gart_enable = &r100_pci_gart_enable, |
.gart_disable = &r100_pci_gart_disable, |
.gart_tlb_flush = &r100_pci_gart_tlb_flush, |
.gart_set_page = &r100_pci_gart_set_page, |
159,32 → 177,38 |
// .set_memory_clock = NULL, |
// .set_pcie_lanes = &rv370_set_pcie_lanes, |
// .set_clock_gating = &radeon_legacy_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &r100_bandwidth_update, |
}; |
/* |
* r420,r423,rv410 |
*/ |
void r420_errata(struct radeon_device *rdev); |
void r420_vram_info(struct radeon_device *rdev); |
int r420_mc_init(struct radeon_device *rdev); |
void r420_mc_fini(struct radeon_device *rdev); |
extern int r420_init(struct radeon_device *rdev); |
extern void r420_fini(struct radeon_device *rdev); |
extern int r420_suspend(struct radeon_device *rdev); |
extern int r420_resume(struct radeon_device *rdev); |
static struct radeon_asic r420_asic = { |
.init = &r300_init, |
.errata = &r420_errata, |
.vram_info = &r420_vram_info, |
.init = &r420_init, |
.fini = &r420_fini, |
.suspend = &r420_suspend, |
.resume = &r420_resume, |
.errata = NULL, |
.vram_info = NULL, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &r300_gpu_reset, |
.mc_init = &r420_mc_init, |
.mc_fini = &r420_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_enable = &r300_gart_enable, |
.gart_disable = &rv370_pcie_gart_disable, |
.mc_init = NULL, |
.mc_fini = NULL, |
.wb_init = NULL, |
.wb_fini = NULL, |
.gart_enable = NULL, |
.gart_disable = NULL, |
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush, |
.gart_set_page = &rv370_pcie_gart_set_page, |
.cp_init = &r100_cp_init, |
// .cp_fini = &r100_cp_fini, |
// .cp_disable = &r100_cp_disable, |
.cp_init = NULL, |
.cp_fini = NULL, |
.cp_disable = NULL, |
.ring_start = &r300_ring_start, |
// .irq_set = &r100_irq_set, |
// .irq_process = &r100_irq_process, |
197,6 → 221,9 |
// .set_memory_clock = &radeon_atom_set_memory_clock, |
// .set_pcie_lanes = &rv370_set_pcie_lanes, |
// .set_clock_gating = &radeon_atom_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &r100_bandwidth_update, |
}; |
207,6 → 234,8 |
void rs400_vram_info(struct radeon_device *rdev); |
int rs400_mc_init(struct radeon_device *rdev); |
void rs400_mc_fini(struct radeon_device *rdev); |
int rs400_gart_init(struct radeon_device *rdev); |
void rs400_gart_fini(struct radeon_device *rdev); |
int rs400_gart_enable(struct radeon_device *rdev); |
void rs400_gart_disable(struct radeon_device *rdev); |
void rs400_gart_tlb_flush(struct radeon_device *rdev); |
217,11 → 246,14 |
.init = &r300_init, |
.errata = &rs400_errata, |
.vram_info = &rs400_vram_info, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &r300_gpu_reset, |
.mc_init = &rs400_mc_init, |
.mc_fini = &rs400_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_init = &rs400_gart_init, |
.gart_fini = &rs400_gart_fini, |
.gart_enable = &rs400_gart_enable, |
.gart_disable = &rs400_gart_disable, |
.gart_tlb_flush = &rs400_gart_tlb_flush, |
229,6 → 261,7 |
.cp_init = &r100_cp_init, |
// .cp_fini = &r100_cp_fini, |
// .cp_disable = &r100_cp_disable, |
.cp_commit = &r100_cp_commit, |
.ring_start = &r300_ring_start, |
// .irq_set = &r100_irq_set, |
// .irq_process = &r100_irq_process, |
241,6 → 274,9 |
// .set_memory_clock = NULL, |
// .set_pcie_lanes = NULL, |
// .set_clock_gating = &radeon_legacy_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &r100_bandwidth_update, |
}; |
247,11 → 283,16 |
/* |
* rs600. |
*/ |
int rs600_init(struct radeon_device *rdev); |
void rs600_errata(struct radeon_device *rdev); |
void rs600_vram_info(struct radeon_device *rdev); |
int rs600_mc_init(struct radeon_device *rdev); |
void rs600_mc_fini(struct radeon_device *rdev); |
int rs600_irq_set(struct radeon_device *rdev); |
int rs600_irq_process(struct radeon_device *rdev); |
u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); |
int rs600_gart_init(struct radeon_device *rdev); |
void rs600_gart_fini(struct radeon_device *rdev); |
int rs600_gart_enable(struct radeon_device *rdev); |
void rs600_gart_disable(struct radeon_device *rdev); |
void rs600_gart_tlb_flush(struct radeon_device *rdev); |
258,16 → 299,19 |
int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); |
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); |
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
void rs600_bandwidth_update(struct radeon_device *rdev); |
static struct radeon_asic rs600_asic = { |
.init = &r300_init, |
.init = &rs600_init, |
.errata = &rs600_errata, |
.vram_info = &rs600_vram_info, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &r300_gpu_reset, |
.mc_init = &rs600_mc_init, |
.mc_fini = &rs600_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_init = &rs600_gart_init, |
.gart_fini = &rs600_gart_fini, |
.gart_enable = &rs600_gart_enable, |
.gart_disable = &rs600_gart_disable, |
.gart_tlb_flush = &rs600_gart_tlb_flush, |
275,6 → 319,7 |
.cp_init = &r100_cp_init, |
// .cp_fini = &r100_cp_fini, |
// .cp_disable = &r100_cp_disable, |
.cp_commit = &r100_cp_commit, |
.ring_start = &r300_ring_start, |
// .irq_set = &rs600_irq_set, |
// .irq_process = &r100_irq_process, |
287,6 → 332,7 |
// .set_memory_clock = &radeon_atom_set_memory_clock, |
// .set_pcie_lanes = NULL, |
// .set_clock_gating = &radeon_atom_set_clock_gating, |
.bandwidth_update = &rs600_bandwidth_update, |
}; |
299,15 → 345,19 |
void rs690_mc_fini(struct radeon_device *rdev); |
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); |
void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
void rs690_bandwidth_update(struct radeon_device *rdev); |
static struct radeon_asic rs690_asic = { |
.init = &r300_init, |
.init = &rs600_init, |
.errata = &rs690_errata, |
.vram_info = &rs690_vram_info, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &r300_gpu_reset, |
.mc_init = &rs690_mc_init, |
.mc_fini = &rs690_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_init = &rs400_gart_init, |
.gart_fini = &rs400_gart_fini, |
.gart_enable = &rs400_gart_enable, |
.gart_disable = &rs400_gart_disable, |
.gart_tlb_flush = &rs400_gart_tlb_flush, |
315,6 → 365,7 |
.cp_init = &r100_cp_init, |
// .cp_fini = &r100_cp_fini, |
// .cp_disable = &r100_cp_disable, |
.cp_commit = &r100_cp_commit, |
.ring_start = &r300_ring_start, |
// .irq_set = &rs600_irq_set, |
// .irq_process = &r100_irq_process, |
327,8 → 378,12 |
// .set_memory_clock = &radeon_atom_set_memory_clock, |
// .set_pcie_lanes = NULL, |
// .set_clock_gating = &radeon_atom_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &rs690_bandwidth_update, |
}; |
/* |
* rv515 |
*/ |
343,18 → 398,20 |
void rv515_ring_start(struct radeon_device *rdev); |
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); |
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
void rv515_bandwidth_update(struct radeon_device *rdev); |
static struct radeon_asic rv515_asic = { |
.init = &rv515_init, |
.errata = &rv515_errata, |
.vram_info = &rv515_vram_info, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &rv515_gpu_reset, |
.mc_init = &rv515_mc_init, |
.mc_fini = &rv515_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_enable = &r300_gart_enable, |
.gart_init = &rv370_pcie_gart_init, |
.gart_fini = &rv370_pcie_gart_fini, |
.gart_enable = &rv370_pcie_gart_enable, |
.gart_disable = &rv370_pcie_gart_disable, |
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush, |
.gart_set_page = &rv370_pcie_gart_set_page, |
361,6 → 418,7 |
.cp_init = &r100_cp_init, |
// .cp_fini = &r100_cp_fini, |
// .cp_disable = &r100_cp_disable, |
.cp_commit = &r100_cp_commit, |
.ring_start = &rv515_ring_start, |
// .irq_set = &r100_irq_set, |
// .irq_process = &r100_irq_process, |
373,6 → 431,9 |
// .set_memory_clock = &radeon_atom_set_memory_clock, |
// .set_pcie_lanes = &rv370_set_pcie_lanes, |
// .set_clock_gating = &radeon_atom_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &rv515_bandwidth_update, |
}; |
383,17 → 444,20 |
void r520_vram_info(struct radeon_device *rdev); |
int r520_mc_init(struct radeon_device *rdev); |
void r520_mc_fini(struct radeon_device *rdev); |
void r520_bandwidth_update(struct radeon_device *rdev); |
static struct radeon_asic r520_asic = { |
.init = &rv515_init, |
.errata = &r520_errata, |
.vram_info = &r520_vram_info, |
.vga_set_state = &r100_vga_set_state, |
.gpu_reset = &rv515_gpu_reset, |
.mc_init = &r520_mc_init, |
.mc_fini = &r520_mc_fini, |
// .wb_init = &r100_wb_init, |
// .wb_fini = &r100_wb_fini, |
.gart_enable = &r300_gart_enable, |
.gart_init = &rv370_pcie_gart_init, |
.gart_fini = &rv370_pcie_gart_fini, |
.gart_enable = &rv370_pcie_gart_enable, |
.gart_disable = &rv370_pcie_gart_disable, |
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush, |
.gart_set_page = &rv370_pcie_gart_set_page, |
400,6 → 464,7 |
.cp_init = &r100_cp_init, |
// .cp_fini = &r100_cp_fini, |
// .cp_disable = &r100_cp_disable, |
.cp_commit = &r100_cp_commit, |
.ring_start = &rv515_ring_start, |
// .irq_set = &r100_irq_set, |
// .irq_process = &r100_irq_process, |
412,11 → 477,23 |
// .set_memory_clock = &radeon_atom_set_memory_clock, |
// .set_pcie_lanes = &rv370_set_pcie_lanes, |
// .set_clock_gating = &radeon_atom_set_clock_gating, |
.set_surface_reg = r100_set_surface_reg, |
.clear_surface_reg = r100_clear_surface_reg, |
.bandwidth_update = &r520_bandwidth_update, |
}; |
/* |
* r600,rv610,rv630,rv620,rv635,rv670,rs780,rv770,rv730,rv710 |
*/ |
int r600_init(struct radeon_device *rdev); |
void r600_fini(struct radeon_device *rdev); |
int r600_suspend(struct radeon_device *rdev); |
int r600_resume(struct radeon_device *rdev); |
void r600_vga_set_state(struct radeon_device *rdev, bool state); |
int r600_wb_init(struct radeon_device *rdev); |
void r600_wb_fini(struct radeon_device *rdev); |
void r600_cp_commit(struct radeon_device *rdev); |
void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); |
uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg); |
void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
/drivers/video/drm/radeon/radeon_atombios.c |
---|
103,7 → 103,8 |
static bool radeon_atom_apply_quirks(struct drm_device *dev, |
uint32_t supported_device, |
int *connector_type, |
struct radeon_i2c_bus_rec *i2c_bus) |
struct radeon_i2c_bus_rec *i2c_bus, |
uint16_t *line_mux) |
{ |
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */ |
127,9 → 128,11 |
if ((dev->pdev->device == 0x5653) && |
(dev->pdev->subsystem_vendor == 0x1462) && |
(dev->pdev->subsystem_device == 0x0291)) { |
if (*connector_type == DRM_MODE_CONNECTOR_LVDS) |
if (*connector_type == DRM_MODE_CONNECTOR_LVDS) { |
i2c_bus->valid = false; |
*line_mux = 53; |
} |
} |
/* Funky macbooks */ |
if ((dev->pdev->device == 0x71C5) && |
140,23 → 143,34 |
return false; |
} |
/* some BIOSes seem to report DAC on HDMI - they hurt me with their lies */ |
if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) || |
(*connector_type == DRM_MODE_CONNECTOR_HDMIB)) { |
if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) { |
return false; |
} |
} |
/* ASUS HD 3600 XT board lists the DVI port as HDMI */ |
if ((dev->pdev->device == 0x9598) && |
(dev->pdev->subsystem_vendor == 0x1043) && |
(dev->pdev->subsystem_device == 0x01da)) { |
if (*connector_type == DRM_MODE_CONNECTOR_HDMIB) { |
*connector_type = DRM_MODE_CONNECTOR_DVID; |
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { |
*connector_type = DRM_MODE_CONNECTOR_DVII; |
} |
} |
/* ASUS HD 3450 board lists the DVI port as HDMI */ |
if ((dev->pdev->device == 0x95C5) && |
(dev->pdev->subsystem_vendor == 0x1043) && |
(dev->pdev->subsystem_device == 0x01e2)) { |
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { |
*connector_type = DRM_MODE_CONNECTOR_DVII; |
} |
} |
/* some BIOSes seem to report DAC on HDMI - usually this is a board with |
* HDMI + VGA reporting as HDMI |
*/ |
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) { |
if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) { |
*connector_type = DRM_MODE_CONNECTOR_VGA; |
*line_mux = 0; |
} |
} |
return true; |
} |
189,11 → 203,11 |
DRM_MODE_CONNECTOR_Composite, |
DRM_MODE_CONNECTOR_SVIDEO, |
DRM_MODE_CONNECTOR_Unknown, |
DRM_MODE_CONNECTOR_Unknown, |
DRM_MODE_CONNECTOR_9PinDIN, |
DRM_MODE_CONNECTOR_Unknown, |
DRM_MODE_CONNECTOR_HDMIA, |
DRM_MODE_CONNECTOR_HDMIB, |
DRM_MODE_CONNECTOR_HDMIB, |
DRM_MODE_CONNECTOR_LVDS, |
DRM_MODE_CONNECTOR_9PinDIN, |
DRM_MODE_CONNECTOR_Unknown, |
215,7 → 229,7 |
ATOM_OBJECT_HEADER *obj_header; |
int i, j, path_size, device_support; |
int connector_type; |
uint16_t igp_lane_info; |
uint16_t igp_lane_info, conn_id; |
bool linkb; |
struct radeon_i2c_bus_rec ddc_bus; |
367,10 → 381,6 |
&& record-> |
ucRecordType <= |
ATOM_MAX_OBJECT_RECORD_NUMBER) { |
DRM_ERROR |
("record type %d\n", |
record-> |
ucRecordType); |
switch (record-> |
ucRecordType) { |
case ATOM_I2C_RECORD_TYPE: |
406,10 → 416,16 |
else |
ddc_bus = radeon_lookup_gpio(dev, line_mux); |
conn_id = le16_to_cpu(path->usConnObjectId); |
if (!radeon_atom_apply_quirks |
(dev, le16_to_cpu(path->usDeviceTag), &connector_type, |
&ddc_bus, &conn_id)) |
continue; |
radeon_add_atom_connector(dev, |
conn_id, |
le16_to_cpu(path-> |
usConnObjectId), |
le16_to_cpu(path-> |
usDeviceTag), |
connector_type, &ddc_bus, |
linkb, igp_lane_info); |
424,7 → 440,7 |
struct bios_connector { |
bool valid; |
uint8_t line_mux; |
uint16_t line_mux; |
uint16_t devices; |
int connector_type; |
struct radeon_i2c_bus_rec ddc_bus; |
468,11 → 484,6 |
continue; |
} |
if (i == ATOM_DEVICE_TV1_INDEX) { |
DRM_DEBUG("Skipping TV Out\n"); |
continue; |
} |
bios_connectors[i].connector_type = |
supported_devices_connector_convert[ci.sucConnectorInfo. |
sbfAccess. |
526,7 → 537,7 |
if (!radeon_atom_apply_quirks |
(dev, (1 << i), &bios_connectors[i].connector_type, |
&bios_connectors[i].ddc_bus)) |
&bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux)) |
continue; |
bios_connectors[i].valid = true; |
708,9 → 719,8 |
return false; |
} |
struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct |
radeon_encoder |
*encoder) |
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, |
struct radeon_encoder_int_tmds *tmds) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
721,7 → 731,6 |
uint8_t frev, crev; |
uint16_t maxfreq; |
int i; |
struct radeon_encoder_int_tmds *tmds = NULL; |
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, |
&crev, &data_offset); |
731,12 → 740,6 |
data_offset); |
if (tmds_info) { |
tmds = |
kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); |
if (!tmds) |
return NULL; |
maxfreq = le16_to_cpu(tmds_info->usMaxFrequency); |
for (i = 0; i < 4; i++) { |
tmds->tmds_pll[i].freq = |
762,8 → 765,9 |
break; |
} |
} |
return true; |
} |
return tmds; |
return false; |
} |
union lvds_info { |
855,6 → 859,72 |
return p_dac; |
} |
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, |
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing, |
int32_t *pixel_clock) |
{ |
struct radeon_mode_info *mode_info = &rdev->mode_info; |
ATOM_ANALOG_TV_INFO *tv_info; |
ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2; |
ATOM_DTD_FORMAT *dtd_timings; |
int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); |
u8 frev, crev; |
uint16_t data_offset; |
atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset); |
switch (crev) { |
case 1: |
tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset); |
if (index > MAX_SUPPORTED_TV_TIMING) |
return false; |
crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total); |
crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp); |
crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart); |
crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth); |
crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total); |
crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp); |
crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart); |
crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth); |
crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo; |
crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight); |
crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft); |
crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom); |
crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop); |
*pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10; |
if (index == 1) { |
/* PAL timings appear to have wrong values for totals */ |
crtc_timing->usH_Total -= 1; |
crtc_timing->usV_Total -= 1; |
} |
break; |
case 2: |
tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset); |
if (index > MAX_SUPPORTED_TV_TIMING_V1_2) |
return false; |
dtd_timings = &tv_info_v1_2->aModeTimings[index]; |
crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time); |
crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive); |
crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset); |
crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth); |
crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time); |
crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive); |
crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset); |
crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth); |
crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess); |
*pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10; |
break; |
} |
return true; |
} |
struct radeon_encoder_tv_dac * |
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) |
{ |
945,10 → 1015,10 |
uint32_t bios_2_scratch, bios_6_scratch; |
if (rdev->family >= CHIP_R600) { |
bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH); |
bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); |
bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); |
} else { |
bios_2_scratch = RREG32(RADEON_BIOS_0_SCRATCH); |
bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); |
bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); |
} |
968,6 → 1038,34 |
} |
void radeon_save_bios_scratch_regs(struct radeon_device *rdev) |
{ |
uint32_t scratch_reg; |
int i; |
if (rdev->family >= CHIP_R600) |
scratch_reg = R600_BIOS_0_SCRATCH; |
else |
scratch_reg = RADEON_BIOS_0_SCRATCH; |
for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) |
rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4)); |
} |
void radeon_restore_bios_scratch_regs(struct radeon_device *rdev) |
{ |
uint32_t scratch_reg; |
int i; |
if (rdev->family >= CHIP_R600) |
scratch_reg = R600_BIOS_0_SCRATCH; |
else |
scratch_reg = RADEON_BIOS_0_SCRATCH; |
for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++) |
WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]); |
} |
void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) |
{ |
struct drm_device *dev = encoder->dev; |
/drivers/video/drm/radeon/radeon_bios.c |
---|
35,7 → 35,7 |
*/ |
static bool radeon_read_bios(struct radeon_device *rdev) |
{ |
uint8_t *bios; |
uint8_t __iomem *bios; |
size_t size; |
rdev->bios = NULL; |
48,7 → 48,7 |
// pci_unmap_rom(rdev->pdev, bios); |
return false; |
} |
rdev->bios = malloc(size); |
rdev->bios = kmalloc(size, GFP_KERNEL); |
if (rdev->bios == NULL) { |
// pci_unmap_rom(rdev->pdev, bios); |
return false; |
58,7 → 58,6 |
return true; |
} |
static bool r700_read_disabled_bios(struct radeon_device *rdev) |
{ |
uint32_t viph_control; |
352,14 → 351,11 |
return legacy_read_disabled_bios(rdev); |
} |
bool radeon_get_bios(struct radeon_device *rdev) |
{ |
bool r; |
uint16_t tmp; |
dbgprintf("%s\n\r",__FUNCTION__); |
r = radeon_read_bios(rdev); |
if (r == false) { |
r = radeon_read_disabled_bios(rdev); |
385,7 → 381,7 |
rdev->is_atom_bios = false; |
} |
dbgprintf("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); |
DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); |
return true; |
free_bios: |
kfree(rdev->bios); |
/drivers/video/drm/radeon/radeon_clocks.c |
---|
102,10 → 102,12 |
p1pll->reference_div = 12; |
if (p2pll->reference_div < 2) |
p2pll->reference_div = 12; |
if (rdev->family < CHIP_RS600) { |
if (spll->reference_div < 2) |
spll->reference_div = |
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & |
RADEON_M_SPLL_REF_DIV_MASK; |
} |
if (mpll->reference_div < 2) |
mpll->reference_div = spll->reference_div; |
} else { |
/drivers/video/drm/radeon/radeon_combios.c |
---|
685,23 → 685,15 |
0x00780000, /* rs480 */ |
}; |
static struct radeon_encoder_tv_dac |
*radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev) |
static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev, |
struct radeon_encoder_tv_dac *tv_dac) |
{ |
struct radeon_encoder_tv_dac *tv_dac = NULL; |
tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); |
if (!tv_dac) |
return NULL; |
tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family]; |
if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250)) |
tv_dac->ps2_tvdac_adj = 0x00880000; |
tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; |
tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; |
return tv_dac; |
return; |
} |
struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct |
713,19 → 705,18 |
uint16_t dac_info; |
uint8_t rev, bg, dac; |
struct radeon_encoder_tv_dac *tv_dac = NULL; |
int found = 0; |
tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); |
if (!tv_dac) |
return NULL; |
if (rdev->bios == NULL) |
return radeon_legacy_get_tv_dac_info_from_table(rdev); |
goto out; |
/* first check TV table */ |
dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); |
if (dac_info) { |
tv_dac = |
kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); |
if (!tv_dac) |
return NULL; |
rev = RBIOS8(dac_info + 0x3); |
if (rev > 4) { |
bg = RBIOS8(dac_info + 0xc) & 0xf; |
739,6 → 730,7 |
bg = RBIOS8(dac_info + 0x10) & 0xf; |
dac = RBIOS8(dac_info + 0x11) & 0xf; |
tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); |
found = 1; |
} else if (rev > 1) { |
bg = RBIOS8(dac_info + 0xc) & 0xf; |
dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf; |
751,22 → 743,16 |
bg = RBIOS8(dac_info + 0xe) & 0xf; |
dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf; |
tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); |
found = 1; |
} |
tv_dac->tv_std = radeon_combios_get_tv_info(encoder); |
} else { |
} |
if (!found) { |
/* then check CRT table */ |
dac_info = |
combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); |
if (dac_info) { |
tv_dac = |
kzalloc(sizeof(struct radeon_encoder_tv_dac), |
GFP_KERNEL); |
if (!tv_dac) |
return NULL; |
rev = RBIOS8(dac_info) & 0x3; |
if (rev < 2) { |
bg = RBIOS8(dac_info + 0x3) & 0xf; |
775,6 → 761,7 |
(bg << 16) | (dac << 20); |
tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; |
tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; |
found = 1; |
} else { |
bg = RBIOS8(dac_info + 0x4) & 0xf; |
dac = RBIOS8(dac_info + 0x5) & 0xf; |
782,12 → 769,15 |
(bg << 16) | (dac << 20); |
tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; |
tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; |
found = 1; |
} |
} else { |
DRM_INFO("No TV DAC info found in BIOS\n"); |
return radeon_legacy_get_tv_dac_info_from_table(rdev); |
} |
} |
out: |
if (!found) /* fallback to defaults */ |
radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac); |
return tv_dac; |
} |
873,8 → 863,10 |
int tmp, i; |
struct radeon_encoder_lvds *lvds = NULL; |
if (rdev->bios == NULL) |
return radeon_legacy_get_lvds_info_from_regs(rdev); |
if (rdev->bios == NULL) { |
lvds = radeon_legacy_get_lvds_info_from_regs(rdev); |
goto out; |
} |
lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); |
975,11 → 967,13 |
lvds->native_mode.flags = 0; |
} |
} |
encoder->native_mode = lvds->native_mode; |
} else { |
DRM_INFO("No panel info found in BIOS\n"); |
return radeon_legacy_get_lvds_info_from_regs(rdev); |
lvds = radeon_legacy_get_lvds_info_from_regs(rdev); |
} |
out: |
if (lvds) |
encoder->native_mode = lvds->native_mode; |
return lvds; |
} |
1004,17 → 998,13 |
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS480 */ |
}; |
static struct radeon_encoder_int_tmds |
*radeon_legacy_get_tmds_info_from_table(struct radeon_device *rdev) |
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, |
struct radeon_encoder_int_tmds *tmds) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
int i; |
struct radeon_encoder_int_tmds *tmds = NULL; |
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); |
if (!tmds) |
return NULL; |
for (i = 0; i < 4; i++) { |
tmds->tmds_pll[i].value = |
default_tmds_pll[rdev->family][i].value; |
1021,12 → 1011,11 |
tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq; |
} |
return tmds; |
return true; |
} |
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct |
radeon_encoder |
*encoder) |
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, |
struct radeon_encoder_int_tmds *tmds) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
1033,20 → 1022,14 |
uint16_t tmds_info; |
int i, n; |
uint8_t ver; |
struct radeon_encoder_int_tmds *tmds = NULL; |
if (rdev->bios == NULL) |
return radeon_legacy_get_tmds_info_from_table(rdev); |
return false; |
tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); |
if (tmds_info) { |
tmds = |
kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); |
if (!tmds) |
return NULL; |
ver = RBIOS8(tmds_info); |
DRM_INFO("DFP table revision: %d\n", ver); |
if (ver == 3) { |
1083,6 → 1066,23 |
} |
} else |
DRM_INFO("No TMDS info found in BIOS\n"); |
return true; |
} |
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct radeon_encoder *encoder) |
{ |
struct radeon_encoder_int_tmds *tmds = NULL; |
bool ret; |
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); |
if (!tmds) |
return NULL; |
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds); |
if (ret == false) |
radeon_legacy_get_tmds_info_from_table(encoder, tmds); |
return tmds; |
} |
/drivers/video/drm/radeon/radeon_connectors.c |
---|
28,6 → 28,7 |
#include "drm_crtc_helper.h" |
#include "radeon_drm.h" |
#include "radeon.h" |
#include "atom.h" |
extern void |
radeon_combios_connected_scratch_regs(struct drm_connector *connector, |
38,6 → 39,15 |
struct drm_encoder *encoder, |
bool connected); |
static void radeon_property_change_mode(struct drm_encoder *encoder) |
{ |
struct drm_crtc *crtc = encoder->crtc; |
if (crtc && crtc->enabled) { |
drm_crtc_helper_set_mode(crtc, &crtc->mode, |
crtc->x, crtc->y, crtc->fb); |
} |
} |
static void |
radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status) |
{ |
77,6 → 87,27 |
} |
} |
struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type) |
{ |
struct drm_mode_object *obj; |
struct drm_encoder *encoder; |
int i; |
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (connector->encoder_ids[i] == 0) |
break; |
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
if (!obj) |
continue; |
encoder = obj_to_encoder(obj); |
if (encoder->encoder_type == encoder_type) |
return encoder; |
} |
return NULL; |
} |
struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) |
{ |
int enc_id = connector->encoder_ids[0]; |
83,8 → 114,6 |
struct drm_mode_object *obj; |
struct drm_encoder *encoder; |
ENTRY(); |
/* pick the encoder ids */ |
if (enc_id) { |
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
96,6 → 125,53 |
return NULL; |
} |
/* |
* radeon_connector_analog_encoder_conflict_solve |
* - search for other connectors sharing this encoder |
* if priority is true, then set them disconnected if this is connected |
* if priority is false, set us disconnected if they are connected |
*/ |
static enum drm_connector_status |
radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector, |
struct drm_encoder *encoder, |
enum drm_connector_status current_status, |
bool priority) |
{ |
struct drm_device *dev = connector->dev; |
struct drm_connector *conflict; |
int i; |
list_for_each_entry(conflict, &dev->mode_config.connector_list, head) { |
if (conflict == connector) |
continue; |
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (conflict->encoder_ids[i] == 0) |
break; |
/* if the IDs match */ |
if (conflict->encoder_ids[i] == encoder->base.id) { |
if (conflict->status != connector_status_connected) |
continue; |
if (priority == true) { |
DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict)); |
DRM_INFO("in favor of %s\n", drm_get_connector_name(connector)); |
conflict->status = connector_status_disconnected; |
radeon_connector_update_scratch_regs(conflict, connector_status_disconnected); |
} else { |
DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector)); |
DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict)); |
current_status = connector_status_disconnected; |
} |
break; |
} |
} |
} |
return current_status; |
} |
static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
128,13 → 204,172 |
return mode; |
} |
static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct drm_display_mode *mode = NULL; |
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
int i; |
struct mode_size { |
int w; |
int h; |
} common_modes[17] = { |
{ 640, 480}, |
{ 720, 480}, |
{ 800, 600}, |
{ 848, 480}, |
{1024, 768}, |
{1152, 768}, |
{1280, 720}, |
{1280, 800}, |
{1280, 854}, |
{1280, 960}, |
{1280, 1024}, |
{1440, 900}, |
{1400, 1050}, |
{1680, 1050}, |
{1600, 1200}, |
{1920, 1080}, |
{1920, 1200} |
}; |
for (i = 0; i < 17; i++) { |
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
if (common_modes[i].w > native_mode->panel_xres || |
common_modes[i].h > native_mode->panel_yres || |
(common_modes[i].w == native_mode->panel_xres && |
common_modes[i].h == native_mode->panel_yres)) |
continue; |
} |
if (common_modes[i].w < 320 || common_modes[i].h < 200) |
continue; |
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false); |
drm_mode_probed_add(connector, mode); |
} |
} |
int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property, |
uint64_t val) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct drm_encoder *encoder; |
struct radeon_encoder *radeon_encoder; |
if (property == rdev->mode_info.coherent_mode_property) { |
struct radeon_encoder_atom_dig *dig; |
/* need to find digital encoder on connector */ |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
if (!encoder) |
return 0; |
radeon_encoder = to_radeon_encoder(encoder); |
if (!radeon_encoder->enc_priv) |
return 0; |
dig = radeon_encoder->enc_priv; |
dig->coherent_mode = val ? true : false; |
radeon_property_change_mode(&radeon_encoder->base); |
} |
if (property == rdev->mode_info.tv_std_property) { |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC); |
if (!encoder) { |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC); |
} |
if (!encoder) |
return 0; |
radeon_encoder = to_radeon_encoder(encoder); |
if (!radeon_encoder->enc_priv) |
return 0; |
if (rdev->is_atom_bios) { |
struct radeon_encoder_atom_dac *dac_int; |
dac_int = radeon_encoder->enc_priv; |
dac_int->tv_std = val; |
} else { |
struct radeon_encoder_tv_dac *dac_int; |
dac_int = radeon_encoder->enc_priv; |
dac_int->tv_std = val; |
} |
radeon_property_change_mode(&radeon_encoder->base); |
} |
if (property == rdev->mode_info.load_detect_property) { |
struct radeon_connector *radeon_connector = |
to_radeon_connector(connector); |
if (val == 0) |
radeon_connector->dac_load_detect = false; |
else |
radeon_connector->dac_load_detect = true; |
} |
if (property == rdev->mode_info.tmds_pll_property) { |
struct radeon_encoder_int_tmds *tmds = NULL; |
bool ret = false; |
/* need to find digital encoder on connector */ |
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); |
if (!encoder) |
return 0; |
radeon_encoder = to_radeon_encoder(encoder); |
tmds = radeon_encoder->enc_priv; |
if (!tmds) |
return 0; |
if (val == 0) { |
if (rdev->is_atom_bios) |
ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds); |
else |
ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds); |
} |
if (val == 1 || ret == false) { |
radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds); |
} |
radeon_property_change_mode(&radeon_encoder->base); |
} |
return 0; |
} |
static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, |
struct drm_connector *connector) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
/* Try to get native mode details from EDID if necessary */ |
if (!native_mode->dotclock) { |
struct drm_display_mode *t, *mode; |
list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { |
if (mode->hdisplay == native_mode->panel_xres && |
mode->vdisplay == native_mode->panel_yres) { |
native_mode->hblank = mode->htotal - mode->hdisplay; |
native_mode->hoverplus = mode->hsync_start - mode->hdisplay; |
native_mode->hsync_width = mode->hsync_end - mode->hsync_start; |
native_mode->vblank = mode->vtotal - mode->vdisplay; |
native_mode->voverplus = mode->vsync_start - mode->vdisplay; |
native_mode->vsync_width = mode->vsync_end - mode->vsync_start; |
native_mode->dotclock = mode->clock; |
DRM_INFO("Determined LVDS native mode details from EDID\n"); |
break; |
} |
} |
} |
if (!native_mode->dotclock) { |
DRM_INFO("No LVDS native mode details, disabling RMX\n"); |
radeon_encoder->rmx_type = RMX_OFF; |
} |
} |
static int radeon_lvds_get_modes(struct drm_connector *connector) |
{ |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
145,6 → 380,12 |
if (radeon_connector->ddc_bus) { |
ret = radeon_ddc_get_modes(radeon_connector); |
if (ret > 0) { |
encoder = radeon_best_single_encoder(connector); |
if (encoder) { |
radeon_fixup_lvds_native_mode(encoder, connector); |
/* add scaled modes */ |
radeon_add_common_modes(encoder, connector); |
} |
return ret; |
} |
} |
158,7 → 399,10 |
if (mode) { |
ret = 1; |
drm_mode_probed_add(connector, mode); |
/* add scaled modes */ |
radeon_add_common_modes(encoder, connector); |
} |
return ret; |
} |
188,6 → 432,42 |
kfree(connector); |
} |
static int radeon_lvds_set_property(struct drm_connector *connector, |
struct drm_property *property, |
uint64_t value) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_encoder *radeon_encoder; |
enum radeon_rmx_type rmx_type; |
DRM_DEBUG("\n"); |
if (property != dev->mode_config.scaling_mode_property) |
return 0; |
if (connector->encoder) |
radeon_encoder = to_radeon_encoder(connector->encoder); |
else { |
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; |
radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector)); |
} |
switch (value) { |
case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break; |
case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break; |
case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break; |
default: |
case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break; |
} |
if (radeon_encoder->rmx_type == rmx_type) |
return 0; |
radeon_encoder->rmx_type = rmx_type; |
radeon_property_change_mode(&radeon_encoder->base); |
return 0; |
} |
struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = { |
.get_modes = radeon_lvds_get_modes, |
.mode_valid = radeon_lvds_mode_valid, |
199,7 → 479,7 |
.detect = radeon_lvds_detect, |
.fill_modes = drm_helper_probe_single_connector_modes, |
.destroy = radeon_connector_destroy, |
.set_property = radeon_connector_set_property, |
.set_property = radeon_lvds_set_property, |
}; |
static int radeon_vga_get_modes(struct drm_connector *connector) |
215,7 → 495,6 |
static int radeon_vga_mode_valid(struct drm_connector *connector, |
struct drm_display_mode *mode) |
{ |
return MODE_OK; |
} |
227,6 → 506,10 |
bool dret; |
enum drm_connector_status ret = connector_status_disconnected; |
encoder = radeon_best_single_encoder(connector); |
if (!encoder) |
ret = connector_status_disconnected; |
radeon_i2c_do_lock(radeon_connector, 1); |
dret = radeon_ddc_probe(radeon_connector); |
radeon_i2c_do_lock(radeon_connector, 0); |
233,16 → 516,14 |
if (dret) |
ret = connector_status_connected; |
else { |
/* if EDID fails to a load detect */ |
encoder = radeon_best_single_encoder(connector); |
if (!encoder) |
ret = connector_status_disconnected; |
else { |
if (radeon_connector->dac_load_detect) { |
encoder_funcs = encoder->helper_private; |
ret = encoder_funcs->detect(encoder, connector); |
} |
} |
if (ret == connector_status_connected) |
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
radeon_connector_update_scratch_regs(connector, ret); |
return ret; |
} |
261,6 → 542,73 |
.set_property = radeon_connector_set_property, |
}; |
static int radeon_tv_get_modes(struct drm_connector *connector) |
{ |
struct drm_device *dev = connector->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct drm_display_mode *tv_mode; |
struct drm_encoder *encoder; |
encoder = radeon_best_single_encoder(connector); |
if (!encoder) |
return 0; |
/* avivo chips can scale any mode */ |
if (rdev->family >= CHIP_RS600) |
/* add scaled modes */ |
radeon_add_common_modes(encoder, connector); |
else { |
/* only 800x600 is supported right now on pre-avivo chips */ |
tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false); |
tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; |
drm_mode_probed_add(connector, tv_mode); |
} |
return 1; |
} |
static int radeon_tv_mode_valid(struct drm_connector *connector, |
struct drm_display_mode *mode) |
{ |
return MODE_OK; |
} |
static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) |
{ |
struct drm_encoder *encoder; |
struct drm_encoder_helper_funcs *encoder_funcs; |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
enum drm_connector_status ret = connector_status_disconnected; |
if (!radeon_connector->dac_load_detect) |
return ret; |
encoder = radeon_best_single_encoder(connector); |
if (!encoder) |
ret = connector_status_disconnected; |
else { |
encoder_funcs = encoder->helper_private; |
ret = encoder_funcs->detect(encoder, connector); |
} |
if (ret == connector_status_connected) |
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); |
radeon_connector_update_scratch_regs(connector, ret); |
return ret; |
} |
struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = { |
.get_modes = radeon_tv_get_modes, |
.mode_valid = radeon_tv_mode_valid, |
.best_encoder = radeon_best_single_encoder, |
}; |
struct drm_connector_funcs radeon_tv_connector_funcs = { |
.dpms = drm_helper_connector_dpms, |
.detect = radeon_tv_detect, |
.fill_modes = drm_helper_probe_single_connector_modes, |
.destroy = radeon_connector_destroy, |
.set_property = radeon_connector_set_property, |
}; |
static int radeon_dvi_get_modes(struct drm_connector *connector) |
{ |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
267,15 → 615,24 |
int ret; |
ret = radeon_ddc_get_modes(radeon_connector); |
/* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */ |
radeon_connector_update_scratch_regs(connector, connector_status_connected); |
return ret; |
} |
/* |
* DVI is complicated |
* Do a DDC probe, if DDC probe passes, get the full EDID so |
* we can do analog/digital monitor detection at this point. |
* If the monitor is an analog monitor or we got no DDC, |
* we need to find the DAC encoder object for this connector. |
* If we got no DDC, we do load detection on the DAC encoder object. |
* If we got analog DDC or load detection passes on the DAC encoder |
* we have to check if this analog encoder is shared with anyone else (TV) |
* if its shared we have to set the other connector to disconnected. |
*/ |
static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) |
{ |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
struct drm_encoder *encoder; |
struct drm_encoder *encoder = NULL; |
struct drm_encoder_helper_funcs *encoder_funcs; |
struct drm_mode_object *obj; |
int i; |
285,9 → 642,29 |
radeon_i2c_do_lock(radeon_connector, 1); |
dret = radeon_ddc_probe(radeon_connector); |
radeon_i2c_do_lock(radeon_connector, 0); |
if (dret) |
if (dret) { |
radeon_i2c_do_lock(radeon_connector, 1); |
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
radeon_i2c_do_lock(radeon_connector, 0); |
if (!radeon_connector->edid) { |
DRM_ERROR("DDC responded but not EDID found for %s\n", |
drm_get_connector_name(connector)); |
} else { |
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); |
/* if this isn't a digital monitor |
then we need to make sure we don't have any |
TV conflicts */ |
ret = connector_status_connected; |
else { |
} |
} |
if ((ret == connector_status_connected) && (radeon_connector->use_digital == true)) |
goto out; |
/* find analog encoder */ |
if (radeon_connector->dac_load_detect) { |
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (connector->encoder_ids[i] == 0) |
break; |
302,15 → 679,23 |
encoder_funcs = encoder->helper_private; |
if (encoder_funcs->detect) { |
if (ret != connector_status_connected) { |
ret = encoder_funcs->detect(encoder, connector); |
if (ret == connector_status_connected) { |
radeon_connector->use_digital = 0; |
radeon_connector->use_digital = false; |
} |
} |
break; |
} |
} |
} |
if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) && |
encoder) { |
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); |
} |
out: |
/* updated in get modes as well since we need to know if it's analog or digital */ |
radeon_connector_update_scratch_regs(connector, ret); |
return ret; |
324,9 → 709,6 |
struct drm_mode_object *obj; |
struct drm_encoder *encoder; |
int i; |
ENTRY(); |
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
if (connector->encoder_ids[i] == 0) |
break; |
337,7 → 719,7 |
encoder = obj_to_encoder(obj); |
if (radeon_connector->use_digital) { |
if (radeon_connector->use_digital == true) { |
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) |
return encoder; |
} else { |
384,6 → 766,7 |
bool linkb, |
uint32_t igp_lane_info) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
struct radeon_connector_atom_dig *radeon_dig_connector; |
390,10 → 773,7 |
uint32_t subpixel_order = SubPixelNone; |
/* fixme - tv/cv/din */ |
if ((connector_type == DRM_MODE_CONNECTOR_Unknown) || |
(connector_type == DRM_MODE_CONNECTOR_SVIDEO) || |
(connector_type == DRM_MODE_CONNECTOR_Composite) || |
(connector_type == DRM_MODE_CONNECTOR_9PinDIN)) |
if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
return; |
/* see if we already added it */ |
422,6 → 802,9 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
break; |
case DRM_MODE_CONNECTOR_DVIA: |
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
431,6 → 814,9 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
break; |
case DRM_MODE_CONNECTOR_DVII: |
case DRM_MODE_CONNECTOR_DVID: |
448,6 → 834,12 |
goto failed; |
} |
subpixel_order = SubPixelHorizontalRGB; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.coherent_mode_property, |
1); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
break; |
case DRM_MODE_CONNECTOR_HDMIA: |
case DRM_MODE_CONNECTOR_HDMIB: |
464,6 → 856,9 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.coherent_mode_property, |
1); |
subpixel_order = SubPixelHorizontalRGB; |
break; |
case DRM_MODE_CONNECTOR_DisplayPort: |
485,6 → 880,13 |
case DRM_MODE_CONNECTOR_SVIDEO: |
case DRM_MODE_CONNECTOR_Composite: |
case DRM_MODE_CONNECTOR_9PinDIN: |
if (radeon_tv == 1) { |
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
break; |
case DRM_MODE_CONNECTOR_LVDS: |
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
500,6 → 902,10 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_mode_create_scaling_mode_property(dev); |
drm_connector_attach_property(&radeon_connector->base, |
dev->mode_config.scaling_mode_property, |
DRM_MODE_SCALE_FULLSCREEN); |
subpixel_order = SubPixelHorizontalRGB; |
break; |
} |
522,15 → 928,13 |
int connector_type, |
struct radeon_i2c_bus_rec *i2c_bus) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct drm_connector *connector; |
struct radeon_connector *radeon_connector; |
uint32_t subpixel_order = SubPixelNone; |
/* fixme - tv/cv/din */ |
if ((connector_type == DRM_MODE_CONNECTOR_Unknown) || |
(connector_type == DRM_MODE_CONNECTOR_SVIDEO) || |
(connector_type == DRM_MODE_CONNECTOR_Composite) || |
(connector_type == DRM_MODE_CONNECTOR_9PinDIN)) |
if (connector_type == DRM_MODE_CONNECTOR_Unknown) |
return; |
/* see if we already added it */ |
559,6 → 963,9 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
break; |
case DRM_MODE_CONNECTOR_DVIA: |
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
568,6 → 975,9 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
break; |
case DRM_MODE_CONNECTOR_DVII: |
case DRM_MODE_CONNECTOR_DVID: |
577,6 → 987,9 |
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
if (!radeon_connector->ddc_bus) |
goto failed; |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
} |
subpixel_order = SubPixelHorizontalRGB; |
break; |
583,6 → 996,13 |
case DRM_MODE_CONNECTOR_SVIDEO: |
case DRM_MODE_CONNECTOR_Composite: |
case DRM_MODE_CONNECTOR_9PinDIN: |
if (radeon_tv == 1) { |
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); |
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); |
drm_connector_attach_property(&radeon_connector->base, |
rdev->mode_info.load_detect_property, |
1); |
} |
break; |
case DRM_MODE_CONNECTOR_LVDS: |
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
592,6 → 1012,9 |
if (!radeon_connector->ddc_bus) |
goto failed; |
} |
drm_connector_attach_property(&radeon_connector->base, |
dev->mode_config.scaling_mode_property, |
DRM_MODE_SCALE_FULLSCREEN); |
subpixel_order = SubPixelHorizontalRGB; |
break; |
} |
/drivers/video/drm/radeon/radeon_cursor.c |
---|
0,0 → 1,260 |
/* |
* Copyright 2007-8 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
*/ |
#include "drmP.h" |
#include "radeon_drm.h" |
#include "radeon.h" |
#define CURSOR_WIDTH 64 |
#define CURSOR_HEIGHT 64 |
static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock) |
{ |
struct radeon_device *rdev = crtc->dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
uint32_t cur_lock; |
if (ASIC_IS_AVIVO(rdev)) { |
cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); |
if (lock) |
cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; |
else |
cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; |
WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); |
} else { |
cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset); |
if (lock) |
cur_lock |= RADEON_CUR_LOCK; |
else |
cur_lock &= ~RADEON_CUR_LOCK; |
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock); |
} |
} |
static void radeon_hide_cursor(struct drm_crtc *crtc) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct radeon_device *rdev = crtc->dev->dev_private; |
if (ASIC_IS_AVIVO(rdev)) { |
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); |
WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); |
} else { |
switch (radeon_crtc->crtc_id) { |
case 0: |
WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); |
break; |
case 1: |
WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); |
break; |
default: |
return; |
} |
WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN); |
} |
} |
static void radeon_show_cursor(struct drm_crtc *crtc) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct radeon_device *rdev = crtc->dev->dev_private; |
if (ASIC_IS_AVIVO(rdev)) { |
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); |
WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | |
(AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); |
} else { |
switch (radeon_crtc->crtc_id) { |
case 0: |
WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); |
break; |
case 1: |
WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); |
break; |
default: |
return; |
} |
WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | |
(RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), |
~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); |
} |
} |
static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, |
uint32_t gpu_addr) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct radeon_device *rdev = crtc->dev->dev_private; |
if (ASIC_IS_AVIVO(rdev)) |
WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); |
else { |
radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; |
/* offset is from DISP(2)_BASE_ADDRESS */ |
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); |
} |
} |
#if 0 |
int radeon_crtc_cursor_set(struct drm_crtc *crtc, |
struct drm_file *file_priv, |
uint32_t handle, |
uint32_t width, |
uint32_t height) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct drm_gem_object *obj; |
uint64_t gpu_addr; |
int ret; |
if (!handle) { |
/* turn off cursor */ |
radeon_hide_cursor(crtc); |
obj = NULL; |
goto unpin; |
} |
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { |
DRM_ERROR("bad cursor width or height %d x %d\n", width, height); |
return -EINVAL; |
} |
radeon_crtc->cursor_width = width; |
radeon_crtc->cursor_height = height; |
obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); |
if (!obj) { |
DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); |
return -EINVAL; |
} |
ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); |
if (ret) |
goto fail; |
radeon_lock_cursor(crtc, true); |
/* XXX only 27 bit offset for legacy cursor */ |
radeon_set_cursor(crtc, obj, gpu_addr); |
radeon_show_cursor(crtc); |
radeon_lock_cursor(crtc, false); |
unpin: |
if (radeon_crtc->cursor_bo) { |
radeon_gem_object_unpin(radeon_crtc->cursor_bo); |
mutex_lock(&crtc->dev->struct_mutex); |
drm_gem_object_unreference(radeon_crtc->cursor_bo); |
mutex_unlock(&crtc->dev->struct_mutex); |
} |
radeon_crtc->cursor_bo = obj; |
return 0; |
fail: |
mutex_lock(&crtc->dev->struct_mutex); |
drm_gem_object_unreference(obj); |
mutex_unlock(&crtc->dev->struct_mutex); |
return 0; |
} |
#endif |
int radeon_crtc_cursor_move(struct drm_crtc *crtc, |
int x, int y) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct radeon_device *rdev = crtc->dev->dev_private; |
int xorigin = 0, yorigin = 0; |
if (x < 0) |
xorigin = -x + 1; |
if (y < 0) |
yorigin = -y + 1; |
if (xorigin >= CURSOR_WIDTH) |
xorigin = CURSOR_WIDTH - 1; |
if (yorigin >= CURSOR_HEIGHT) |
yorigin = CURSOR_HEIGHT - 1; |
radeon_lock_cursor(crtc, true); |
if (ASIC_IS_AVIVO(rdev)) { |
int w = radeon_crtc->cursor_width; |
int i = 0; |
struct drm_crtc *crtc_p; |
/* avivo cursor are offset into the total surface */ |
x += crtc->x; |
y += crtc->y; |
DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); |
/* avivo cursor image can't end on 128 pixel boundry or |
* go past the end of the frame if both crtcs are enabled |
*/ |
list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) { |
if (crtc_p->enabled) |
i++; |
} |
if (i > 1) { |
int cursor_end, frame_end; |
cursor_end = x - xorigin + w; |
frame_end = crtc->x + crtc->mode.crtc_hdisplay; |
if (cursor_end >= frame_end) { |
w = w - (cursor_end - frame_end); |
if (!(frame_end & 0x7f)) |
w--; |
} else { |
if (!(cursor_end & 0x7f)) |
w--; |
} |
if (w <= 0) |
w = 1; |
} |
WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, |
((xorigin ? 0 : x) << 16) | |
(yorigin ? 0 : y)); |
WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); |
WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, |
((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); |
} else { |
if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) |
y *= 2; |
WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset, |
(RADEON_CUR_LOCK |
| (xorigin << 16) |
| yorigin)); |
WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset, |
(RADEON_CUR_LOCK |
| ((xorigin ? 0 : x) << 16) |
| (yorigin ? 0 : y))); |
/* offset is from DISP(2)_BASE_ADDRESS */ |
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + |
(yorigin * 256))); |
} |
radeon_lock_cursor(crtc, false); |
return 0; |
} |
/drivers/video/drm/radeon/radeon_device.c |
---|
27,8 → 27,8 |
*/ |
//#include <linux/console.h> |
#include <drmP.h> |
#include <drm_crtc_helper.h> |
#include <drm/drmP.h> |
#include <drm/drm_crtc_helper.h> |
#include "radeon_drm.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
43,14 → 43,15 |
int radeon_gart_size = 512; /* default gart size */ |
int radeon_benchmarking = 0; |
int radeon_connector_table = 0; |
int radeon_tv = 1; |
/* |
* Clear GPU surface registers. |
*/ |
static void radeon_surface_init(struct radeon_device *rdev) |
void radeon_surface_init(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
/* FIXME: check this out */ |
if (rdev->family < CHIP_R600) { |
61,6 → 62,8 |
i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), |
0); |
} |
/* enable surfaces */ |
WREG32(RADEON_SURFACE_CNTL, 0); |
} |
} |
67,7 → 70,7 |
/* |
* GPU scratch registers helpers function. |
*/ |
static void radeon_scratch_init(struct radeon_device *rdev) |
void radeon_scratch_init(struct radeon_device *rdev) |
{ |
int i; |
132,7 → 135,7 |
if (rdev->mc.vram_location != 0xFFFFFFFFUL) { |
/* vram location was already setup try to put gtt after |
* if it fits */ |
tmp = rdev->mc.vram_location + rdev->mc.vram_size; |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size; |
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); |
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { |
rdev->mc.gtt_location = tmp; |
147,13 → 150,13 |
} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { |
/* gtt location was already setup try to put vram before |
* if it fits */ |
if (rdev->mc.vram_size < rdev->mc.gtt_location) { |
if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) { |
rdev->mc.vram_location = 0; |
} else { |
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; |
tmp += (rdev->mc.vram_size - 1); |
tmp &= ~(rdev->mc.vram_size - 1); |
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { |
tmp += (rdev->mc.mc_vram_size - 1); |
tmp &= ~(rdev->mc.mc_vram_size - 1); |
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) { |
rdev->mc.vram_location = tmp; |
} else { |
printk(KERN_ERR "[drm] vram too big to fit " |
163,16 → 166,22 |
} |
} else { |
rdev->mc.vram_location = 0; |
rdev->mc.gtt_location = rdev->mc.vram_size; |
tmp = rdev->mc.mc_vram_size; |
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); |
rdev->mc.gtt_location = tmp; |
} |
DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); |
rdev->mc.vram_start = rdev->mc.vram_location; |
rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
rdev->mc.gtt_start = rdev->mc.gtt_location; |
rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; |
DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20)); |
DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", |
rdev->mc.vram_location, |
rdev->mc.vram_location + rdev->mc.vram_size - 1); |
DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); |
(unsigned)rdev->mc.vram_location, |
(unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1)); |
DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20)); |
DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", |
rdev->mc.gtt_location, |
rdev->mc.gtt_location + rdev->mc.gtt_size - 1); |
(unsigned)rdev->mc.gtt_location, |
(unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1)); |
return 0; |
} |
180,11 → 189,11 |
/* |
* GPU helpers function. |
*/ |
static bool radeon_card_posted(struct radeon_device *rdev) |
bool radeon_card_posted(struct radeon_device *rdev) |
{ |
uint32_t reg; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
/* first check CRTCs */ |
if (ASIC_IS_AVIVO(rdev)) { |
234,34 → 243,28 |
void radeon_register_accessor_init(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
rdev->mm_rreg = &r100_mm_rreg; |
rdev->mm_wreg = &r100_mm_wreg; |
rdev->mc_rreg = &radeon_invalid_rreg; |
rdev->mc_wreg = &radeon_invalid_wreg; |
rdev->pll_rreg = &radeon_invalid_rreg; |
rdev->pll_wreg = &radeon_invalid_wreg; |
rdev->pcie_rreg = &radeon_invalid_rreg; |
rdev->pcie_wreg = &radeon_invalid_wreg; |
rdev->pciep_rreg = &radeon_invalid_rreg; |
rdev->pciep_wreg = &radeon_invalid_wreg; |
/* Don't change order as we are overridding accessor. */ |
if (rdev->family < CHIP_RV515) { |
rdev->pcie_rreg = &rv370_pcie_rreg; |
rdev->pcie_wreg = &rv370_pcie_wreg; |
rdev->pcie_reg_mask = 0xff; |
} else { |
rdev->pcie_reg_mask = 0x7ff; |
} |
if (rdev->family >= CHIP_RV515) { |
rdev->pcie_rreg = &rv515_pcie_rreg; |
rdev->pcie_wreg = &rv515_pcie_wreg; |
} |
/* FIXME: not sure here */ |
if (rdev->family <= CHIP_R580) { |
rdev->pll_rreg = &r100_pll_rreg; |
rdev->pll_wreg = &r100_pll_wreg; |
} |
if (rdev->family >= CHIP_R420) { |
rdev->mc_rreg = &r420_mc_rreg; |
rdev->mc_wreg = &r420_mc_wreg; |
} |
if (rdev->family >= CHIP_RV515) { |
rdev->mc_rreg = &rv515_mc_rreg; |
rdev->mc_wreg = &rv515_mc_wreg; |
270,19 → 273,19 |
rdev->mc_rreg = &rs400_mc_rreg; |
rdev->mc_wreg = &rs400_mc_wreg; |
} |
if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { |
rdev->mc_rreg = &rs690_mc_rreg; |
rdev->mc_wreg = &rs690_mc_wreg; |
// if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { |
// rdev->mc_rreg = &rs690_mc_rreg; |
// rdev->mc_wreg = &rs690_mc_wreg; |
// } |
// if (rdev->family == CHIP_RS600) { |
// rdev->mc_rreg = &rs600_mc_rreg; |
// rdev->mc_wreg = &rs600_mc_wreg; |
// } |
// if (rdev->family >= CHIP_R600) { |
// rdev->pciep_rreg = &r600_pciep_rreg; |
// rdev->pciep_wreg = &r600_pciep_wreg; |
// } |
} |
if (rdev->family == CHIP_RS600) { |
rdev->mc_rreg = &rs600_mc_rreg; |
rdev->mc_wreg = &rs600_mc_wreg; |
} |
if (rdev->family >= CHIP_R600) { |
rdev->pciep_rreg = &r600_pciep_rreg; |
rdev->pciep_wreg = &r600_pciep_wreg; |
} |
} |
/* |
290,9 → 293,6 |
*/ |
int radeon_asic_init(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
radeon_register_accessor_init(rdev); |
switch (rdev->family) { |
case CHIP_R100: |
311,6 → 311,14 |
case CHIP_RV350: |
case CHIP_RV380: |
rdev->asic = &r300_asic; |
if (rdev->flags & RADEON_IS_PCIE) { |
rdev->asic->gart_init = &rv370_pcie_gart_init; |
rdev->asic->gart_fini = &rv370_pcie_gart_fini; |
rdev->asic->gart_enable = &rv370_pcie_gart_enable; |
rdev->asic->gart_disable = &rv370_pcie_gart_disable; |
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; |
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; |
} |
break; |
case CHIP_R420: |
case CHIP_R423: |
322,11 → 330,11 |
rdev->asic = &rs400_asic; |
break; |
case CHIP_RS600: |
rdev->asic = &rs600_asic; |
// rdev->asic = &rs600_asic; |
break; |
case CHIP_RS690: |
case CHIP_RS740: |
rdev->asic = &rs690_asic; |
// rdev->asic = &rs690_asic; |
break; |
case CHIP_RV515: |
rdev->asic = &rv515_asic; |
363,9 → 371,8 |
{ |
int r; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
radeon_get_clock_info(rdev->ddev); |
r = radeon_static_clocks_init(rdev->ddev); |
if (r) { |
return r; |
439,7 → 446,7 |
int radeon_atombios_init(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
atom_card_info.dev = rdev->ddev; |
rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios); |
465,6 → 472,7 |
int radeon_modeset_init(struct radeon_device *rdev); |
void radeon_modeset_fini(struct radeon_device *rdev); |
/* |
* Radeon device. |
*/ |
474,8 → 482,9 |
uint32_t flags) |
{ |
int r, ret; |
int dma_bits; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
DRM_INFO("radeon: Initializing kernel modesetting.\n"); |
rdev->shutdown = false; |
494,35 → 503,53 |
// mutex_init(&rdev->cp.mutex); |
// rwlock_init(&rdev->fence_drv.lock); |
/* Set asic functions */ |
r = radeon_asic_init(rdev); |
if (r) { |
return r; |
} |
if (radeon_agpmode == -1) { |
rdev->flags &= ~RADEON_IS_AGP; |
if (rdev->family > CHIP_RV515 || |
if (rdev->family >= CHIP_RV515 || |
rdev->family == CHIP_RV380 || |
rdev->family == CHIP_RV410 || |
rdev->family == CHIP_R423) { |
DRM_INFO("Forcing AGP to PCIE mode\n"); |
rdev->flags |= RADEON_IS_PCIE; |
rdev->asic->gart_init = &rv370_pcie_gart_init; |
rdev->asic->gart_fini = &rv370_pcie_gart_fini; |
rdev->asic->gart_enable = &rv370_pcie_gart_enable; |
rdev->asic->gart_disable = &rv370_pcie_gart_disable; |
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; |
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; |
} else { |
DRM_INFO("Forcing AGP to PCI mode\n"); |
rdev->flags |= RADEON_IS_PCI; |
rdev->asic->gart_init = &r100_pci_gart_init; |
rdev->asic->gart_fini = &r100_pci_gart_fini; |
rdev->asic->gart_enable = &r100_pci_gart_enable; |
rdev->asic->gart_disable = &r100_pci_gart_disable; |
rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; |
rdev->asic->gart_set_page = &r100_pci_gart_set_page; |
} |
} |
/* Set asic functions */ |
r = radeon_asic_init(rdev); |
if (r) { |
return r; |
} |
/* set DMA mask + need_dma32 flags. |
* PCIE - can handle 40-bits. |
* IGP - can handle 40-bits (in theory) |
* AGP - generally dma32 is safest |
* PCI - only dma32 |
*/ |
rdev->need_dma32 = false; |
if (rdev->flags & RADEON_IS_AGP) |
rdev->need_dma32 = true; |
if (rdev->flags & RADEON_IS_PCI) |
rdev->need_dma32 = true; |
r = rdev->asic->init(rdev); |
dma_bits = rdev->need_dma32 ? 32 : 40; |
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); |
if (r) { |
return r; |
} |
/* Report DMA addressing limitation */ |
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); |
if (r) { |
printk(KERN_WARNING "radeon: No suitable DMA available.\n"); |
} |
541,6 → 568,13 |
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base); |
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); |
rdev->new_init_path = false; |
r = radeon_init(rdev); |
if (r) { |
return r; |
} |
if (!rdev->new_init_path) { |
/* Setup errata flags */ |
radeon_errata(rdev); |
/* Initialize scratch registers */ |
548,7 → 582,6 |
/* Initialize surface registers */ |
radeon_surface_init(rdev); |
/* TODO: disable VGA need to use VGA request */ |
/* BIOS*/ |
if (!radeon_get_bios(rdev)) { |
if (ASIC_IS_AVIVO(rdev)) |
578,23 → 611,9 |
radeon_combios_asic_init(rdev->ddev); |
} |
} |
/* Get vram informations */ |
/* Get clock & vram information */ |
radeon_get_clock_info(rdev->ddev); |
radeon_vram_info(rdev); |
/* Device is severly broken if aper size > vram size. |
* for RN50/M6/M7 - Novell bug 204882 ? |
*/ |
if (rdev->mc.vram_size < rdev->mc.aper_size) { |
rdev->mc.aper_size = rdev->mc.vram_size; |
} |
/* Add an MTRR for the VRAM */ |
// rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, |
// MTRR_TYPE_WRCOMB, 1); |
DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", |
rdev->mc.vram_size >> 20, |
(unsigned)rdev->mc.aper_size >> 20); |
DRM_INFO("RAM width %dbits %cDR\n", |
rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); |
/* Initialize clocks */ |
r = radeon_clocks_init(rdev); |
if (r) { |
606,74 → 625,51 |
if (r) { |
return r; |
} |
/* Fence driver */ |
// r = radeon_fence_driver_init(rdev); |
// if (r) { |
// return r; |
// } |
// r = radeon_irq_kms_init(rdev); |
// if (r) { |
// return r; |
// } |
/* Memory manager */ |
r = radeon_object_init(rdev); |
if (r) { |
return r; |
} |
r = radeon_gpu_gart_init(rdev); |
if (r) |
return r; |
/* Initialize GART (initialize after TTM so we can allocate |
* memory through TTM but finalize after TTM) */ |
r = radeon_gart_enable(rdev); |
if (!r) { |
if (r) |
return 0; |
r = radeon_gem_init(rdev); |
} |
if (r) |
return 0; |
/* 1M ring buffer */ |
if (!r) { |
r = radeon_cp_init(rdev, 1024 * 1024); |
} |
// if (!r) { |
// r = radeon_wb_init(rdev); |
// if (r) { |
// DRM_ERROR("radeon: failled initializing WB (%d).\n", r); |
// return r; |
// } |
// } |
// r = radeon_cp_init(rdev, 1024 * 1024); |
// if (r) |
// return 0; |
#if 0 |
if (!r) { |
r = radeon_wb_init(rdev); |
if (r) |
DRM_ERROR("radeon: failled initializing WB (%d).\n", r); |
r = radeon_ib_pool_init(rdev); |
if (r) { |
DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); |
return r; |
} |
} |
if (!r) { |
if (r) |
return 0; |
r = radeon_ib_test(rdev); |
if (r) { |
DRM_ERROR("radeon: failled testing IB (%d).\n", r); |
return r; |
} |
} |
if (r) |
return 0; |
#endif |
ret = r; |
rdev->accel_working = true; |
r = radeon_modeset_init(rdev); |
if (r) { |
return r; |
} |
// if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) { |
// rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private; |
DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); |
// if (radeon_testing) { |
// radeon_test_moves(rdev); |
// } |
if (!ret) { |
DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); |
} |
if (radeon_benchmarking) { |
// if (radeon_benchmarking) { |
// radeon_benchmark(rdev); |
// } |
return 0; |
} |
return ret; |
// return -1; |
} |
static struct pci_device_id pciidlist[] = { |
radeon_PCI_IDS |
680,7 → 676,7 |
}; |
u32_t __stdcall drvEntry(int action) |
u32_t drvEntry(int action, char *cmdline) |
{ |
struct pci_device_id *ent; |
697,6 → 693,9 |
return 0; |
} |
if(cmdline) |
dbgprintf("cmdline: %s\n", cmdline); |
enum_pci_devices(); |
ent = find_pci_device(&device, pciidlist); |
932,3 → 931,6 |
/drivers/video/drm/radeon/radeon_display.c |
---|
158,9 → 158,6 |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
if (radeon_crtc->mode_set.mode) { |
drm_mode_destroy(crtc->dev, radeon_crtc->mode_set.mode); |
} |
drm_crtc_cleanup(crtc); |
kfree(radeon_crtc); |
} |
167,7 → 164,7 |
static const struct drm_crtc_funcs radeon_crtc_funcs = { |
// .cursor_set = radeon_crtc_cursor_set, |
// .cursor_move = radeon_crtc_cursor_move, |
.cursor_move = radeon_crtc_cursor_move, |
.gamma_set = radeon_crtc_gamma_set, |
.set_config = drm_crtc_helper_set_config, |
.destroy = radeon_crtc_destroy, |
179,8 → 176,6 |
struct radeon_crtc *radeon_crtc; |
int i; |
ENTRY(); |
radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); |
if (radeon_crtc == NULL) |
return; |
189,10 → 184,13 |
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); |
radeon_crtc->crtc_id = index; |
rdev->mode_info.crtcs[index] = radeon_crtc; |
#if 0 |
radeon_crtc->mode_set.crtc = &radeon_crtc->base; |
radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1); |
radeon_crtc->mode_set.num_connectors = 0; |
#endif |
for (i = 0; i < 256; i++) { |
radeon_crtc->lut_r[i] = i << 2; |
204,8 → 202,6 |
radeon_atombios_init_crtc(dev, radeon_crtc); |
else |
radeon_legacy_init_crtc(dev, radeon_crtc); |
LEAVE(); |
} |
static const char *encoder_names[34] = { |
316,14 → 312,12 |
} |
} |
bool radeon_setup_enc_conn(struct drm_device *dev) |
static bool radeon_setup_enc_conn(struct drm_device *dev) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct drm_connector *drm_connector; |
bool ret = false; |
ENTRY(); |
if (rdev->bios) { |
if (rdev->is_atom_bios) { |
if (rdev->family >= CHIP_R600) |
341,7 → 335,6 |
list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) |
radeon_ddc_dump(drm_connector); |
} |
LEAVE(); |
return ret; |
} |
353,9 → 346,13 |
if (!radeon_connector->ddc_bus) |
return -1; |
if (!radeon_connector->edid) { |
radeon_i2c_do_lock(radeon_connector, 1); |
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); |
radeon_i2c_do_lock(radeon_connector, 0); |
} else |
edid = radeon_connector->edid; |
if (edid) { |
/* update digital bits here */ |
if (edid->input & DRM_EDID_INPUT_DIGITAL) |
368,7 → 365,7 |
return ret; |
} |
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); |
return -1; |
return 0; |
} |
static int radeon_ddc_dump(struct drm_connector *connector) |
498,6 → 495,10 |
tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; |
current_freq = radeon_div(tmp, ref_div * post_div); |
if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { |
error = freq - current_freq; |
error = error < 0 ? 0xffffffff : error; |
} else |
error = abs(current_freq - freq); |
vco_diff = abs(vco - best_vco); |
556,7 → 557,6 |
*post_div_p = best_post_div; |
} |
static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) |
{ |
struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); |
590,7 → 590,6 |
.create_handle = radeon_user_framebuffer_create_handle, |
}; |
struct drm_framebuffer * |
radeon_framebuffer_create(struct drm_device *dev, |
struct drm_mode_fb_cmd *mode_cmd, |
622,17 → 621,90 |
// return radeon_framebuffer_create(dev, mode_cmd, obj); |
} |
static const struct drm_mode_config_funcs radeon_mode_funcs = { |
// .fb_create = radeon_user_framebuffer_create, |
.fb_changed = radeonfb_probe, |
}; |
int radeon_modeset_init(struct radeon_device *rdev) |
struct drm_prop_enum_list { |
int type; |
char *name; |
}; |
static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] = |
{ { 0, "driver" }, |
{ 1, "bios" }, |
}; |
static struct drm_prop_enum_list radeon_tv_std_enum_list[] = |
{ { TV_STD_NTSC, "ntsc" }, |
{ TV_STD_PAL, "pal" }, |
{ TV_STD_PAL_M, "pal-m" }, |
{ TV_STD_PAL_60, "pal-60" }, |
{ TV_STD_NTSC_J, "ntsc-j" }, |
{ TV_STD_SCART_PAL, "scart-pal" }, |
{ TV_STD_PAL_CN, "pal-cn" }, |
{ TV_STD_SECAM, "secam" }, |
}; |
int radeon_modeset_create_props(struct radeon_device *rdev) |
{ |
int i, sz; |
dbgprintf("%s\n",__FUNCTION__); |
if (rdev->is_atom_bios) { |
rdev->mode_info.coherent_mode_property = |
drm_property_create(rdev->ddev, |
DRM_MODE_PROP_RANGE, |
"coherent", 2); |
if (!rdev->mode_info.coherent_mode_property) |
return -ENOMEM; |
rdev->mode_info.coherent_mode_property->values[0] = 0; |
rdev->mode_info.coherent_mode_property->values[0] = 1; |
} |
if (!ASIC_IS_AVIVO(rdev)) { |
sz = ARRAY_SIZE(radeon_tmds_pll_enum_list); |
rdev->mode_info.tmds_pll_property = |
drm_property_create(rdev->ddev, |
DRM_MODE_PROP_ENUM, |
"tmds_pll", sz); |
for (i = 0; i < sz; i++) { |
drm_property_add_enum(rdev->mode_info.tmds_pll_property, |
i, |
radeon_tmds_pll_enum_list[i].type, |
radeon_tmds_pll_enum_list[i].name); |
} |
} |
rdev->mode_info.load_detect_property = |
drm_property_create(rdev->ddev, |
DRM_MODE_PROP_RANGE, |
"load detection", 2); |
if (!rdev->mode_info.load_detect_property) |
return -ENOMEM; |
rdev->mode_info.load_detect_property->values[0] = 0; |
rdev->mode_info.load_detect_property->values[0] = 1; |
drm_mode_create_scaling_mode_property(rdev->ddev); |
sz = ARRAY_SIZE(radeon_tv_std_enum_list); |
rdev->mode_info.tv_std_property = |
drm_property_create(rdev->ddev, |
DRM_MODE_PROP_ENUM, |
"tv standard", sz); |
for (i = 0; i < sz; i++) { |
drm_property_add_enum(rdev->mode_info.tv_std_property, |
i, |
radeon_tv_std_enum_list[i].type, |
radeon_tv_std_enum_list[i].name); |
} |
return 0; |
} |
int radeon_modeset_init(struct radeon_device *rdev) |
{ |
int num_crtc = 2, i; |
int ret; |
651,6 → 723,10 |
rdev->ddev->mode_config.fb_base = rdev->mc.aper_base; |
ret = radeon_modeset_create_props(rdev); |
if (ret) { |
return ret; |
} |
/* allocate crtcs - TODO single crtc */ |
for (i = 0; i < num_crtc; i++) { |
radeon_crtc_init(rdev->ddev, i); |
662,9 → 738,6 |
return ret; |
} |
drm_helper_initial_config(rdev->ddev); |
dbgprintf("done %s\n",__FUNCTION__); |
return 0; |
} |
676,36 → 749,50 |
} |
} |
void radeon_init_disp_bandwidth(struct drm_device *dev) |
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct drm_display_mode *modes[2]; |
int pixel_bytes[2]; |
struct drm_crtc *crtc; |
pixel_bytes[0] = pixel_bytes[1] = 0; |
modes[0] = modes[1] = NULL; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_device *dev = crtc->dev; |
struct drm_encoder *encoder; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct radeon_encoder *radeon_encoder; |
bool first = true; |
if (crtc->enabled && crtc->fb) { |
modes[radeon_crtc->crtc_id] = &crtc->mode; |
pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8; |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
radeon_encoder = to_radeon_encoder(encoder); |
if (encoder->crtc != crtc) |
continue; |
if (first) { |
radeon_crtc->rmx_type = radeon_encoder->rmx_type; |
memcpy(&radeon_crtc->native_mode, |
&radeon_encoder->native_mode, |
sizeof(struct radeon_native_mode)); |
first = false; |
} else { |
if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) { |
/* WARNING: Right now this can't happen but |
* in the future we need to check that scaling |
* are consistent accross different encoder |
* (ie all encoder can work with the same |
* scaling). |
*/ |
DRM_ERROR("Scaling not consistent accross encoder.\n"); |
return false; |
} |
} |
if (ASIC_IS_AVIVO(rdev)) { |
radeon_init_disp_bw_avivo(dev, |
modes[0], |
pixel_bytes[0], |
modes[1], |
pixel_bytes[1]); |
} |
if (radeon_crtc->rmx_type != RMX_OFF) { |
fixed20_12 a, b; |
a.full = rfixed_const(crtc->mode.vdisplay); |
b.full = rfixed_const(radeon_crtc->native_mode.panel_xres); |
radeon_crtc->vsc.full = rfixed_div(a, b); |
a.full = rfixed_const(crtc->mode.hdisplay); |
b.full = rfixed_const(radeon_crtc->native_mode.panel_yres); |
radeon_crtc->hsc.full = rfixed_div(a, b); |
} else { |
radeon_init_disp_bw_legacy(dev, |
modes[0], |
pixel_bytes[0], |
modes[1], |
pixel_bytes[1]); |
radeon_crtc->vsc.full = rfixed_const(1); |
radeon_crtc->hsc.full = rfixed_const(1); |
} |
return true; |
} |
/drivers/video/drm/radeon/radeon_encoders.c |
---|
126,6 → 126,23 |
} |
} |
void radeon_encoder_set_active_device(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct drm_connector *connector; |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
if (connector->encoder == encoder) { |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices; |
DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n", |
radeon_encoder->active_device, radeon_encoder->devices, |
radeon_connector->devices, encoder->encoder_type); |
} |
} |
} |
static struct drm_connector * |
radeon_get_connector_for_encoder(struct drm_encoder *encoder) |
{ |
154,7 → 171,6 |
if (mode->hdisplay < native_mode->panel_xres || |
mode->vdisplay < native_mode->panel_yres) { |
radeon_encoder->flags |= RADEON_USE_RMX; |
if (ASIC_IS_AVIVO(rdev)) { |
adjusted_mode->hdisplay = native_mode->panel_xres; |
adjusted_mode->vdisplay = native_mode->panel_yres; |
201,11 → 217,8 |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
radeon_encoder->flags &= ~RADEON_USE_RMX; |
drm_mode_set_crtcinfo(adjusted_mode, 0); |
if (radeon_encoder->rmx_type != RMX_OFF) |
227,9 → 240,12 |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
DAC_ENCODER_CONTROL_PS_ALLOCATION args; |
int index = 0, num = 0; |
/* fixme - fill in enc_priv for atom dac */ |
struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; |
enum radeon_tv_std tv_std = TV_STD_NTSC; |
if (dac_info->tv_std) |
tv_std = dac_info->tv_std; |
memset(&args, 0, sizeof(args)); |
switch (radeon_encoder->encoder_id) { |
247,9 → 263,9 |
args.ucAction = action; |
if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT)) |
args.ucDacStandard = ATOM_DAC1_PS2; |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
args.ucDacStandard = ATOM_DAC1_CV; |
else { |
switch (tv_std) { |
282,9 → 298,12 |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
TV_ENCODER_CONTROL_PS_ALLOCATION args; |
int index = 0; |
/* fixme - fill in enc_priv for atom dac */ |
struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; |
enum radeon_tv_std tv_std = TV_STD_NTSC; |
if (dac_info->tv_std) |
tv_std = dac_info->tv_std; |
memset(&args, 0, sizeof(args)); |
index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); |
291,7 → 310,7 |
args.sTVEncoder.ucAction = action; |
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
args.sTVEncoder.ucTvStandard = ATOM_TV_CV; |
else { |
switch (tv_std) { |
523,6 → 542,7 |
switch (connector->connector_type) { |
case DRM_MODE_CONNECTOR_DVII: |
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ |
if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) |
return ATOM_ENCODER_MODE_HDMI; |
else if (radeon_connector->use_digital) |
532,7 → 552,6 |
break; |
case DRM_MODE_CONNECTOR_DVID: |
case DRM_MODE_CONNECTOR_HDMIA: |
case DRM_MODE_CONNECTOR_HDMIB: |
default: |
if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) |
return ATOM_ENCODER_MODE_HDMI; |
808,234 → 827,6 |
} |
static void atom_rv515_force_tv_scaler(struct radeon_device *rdev) |
{ |
WREG32(0x659C, 0x0); |
WREG32(0x6594, 0x705); |
WREG32(0x65A4, 0x10001); |
WREG32(0x65D8, 0x0); |
WREG32(0x65B0, 0x0); |
WREG32(0x65C0, 0x0); |
WREG32(0x65D4, 0x0); |
WREG32(0x6578, 0x0); |
WREG32(0x657C, 0x841880A8); |
WREG32(0x6578, 0x1); |
WREG32(0x657C, 0x84208680); |
WREG32(0x6578, 0x2); |
WREG32(0x657C, 0xBFF880B0); |
WREG32(0x6578, 0x100); |
WREG32(0x657C, 0x83D88088); |
WREG32(0x6578, 0x101); |
WREG32(0x657C, 0x84608680); |
WREG32(0x6578, 0x102); |
WREG32(0x657C, 0xBFF080D0); |
WREG32(0x6578, 0x200); |
WREG32(0x657C, 0x83988068); |
WREG32(0x6578, 0x201); |
WREG32(0x657C, 0x84A08680); |
WREG32(0x6578, 0x202); |
WREG32(0x657C, 0xBFF080F8); |
WREG32(0x6578, 0x300); |
WREG32(0x657C, 0x83588058); |
WREG32(0x6578, 0x301); |
WREG32(0x657C, 0x84E08660); |
WREG32(0x6578, 0x302); |
WREG32(0x657C, 0xBFF88120); |
WREG32(0x6578, 0x400); |
WREG32(0x657C, 0x83188040); |
WREG32(0x6578, 0x401); |
WREG32(0x657C, 0x85008660); |
WREG32(0x6578, 0x402); |
WREG32(0x657C, 0xBFF88150); |
WREG32(0x6578, 0x500); |
WREG32(0x657C, 0x82D88030); |
WREG32(0x6578, 0x501); |
WREG32(0x657C, 0x85408640); |
WREG32(0x6578, 0x502); |
WREG32(0x657C, 0xBFF88180); |
WREG32(0x6578, 0x600); |
WREG32(0x657C, 0x82A08018); |
WREG32(0x6578, 0x601); |
WREG32(0x657C, 0x85808620); |
WREG32(0x6578, 0x602); |
WREG32(0x657C, 0xBFF081B8); |
WREG32(0x6578, 0x700); |
WREG32(0x657C, 0x82608010); |
WREG32(0x6578, 0x701); |
WREG32(0x657C, 0x85A08600); |
WREG32(0x6578, 0x702); |
WREG32(0x657C, 0x800081F0); |
WREG32(0x6578, 0x800); |
WREG32(0x657C, 0x8228BFF8); |
WREG32(0x6578, 0x801); |
WREG32(0x657C, 0x85E085E0); |
WREG32(0x6578, 0x802); |
WREG32(0x657C, 0xBFF88228); |
WREG32(0x6578, 0x10000); |
WREG32(0x657C, 0x82A8BF00); |
WREG32(0x6578, 0x10001); |
WREG32(0x657C, 0x82A08CC0); |
WREG32(0x6578, 0x10002); |
WREG32(0x657C, 0x8008BEF8); |
WREG32(0x6578, 0x10100); |
WREG32(0x657C, 0x81F0BF28); |
WREG32(0x6578, 0x10101); |
WREG32(0x657C, 0x83608CA0); |
WREG32(0x6578, 0x10102); |
WREG32(0x657C, 0x8018BED0); |
WREG32(0x6578, 0x10200); |
WREG32(0x657C, 0x8148BF38); |
WREG32(0x6578, 0x10201); |
WREG32(0x657C, 0x84408C80); |
WREG32(0x6578, 0x10202); |
WREG32(0x657C, 0x8008BEB8); |
WREG32(0x6578, 0x10300); |
WREG32(0x657C, 0x80B0BF78); |
WREG32(0x6578, 0x10301); |
WREG32(0x657C, 0x85008C20); |
WREG32(0x6578, 0x10302); |
WREG32(0x657C, 0x8020BEA0); |
WREG32(0x6578, 0x10400); |
WREG32(0x657C, 0x8028BF90); |
WREG32(0x6578, 0x10401); |
WREG32(0x657C, 0x85E08BC0); |
WREG32(0x6578, 0x10402); |
WREG32(0x657C, 0x8018BE90); |
WREG32(0x6578, 0x10500); |
WREG32(0x657C, 0xBFB8BFB0); |
WREG32(0x6578, 0x10501); |
WREG32(0x657C, 0x86C08B40); |
WREG32(0x6578, 0x10502); |
WREG32(0x657C, 0x8010BE90); |
WREG32(0x6578, 0x10600); |
WREG32(0x657C, 0xBF58BFC8); |
WREG32(0x6578, 0x10601); |
WREG32(0x657C, 0x87A08AA0); |
WREG32(0x6578, 0x10602); |
WREG32(0x657C, 0x8010BE98); |
WREG32(0x6578, 0x10700); |
WREG32(0x657C, 0xBF10BFF0); |
WREG32(0x6578, 0x10701); |
WREG32(0x657C, 0x886089E0); |
WREG32(0x6578, 0x10702); |
WREG32(0x657C, 0x8018BEB0); |
WREG32(0x6578, 0x10800); |
WREG32(0x657C, 0xBED8BFE8); |
WREG32(0x6578, 0x10801); |
WREG32(0x657C, 0x89408940); |
WREG32(0x6578, 0x10802); |
WREG32(0x657C, 0xBFE8BED8); |
WREG32(0x6578, 0x20000); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x20001); |
WREG32(0x657C, 0x90008000); |
WREG32(0x6578, 0x20002); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x20003); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x20100); |
WREG32(0x657C, 0x80108000); |
WREG32(0x6578, 0x20101); |
WREG32(0x657C, 0x8FE0BF70); |
WREG32(0x6578, 0x20102); |
WREG32(0x657C, 0xBFE880C0); |
WREG32(0x6578, 0x20103); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x20200); |
WREG32(0x657C, 0x8018BFF8); |
WREG32(0x6578, 0x20201); |
WREG32(0x657C, 0x8F80BF08); |
WREG32(0x6578, 0x20202); |
WREG32(0x657C, 0xBFD081A0); |
WREG32(0x6578, 0x20203); |
WREG32(0x657C, 0xBFF88000); |
WREG32(0x6578, 0x20300); |
WREG32(0x657C, 0x80188000); |
WREG32(0x6578, 0x20301); |
WREG32(0x657C, 0x8EE0BEC0); |
WREG32(0x6578, 0x20302); |
WREG32(0x657C, 0xBFB082A0); |
WREG32(0x6578, 0x20303); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x20400); |
WREG32(0x657C, 0x80188000); |
WREG32(0x6578, 0x20401); |
WREG32(0x657C, 0x8E00BEA0); |
WREG32(0x6578, 0x20402); |
WREG32(0x657C, 0xBF8883C0); |
WREG32(0x6578, 0x20403); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x20500); |
WREG32(0x657C, 0x80188000); |
WREG32(0x6578, 0x20501); |
WREG32(0x657C, 0x8D00BE90); |
WREG32(0x6578, 0x20502); |
WREG32(0x657C, 0xBF588500); |
WREG32(0x6578, 0x20503); |
WREG32(0x657C, 0x80008008); |
WREG32(0x6578, 0x20600); |
WREG32(0x657C, 0x80188000); |
WREG32(0x6578, 0x20601); |
WREG32(0x657C, 0x8BC0BE98); |
WREG32(0x6578, 0x20602); |
WREG32(0x657C, 0xBF308660); |
WREG32(0x6578, 0x20603); |
WREG32(0x657C, 0x80008008); |
WREG32(0x6578, 0x20700); |
WREG32(0x657C, 0x80108000); |
WREG32(0x6578, 0x20701); |
WREG32(0x657C, 0x8A80BEB0); |
WREG32(0x6578, 0x20702); |
WREG32(0x657C, 0xBF0087C0); |
WREG32(0x6578, 0x20703); |
WREG32(0x657C, 0x80008008); |
WREG32(0x6578, 0x20800); |
WREG32(0x657C, 0x80108000); |
WREG32(0x6578, 0x20801); |
WREG32(0x657C, 0x8920BED0); |
WREG32(0x6578, 0x20802); |
WREG32(0x657C, 0xBED08920); |
WREG32(0x6578, 0x20803); |
WREG32(0x657C, 0x80008010); |
WREG32(0x6578, 0x30000); |
WREG32(0x657C, 0x90008000); |
WREG32(0x6578, 0x30001); |
WREG32(0x657C, 0x80008000); |
WREG32(0x6578, 0x30100); |
WREG32(0x657C, 0x8FE0BF90); |
WREG32(0x6578, 0x30101); |
WREG32(0x657C, 0xBFF880A0); |
WREG32(0x6578, 0x30200); |
WREG32(0x657C, 0x8F60BF40); |
WREG32(0x6578, 0x30201); |
WREG32(0x657C, 0xBFE88180); |
WREG32(0x6578, 0x30300); |
WREG32(0x657C, 0x8EC0BF00); |
WREG32(0x6578, 0x30301); |
WREG32(0x657C, 0xBFC88280); |
WREG32(0x6578, 0x30400); |
WREG32(0x657C, 0x8DE0BEE0); |
WREG32(0x6578, 0x30401); |
WREG32(0x657C, 0xBFA083A0); |
WREG32(0x6578, 0x30500); |
WREG32(0x657C, 0x8CE0BED0); |
WREG32(0x6578, 0x30501); |
WREG32(0x657C, 0xBF7884E0); |
WREG32(0x6578, 0x30600); |
WREG32(0x657C, 0x8BA0BED8); |
WREG32(0x6578, 0x30601); |
WREG32(0x657C, 0xBF508640); |
WREG32(0x6578, 0x30700); |
WREG32(0x657C, 0x8A60BEE8); |
WREG32(0x6578, 0x30701); |
WREG32(0x657C, 0xBF2087A0); |
WREG32(0x6578, 0x30800); |
WREG32(0x657C, 0x8900BF00); |
WREG32(0x6578, 0x30801); |
WREG32(0x657C, 0xBF008900); |
} |
static void |
atombios_yuv_setup(struct drm_encoder *encoder, bool enable) |
{ |
1056,10 → 847,10 |
/* XXX: fix up scratch reg handling */ |
temp = RREG32(reg); |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
WREG32(reg, (ATOM_S3_TV1_ACTIVE | |
(radeon_crtc->crtc_id << 18))); |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); |
else |
WREG32(reg, 0); |
1074,129 → 865,6 |
} |
static void |
atombios_overscan_setup(struct drm_encoder *encoder, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
SET_CRTC_OVERSCAN_PS_ALLOCATION args; |
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); |
memset(&args, 0, sizeof(args)); |
args.usOverscanRight = 0; |
args.usOverscanLeft = 0; |
args.usOverscanBottom = 0; |
args.usOverscanTop = 0; |
args.ucCRTC = radeon_crtc->crtc_id; |
if (radeon_encoder->flags & RADEON_USE_RMX) { |
if (radeon_encoder->rmx_type == RMX_FULL) { |
args.usOverscanRight = 0; |
args.usOverscanLeft = 0; |
args.usOverscanBottom = 0; |
args.usOverscanTop = 0; |
} else if (radeon_encoder->rmx_type == RMX_CENTER) { |
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; |
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; |
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; |
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; |
} else if (radeon_encoder->rmx_type == RMX_ASPECT) { |
int a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; |
int a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; |
if (a1 > a2) { |
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; |
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; |
} else if (a2 > a1) { |
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; |
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; |
} |
} |
} |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
} |
static void |
atombios_scaler_setup(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
ENABLE_SCALER_PS_ALLOCATION args; |
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); |
/* fixme - fill in enc_priv for atom dac */ |
enum radeon_tv_std tv_std = TV_STD_NTSC; |
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) |
return; |
memset(&args, 0, sizeof(args)); |
args.ucScaler = radeon_crtc->crtc_id; |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { |
switch (tv_std) { |
case TV_STD_NTSC: |
default: |
args.ucTVStandard = ATOM_TV_NTSC; |
break; |
case TV_STD_PAL: |
args.ucTVStandard = ATOM_TV_PAL; |
break; |
case TV_STD_PAL_M: |
args.ucTVStandard = ATOM_TV_PALM; |
break; |
case TV_STD_PAL_60: |
args.ucTVStandard = ATOM_TV_PAL60; |
break; |
case TV_STD_NTSC_J: |
args.ucTVStandard = ATOM_TV_NTSCJ; |
break; |
case TV_STD_SCART_PAL: |
args.ucTVStandard = ATOM_TV_PAL; /* ??? */ |
break; |
case TV_STD_SECAM: |
args.ucTVStandard = ATOM_TV_SECAM; |
break; |
case TV_STD_PAL_CN: |
args.ucTVStandard = ATOM_TV_PALCN; |
break; |
} |
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
} else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) { |
args.ucTVStandard = ATOM_TV_CV; |
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; |
} else if (radeon_encoder->flags & RADEON_USE_RMX) { |
if (radeon_encoder->rmx_type == RMX_FULL) |
args.ucEnable = ATOM_SCALER_EXPANSION; |
else if (radeon_encoder->rmx_type == RMX_CENTER) |
args.ucEnable = ATOM_SCALER_CENTER; |
else if (radeon_encoder->rmx_type == RMX_ASPECT) |
args.ucEnable = ATOM_SCALER_EXPANSION; |
} else { |
if (ASIC_IS_AVIVO(rdev)) |
args.ucEnable = ATOM_SCALER_DISABLE; |
else |
args.ucEnable = ATOM_SCALER_CENTER; |
} |
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) |
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) { |
atom_rv515_force_tv_scaler(rdev); |
} |
} |
static void |
radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) |
{ |
struct drm_device *dev = encoder->dev; |
1205,9 → 873,19 |
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; |
int index = 0; |
bool is_dig = false; |
int devices; |
memset(&args, 0, sizeof(args)); |
/* on DPMS off we have no idea if active device is meaningful */ |
if (mode != DRM_MODE_DPMS_ON && !radeon_encoder->active_device) |
devices = radeon_encoder->devices; |
else |
devices = radeon_encoder->active_device; |
DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n", |
radeon_encoder->encoder_id, mode, radeon_encoder->devices, |
radeon_encoder->active_device); |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_TMDS1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
1235,9 → 913,9 |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DAC1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (devices & (ATOM_DEVICE_TV_SUPPORT)) |
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (devices & (ATOM_DEVICE_CV_SUPPORT)) |
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); |
else |
index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); |
1244,9 → 922,9 |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DAC2: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (devices & (ATOM_DEVICE_TV_SUPPORT)) |
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (devices & (ATOM_DEVICE_CV_SUPPORT)) |
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); |
else |
index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); |
1333,9 → 1011,9 |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DAC1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; |
else |
args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; |
1342,9 → 1020,9 |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DAC2: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; |
else |
args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; |
1373,17 → 1051,17 |
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
else |
args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; |
break; |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) |
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) |
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT)) |
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; |
else |
args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; |
1448,12 → 1126,10 |
radeon_encoder->pixel_clock = adjusted_mode->clock; |
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); |
atombios_overscan_setup(encoder, mode, adjusted_mode); |
atombios_scaler_setup(encoder); |
atombios_set_encoder_crtc_source(encoder); |
if (ASIC_IS_AVIVO(rdev)) { |
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) |
atombios_yuv_setup(encoder, true); |
else |
atombios_yuv_setup(encoder, false); |
1491,7 → 1167,7 |
case ENCODER_OBJECT_ID_INTERNAL_DAC2: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: |
atombios_dac_setup(encoder, ATOM_ENABLE); |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) |
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) |
atombios_tv_setup(encoder, ATOM_ENABLE); |
break; |
} |
1499,11 → 1175,12 |
} |
static bool |
atombios_dac_load_detect(struct drm_encoder *encoder) |
atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | |
ATOM_DEVICE_CV_SUPPORT | |
1524,15 → 1201,15 |
else |
args.sDacload.ucDacType = ATOM_DAC_B; |
if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) |
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) |
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); |
else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) |
else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) |
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); |
else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { |
else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { |
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); |
if (crev >= 3) |
args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; |
} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { |
} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { |
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); |
if (crev >= 3) |
args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; |
1551,9 → 1228,10 |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
uint32_t bios_0_scratch; |
if (!atombios_dac_load_detect(encoder)) { |
if (!atombios_dac_load_detect(encoder, connector)) { |
DRM_DEBUG("detect returned false \n"); |
return connector_status_unknown; |
} |
1563,17 → 1241,20 |
else |
bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); |
DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch); |
if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { |
DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); |
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { |
if (bios_0_scratch & ATOM_S0_CRT1_MASK) |
return connector_status_connected; |
} else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { |
} |
if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { |
if (bios_0_scratch & ATOM_S0_CRT2_MASK) |
return connector_status_connected; |
} else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { |
} |
if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { |
if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) |
return connector_status_connected; |
} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { |
} |
if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { |
if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) |
return connector_status_connected; /* CTV */ |
else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) |
1586,6 → 1267,8 |
{ |
radeon_atom_output_lock(encoder, true); |
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder_set_active_device(encoder); |
} |
static void radeon_atom_encoder_commit(struct drm_encoder *encoder) |
1594,6 → 1277,13 |
radeon_atom_output_lock(encoder, false); |
} |
static void radeon_atom_encoder_disable(struct drm_encoder *encoder) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder->active_device = 0; |
} |
static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { |
.dpms = radeon_atom_encoder_dpms, |
.mode_fixup = radeon_atom_mode_fixup, |
1600,6 → 1290,7 |
.prepare = radeon_atom_encoder_prepare, |
.mode_set = radeon_atom_encoder_mode_set, |
.commit = radeon_atom_encoder_commit, |
.disable = radeon_atom_encoder_disable, |
/* no detect for TMDS/LVDS yet */ |
}; |
1624,6 → 1315,18 |
.destroy = radeon_enc_destroy, |
}; |
struct radeon_encoder_atom_dac * |
radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) |
{ |
struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL); |
if (!dac) |
return NULL; |
dac->tv_std = TV_STD_NTSC; |
return dac; |
} |
struct radeon_encoder_atom_dig * |
radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) |
{ |
1667,6 → 1370,7 |
radeon_encoder->encoder_id = encoder_id; |
radeon_encoder->devices = supported_device; |
radeon_encoder->rmx_type = RMX_OFF; |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
1691,6 → 1395,7 |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: |
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); |
radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder); |
drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DVO1: |
1700,8 → 1405,14 |
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: |
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: |
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
radeon_encoder->rmx_type = RMX_FULL; |
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); |
radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); |
} else { |
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); |
radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); |
} |
drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); |
break; |
} |
/drivers/video/drm/radeon/radeon_family.h |
---|
0,0 → 1,97 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
/* this file defines the CHIP_ and family flags used in the pciids, |
* its is common between kms and non-kms because duplicating it and |
* changing one place is fail. |
*/ |
#ifndef RADEON_FAMILY_H |
#define RADEON_FAMILY_H |
/* |
* Radeon chip families |
*/ |
enum radeon_family { |
CHIP_R100, |
CHIP_RV100, |
CHIP_RS100, |
CHIP_RV200, |
CHIP_RS200, |
CHIP_R200, |
CHIP_RV250, |
CHIP_RS300, |
CHIP_RV280, |
CHIP_R300, |
CHIP_R350, |
CHIP_RV350, |
CHIP_RV380, |
CHIP_R420, |
CHIP_R423, |
CHIP_RV410, |
CHIP_RS400, |
CHIP_RS480, |
CHIP_RS600, |
CHIP_RS690, |
CHIP_RS740, |
CHIP_RV515, |
CHIP_R520, |
CHIP_RV530, |
CHIP_RV560, |
CHIP_RV570, |
CHIP_R580, |
CHIP_R600, |
CHIP_RV610, |
CHIP_RV630, |
CHIP_RV670, |
CHIP_RV620, |
CHIP_RV635, |
CHIP_RS780, |
CHIP_RS880, |
CHIP_RV770, |
CHIP_RV730, |
CHIP_RV710, |
CHIP_RV740, |
CHIP_LAST, |
}; |
/* |
* Chip flags |
*/ |
enum radeon_chip_flags { |
RADEON_FAMILY_MASK = 0x0000ffffUL, |
RADEON_FLAGS_MASK = 0xffff0000UL, |
RADEON_IS_MOBILITY = 0x00010000UL, |
RADEON_IS_IGP = 0x00020000UL, |
RADEON_SINGLE_CRTC = 0x00040000UL, |
RADEON_IS_AGP = 0x00080000UL, |
RADEON_HAS_HIERZ = 0x00100000UL, |
RADEON_IS_PCIE = 0x00200000UL, |
RADEON_NEW_MEMMAP = 0x00400000UL, |
RADEON_IS_PCI = 0x00800000UL, |
RADEON_IS_IGPGART = 0x01000000UL, |
}; |
#endif |
/drivers/video/drm/radeon/radeon_fb.c |
---|
27,16 → 27,8 |
* Modularization |
*/ |
//#include <linux/module.h> |
//#include <linux/kernel.h> |
//#include <linux/errno.h> |
//#include <linux/string.h> |
//#include <linux/mm.h> |
//#include <linux/tty.h> |
//#include <linux/slab.h> |
//#include <linux/delay.h> |
//#include <linux/fb.h> |
//#include <linux/init.h> |
#include <linux/module.h> |
#include <linux/fb.h> |
#include "drmP.h" |
#include "drm.h" |
45,559 → 37,29 |
#include "radeon_drm.h" |
#include "radeon.h" |
#include "drm_fb_helper.h" |
#include <drm_mm.h> |
#include "radeon_object.h" |
struct fb_info *framebuffer_alloc(size_t size); |
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ |
#define FB_VISUAL_TRUECOLOR 2 /* True color */ |
struct fb_fix_screeninfo { |
char id[16]; /* identification string eg "TT Builtin" */ |
unsigned long smem_start; /* Start of frame buffer mem */ |
/* (physical address) */ |
__u32 smem_len; /* Length of frame buffer mem */ |
__u32 type; /* see FB_TYPE_* */ |
__u32 type_aux; /* Interleave for interleaved Planes */ |
__u32 visual; /* see FB_VISUAL_* */ |
__u16 xpanstep; /* zero if no hardware panning */ |
__u16 ypanstep; /* zero if no hardware panning */ |
__u16 ywrapstep; /* zero if no hardware ywrap */ |
__u32 line_length; /* length of a line in bytes */ |
unsigned long mmio_start; /* Start of Memory Mapped I/O */ |
/* (physical address) */ |
__u32 mmio_len; /* Length of Memory Mapped I/O */ |
__u32 accel; /* Indicate to driver which */ |
/* specific chip/card we have */ |
__u16 reserved[3]; /* Reserved for future compatibility */ |
}; |
struct fb_bitfield { |
__u32 offset; /* beginning of bitfield */ |
__u32 length; /* length of bitfield */ |
__u32 msb_right; /* != 0 : Most significant bit is */ |
/* right */ |
}; |
struct fb_var_screeninfo { |
__u32 xres; /* visible resolution */ |
__u32 yres; |
__u32 xres_virtual; /* virtual resolution */ |
__u32 yres_virtual; |
__u32 xoffset; /* offset from virtual to visible */ |
__u32 yoffset; /* resolution */ |
__u32 bits_per_pixel; /* guess what */ |
__u32 grayscale; /* != 0 Graylevels instead of colors */ |
struct fb_bitfield red; /* bitfield in fb mem if true color, */ |
struct fb_bitfield green; /* else only length is significant */ |
struct fb_bitfield blue; |
struct fb_bitfield transp; /* transparency */ |
__u32 nonstd; /* != 0 Non standard pixel format */ |
__u32 activate; /* see FB_ACTIVATE_* */ |
__u32 height; /* height of picture in mm */ |
__u32 width; /* width of picture in mm */ |
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */ |
/* Timing: All values in pixclocks, except pixclock (of course) */ |
__u32 pixclock; /* pixel clock in ps (pico seconds) */ |
__u32 left_margin; /* time from sync to picture */ |
__u32 right_margin; /* time from picture to sync */ |
__u32 upper_margin; /* time from sync to picture */ |
__u32 lower_margin; |
__u32 hsync_len; /* length of horizontal sync */ |
__u32 vsync_len; /* length of vertical sync */ |
__u32 sync; /* see FB_SYNC_* */ |
__u32 vmode; /* see FB_VMODE_* */ |
__u32 rotate; /* angle we rotate counter clockwise */ |
__u32 reserved[5]; /* Reserved for future compatibility */ |
}; |
struct fb_chroma { |
__u32 redx; /* in fraction of 1024 */ |
__u32 greenx; |
__u32 bluex; |
__u32 whitex; |
__u32 redy; |
__u32 greeny; |
__u32 bluey; |
__u32 whitey; |
}; |
struct fb_videomode { |
const char *name; /* optional */ |
u32 refresh; /* optional */ |
u32 xres; |
u32 yres; |
u32 pixclock; |
u32 left_margin; |
u32 right_margin; |
u32 upper_margin; |
u32 lower_margin; |
u32 hsync_len; |
u32 vsync_len; |
u32 sync; |
u32 vmode; |
u32 flag; |
}; |
struct fb_monspecs { |
struct fb_chroma chroma; |
struct fb_videomode *modedb; /* mode database */ |
__u8 manufacturer[4]; /* Manufacturer */ |
__u8 monitor[14]; /* Monitor String */ |
__u8 serial_no[14]; /* Serial Number */ |
__u8 ascii[14]; /* ? */ |
__u32 modedb_len; /* mode database length */ |
__u32 model; /* Monitor Model */ |
__u32 serial; /* Serial Number - Integer */ |
__u32 year; /* Year manufactured */ |
__u32 week; /* Week Manufactured */ |
__u32 hfmin; /* hfreq lower limit (Hz) */ |
__u32 hfmax; /* hfreq upper limit (Hz) */ |
__u32 dclkmin; /* pixelclock lower limit (Hz) */ |
__u32 dclkmax; /* pixelclock upper limit (Hz) */ |
__u16 input; /* display type - see FB_DISP_* */ |
__u16 dpms; /* DPMS support - see FB_DPMS_ */ |
__u16 signal; /* Signal Type - see FB_SIGNAL_* */ |
__u16 vfmin; /* vfreq lower limit (Hz) */ |
__u16 vfmax; /* vfreq upper limit (Hz) */ |
__u16 gamma; /* Gamma - in fractions of 100 */ |
__u16 gtf : 1; /* supports GTF */ |
__u16 misc; /* Misc flags - see FB_MISC_* */ |
__u8 version; /* EDID version... */ |
__u8 revision; /* ...and revision */ |
__u8 max_x; /* Maximum horizontal size (cm) */ |
__u8 max_y; /* Maximum vertical size (cm) */ |
}; |
struct fb_info { |
int node; |
int flags; |
// struct mutex lock; /* Lock for open/release/ioctl funcs */ |
// struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ |
struct fb_var_screeninfo var; /* Current var */ |
struct fb_fix_screeninfo fix; /* Current fix */ |
struct fb_monspecs monspecs; /* Current Monitor specs */ |
// struct work_struct queue; /* Framebuffer event queue */ |
// struct fb_pixmap pixmap; /* Image hardware mapper */ |
// struct fb_pixmap sprite; /* Cursor hardware mapper */ |
// struct fb_cmap cmap; /* Current cmap */ |
struct list_head modelist; /* mode list */ |
struct fb_videomode *mode; /* current mode */ |
#ifdef CONFIG_FB_BACKLIGHT |
/* assigned backlight device */ |
/* set before framebuffer registration, |
remove after unregister */ |
struct backlight_device *bl_dev; |
/* Backlight level curve */ |
struct mutex bl_curve_mutex; |
u8 bl_curve[FB_BACKLIGHT_LEVELS]; |
#endif |
#ifdef CONFIG_FB_DEFERRED_IO |
struct delayed_work deferred_work; |
struct fb_deferred_io *fbdefio; |
#endif |
struct fb_ops *fbops; |
// struct device *device; /* This is the parent */ |
// struct device *dev; /* This is this fb device */ |
int class_flag; /* private sysfs flags */ |
#ifdef CONFIG_FB_TILEBLITTING |
struct fb_tile_ops *tileops; /* Tile Blitting */ |
#endif |
char __iomem *screen_base; /* Virtual address */ |
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ |
void *pseudo_palette; /* Fake palette of 16 colors */ |
#define FBINFO_STATE_RUNNING 0 |
#define FBINFO_STATE_SUSPENDED 1 |
u32 state; /* Hardware state i.e suspend */ |
void *fbcon_par; /* fbcon use-only private area */ |
/* From here on everything is device dependent */ |
void *par; |
/* we need the PCI or similiar aperture base/size not |
smem_start/size as smem_start may just be an object |
allocated inside the aperture so may not actually overlap */ |
resource_size_t aperture_base; |
resource_size_t aperture_size; |
}; |
struct radeon_fb_device { |
struct drm_fb_helper helper; |
struct radeon_framebuffer *rfb; |
struct radeon_device *rdev; |
struct drm_display_mode *mode; |
struct radeon_framebuffer *rfb; |
int crtc_count; |
/* crtc currently bound to this */ |
uint32_t crtc_ids[2]; |
}; |
int radeon_gem_fb_object_create(struct radeon_device *rdev, int size, |
int alignment, int initial_domain, |
bool discardable, bool kernel, |
bool interruptible, |
struct drm_gem_object **obj); |
struct fb_info *framebuffer_alloc(size_t size); |
#if 0 |
static int radeonfb_setcolreg(unsigned regno, |
unsigned red, |
unsigned green, |
unsigned blue, |
unsigned transp, |
struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_crtc *crtc; |
int i; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct drm_mode_set *modeset = &radeon_crtc->mode_set; |
struct drm_framebuffer *fb = modeset->fb; |
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
if (i == rfbdev->crtc_count) { |
continue; |
} |
if (regno > 255) { |
return 1; |
} |
if (fb->depth == 8) { |
radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno); |
return 0; |
} |
if (regno < 16) { |
switch (fb->depth) { |
case 15: |
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | |
((green & 0xf800) >> 6) | |
((blue & 0xf800) >> 11); |
break; |
case 16: |
fb->pseudo_palette[regno] = (red & 0xf800) | |
((green & 0xfc00) >> 5) | |
((blue & 0xf800) >> 11); |
break; |
case 24: |
case 32: |
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | |
(green & 0xff00) | |
((blue & 0xff00) >> 8); |
break; |
} |
} |
} |
return 0; |
} |
static int radeonfb_check_var(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct radeon_framebuffer *rfb = rfbdev->rfb; |
struct drm_framebuffer *fb = &rfb->base; |
int depth; |
if (var->pixclock == -1 || !var->pixclock) { |
return -EINVAL; |
} |
/* Need to resize the fb object !!! */ |
if (var->xres > fb->width || var->yres > fb->height) { |
DRM_ERROR("Requested width/height is greater than current fb " |
"object %dx%d > %dx%d\n", var->xres, var->yres, |
fb->width, fb->height); |
DRM_ERROR("Need resizing code.\n"); |
return -EINVAL; |
} |
switch (var->bits_per_pixel) { |
case 16: |
depth = (var->green.length == 6) ? 16 : 15; |
break; |
case 32: |
depth = (var->transp.length > 0) ? 32 : 24; |
break; |
default: |
depth = var->bits_per_pixel; |
break; |
} |
switch (depth) { |
case 8: |
var->red.offset = 0; |
var->green.offset = 0; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 15: |
var->red.offset = 10; |
var->green.offset = 5; |
var->blue.offset = 0; |
var->red.length = 5; |
var->green.length = 5; |
var->blue.length = 5; |
var->transp.length = 1; |
var->transp.offset = 15; |
break; |
case 16: |
var->red.offset = 11; |
var->green.offset = 5; |
var->blue.offset = 0; |
var->red.length = 5; |
var->green.length = 6; |
var->blue.length = 5; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 24: |
var->red.offset = 16; |
var->green.offset = 8; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 0; |
var->transp.offset = 0; |
break; |
case 32: |
var->red.offset = 16; |
var->green.offset = 8; |
var->blue.offset = 0; |
var->red.length = 8; |
var->green.length = 8; |
var->blue.length = 8; |
var->transp.length = 8; |
var->transp.offset = 24; |
break; |
default: |
return -EINVAL; |
} |
return 0; |
} |
#endif |
/* this will let fbcon do the mode init */ |
static int radeonfb_set_par(struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct fb_var_screeninfo *var = &info->var; |
struct drm_crtc *crtc; |
int ret; |
int i; |
if (var->pixclock != -1) { |
DRM_ERROR("PIXEL CLCOK SET\n"); |
return -EINVAL; |
} |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
if (i == rfbdev->crtc_count) { |
continue; |
} |
if (crtc->fb == radeon_crtc->mode_set.fb) { |
// mutex_lock(&dev->mode_config.mutex); |
ret = crtc->funcs->set_config(&radeon_crtc->mode_set); |
// mutex_unlock(&dev->mode_config.mutex); |
if (ret) { |
return ret; |
} |
} |
} |
return 0; |
} |
#if 0 |
static int radeonfb_pan_display(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_mode_set *modeset; |
struct drm_crtc *crtc; |
struct radeon_crtc *radeon_crtc; |
int ret = 0; |
int i; |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
if (i == rfbdev->crtc_count) { |
continue; |
} |
radeon_crtc = to_radeon_crtc(crtc); |
modeset = &radeon_crtc->mode_set; |
modeset->x = var->xoffset; |
modeset->y = var->yoffset; |
if (modeset->num_connectors) { |
mutex_lock(&dev->mode_config.mutex); |
ret = crtc->funcs->set_config(modeset); |
mutex_unlock(&dev->mode_config.mutex); |
if (!ret) { |
info->var.xoffset = var->xoffset; |
info->var.yoffset = var->yoffset; |
} |
} |
} |
return ret; |
} |
static void radeonfb_on(struct fb_info *info) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
int i; |
/* |
* For each CRTC in this fb, find all associated encoders |
* and turn them off, then turn off the CRTC. |
*/ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
mutex_lock(&dev->mode_config.mutex); |
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); |
mutex_unlock(&dev->mode_config.mutex); |
/* Found a CRTC on this fb, now find encoders */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct drm_encoder_helper_funcs *encoder_funcs; |
encoder_funcs = encoder->helper_private; |
mutex_lock(&dev->mode_config.mutex); |
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
} |
} |
static void radeonfb_off(struct fb_info *info, int dpms_mode) |
{ |
struct radeon_fb_device *rfbdev = info->par; |
struct drm_device *dev = rfbdev->rdev->ddev; |
struct drm_crtc *crtc; |
struct drm_encoder *encoder; |
int i; |
/* |
* For each CRTC in this fb, find all associated encoders |
* and turn them off, then turn off the CRTC. |
*/ |
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
for (i = 0; i < rfbdev->crtc_count; i++) { |
if (crtc->base.id == rfbdev->crtc_ids[i]) { |
break; |
} |
} |
/* Found a CRTC on this fb, now find encoders */ |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct drm_encoder_helper_funcs *encoder_funcs; |
encoder_funcs = encoder->helper_private; |
mutex_lock(&dev->mode_config.mutex); |
encoder_funcs->dpms(encoder, dpms_mode); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
if (dpms_mode == DRM_MODE_DPMS_OFF) { |
mutex_lock(&dev->mode_config.mutex); |
crtc_funcs->dpms(crtc, dpms_mode); |
mutex_unlock(&dev->mode_config.mutex); |
} |
} |
} |
int radeonfb_blank(int blank, struct fb_info *info) |
{ |
switch (blank) { |
case FB_BLANK_UNBLANK: |
radeonfb_on(info); |
break; |
case FB_BLANK_NORMAL: |
radeonfb_off(info, DRM_MODE_DPMS_STANDBY); |
break; |
case FB_BLANK_HSYNC_SUSPEND: |
radeonfb_off(info, DRM_MODE_DPMS_STANDBY); |
break; |
case FB_BLANK_VSYNC_SUSPEND: |
radeonfb_off(info, DRM_MODE_DPMS_SUSPEND); |
break; |
case FB_BLANK_POWERDOWN: |
radeonfb_off(info, DRM_MODE_DPMS_OFF); |
break; |
} |
return 0; |
} |
static struct fb_ops radeonfb_ops = { |
.owner = THIS_MODULE, |
.fb_check_var = radeonfb_check_var, |
.fb_set_par = radeonfb_set_par, |
.fb_setcolreg = radeonfb_setcolreg, |
.fb_fillrect = cfb_fillrect, |
.fb_copyarea = cfb_copyarea, |
.fb_imageblit = cfb_imageblit, |
.fb_pan_display = radeonfb_pan_display, |
.fb_blank = radeonfb_blank, |
// .owner = THIS_MODULE, |
.fb_check_var = drm_fb_helper_check_var, |
.fb_set_par = drm_fb_helper_set_par, |
.fb_setcolreg = drm_fb_helper_setcolreg, |
// .fb_fillrect = cfb_fillrect, |
// .fb_copyarea = cfb_copyarea, |
// .fb_imageblit = cfb_imageblit, |
// .fb_pan_display = drm_fb_helper_pan_display, |
.fb_blank = drm_fb_helper_blank, |
}; |
/** |
640,26 → 102,10 |
} |
EXPORT_SYMBOL(radeonfb_resize); |
static struct drm_mode_set panic_mode; |
int radeonfb_panic(struct notifier_block *n, unsigned long ununsed, |
void *panic_str) |
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) |
{ |
DRM_ERROR("panic occurred, switching back to text console\n"); |
drm_crtc_helper_set_config(&panic_mode); |
return 0; |
} |
EXPORT_SYMBOL(radeonfb_panic); |
static struct notifier_block paniced = { |
.notifier_call = radeonfb_panic, |
}; |
#endif |
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) |
{ |
int aligned = width; |
int align_large = (ASIC_IS_AVIVO(rdev)); |
int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; |
int pitch_mask = 0; |
switch (bpp / 8) { |
680,11 → 126,16 |
return aligned; |
} |
int radeonfb_create(struct radeon_device *rdev, |
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { |
.gamma_set = radeon_crtc_fb_gamma_set, |
}; |
int radeonfb_create(struct drm_device *dev, |
uint32_t fb_width, uint32_t fb_height, |
uint32_t surface_width, uint32_t surface_height, |
struct radeon_framebuffer **rfb_p) |
struct drm_framebuffer **fb_p) |
{ |
struct radeon_device *rdev = dev->dev_private; |
struct fb_info *info; |
struct radeon_fb_device *rfbdev; |
struct drm_framebuffer *fb = NULL; |
697,15 → 148,15 |
u64 fb_gpuaddr; |
void *fbptr = NULL; |
unsigned long tmp; |
bool fb_tiled = false; /* useful for testing */ |
u32 tiling_flags = 0; |
ENTRY(); |
mode_cmd.width = surface_width; |
mode_cmd.height = surface_height; |
mode_cmd.bpp = 32; |
/* need to align pitch with crtc limits */ |
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); |
mode_cmd.depth = 32; |
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); |
mode_cmd.depth = 24; |
size = mode_cmd.pitch * mode_cmd.height; |
aligned_size = ALIGN(size, PAGE_SIZE); |
715,7 → 166,6 |
false, 0, |
false, &gobj); |
if (ret) { |
printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", |
surface_width, surface_height); |
724,7 → 174,7 |
} |
robj = gobj->driver_private; |
// mutex_lock(&rdev->ddev->struct_mutex); |
mutex_lock(&rdev->ddev->struct_mutex); |
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); |
if (fb == NULL) { |
DRM_ERROR("failed to allocate fb.\n"); |
740,8 → 190,8 |
list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); |
*fb_p = fb; |
rfb = to_radeon_framebuffer(fb); |
*rfb_p = rfb; |
rdev->fbdev_rfb = rfb; |
rdev->fbdev_robj = robj; |
750,7 → 200,15 |
ret = -ENOMEM; |
goto out_unref; |
} |
rdev->fbdev_info = info; |
rfbdev = info->par; |
rfbdev->helper.funcs = &radeon_fb_helper_funcs; |
rfbdev->helper.dev = dev; |
ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, 2, |
RADEONFB_CONN_LIMIT); |
if (ret) |
goto out_unref; |
// ret = radeon_object_kmap(robj, &fbptr); |
// if (ret) { |
757,37 → 215,28 |
// goto out_unref; |
// } |
fbptr = (void*)0xFE000000; // LFB_BASE |
strcpy(info->fix.id, "radeondrmfb"); |
strcpy(info->fix.id, "radeondrmfb"); |
info->fix.type = FB_TYPE_PACKED_PIXELS; |
info->fix.visual = FB_VISUAL_TRUECOLOR; |
info->fix.type_aux = 0; |
info->fix.xpanstep = 1; /* doing it in hw */ |
info->fix.ypanstep = 1; /* doing it in hw */ |
info->fix.ywrapstep = 0; |
// info->fix.accel = FB_ACCEL_NONE; |
info->fix.type_aux = 0; |
// info->flags = FBINFO_DEFAULT; |
// info->fbops = &radeonfb_ops; |
info->fix.line_length = fb->pitch; |
drm_fb_helper_fill_fix(info, fb->pitch); |
info->flags = FBINFO_DEFAULT; |
info->fbops = &radeonfb_ops; |
tmp = fb_gpuaddr - rdev->mc.vram_location; |
info->fix.smem_start = rdev->mc.aper_base + tmp; |
info->fix.smem_len = size; |
info->screen_base = fbptr; |
info->screen_size = size; |
info->pseudo_palette = fb->pseudo_palette; |
info->var.xres_virtual = fb->width; |
info->var.yres_virtual = fb->height; |
info->var.bits_per_pixel = fb->bits_per_pixel; |
info->var.xoffset = 0; |
info->var.yoffset = 0; |
// info->var.activate = FB_ACTIVATE_NOW; |
info->var.height = -1; |
info->var.width = -1; |
info->var.xres = fb_width; |
info->var.yres = fb_height; |
drm_fb_helper_fill_var(info, fb, fb_width, fb_height); |
/* setup aperture base/size for vesafb takeover */ |
info->aperture_base = rdev->ddev->mode_config.fb_base; |
info->aperture_size = rdev->mc.real_vram_size; |
info->fix.mmio_start = 0; |
info->fix.mmio_len = 0; |
// info->pixmap.size = 64*1024; |
805,60 → 254,6 |
DRM_INFO("fb depth is %d\n", fb->depth); |
DRM_INFO(" pitch is %d\n", fb->pitch); |
switch (fb->depth) { |
case 8: |
info->var.red.offset = 0; |
info->var.green.offset = 0; |
info->var.blue.offset = 0; |
info->var.red.length = 8; /* 8bit DAC */ |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 0; |
info->var.transp.length = 0; |
break; |
case 15: |
info->var.red.offset = 10; |
info->var.green.offset = 5; |
info->var.blue.offset = 0; |
info->var.red.length = 5; |
info->var.green.length = 5; |
info->var.blue.length = 5; |
info->var.transp.offset = 15; |
info->var.transp.length = 1; |
break; |
case 16: |
info->var.red.offset = 11; |
info->var.green.offset = 5; |
info->var.blue.offset = 0; |
info->var.red.length = 5; |
info->var.green.length = 6; |
info->var.blue.length = 5; |
info->var.transp.offset = 0; |
break; |
case 24: |
info->var.red.offset = 16; |
info->var.green.offset = 8; |
info->var.blue.offset = 0; |
info->var.red.length = 8; |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 0; |
info->var.transp.length = 0; |
break; |
case 32: |
info->var.red.offset = 16; |
info->var.green.offset = 8; |
info->var.blue.offset = 0; |
info->var.red.length = 8; |
info->var.green.length = 8; |
info->var.blue.length = 8; |
info->var.transp.offset = 24; |
info->var.transp.length = 8; |
break; |
default: |
break; |
} |
dbgprintf("fb = %x\n", fb); |
fb->fbdev = info; |
865,7 → 260,7 |
rfbdev->rfb = rfb; |
rfbdev->rdev = rdev; |
// mutex_unlock(&rdev->ddev->struct_mutex); |
mutex_unlock(&rdev->ddev->struct_mutex); |
return 0; |
out_unref: |
879,156 → 274,15 |
kfree(fb); |
} |
// drm_gem_object_unreference(gobj); |
// mutex_unlock(&rdev->ddev->struct_mutex); |
mutex_unlock(&rdev->ddev->struct_mutex); |
out: |
return ret; |
} |
static int radeonfb_single_fb_probe(struct radeon_device *rdev) |
{ |
struct drm_crtc *crtc; |
struct drm_connector *connector; |
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1; |
unsigned int surface_width = 0, surface_height = 0; |
int new_fb = 0; |
int crtc_count = 0; |
int ret, i, conn_count = 0; |
struct radeon_framebuffer *rfb; |
struct fb_info *info; |
struct radeon_fb_device *rfbdev; |
struct drm_mode_set *modeset = NULL; |
ENTRY(); |
/* first up get a count of crtcs now in use and new min/maxes width/heights */ |
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { |
if (drm_helper_crtc_in_use(crtc)) { |
if (crtc->desired_mode) { |
if (crtc->desired_mode->hdisplay < fb_width) |
fb_width = crtc->desired_mode->hdisplay; |
if (crtc->desired_mode->vdisplay < fb_height) |
fb_height = crtc->desired_mode->vdisplay; |
if (crtc->desired_mode->hdisplay > surface_width) |
surface_width = crtc->desired_mode->hdisplay; |
if (crtc->desired_mode->vdisplay > surface_height) |
surface_height = crtc->desired_mode->vdisplay; |
} |
crtc_count++; |
} |
} |
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) { |
/* hmm everyone went away - assume VGA cable just fell out |
and will come back later. */ |
dbgprintf("crtc count %x width %x height %x\n", |
crtc_count, fb_width, fb_height); |
return 0; |
} |
/* do we have an fb already? */ |
if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) { |
/* create an fb if we don't have one */ |
ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb); |
if (ret) { |
return -EINVAL; |
} |
new_fb = 1; |
} else { |
struct drm_framebuffer *fb; |
fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head); |
rfb = to_radeon_framebuffer(fb); |
/* if someone hotplugs something bigger than we have already allocated, we are pwned. |
As really we can't resize an fbdev that is in the wild currently due to fbdev |
not really being designed for the lower layers moving stuff around under it. |
- so in the grand style of things - punt. */ |
if ((fb->width < surface_width) || (fb->height < surface_height)) { |
DRM_ERROR("Framebuffer not large enough to scale console onto.\n"); |
return -EINVAL; |
} |
} |
info = rfb->base.fbdev; |
rdev->fbdev_info = info; |
rfbdev = info->par; |
crtc_count = 0; |
/* okay we need to setup new connector sets in the crtcs */ |
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
modeset = &radeon_crtc->mode_set; |
modeset->fb = &rfb->base; |
conn_count = 0; |
list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) { |
if (connector->encoder) |
if (connector->encoder->crtc == modeset->crtc) { |
modeset->connectors[conn_count] = connector; |
conn_count++; |
if (conn_count > RADEONFB_CONN_LIMIT) |
BUG(); |
} |
} |
for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++) |
modeset->connectors[i] = NULL; |
rfbdev->crtc_ids[crtc_count++] = crtc->base.id; |
modeset->num_connectors = conn_count; |
if (modeset->crtc->desired_mode) { |
if (modeset->mode) { |
drm_mode_destroy(rdev->ddev, modeset->mode); |
} |
modeset->mode = drm_mode_duplicate(rdev->ddev, |
modeset->crtc->desired_mode); |
} |
} |
rfbdev->crtc_count = crtc_count; |
if (new_fb) { |
info->var.pixclock = -1; |
// if (register_framebuffer(info) < 0) |
// return -EINVAL; |
} else { |
radeonfb_set_par(info); |
} |
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
info->fix.id); |
/* Switch back to kernel console on panic */ |
// panic_mode = *modeset; |
// atomic_notifier_chain_register(&panic_notifier_list, &paniced); |
// printk(KERN_INFO "registered panic notifier\n"); |
LEAVE(); |
return 0; |
} |
int radeonfb_probe(struct drm_device *dev) |
{ |
int ret; |
/* something has changed in the lower levels of hell - deal with it |
here */ |
/* two modes : a) 1 fb to rule all crtcs. |
b) one fb per crtc. |
two actions 1) new connected device |
2) device removed. |
case a/1 : if the fb surface isn't big enough - resize the surface fb. |
if the fb size isn't big enough - resize fb into surface. |
if everything big enough configure the new crtc/etc. |
case a/2 : undo the configuration |
possibly resize down the fb to fit the new configuration. |
case b/1 : see if it is on a new crtc - setup a new fb and add it. |
case b/2 : teardown the new fb. |
*/ |
ret = radeonfb_single_fb_probe(dev->dev_private); |
ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create); |
return ret; |
} |
EXPORT_SYMBOL(radeonfb_probe); |
1044,6 → 298,7 |
} |
info = fb->fbdev; |
if (info) { |
struct radeon_fb_device *rfbdev = info->par; |
robj = rfb->obj->driver_private; |
// unregister_framebuffer(info); |
// radeon_object_kunmap(robj); |
1052,8 → 307,7 |
} |
printk(KERN_INFO "unregistered panic notifier\n"); |
// atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); |
// memset(&panic_mode, 0, sizeof(struct drm_mode_set)); |
return 0; |
} |
EXPORT_SYMBOL(radeonfb_remove); |
1192,8 → 446,6 |
bool ret; |
ENTRY(); |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
{ |
struct drm_display_mode *mode; |
1244,17 → 496,17 |
fb->width = width; |
fb->height = height; |
fb->pitch = radeon_align_pitch(dev->dev_private, width, 32) |
* ((32 + 1) / 8); |
fb->pitch = radeon_align_pitch(dev->dev_private, width, 32, false) * ((32 + 1) / 8); |
crtc->fb = fb; |
ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb); |
sysSetScreen(width,height); |
sysSetScreen(width, height, fb->pitch); |
if (ret == true) |
{ |
dbgprintf("new mode %d %d pitch %d\n", width, height, fb->pitch); |
} |
else |
{ |
/drivers/video/drm/radeon/radeon_fence.c |
---|
53,9 → 53,9 |
* away |
*/ |
WREG32(rdev->fence_drv.scratch_reg, fence->seq); |
} else { |
} else |
radeon_fence_ring_emit(rdev, fence); |
} |
fence->emited = true; |
fence->timeout = jiffies + ((2000 * HZ) / 1000); |
list_del(&fence->list); |
168,9 → 168,40 |
return signaled; |
} |
int radeon_fence_wait(struct radeon_fence *fence, bool interruptible) |
int r600_fence_wait(struct radeon_fence *fence, bool intr, bool lazy) |
{ |
struct radeon_device *rdev; |
int ret = 0; |
rdev = fence->rdev; |
__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); |
while (1) { |
if (radeon_fence_signaled(fence)) |
break; |
if (time_after_eq(jiffies, fence->timeout)) { |
ret = -EBUSY; |
break; |
} |
if (lazy) |
schedule_timeout(1); |
if (intr && signal_pending(current)) { |
ret = -ERESTARTSYS; |
break; |
} |
} |
__set_current_state(TASK_RUNNING); |
return ret; |
} |
int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
{ |
struct radeon_device *rdev; |
unsigned long cur_jiffies; |
unsigned long timeout; |
bool expired = false; |
185,6 → 216,14 |
if (radeon_fence_signaled(fence)) { |
return 0; |
} |
if (rdev->family >= CHIP_R600) { |
r = r600_fence_wait(fence, intr, 0); |
if (r == -ERESTARTSYS) |
return -EBUSY; |
return r; |
} |
retry: |
cur_jiffies = jiffies; |
timeout = HZ / 100; |
191,11 → 230,11 |
if (time_after(fence->timeout, cur_jiffies)) { |
timeout = fence->timeout - cur_jiffies; |
} |
if (interruptible) { |
if (intr) { |
r = wait_event_interruptible_timeout(rdev->fence_drv.queue, |
radeon_fence_signaled(fence), timeout); |
if (unlikely(r == -ERESTARTSYS)) { |
return -ERESTART; |
return -EBUSY; |
} |
} else { |
r = wait_event_timeout(rdev->fence_drv.queue, |
/drivers/video/drm/radeon/radeon_gart.c |
---|
75,10 → 75,9 |
int radeon_gart_table_vram_alloc(struct radeon_device *rdev) |
{ |
uint32_t gpu_addr; |
int r; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
if (rdev->gart.table.vram.robj == NULL) { |
r = radeon_object_create(rdev, NULL, |
90,6 → 89,14 |
return r; |
} |
} |
return 0; |
} |
int radeon_gart_table_vram_pin(struct radeon_device *rdev) |
{ |
uint64_t gpu_addr; |
int r; |
r = radeon_object_pin(rdev->gart.table.vram.robj, |
RADEON_GEM_DOMAIN_VRAM, &gpu_addr); |
if (r) { |
175,7 → 182,8 |
uint64_t page_base; |
int i, j; |
dbgprintf("%s ",__FUNCTION__); |
ENTER(); |
dbgprintf("offset %x pages %x list %x\n", |
offset, pages, pagelist); |
207,7 → 215,7 |
mb(); |
radeon_gart_tlb_flush(rdev); |
dbgprintf("done %s\n",__FUNCTION__); |
LEAVE(); |
return 0; |
} |
215,7 → 223,7 |
int radeon_gart_init(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
if (rdev->gart.pages) { |
return 0; |
/drivers/video/drm/radeon/radeon_gem.c |
---|
182,9 → 182,9 |
struct radeon_device *rdev = dev->dev_private; |
struct drm_radeon_gem_info *args = data; |
args->vram_size = rdev->mc.vram_size; |
args->vram_size = rdev->mc.real_vram_size; |
/* FIXME: report somethings that makes sense */ |
args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024); |
args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024); |
args->gart_size = rdev->mc.gtt_size; |
return 0; |
} |
/drivers/video/drm/radeon/radeon_legacy_crtc.c |
---|
23,12 → 23,178 |
* Authors: Dave Airlie |
* Alex Deucher |
*/ |
#include <drmP.h> |
#include <drm_crtc_helper.h> |
#include "radeon_drm.h" |
#include <drm/drmP.h> |
#include <drm/drm_crtc_helper.h> |
#include <drm/radeon_drm.h> |
#include "radeon_fixed.h" |
#include "radeon.h" |
#include "atom.h" |
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
int xres = mode->hdisplay; |
int yres = mode->vdisplay; |
bool hscale = true, vscale = true; |
int hsync_wid; |
int vsync_wid; |
int hsync_start; |
int blank_width; |
u32 scale, inc, crtc_more_cntl; |
u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active; |
u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp; |
u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp; |
struct radeon_native_mode *native_mode = &radeon_crtc->native_mode; |
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & |
(RADEON_VERT_STRETCH_RESERVED | |
RADEON_VERT_AUTO_RATIO_INC); |
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & |
(RADEON_HORZ_FP_LOOP_STRETCH | |
RADEON_HORZ_AUTO_RATIO_INC); |
crtc_more_cntl = 0; |
if ((rdev->family == CHIP_RS100) || |
(rdev->family == CHIP_RS200)) { |
/* This is to workaround the asic bug for RMX, some versions |
of BIOS dosen't have this register initialized correctly. */ |
crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; |
} |
fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) |
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); |
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; |
if (!hsync_wid) |
hsync_wid = 1; |
hsync_start = mode->crtc_hsync_start - 8; |
fp_h_sync_strt_wid = ((hsync_start & 0x1fff) |
| ((hsync_wid & 0x3f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NHSYNC) |
? RADEON_CRTC_H_SYNC_POL |
: 0)); |
fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) |
| ((mode->crtc_vdisplay - 1) << 16)); |
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; |
if (!vsync_wid) |
vsync_wid = 1; |
fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) |
| ((vsync_wid & 0x1f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NVSYNC) |
? RADEON_CRTC_V_SYNC_POL |
: 0)); |
fp_horz_vert_active = 0; |
if (native_mode->panel_xres == 0 || |
native_mode->panel_yres == 0) { |
hscale = false; |
vscale = false; |
} else { |
if (xres > native_mode->panel_xres) |
xres = native_mode->panel_xres; |
if (yres > native_mode->panel_yres) |
yres = native_mode->panel_yres; |
if (xres == native_mode->panel_xres) |
hscale = false; |
if (yres == native_mode->panel_yres) |
vscale = false; |
} |
switch (radeon_crtc->rmx_type) { |
case RMX_FULL: |
case RMX_ASPECT: |
if (!hscale) |
fp_horz_stretch |= ((xres/8-1) << 16); |
else { |
inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; |
scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) |
/ native_mode->panel_xres + 1; |
fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | |
RADEON_HORZ_STRETCH_BLEND | |
RADEON_HORZ_STRETCH_ENABLE | |
((native_mode->panel_xres/8-1) << 16)); |
} |
if (!vscale) |
fp_vert_stretch |= ((yres-1) << 12); |
else { |
inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; |
scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) |
/ native_mode->panel_yres + 1; |
fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | |
RADEON_VERT_STRETCH_ENABLE | |
RADEON_VERT_STRETCH_BLEND | |
((native_mode->panel_yres-1) << 12)); |
} |
break; |
case RMX_CENTER: |
fp_horz_stretch |= ((xres/8-1) << 16); |
fp_vert_stretch |= ((yres-1) << 12); |
crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | |
RADEON_CRTC_AUTO_VERT_CENTER_EN); |
blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; |
if (blank_width > 110) |
blank_width = 110; |
fp_crtc_h_total_disp = (((blank_width) & 0x3ff) |
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); |
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; |
if (!hsync_wid) |
hsync_wid = 1; |
fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) |
| ((hsync_wid & 0x3f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NHSYNC) |
? RADEON_CRTC_H_SYNC_POL |
: 0)); |
fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) |
| ((mode->crtc_vdisplay - 1) << 16)); |
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; |
if (!vsync_wid) |
vsync_wid = 1; |
fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) |
| ((vsync_wid & 0x1f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NVSYNC) |
? RADEON_CRTC_V_SYNC_POL |
: 0))); |
fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) | |
(((native_mode->panel_xres / 8) & 0x1ff) << 16)); |
break; |
case RMX_OFF: |
default: |
fp_horz_stretch |= ((xres/8-1) << 16); |
fp_vert_stretch |= ((yres-1) << 12); |
break; |
} |
WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); |
WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); |
WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); |
WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); |
WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); |
WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); |
WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); |
WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); |
} |
void radeon_restore_common_regs(struct drm_device *dev) |
{ |
/* don't need this yet */ |
145,10 → 311,13 |
RADEON_CRTC_DISP_REQ_EN_B)); |
WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); |
} |
// drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); |
radeon_crtc_load_lut(crtc); |
break; |
case DRM_MODE_DPMS_STANDBY: |
case DRM_MODE_DPMS_SUSPEND: |
case DRM_MODE_DPMS_OFF: |
// drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id); |
if (radeon_crtc->crtc_id) |
WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); |
else { |
158,11 → 327,7 |
} |
break; |
} |
if (mode != DRM_MODE_DPMS_OFF) { |
radeon_crtc_load_lut(crtc); |
} |
} |
/* properly set crtc bpp when using atombios */ |
void radeon_legacy_atom_set_surface(struct drm_crtc *crtc) |
176,6 → 341,9 |
uint32_t crtc_pitch; |
switch (crtc->fb->bits_per_pixel) { |
case 8: |
format = 2; |
break; |
case 15: /* 555 */ |
format = 3; |
break; |
235,16 → 403,44 |
uint64_t base; |
uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; |
uint32_t crtc_pitch, pitch_pixels; |
uint32_t tiling_flags; |
int format; |
uint32_t gen_cntl_reg, gen_cntl_val; |
DRM_DEBUG("\n"); |
radeon_fb = to_radeon_framebuffer(crtc->fb); |
switch (crtc->fb->bits_per_pixel) { |
case 8: |
format = 2; |
break; |
case 15: /* 555 */ |
format = 3; |
break; |
case 16: /* 565 */ |
format = 4; |
break; |
case 24: /* RGB */ |
format = 5; |
break; |
case 32: /* xRGB */ |
format = 6; |
break; |
default: |
return false; |
} |
obj = radeon_fb->obj; |
// if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) { |
// return -EINVAL; |
// } |
crtc_offset = (u32)base; |
/* if scanout was in GTT this really wouldn't work */ |
/* crtc offset is from display base addr not FB location */ |
radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location; |
base -= radeon_crtc->legacy_display_base_addr; |
crtc_offset_cntl = 0; |
pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); |
253,8 → 449,12 |
(crtc->fb->bits_per_pixel * 8)); |
crtc_pitch |= crtc_pitch << 16; |
/* TODO tiling */ |
if (0) { |
// radeon_object_get_tiling_flags(obj->driver_private, |
// &tiling_flags, NULL); |
if (tiling_flags & RADEON_TILING_MICRO) |
DRM_ERROR("trying to scanout microtiled buffer\n"); |
if (tiling_flags & RADEON_TILING_MACRO) { |
if (ASIC_IS_R300(rdev)) |
crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | |
R300_CRTC_MICRO_TILE_BUFFER_DIS | |
270,15 → 470,13 |
crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; |
} |
/* TODO more tiling */ |
if (0) { |
if (tiling_flags & RADEON_TILING_MACRO) { |
if (ASIC_IS_R300(rdev)) { |
crtc_tile_x0_y0 = x | (y << 16); |
base &= ~0x7ff; |
} else { |
int byteshift = crtc->fb->bits_per_pixel >> 4; |
int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; |
int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; |
base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); |
crtc_offset_cntl |= (y % 16); |
} |
285,6 → 483,9 |
} else { |
int offset = y * pitch_pixels + x; |
switch (crtc->fb->bits_per_pixel) { |
case 8: |
offset *= 1; |
break; |
case 15: |
case 16: |
offset *= 2; |
303,11 → 504,19 |
base &= ~7; |
/* update sarea TODO */ |
if (radeon_crtc->crtc_id == 1) |
gen_cntl_reg = RADEON_CRTC2_GEN_CNTL; |
else |
gen_cntl_reg = RADEON_CRTC_GEN_CNTL; |
gen_cntl_val = RREG32(gen_cntl_reg); |
gen_cntl_val &= ~(0xf << 8); |
gen_cntl_val |= (format << 8); |
WREG32(gen_cntl_reg, gen_cntl_val); |
crtc_offset = (u32)base; |
WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, rdev->mc.vram_location); |
WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr); |
if (ASIC_IS_R300(rdev)) { |
if (radeon_crtc->crtc_id) |
331,6 → 540,7 |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct drm_encoder *encoder; |
int format; |
int hsync_start; |
int hsync_wid; |
339,10 → 549,24 |
uint32_t crtc_h_sync_strt_wid; |
uint32_t crtc_v_total_disp; |
uint32_t crtc_v_sync_strt_wid; |
bool is_tv = false; |
DRM_DEBUG("\n"); |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { |
is_tv = true; |
DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id); |
break; |
} |
} |
} |
switch (crtc->fb->bits_per_pixel) { |
case 8: |
format = 2; |
break; |
case 15: /* 555 */ |
format = 3; |
break; |
472,6 → 696,11 |
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); |
} |
if (is_tv) |
radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp, |
&crtc_h_sync_strt_wid, &crtc_v_total_disp, |
&crtc_v_sync_strt_wid); |
WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp); |
WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid); |
WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp); |
498,7 → 727,7 |
uint32_t pll_ref_div = 0; |
uint32_t pll_fb_post_div = 0; |
uint32_t htotal_cntl = 0; |
bool is_tv = false; |
struct radeon_pll *pll; |
struct { |
533,6 → 762,13 |
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
if (encoder->crtc == crtc) { |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) { |
is_tv = true; |
break; |
} |
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; |
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { |
596,6 → 832,12 |
~(RADEON_PIX2CLK_SRC_SEL_MASK)) | |
RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); |
if (is_tv) { |
radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl, |
&pll_ref_div, &pll_fb_post_div, |
&pixclks_cntl); |
} |
WREG32_PLL_P(RADEON_PIXCLKS_CNTL, |
RADEON_PIX2CLK_SRC_SEL_CPUCLK, |
~(RADEON_PIX2CLK_SRC_SEL_MASK)); |
650,6 → 892,15 |
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); |
} else { |
uint32_t pixclks_cntl; |
if (is_tv) { |
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); |
radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div, |
&pll_fb_post_div, &pixclks_cntl); |
} |
if (rdev->flags & RADEON_IS_MOBILITY) { |
/* A temporal workaround for the occational blanking on certain laptop panels. |
This appears to related to the PLL divider registers (fail to lock?). |
744,6 → 995,8 |
RADEON_VCLK_SRC_SEL_PPLLCLK, |
~(RADEON_VCLK_SRC_SEL_MASK)); |
if (is_tv) |
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); |
} |
} |
751,6 → 1004,8 |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) |
return false; |
return true; |
} |
759,16 → 1014,25 |
struct drm_display_mode *adjusted_mode, |
int x, int y, struct drm_framebuffer *old_fb) |
{ |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
struct drm_device *dev = crtc->dev; |
struct radeon_device *rdev = dev->dev_private; |
DRM_DEBUG("\n"); |
/* TODO TV */ |
radeon_crtc_set_base(crtc, x, y, old_fb); |
radeon_set_crtc_timing(crtc, adjusted_mode); |
radeon_set_pll(crtc, adjusted_mode); |
radeon_init_disp_bandwidth(crtc->dev); |
radeon_bandwidth_update(rdev); |
if (radeon_crtc->crtc_id == 0) { |
radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode); |
} else { |
if (radeon_crtc->rmx_type != RMX_OFF) { |
/* FIXME: only first crtc has rmx what should we |
* do ? |
*/ |
DRM_ERROR("Mode need scaling but only first crtc can do that.\n"); |
} |
} |
return 0; |
} |
799,478 → 1063,3 |
radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP; |
drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs); |
} |
void radeon_init_disp_bw_legacy(struct drm_device *dev, |
struct drm_display_mode *mode1, |
uint32_t pixel_bytes1, |
struct drm_display_mode *mode2, |
uint32_t pixel_bytes2) |
{ |
struct radeon_device *rdev = dev->dev_private; |
fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; |
fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; |
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; |
uint32_t temp, data, mem_trcd, mem_trp, mem_tras; |
fixed20_12 memtcas_ff[8] = { |
fixed_init(1), |
fixed_init(2), |
fixed_init(3), |
fixed_init(0), |
fixed_init_half(1), |
fixed_init_half(2), |
fixed_init(0), |
}; |
fixed20_12 memtcas_rs480_ff[8] = { |
fixed_init(0), |
fixed_init(1), |
fixed_init(2), |
fixed_init(3), |
fixed_init(0), |
fixed_init_half(1), |
fixed_init_half(2), |
fixed_init_half(3), |
}; |
fixed20_12 memtcas2_ff[8] = { |
fixed_init(0), |
fixed_init(1), |
fixed_init(2), |
fixed_init(3), |
fixed_init(4), |
fixed_init(5), |
fixed_init(6), |
fixed_init(7), |
}; |
fixed20_12 memtrbs[8] = { |
fixed_init(1), |
fixed_init_half(1), |
fixed_init(2), |
fixed_init_half(2), |
fixed_init(3), |
fixed_init_half(3), |
fixed_init(4), |
fixed_init_half(4) |
}; |
fixed20_12 memtrbs_r4xx[8] = { |
fixed_init(4), |
fixed_init(5), |
fixed_init(6), |
fixed_init(7), |
fixed_init(8), |
fixed_init(9), |
fixed_init(10), |
fixed_init(11) |
}; |
fixed20_12 min_mem_eff; |
fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; |
fixed20_12 cur_latency_mclk, cur_latency_sclk; |
fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, |
disp_drain_rate2, read_return_rate; |
fixed20_12 time_disp1_drop_priority; |
int c; |
int cur_size = 16; /* in octawords */ |
int critical_point = 0, critical_point2; |
/* uint32_t read_return_rate, time_disp1_drop_priority; */ |
int stop_req, max_stop_req; |
min_mem_eff.full = rfixed_const_8(0); |
/* get modes */ |
if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { |
uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); |
mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); |
mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); |
/* check crtc enables */ |
if (mode2) |
mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); |
if (mode1) |
mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); |
WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); |
} |
/* |
* determine is there is enough bw for current mode |
*/ |
mclk_ff.full = rfixed_const(rdev->clock.default_mclk); |
temp_ff.full = rfixed_const(100); |
mclk_ff.full = rfixed_div(mclk_ff, temp_ff); |
sclk_ff.full = rfixed_const(rdev->clock.default_sclk); |
sclk_ff.full = rfixed_div(sclk_ff, temp_ff); |
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); |
temp_ff.full = rfixed_const(temp); |
mem_bw.full = rfixed_mul(mclk_ff, temp_ff); |
pix_clk.full = 0; |
pix_clk2.full = 0; |
peak_disp_bw.full = 0; |
if (mode1) { |
temp_ff.full = rfixed_const(1000); |
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ |
pix_clk.full = rfixed_div(pix_clk, temp_ff); |
temp_ff.full = rfixed_const(pixel_bytes1); |
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); |
} |
if (mode2) { |
temp_ff.full = rfixed_const(1000); |
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ |
pix_clk2.full = rfixed_div(pix_clk2, temp_ff); |
temp_ff.full = rfixed_const(pixel_bytes2); |
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); |
} |
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); |
if (peak_disp_bw.full >= mem_bw.full) { |
DRM_ERROR("You may not have enough display bandwidth for current mode\n" |
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); |
} |
/* Get values from the EXT_MEM_CNTL register...converting its contents. */ |
temp = RREG32(RADEON_MEM_TIMING_CNTL); |
if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ |
mem_trcd = ((temp >> 2) & 0x3) + 1; |
mem_trp = ((temp & 0x3)) + 1; |
mem_tras = ((temp & 0x70) >> 4) + 1; |
} else if (rdev->family == CHIP_R300 || |
rdev->family == CHIP_R350) { /* r300, r350 */ |
mem_trcd = (temp & 0x7) + 1; |
mem_trp = ((temp >> 8) & 0x7) + 1; |
mem_tras = ((temp >> 11) & 0xf) + 4; |
} else if (rdev->family == CHIP_RV350 || |
rdev->family <= CHIP_RV380) { |
/* rv3x0 */ |
mem_trcd = (temp & 0x7) + 3; |
mem_trp = ((temp >> 8) & 0x7) + 3; |
mem_tras = ((temp >> 11) & 0xf) + 6; |
} else if (rdev->family == CHIP_R420 || |
rdev->family == CHIP_R423 || |
rdev->family == CHIP_RV410) { |
/* r4xx */ |
mem_trcd = (temp & 0xf) + 3; |
if (mem_trcd > 15) |
mem_trcd = 15; |
mem_trp = ((temp >> 8) & 0xf) + 3; |
if (mem_trp > 15) |
mem_trp = 15; |
mem_tras = ((temp >> 12) & 0x1f) + 6; |
if (mem_tras > 31) |
mem_tras = 31; |
} else { /* RV200, R200 */ |
mem_trcd = (temp & 0x7) + 1; |
mem_trp = ((temp >> 8) & 0x7) + 1; |
mem_tras = ((temp >> 12) & 0xf) + 4; |
} |
/* convert to FF */ |
trcd_ff.full = rfixed_const(mem_trcd); |
trp_ff.full = rfixed_const(mem_trp); |
tras_ff.full = rfixed_const(mem_tras); |
/* Get values from the MEM_SDRAM_MODE_REG register...converting its */ |
temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); |
data = (temp & (7 << 20)) >> 20; |
if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { |
if (rdev->family == CHIP_RS480) /* don't think rs400 */ |
tcas_ff = memtcas_rs480_ff[data]; |
else |
tcas_ff = memtcas_ff[data]; |
} else |
tcas_ff = memtcas2_ff[data]; |
if (rdev->family == CHIP_RS400 || |
rdev->family == CHIP_RS480) { |
/* extra cas latency stored in bits 23-25 0-4 clocks */ |
data = (temp >> 23) & 0x7; |
if (data < 5) |
tcas_ff.full += rfixed_const(data); |
} |
if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { |
/* on the R300, Tcas is included in Trbs. |
*/ |
temp = RREG32(RADEON_MEM_CNTL); |
data = (R300_MEM_NUM_CHANNELS_MASK & temp); |
if (data == 1) { |
if (R300_MEM_USE_CD_CH_ONLY & temp) { |
temp = RREG32(R300_MC_IND_INDEX); |
temp &= ~R300_MC_IND_ADDR_MASK; |
temp |= R300_MC_READ_CNTL_CD_mcind; |
WREG32(R300_MC_IND_INDEX, temp); |
temp = RREG32(R300_MC_IND_DATA); |
data = (R300_MEM_RBS_POSITION_C_MASK & temp); |
} else { |
temp = RREG32(R300_MC_READ_CNTL_AB); |
data = (R300_MEM_RBS_POSITION_A_MASK & temp); |
} |
} else { |
temp = RREG32(R300_MC_READ_CNTL_AB); |
data = (R300_MEM_RBS_POSITION_A_MASK & temp); |
} |
if (rdev->family == CHIP_RV410 || |
rdev->family == CHIP_R420 || |
rdev->family == CHIP_R423) |
trbs_ff = memtrbs_r4xx[data]; |
else |
trbs_ff = memtrbs[data]; |
tcas_ff.full += trbs_ff.full; |
} |
sclk_eff_ff.full = sclk_ff.full; |
// if (rdev->flags & RADEON_IS_AGP) { |
// fixed20_12 agpmode_ff; |
// agpmode_ff.full = rfixed_const(radeon_agpmode); |
// temp_ff.full = rfixed_const_666(16); |
// sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); |
// } |
/* TODO PCIE lanes may affect this - agpmode == 16?? */ |
if (ASIC_IS_R300(rdev)) { |
sclk_delay_ff.full = rfixed_const(250); |
} else { |
if ((rdev->family == CHIP_RV100) || |
rdev->flags & RADEON_IS_IGP) { |
if (rdev->mc.vram_is_ddr) |
sclk_delay_ff.full = rfixed_const(41); |
else |
sclk_delay_ff.full = rfixed_const(33); |
} else { |
if (rdev->mc.vram_width == 128) |
sclk_delay_ff.full = rfixed_const(57); |
else |
sclk_delay_ff.full = rfixed_const(41); |
} |
} |
mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); |
if (rdev->mc.vram_is_ddr) { |
if (rdev->mc.vram_width == 32) { |
k1.full = rfixed_const(40); |
c = 3; |
} else { |
k1.full = rfixed_const(20); |
c = 1; |
} |
} else { |
k1.full = rfixed_const(40); |
c = 3; |
} |
temp_ff.full = rfixed_const(2); |
mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); |
temp_ff.full = rfixed_const(c); |
mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); |
temp_ff.full = rfixed_const(4); |
mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); |
mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); |
mc_latency_mclk.full += k1.full; |
mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); |
mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); |
/* |
HW cursor time assuming worst case of full size colour cursor. |
*/ |
temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); |
temp_ff.full += trcd_ff.full; |
if (temp_ff.full < tras_ff.full) |
temp_ff.full = tras_ff.full; |
cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); |
temp_ff.full = rfixed_const(cur_size); |
cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); |
/* |
Find the total latency for the display data. |
*/ |
disp_latency_overhead.full = rfixed_const(80); |
disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); |
mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; |
mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; |
if (mc_latency_mclk.full > mc_latency_sclk.full) |
disp_latency.full = mc_latency_mclk.full; |
else |
disp_latency.full = mc_latency_sclk.full; |
/* setup Max GRPH_STOP_REQ default value */ |
if (ASIC_IS_RV100(rdev)) |
max_stop_req = 0x5c; |
else |
max_stop_req = 0x7c; |
if (mode1) { |
/* CRTC1 |
Set GRPH_BUFFER_CNTL register using h/w defined optimal values. |
GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] |
*/ |
stop_req = mode1->hdisplay * pixel_bytes1 / 16; |
if (stop_req > max_stop_req) |
stop_req = max_stop_req; |
/* |
Find the drain rate of the display buffer. |
*/ |
temp_ff.full = rfixed_const((16/pixel_bytes1)); |
disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); |
/* |
Find the critical point of the display buffer. |
*/ |
crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); |
crit_point_ff.full += rfixed_const_half(0); |
critical_point = rfixed_trunc(crit_point_ff); |
if (rdev->disp_priority == 2) { |
critical_point = 0; |
} |
/* |
The critical point should never be above max_stop_req-4. Setting |
GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. |
*/ |
if (max_stop_req - critical_point < 4) |
critical_point = 0; |
if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { |
/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ |
critical_point = 0x10; |
} |
temp = RREG32(RADEON_GRPH_BUFFER_CNTL); |
temp &= ~(RADEON_GRPH_STOP_REQ_MASK); |
temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); |
temp &= ~(RADEON_GRPH_START_REQ_MASK); |
if ((rdev->family == CHIP_R350) && |
(stop_req > 0x15)) { |
stop_req -= 0x10; |
} |
temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); |
temp |= RADEON_GRPH_BUFFER_SIZE; |
temp &= ~(RADEON_GRPH_CRITICAL_CNTL | |
RADEON_GRPH_CRITICAL_AT_SOF | |
RADEON_GRPH_STOP_CNTL); |
/* |
Write the result into the register. |
*/ |
WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | |
(critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); |
#if 0 |
if ((rdev->family == CHIP_RS400) || |
(rdev->family == CHIP_RS480)) { |
/* attempt to program RS400 disp regs correctly ??? */ |
temp = RREG32(RS400_DISP1_REG_CNTL); |
temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | |
RS400_DISP1_STOP_REQ_LEVEL_MASK); |
WREG32(RS400_DISP1_REQ_CNTL1, (temp | |
(critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | |
(critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); |
temp = RREG32(RS400_DMIF_MEM_CNTL1); |
temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | |
RS400_DISP1_CRITICAL_POINT_STOP_MASK); |
WREG32(RS400_DMIF_MEM_CNTL1, (temp | |
(critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | |
(critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); |
} |
#endif |
DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", |
/* (unsigned int)info->SavedReg->grph_buffer_cntl, */ |
(unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); |
} |
if (mode2) { |
u32 grph2_cntl; |
stop_req = mode2->hdisplay * pixel_bytes2 / 16; |
if (stop_req > max_stop_req) |
stop_req = max_stop_req; |
/* |
Find the drain rate of the display buffer. |
*/ |
temp_ff.full = rfixed_const((16/pixel_bytes2)); |
disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); |
grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); |
grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); |
grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); |
grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); |
if ((rdev->family == CHIP_R350) && |
(stop_req > 0x15)) { |
stop_req -= 0x10; |
} |
grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); |
grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; |
grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | |
RADEON_GRPH_CRITICAL_AT_SOF | |
RADEON_GRPH_STOP_CNTL); |
if ((rdev->family == CHIP_RS100) || |
(rdev->family == CHIP_RS200)) |
critical_point2 = 0; |
else { |
temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; |
temp_ff.full = rfixed_const(temp); |
temp_ff.full = rfixed_mul(mclk_ff, temp_ff); |
if (sclk_ff.full < temp_ff.full) |
temp_ff.full = sclk_ff.full; |
read_return_rate.full = temp_ff.full; |
if (mode1) { |
temp_ff.full = read_return_rate.full - disp_drain_rate.full; |
time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); |
} else { |
time_disp1_drop_priority.full = 0; |
} |
crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; |
crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); |
crit_point_ff.full += rfixed_const_half(0); |
critical_point2 = rfixed_trunc(crit_point_ff); |
if (rdev->disp_priority == 2) { |
critical_point2 = 0; |
} |
if (max_stop_req - critical_point2 < 4) |
critical_point2 = 0; |
} |
if (critical_point2 == 0 && rdev->family == CHIP_R300) { |
/* some R300 cards have problem with this set to 0 */ |
critical_point2 = 0x10; |
} |
WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | |
(critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); |
if ((rdev->family == CHIP_RS400) || |
(rdev->family == CHIP_RS480)) { |
#if 0 |
/* attempt to program RS400 disp2 regs correctly ??? */ |
temp = RREG32(RS400_DISP2_REQ_CNTL1); |
temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | |
RS400_DISP2_STOP_REQ_LEVEL_MASK); |
WREG32(RS400_DISP2_REQ_CNTL1, (temp | |
(critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | |
(critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); |
temp = RREG32(RS400_DISP2_REQ_CNTL2); |
temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | |
RS400_DISP2_CRITICAL_POINT_STOP_MASK); |
WREG32(RS400_DISP2_REQ_CNTL2, (temp | |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); |
#endif |
WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); |
WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); |
WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); |
WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); |
} |
DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", |
(unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); |
} |
} |
/drivers/video/drm/radeon/radeon_legacy_encoders.c |
---|
29,171 → 29,16 |
#include "radeon.h" |
#include "atom.h" |
static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
static void radeon_legacy_encoder_disable(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
int xres = mode->hdisplay; |
int yres = mode->vdisplay; |
bool hscale = true, vscale = true; |
int hsync_wid; |
int vsync_wid; |
int hsync_start; |
uint32_t scale, inc; |
uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active; |
uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp; |
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
struct drm_encoder_helper_funcs *encoder_funcs; |
DRM_DEBUG("\n"); |
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & |
(RADEON_VERT_STRETCH_RESERVED | |
RADEON_VERT_AUTO_RATIO_INC); |
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & |
(RADEON_HORZ_FP_LOOP_STRETCH | |
RADEON_HORZ_AUTO_RATIO_INC); |
crtc_more_cntl = 0; |
if ((rdev->family == CHIP_RS100) || |
(rdev->family == CHIP_RS200)) { |
/* This is to workaround the asic bug for RMX, some versions |
of BIOS dosen't have this register initialized correctly. */ |
crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; |
encoder_funcs = encoder->helper_private; |
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder->active_device = 0; |
} |
fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) |
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); |
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; |
if (!hsync_wid) |
hsync_wid = 1; |
hsync_start = mode->crtc_hsync_start - 8; |
fp_h_sync_strt_wid = ((hsync_start & 0x1fff) |
| ((hsync_wid & 0x3f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NHSYNC) |
? RADEON_CRTC_H_SYNC_POL |
: 0)); |
fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) |
| ((mode->crtc_vdisplay - 1) << 16)); |
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; |
if (!vsync_wid) |
vsync_wid = 1; |
fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) |
| ((vsync_wid & 0x1f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NVSYNC) |
? RADEON_CRTC_V_SYNC_POL |
: 0)); |
fp_horz_vert_active = 0; |
if (native_mode->panel_xres == 0 || |
native_mode->panel_yres == 0) { |
hscale = false; |
vscale = false; |
} else { |
if (xres > native_mode->panel_xres) |
xres = native_mode->panel_xres; |
if (yres > native_mode->panel_yres) |
yres = native_mode->panel_yres; |
if (xres == native_mode->panel_xres) |
hscale = false; |
if (yres == native_mode->panel_yres) |
vscale = false; |
} |
if (radeon_encoder->flags & RADEON_USE_RMX) { |
if (radeon_encoder->rmx_type != RMX_CENTER) { |
if (!hscale) |
fp_horz_stretch |= ((xres/8-1) << 16); |
else { |
inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; |
scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) |
/ native_mode->panel_xres + 1; |
fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | |
RADEON_HORZ_STRETCH_BLEND | |
RADEON_HORZ_STRETCH_ENABLE | |
((native_mode->panel_xres/8-1) << 16)); |
} |
if (!vscale) |
fp_vert_stretch |= ((yres-1) << 12); |
else { |
inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; |
scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) |
/ native_mode->panel_yres + 1; |
fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | |
RADEON_VERT_STRETCH_ENABLE | |
RADEON_VERT_STRETCH_BLEND | |
((native_mode->panel_yres-1) << 12)); |
} |
} else if (radeon_encoder->rmx_type == RMX_CENTER) { |
int blank_width; |
fp_horz_stretch |= ((xres/8-1) << 16); |
fp_vert_stretch |= ((yres-1) << 12); |
crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | |
RADEON_CRTC_AUTO_VERT_CENTER_EN); |
blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; |
if (blank_width > 110) |
blank_width = 110; |
fp_crtc_h_total_disp = (((blank_width) & 0x3ff) |
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); |
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; |
if (!hsync_wid) |
hsync_wid = 1; |
fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) |
| ((hsync_wid & 0x3f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NHSYNC) |
? RADEON_CRTC_H_SYNC_POL |
: 0)); |
fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) |
| ((mode->crtc_vdisplay - 1) << 16)); |
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; |
if (!vsync_wid) |
vsync_wid = 1; |
fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) |
| ((vsync_wid & 0x1f) << 16) |
| ((mode->flags & DRM_MODE_FLAG_NVSYNC) |
? RADEON_CRTC_V_SYNC_POL |
: 0))); |
fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) | |
(((native_mode->panel_xres / 8) & 0x1ff) << 16)); |
} |
} else { |
fp_horz_stretch |= ((xres/8-1) << 16); |
fp_vert_stretch |= ((yres-1) << 12); |
} |
WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); |
WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); |
WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); |
WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); |
WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); |
WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); |
WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); |
WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); |
} |
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) |
{ |
struct drm_device *dev = encoder->dev; |
262,6 → 107,8 |
else |
radeon_combios_output_lock(encoder, true); |
radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder_set_active_device(encoder); |
} |
static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) |
287,9 → 134,6 |
DRM_DEBUG("\n"); |
if (radeon_crtc->crtc_id == 0) |
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); |
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); |
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; |
318,7 → 162,7 |
if (radeon_crtc->crtc_id == 0) { |
if (ASIC_IS_R300(rdev)) { |
if (radeon_encoder->flags & RADEON_USE_RMX) |
if (radeon_encoder->rmx_type != RMX_OFF) |
lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; |
} else |
lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; |
350,8 → 194,6 |
drm_mode_set_crtcinfo(adjusted_mode, 0); |
radeon_encoder->flags &= ~RADEON_USE_RMX; |
if (radeon_encoder->rmx_type != RMX_OFF) |
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); |
364,6 → 206,7 |
.prepare = radeon_legacy_lvds_prepare, |
.mode_set = radeon_legacy_lvds_mode_set, |
.commit = radeon_legacy_lvds_commit, |
.disable = radeon_legacy_encoder_disable, |
}; |
429,6 → 272,7 |
else |
radeon_combios_output_lock(encoder, true); |
radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder_set_active_device(encoder); |
} |
static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) |
455,9 → 299,6 |
DRM_DEBUG("\n"); |
if (radeon_crtc->crtc_id == 0) |
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); |
if (radeon_crtc->crtc_id == 0) { |
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { |
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & |
574,6 → 415,7 |
.mode_set = radeon_legacy_primary_dac_mode_set, |
.commit = radeon_legacy_primary_dac_commit, |
.detect = radeon_legacy_primary_dac_detect, |
.disable = radeon_legacy_encoder_disable, |
}; |
626,6 → 468,7 |
else |
radeon_combios_output_lock(encoder, true); |
radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder_set_active_device(encoder); |
} |
static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) |
653,9 → 496,6 |
DRM_DEBUG("\n"); |
if (radeon_crtc->crtc_id == 0) |
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); |
tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); |
tmp &= 0xfffff; |
if (rdev->family == CHIP_RV280) { |
711,7 → 551,7 |
if (radeon_crtc->crtc_id == 0) { |
if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { |
fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; |
if (radeon_encoder->flags & RADEON_USE_RMX) |
if (radeon_encoder->rmx_type != RMX_OFF) |
fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; |
else |
fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; |
741,6 → 581,7 |
.prepare = radeon_legacy_tmds_int_prepare, |
.mode_set = radeon_legacy_tmds_int_mode_set, |
.commit = radeon_legacy_tmds_int_commit, |
.disable = radeon_legacy_encoder_disable, |
}; |
795,6 → 636,7 |
else |
radeon_combios_output_lock(encoder, true); |
radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder_set_active_device(encoder); |
} |
static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder) |
820,9 → 662,6 |
DRM_DEBUG("\n"); |
if (radeon_crtc->crtc_id == 0) |
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); |
if (rdev->is_atom_bios) { |
radeon_encoder->pixel_clock = adjusted_mode->clock; |
atombios_external_tmds_setup(encoder, ATOM_ENABLE); |
856,7 → 695,7 |
if (radeon_crtc->crtc_id == 0) { |
if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { |
fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; |
if (radeon_encoder->flags & RADEON_USE_RMX) |
if (radeon_encoder->rmx_type != RMX_OFF) |
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; |
else |
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; |
884,6 → 723,7 |
.prepare = radeon_legacy_tmds_ext_prepare, |
.mode_set = radeon_legacy_tmds_ext_mode_set, |
.commit = radeon_legacy_tmds_ext_commit, |
.disable = radeon_legacy_encoder_disable, |
}; |
905,17 → 745,21 |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0; |
/* uint32_t tv_master_cntl = 0; */ |
uint32_t tv_master_cntl = 0; |
bool is_tv; |
DRM_DEBUG("\n"); |
is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false; |
if (rdev->family == CHIP_R200) |
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); |
else { |
if (is_tv) |
tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); |
else |
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); |
/* FIXME TV */ |
/* tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); */ |
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); |
} |
924,8 → 768,11 |
if (rdev->family == CHIP_R200) { |
fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); |
} else { |
if (is_tv) |
tv_master_cntl |= RADEON_TV_ON; |
else |
crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; |
/* tv_master_cntl |= RADEON_TV_ON; */ |
if (rdev->family == CHIP_R420 || |
rdev->family == CHIP_R423 || |
rdev->family == CHIP_RV410) |
946,8 → 793,11 |
if (rdev->family == CHIP_R200) |
fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); |
else { |
if (is_tv) |
tv_master_cntl &= ~RADEON_TV_ON; |
else |
crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; |
/* tv_master_cntl &= ~RADEON_TV_ON; */ |
if (rdev->family == CHIP_R420 || |
rdev->family == CHIP_R423 || |
rdev->family == CHIP_RV410) |
967,8 → 817,10 |
if (rdev->family == CHIP_R200) { |
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); |
} else { |
if (is_tv) |
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); |
else |
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); |
/* WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); */ |
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); |
} |
987,6 → 839,7 |
else |
radeon_combios_output_lock(encoder, true); |
radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF); |
radeon_encoder_set_active_device(encoder); |
} |
static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder) |
1009,13 → 862,14 |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; |
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0; |
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0; |
bool is_tv = false; |
DRM_DEBUG("\n"); |
if (radeon_crtc->crtc_id == 0) |
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); |
is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false; |
if (rdev->family != CHIP_R200) { |
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); |
1039,7 → 893,7 |
} |
/* FIXME TV */ |
if (radeon_encoder->enc_priv) { |
if (tv_dac) { |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | |
RADEON_TV_DAC_NHOLD | |
1056,11 → 910,52 |
if (ASIC_IS_R300(rdev)) { |
gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1; |
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); |
} else if (rdev->family == CHIP_R200) |
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); |
} |
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) |
disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL); |
else |
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); |
if (rdev->family == CHIP_R200) |
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); |
if (is_tv) { |
uint32_t dac_cntl; |
dac_cntl = RREG32(RADEON_DAC_CNTL); |
dac_cntl &= ~RADEON_DAC_TVO_EN; |
WREG32(RADEON_DAC_CNTL, dac_cntl); |
if (ASIC_IS_R300(rdev)) |
gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1; |
dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL; |
if (radeon_crtc->crtc_id == 0) { |
if (ASIC_IS_R300(rdev)) { |
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; |
disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC | |
RADEON_DISP_TV_SOURCE_CRTC); |
} |
if (rdev->family >= CHIP_R200) { |
disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2; |
} else { |
disp_hw_debug |= RADEON_CRT2_DISP1_SEL; |
} |
} else { |
if (ASIC_IS_R300(rdev)) { |
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; |
disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC; |
} |
if (rdev->family >= CHIP_R200) { |
disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2; |
} else { |
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; |
} |
} |
WREG32(RADEON_DAC_CNTL2, dac2_cntl); |
} else { |
dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL; |
if (radeon_crtc->crtc_id == 0) { |
1083,17 → 978,25 |
} else |
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; |
} |
WREG32(RADEON_DAC_CNTL2, dac2_cntl); |
} |
if (ASIC_IS_R300(rdev)) { |
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); |
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl); |
} else if (rdev->family == CHIP_R200) |
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); |
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); |
} |
if (rdev->family >= CHIP_R200) |
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl); |
else |
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); |
if (rdev->family == CHIP_R200) |
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); |
if (is_tv) |
radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode); |
if (rdev->is_atom_bios) |
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); |
else |
1101,6 → 1004,141 |
} |
static bool r300_legacy_tv_detect(struct drm_encoder *encoder, |
struct drm_connector *connector) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; |
uint32_t disp_output_cntl, gpiopad_a, tmp; |
bool found = false; |
/* save regs needed */ |
gpiopad_a = RREG32(RADEON_GPIOPAD_A); |
dac_cntl2 = RREG32(RADEON_DAC_CNTL2); |
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); |
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); |
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); |
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); |
WREG32_P(RADEON_GPIOPAD_A, 0, ~1); |
WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL); |
WREG32(RADEON_CRTC2_GEN_CNTL, |
RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT); |
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; |
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; |
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); |
WREG32(RADEON_DAC_EXT_CNTL, |
RADEON_DAC2_FORCE_BLANK_OFF_EN | |
RADEON_DAC2_FORCE_DATA_EN | |
RADEON_DAC_FORCE_DATA_SEL_RGB | |
(0xec << RADEON_DAC_FORCE_DATA_SHIFT)); |
WREG32(RADEON_TV_DAC_CNTL, |
RADEON_TV_DAC_STD_NTSC | |
(8 << RADEON_TV_DAC_BGADJ_SHIFT) | |
(6 << RADEON_TV_DAC_DACADJ_SHIFT)); |
RREG32(RADEON_TV_DAC_CNTL); |
mdelay(4); |
WREG32(RADEON_TV_DAC_CNTL, |
RADEON_TV_DAC_NBLANK | |
RADEON_TV_DAC_NHOLD | |
RADEON_TV_MONITOR_DETECT_EN | |
RADEON_TV_DAC_STD_NTSC | |
(8 << RADEON_TV_DAC_BGADJ_SHIFT) | |
(6 << RADEON_TV_DAC_DACADJ_SHIFT)); |
RREG32(RADEON_TV_DAC_CNTL); |
mdelay(6); |
tmp = RREG32(RADEON_TV_DAC_CNTL); |
if ((tmp & RADEON_TV_DAC_GDACDET) != 0) { |
found = true; |
DRM_DEBUG("S-video TV connection detected\n"); |
} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) { |
found = true; |
DRM_DEBUG("Composite TV connection detected\n"); |
} |
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); |
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); |
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); |
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); |
WREG32(RADEON_DAC_CNTL2, dac_cntl2); |
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); |
return found; |
} |
static bool radeon_legacy_tv_detect(struct drm_encoder *encoder, |
struct drm_connector *connector) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
uint32_t tv_dac_cntl, dac_cntl2; |
uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp; |
bool found = false; |
if (ASIC_IS_R300(rdev)) |
return r300_legacy_tv_detect(encoder, connector); |
dac_cntl2 = RREG32(RADEON_DAC_CNTL2); |
tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); |
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); |
config_cntl = RREG32(RADEON_CONFIG_CNTL); |
tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL); |
tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; |
WREG32(RADEON_DAC_CNTL2, tmp); |
tmp = tv_master_cntl | RADEON_TV_ON; |
tmp &= ~(RADEON_TV_ASYNC_RST | |
RADEON_RESTART_PHASE_FIX | |
RADEON_CRT_FIFO_CE_EN | |
RADEON_TV_FIFO_CE_EN | |
RADEON_RE_SYNC_NOW_SEL_MASK); |
tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; |
WREG32(RADEON_TV_MASTER_CNTL, tmp); |
tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | |
RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | |
(8 << RADEON_TV_DAC_BGADJ_SHIFT); |
if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) |
tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); |
else |
tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); |
WREG32(RADEON_TV_DAC_CNTL, tmp); |
tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | |
RADEON_RED_MX_FORCE_DAC_DATA | |
RADEON_GRN_MX_FORCE_DAC_DATA | |
RADEON_BLU_MX_FORCE_DAC_DATA | |
(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); |
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); |
mdelay(3); |
tmp = RREG32(RADEON_TV_DAC_CNTL); |
if (tmp & RADEON_TV_DAC_GDACDET) { |
found = true; |
DRM_DEBUG("S-video TV connection detected\n"); |
} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) { |
found = true; |
DRM_DEBUG("Composite TV connection detected\n"); |
} |
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); |
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); |
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); |
WREG32(RADEON_DAC_CNTL2, dac_cntl2); |
return found; |
} |
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, |
struct drm_connector *connector) |
{ |
1109,10 → 1147,30 |
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; |
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; |
enum drm_connector_status found = connector_status_disconnected; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
bool color = true; |
/* FIXME tv */ |
if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO || |
connector->connector_type == DRM_MODE_CONNECTOR_Composite || |
connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) { |
bool tv_detect; |
if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT)) |
return connector_status_disconnected; |
tv_detect = radeon_legacy_tv_detect(encoder, connector); |
if (tv_detect && tv_dac) |
found = connector_status_connected; |
return found; |
} |
/* don't probe if the encoder is being used for something else not CRT related */ |
if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) { |
DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device); |
return connector_status_disconnected; |
} |
/* save the regs we need */ |
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); |
gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; |
1194,8 → 1252,7 |
} |
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); |
/* return found; */ |
return connector_status_disconnected; |
return found; |
} |
1206,6 → 1263,7 |
.mode_set = radeon_legacy_tv_dac_mode_set, |
.commit = radeon_legacy_tv_dac_commit, |
.detect = radeon_legacy_tv_dac_detect, |
.disable = radeon_legacy_encoder_disable, |
}; |
1213,6 → 1271,30 |
.destroy = radeon_enc_destroy, |
}; |
static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder_int_tmds *tmds = NULL; |
bool ret; |
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); |
if (!tmds) |
return NULL; |
if (rdev->is_atom_bios) |
ret = radeon_atombios_get_tmds_info(encoder, tmds); |
else |
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds); |
if (ret == false) |
radeon_legacy_get_tmds_info_from_table(encoder, tmds); |
return tmds; |
} |
void |
radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) |
{ |
1243,9 → 1325,11 |
radeon_encoder->encoder_id = encoder_id; |
radeon_encoder->devices = supported_device; |
radeon_encoder->rmx_type = RMX_OFF; |
switch (radeon_encoder->encoder_id) { |
case ENCODER_OBJECT_ID_INTERNAL_LVDS: |
encoder->possible_crtcs = 0x1; |
drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS); |
drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); |
if (rdev->is_atom_bios) |
1257,10 → 1341,7 |
case ENCODER_OBJECT_ID_INTERNAL_TMDS1: |
drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS); |
drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); |
if (rdev->is_atom_bios) |
radeon_encoder->enc_priv = radeon_atombios_get_tmds_info(radeon_encoder); |
else |
radeon_encoder->enc_priv = radeon_combios_get_tmds_info(radeon_encoder); |
radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder); |
break; |
case ENCODER_OBJECT_ID_INTERNAL_DAC1: |
drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC); |
/drivers/video/drm/radeon/radeon_legacy_tv.c |
---|
0,0 → 1,904 |
#include "drmP.h" |
#include "drm_crtc_helper.h" |
#include "radeon.h" |
/* |
* Integrated TV out support based on the GATOS code by |
* Federico Ulivi <fulivi@lycos.com> |
*/ |
/* |
* Limits of h/v positions (hPos & vPos) |
*/ |
#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */ |
#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */ |
/* |
* Unit for hPos (in TV clock periods) |
*/ |
#define H_POS_UNIT 10 |
/* |
* Indexes in h. code timing table for horizontal line position adjustment |
*/ |
#define H_TABLE_POS1 6 |
#define H_TABLE_POS2 8 |
/* |
* Limits of hor. size (hSize) |
*/ |
#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */ |
/* tv standard constants */ |
#define NTSC_TV_CLOCK_T 233 |
#define NTSC_TV_VFTOTAL 1 |
#define NTSC_TV_LINES_PER_FRAME 525 |
#define NTSC_TV_ZERO_H_SIZE 479166 |
#define NTSC_TV_H_SIZE_UNIT 9478 |
#define PAL_TV_CLOCK_T 188 |
#define PAL_TV_VFTOTAL 3 |
#define PAL_TV_LINES_PER_FRAME 625 |
#define PAL_TV_ZERO_H_SIZE 473200 |
#define PAL_TV_H_SIZE_UNIT 9360 |
/* tv pll setting for 27 mhz ref clk */ |
#define NTSC_TV_PLL_M_27 22 |
#define NTSC_TV_PLL_N_27 175 |
#define NTSC_TV_PLL_P_27 5 |
#define PAL_TV_PLL_M_27 113 |
#define PAL_TV_PLL_N_27 668 |
#define PAL_TV_PLL_P_27 3 |
/* tv pll setting for 14 mhz ref clk */ |
#define NTSC_TV_PLL_M_14 33 |
#define NTSC_TV_PLL_N_14 693 |
#define NTSC_TV_PLL_P_14 7 |
#define VERT_LEAD_IN_LINES 2 |
#define FRAC_BITS 0xe |
#define FRAC_MASK 0x3fff |
struct radeon_tv_mode_constants { |
uint16_t hor_resolution; |
uint16_t ver_resolution; |
enum radeon_tv_std standard; |
uint16_t hor_total; |
uint16_t ver_total; |
uint16_t hor_start; |
uint16_t hor_syncstart; |
uint16_t ver_syncstart; |
unsigned def_restart; |
uint16_t crtcPLL_N; |
uint8_t crtcPLL_M; |
uint8_t crtcPLL_post_div; |
unsigned pix_to_tv; |
}; |
static const uint16_t hor_timing_NTSC[] = { |
0x0007, |
0x003f, |
0x0263, |
0x0a24, |
0x2a6b, |
0x0a36, |
0x126d, /* H_TABLE_POS1 */ |
0x1bfe, |
0x1a8f, /* H_TABLE_POS2 */ |
0x1ec7, |
0x3863, |
0x1bfe, |
0x1bfe, |
0x1a2a, |
0x1e95, |
0x0e31, |
0x201b, |
0 |
}; |
static const uint16_t vert_timing_NTSC[] = { |
0x2001, |
0x200d, |
0x1006, |
0x0c06, |
0x1006, |
0x1818, |
0x21e3, |
0x1006, |
0x0c06, |
0x1006, |
0x1817, |
0x21d4, |
0x0002, |
0 |
}; |
static const uint16_t hor_timing_PAL[] = { |
0x0007, |
0x0058, |
0x027c, |
0x0a31, |
0x2a77, |
0x0a95, |
0x124f, /* H_TABLE_POS1 */ |
0x1bfe, |
0x1b22, /* H_TABLE_POS2 */ |
0x1ef9, |
0x387c, |
0x1bfe, |
0x1bfe, |
0x1b31, |
0x1eb5, |
0x0e43, |
0x201b, |
0 |
}; |
static const uint16_t vert_timing_PAL[] = { |
0x2001, |
0x200c, |
0x1005, |
0x0c05, |
0x1005, |
0x1401, |
0x1821, |
0x2240, |
0x1005, |
0x0c05, |
0x1005, |
0x1401, |
0x1822, |
0x2230, |
0x0002, |
0 |
}; |
/********************************************************************** |
* |
* availableModes |
* |
* Table of all allowed modes for tv output |
* |
**********************************************************************/ |
static const struct radeon_tv_mode_constants available_tv_modes[] = { |
{ /* NTSC timing for 27 Mhz ref clk */ |
800, /* horResolution */ |
600, /* verResolution */ |
TV_STD_NTSC, /* standard */ |
990, /* horTotal */ |
740, /* verTotal */ |
813, /* horStart */ |
824, /* horSyncStart */ |
632, /* verSyncStart */ |
625592, /* defRestart */ |
592, /* crtcPLL_N */ |
91, /* crtcPLL_M */ |
4, /* crtcPLL_postDiv */ |
1022, /* pixToTV */ |
}, |
{ /* PAL timing for 27 Mhz ref clk */ |
800, /* horResolution */ |
600, /* verResolution */ |
TV_STD_PAL, /* standard */ |
1144, /* horTotal */ |
706, /* verTotal */ |
812, /* horStart */ |
824, /* horSyncStart */ |
669, /* verSyncStart */ |
696700, /* defRestart */ |
1382, /* crtcPLL_N */ |
231, /* crtcPLL_M */ |
4, /* crtcPLL_postDiv */ |
759, /* pixToTV */ |
}, |
{ /* NTSC timing for 14 Mhz ref clk */ |
800, /* horResolution */ |
600, /* verResolution */ |
TV_STD_NTSC, /* standard */ |
1018, /* horTotal */ |
727, /* verTotal */ |
813, /* horStart */ |
840, /* horSyncStart */ |
633, /* verSyncStart */ |
630627, /* defRestart */ |
347, /* crtcPLL_N */ |
14, /* crtcPLL_M */ |
8, /* crtcPLL_postDiv */ |
1022, /* pixToTV */ |
}, |
}; |
#define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes) |
static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder, |
uint16_t *pll_ref_freq) |
{ |
struct drm_device *dev = radeon_encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_crtc *radeon_crtc; |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
const struct radeon_tv_mode_constants *const_ptr; |
struct radeon_pll *pll; |
radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc); |
if (radeon_crtc->crtc_id == 1) |
pll = &rdev->clock.p2pll; |
else |
pll = &rdev->clock.p1pll; |
if (pll_ref_freq) |
*pll_ref_freq = pll->reference_freq; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M) { |
if (pll->reference_freq == 2700) |
const_ptr = &available_tv_modes[0]; |
else |
const_ptr = &available_tv_modes[2]; |
} else { |
if (pll->reference_freq == 2700) |
const_ptr = &available_tv_modes[1]; |
else |
const_ptr = &available_tv_modes[1]; /* FIX ME */ |
} |
return const_ptr; |
} |
static long YCOEF_value[5] = { 2, 2, 0, 4, 0 }; |
static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 }; |
static long SLOPE_value[5] = { 1, 2, 2, 4, 8 }; |
static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 }; |
static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests, |
unsigned n_wait_loops, unsigned cnt_threshold) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
uint32_t save_pll_test; |
unsigned int i, j; |
WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100); |
save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL); |
WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B); |
WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL); |
for (i = 0; i < n_tests; i++) { |
WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0); |
for (j = 0; j < n_wait_loops; j++) |
if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold) |
break; |
} |
WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test); |
WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff); |
} |
static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder, |
uint16_t addr, uint32_t value) |
{ |
struct drm_device *dev = radeon_encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
uint32_t tmp; |
int i = 0; |
WREG32(RADEON_TV_HOST_WRITE_DATA, value); |
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr); |
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT); |
do { |
tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL); |
if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0) |
break; |
i++; |
} while (i < 10000); |
WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0); |
} |
#if 0 /* included for completeness */ |
static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr) |
{ |
struct drm_device *dev = radeon_encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
uint32_t tmp; |
int i = 0; |
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr); |
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD); |
do { |
tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL); |
if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0) |
break; |
i++; |
} while (i < 10000); |
WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0); |
return RREG32(RADEON_TV_HOST_READ_DATA); |
} |
#endif |
static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr) |
{ |
uint16_t h_table; |
switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) { |
case 0: |
h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL; |
break; |
case 1: |
h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2; |
break; |
case 2: |
h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2; |
break; |
default: |
h_table = 0; |
break; |
} |
return h_table; |
} |
static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr) |
{ |
uint16_t v_table; |
switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) { |
case 0: |
v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1; |
break; |
case 1: |
v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1; |
break; |
case 2: |
v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1; |
break; |
default: |
v_table = 0; |
break; |
} |
return v_table; |
} |
static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder) |
{ |
struct drm_device *dev = radeon_encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
uint16_t h_table, v_table; |
uint32_t tmp; |
int i; |
WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr); |
h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr); |
v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr); |
for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) { |
tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]); |
radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp); |
if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0) |
break; |
} |
for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) { |
tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]); |
radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp); |
if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0) |
break; |
} |
} |
static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder) |
{ |
struct drm_device *dev = radeon_encoder->base.dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart); |
WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart); |
WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart); |
} |
static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
struct radeon_crtc *radeon_crtc; |
int restart; |
unsigned int h_total, v_total, f_total; |
int v_offset, h_offset; |
u16 p1, p2, h_inc; |
bool h_changed; |
const struct radeon_tv_mode_constants *const_ptr; |
struct radeon_pll *pll; |
radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc); |
if (radeon_crtc->crtc_id == 1) |
pll = &rdev->clock.p2pll; |
else |
pll = &rdev->clock.p1pll; |
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); |
if (!const_ptr) |
return false; |
h_total = const_ptr->hor_total; |
v_total = const_ptr->ver_total; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M || |
tv_dac->tv_std == TV_STD_PAL_60) |
f_total = NTSC_TV_VFTOTAL + 1; |
else |
f_total = PAL_TV_VFTOTAL + 1; |
/* adjust positions 1&2 in hor. cod timing table */ |
h_offset = tv_dac->h_pos * H_POS_UNIT; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M) { |
h_offset -= 50; |
p1 = hor_timing_NTSC[H_TABLE_POS1]; |
p2 = hor_timing_NTSC[H_TABLE_POS2]; |
} else { |
p1 = hor_timing_PAL[H_TABLE_POS1]; |
p2 = hor_timing_PAL[H_TABLE_POS2]; |
} |
p1 = (u16)((int)p1 + h_offset); |
p2 = (u16)((int)p2 - h_offset); |
h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] || |
p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]); |
tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1; |
tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2; |
/* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */ |
h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000; |
/* adjust restart */ |
restart = const_ptr->def_restart; |
/* |
* convert v_pos TV lines to n. of CRTC pixels |
*/ |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M || |
tv_dac->tv_std == TV_STD_PAL_60) |
v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME); |
else |
v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME); |
restart -= v_offset + h_offset; |
DRM_DEBUG("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n", |
const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart); |
tv_dac->tv.hrestart = restart % h_total; |
restart /= h_total; |
tv_dac->tv.vrestart = restart % v_total; |
restart /= v_total; |
tv_dac->tv.frestart = restart % f_total; |
DRM_DEBUG("compute_restart: F/H/V=%u,%u,%u\n", |
(unsigned)tv_dac->tv.frestart, |
(unsigned)tv_dac->tv.vrestart, |
(unsigned)tv_dac->tv.hrestart); |
/* compute h_inc from hsize */ |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M) |
h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) / |
(tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE))); |
else |
h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) / |
(tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE))); |
tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) | |
((u32)h_inc << RADEON_H_INC_SHIFT); |
DRM_DEBUG("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc); |
return h_changed; |
} |
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode) |
{ |
struct drm_device *dev = encoder->dev; |
struct radeon_device *rdev = dev->dev_private; |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; |
const struct radeon_tv_mode_constants *const_ptr; |
struct radeon_crtc *radeon_crtc; |
int i; |
uint16_t pll_ref_freq; |
uint32_t vert_space, flicker_removal, tmp; |
uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl; |
uint32_t tv_modulator_cntl1, tv_modulator_cntl2; |
uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2; |
uint32_t tv_pll_cntl, tv_pll_cntl1, tv_ftotal; |
uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl; |
uint32_t m, n, p; |
const uint16_t *hor_timing; |
const uint16_t *vert_timing; |
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq); |
if (!const_ptr) |
return; |
radeon_crtc = to_radeon_crtc(encoder->crtc); |
tv_master_cntl = (RADEON_VIN_ASYNC_RST | |
RADEON_CRT_FIFO_CE_EN | |
RADEON_TV_FIFO_CE_EN | |
RADEON_TV_ON); |
if (!ASIC_IS_R300(rdev)) |
tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J) |
tv_master_cntl |= RADEON_RESTART_PHASE_FIX; |
tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT | |
RADEON_SYNC_TIP_LEVEL | |
RADEON_YFLT_EN | |
RADEON_UVFLT_EN | |
(6 << RADEON_CY_FILT_BLEND_SHIFT)); |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J) { |
tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) | |
(0x3b << RADEON_BLANK_LEVEL_SHIFT); |
tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) | |
((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); |
} else if (tv_dac->tv_std == TV_STD_SCART_PAL) { |
tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN; |
tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) | |
((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); |
} else { |
tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN | |
(0x3b << RADEON_SET_UP_LEVEL_SHIFT) | |
(0x3b << RADEON_BLANK_LEVEL_SHIFT); |
tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) | |
((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); |
} |
tv_rgb_cntl = (RADEON_RGB_DITHER_EN |
| RADEON_TVOUT_SCALE_EN |
| (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT) |
| (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT) |
| RADEON_RGB_ATTEN_SEL(0x3) |
| RADEON_RGB_ATTEN_VAL(0xc)); |
if (radeon_crtc->crtc_id == 1) |
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2; |
else { |
if (radeon_crtc->rmx_type != RMX_OFF) |
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX; |
else |
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1; |
} |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M || |
tv_dac->tv_std == TV_STD_PAL_60) |
vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME; |
else |
vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME; |
tmp = RREG32(RADEON_TV_VSCALER_CNTL1); |
tmp &= 0xe3ff0000; |
tmp |= (vert_space * (1 << FRAC_BITS) / 10000); |
tv_vscaler_cntl1 = tmp; |
if (pll_ref_freq == 2700) |
tv_vscaler_cntl1 |= RADEON_RESTART_FIELD; |
if (const_ptr->hor_resolution == 1024) |
tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT); |
else |
tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT); |
/* scale up for int divide */ |
tmp = const_ptr->ver_total * 2 * 1000; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M || |
tv_dac->tv_std == TV_STD_PAL_60) { |
tmp /= NTSC_TV_LINES_PER_FRAME; |
} else { |
tmp /= PAL_TV_LINES_PER_FRAME; |
} |
flicker_removal = (tmp + 500) / 1000; |
if (flicker_removal < 3) |
flicker_removal = 3; |
for (i = 0; i < 6; ++i) { |
if (flicker_removal == SLOPE_limit[i]) |
break; |
} |
tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + |
5001) / 10000 / 8 | ((SLOPE_value[i] * |
(1 << (FRAC_BITS - 1)) / 8) << 16); |
tv_y_fall_cntl = |
(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) | |
RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) / |
1024; |
tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG| |
(flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024; |
tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0; |
tv_vscaler_cntl2 |= (0x10 << 24) | |
RADEON_DITHER_MODE | |
RADEON_Y_OUTPUT_DITHER_EN | |
RADEON_UV_OUTPUT_DITHER_EN | |
RADEON_UV_TO_BUF_DITHER_EN; |
tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK; |
tmp = ((16384 * 256 * 10) / tmp + 5) / 10; |
tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000; |
tv_dac->tv.timing_cntl = tmp; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M || |
tv_dac->tv_std == TV_STD_PAL_60) |
tv_dac_cntl = tv_dac->ntsc_tvdac_adj; |
else |
tv_dac_cntl = tv_dac->pal_tvdac_adj; |
tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J) |
tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; |
else |
tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J) { |
if (pll_ref_freq == 2700) { |
m = NTSC_TV_PLL_M_27; |
n = NTSC_TV_PLL_N_27; |
p = NTSC_TV_PLL_P_27; |
} else { |
m = NTSC_TV_PLL_M_14; |
n = NTSC_TV_PLL_N_14; |
p = NTSC_TV_PLL_P_14; |
} |
} else { |
if (pll_ref_freq == 2700) { |
m = PAL_TV_PLL_M_27; |
n = PAL_TV_PLL_N_27; |
p = PAL_TV_PLL_P_27; |
} else { |
m = PAL_TV_PLL_M_27; |
n = PAL_TV_PLL_N_27; |
p = PAL_TV_PLL_P_27; |
} |
} |
tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) | |
(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | |
((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | |
(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | |
((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); |
tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK) << RADEON_TVPCP_SHIFT) | |
((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) | |
((1 & RADEON_TVPDC_MASK) << RADEON_TVPDC_SHIFT) | |
RADEON_TVCLK_SRC_SEL_TVPLL | |
RADEON_TVPLL_TEST_DIS); |
tv_dac->tv.tv_uv_adr = 0xc8; |
if (tv_dac->tv_std == TV_STD_NTSC || |
tv_dac->tv_std == TV_STD_NTSC_J || |
tv_dac->tv_std == TV_STD_PAL_M || |
tv_dac->tv_std == TV_STD_PAL_60) { |
tv_ftotal = NTSC_TV_VFTOTAL; |
hor_timing = hor_timing_NTSC; |
vert_timing = vert_timing_NTSC; |
} else { |
hor_timing = hor_timing_PAL; |
vert_timing = vert_timing_PAL; |
tv_ftotal = PAL_TV_VFTOTAL; |
} |
for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) { |
if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0) |
break; |
} |
for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) { |
if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0) |
break; |
} |
radeon_legacy_tv_init_restarts(encoder); |
/* play with DAC_CNTL */ |
/* play with GPIOPAD_A */ |
/* DISP_OUTPUT_CNTL */ |
/* use reference freq */ |
/* program the TV registers */ |
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST | |
RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST)); |
tmp = RREG32(RADEON_TV_DAC_CNTL); |
tmp &= ~RADEON_TV_DAC_NBLANK; |
tmp |= RADEON_TV_DAC_BGSLEEP | |
RADEON_TV_DAC_RDACPD | |
RADEON_TV_DAC_GDACPD | |
RADEON_TV_DAC_BDACPD; |
WREG32(RADEON_TV_DAC_CNTL, tmp); |
/* TV PLL */ |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL); |
WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl); |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET); |
radeon_wait_pll_lock(encoder, 200, 800, 135); |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET); |
radeon_wait_pll_lock(encoder, 300, 160, 27); |
radeon_wait_pll_lock(encoder, 200, 800, 135); |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf); |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL); |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK); |
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP); |
/* TV HV */ |
WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl); |
WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1); |
WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1); |
WREG32(RADEON_TV_HSTART, const_ptr->hor_start); |
WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1); |
WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1); |
WREG32(RADEON_TV_FTOTAL, tv_ftotal); |
WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1); |
WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2); |
WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl); |
WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl); |
WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl); |
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST | |
RADEON_CRT_ASYNC_RST)); |
/* TV restarts */ |
radeon_legacy_write_tv_restarts(radeon_encoder); |
/* tv timings */ |
radeon_restore_tv_timing_tables(radeon_encoder); |
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST)); |
/* tv std */ |
WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE)); |
WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl); |
WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1); |
WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2); |
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN | |
RADEON_C_GRN_EN | |
RADEON_CMP_BLU_EN | |
RADEON_DAC_DITHER_EN)); |
WREG32(RADEON_TV_CRC_CNTL, 0); |
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); |
WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) | |
(0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT))); |
WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) | |
(0x100 << RADEON_Y_GAIN_SHIFT))); |
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); |
} |
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder, |
uint32_t *h_total_disp, uint32_t *h_sync_strt_wid, |
uint32_t *v_total_disp, uint32_t *v_sync_strt_wid) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
const struct radeon_tv_mode_constants *const_ptr; |
uint32_t tmp; |
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); |
if (!const_ptr) |
return; |
*h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | |
(((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); |
tmp = *h_sync_strt_wid; |
tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR); |
tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | |
(const_ptr->hor_syncstart & 7); |
*h_sync_strt_wid = tmp; |
*v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | |
((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT); |
tmp = *v_sync_strt_wid; |
tmp &= ~RADEON_CRTC_V_SYNC_STRT; |
tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); |
*v_sync_strt_wid = tmp; |
} |
static inline int get_post_div(int value) |
{ |
int post_div; |
switch (value) { |
case 1: post_div = 0; break; |
case 2: post_div = 1; break; |
case 3: post_div = 4; break; |
case 4: post_div = 2; break; |
case 6: post_div = 6; break; |
case 8: post_div = 3; break; |
case 12: post_div = 7; break; |
case 16: |
default: post_div = 5; break; |
} |
return post_div; |
} |
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder, |
uint32_t *htotal_cntl, uint32_t *ppll_ref_div, |
uint32_t *ppll_div_3, uint32_t *pixclks_cntl) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
const struct radeon_tv_mode_constants *const_ptr; |
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); |
if (!const_ptr) |
return; |
*htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN; |
*ppll_ref_div = const_ptr->crtcPLL_M; |
*ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16); |
*pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL); |
*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK; |
} |
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, |
uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div, |
uint32_t *p2pll_div_0, uint32_t *pixclks_cntl) |
{ |
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
const struct radeon_tv_mode_constants *const_ptr; |
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL); |
if (!const_ptr) |
return; |
*htotal2_cntl = (const_ptr->hor_total & 0x7); |
*p2pll_ref_div = const_ptr->crtcPLL_M; |
*p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16); |
*pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; |
*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL; |
} |
/drivers/video/drm/radeon/radeon_mode.h |
---|
34,8 → 34,12 |
#include <drm_mode.h> |
#include <drm_edid.h> |
#include <linux/i2c.h> |
#include <linux/i2c-id.h> |
#include <linux/i2c-algo-bit.h> |
#include "radeon_fixed.h" |
struct radeon_device; |
#define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base) |
#define to_radeon_connector(x) container_of(x, struct radeon_connector, base) |
#define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base) |
123,6 → 127,7 |
#define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) |
#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) |
#define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) |
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) |
struct radeon_pll { |
uint16_t reference_freq; |
169,36 → 174,63 |
struct atom_context *atom_context; |
enum radeon_connector_table connector_table; |
bool mode_config_initialized; |
struct radeon_crtc *crtcs[2]; |
/* DVI-I properties */ |
struct drm_property *coherent_mode_property; |
/* DAC enable load detect */ |
struct drm_property *load_detect_property; |
/* TV standard load detect */ |
struct drm_property *tv_std_property; |
/* legacy TMDS PLL detect */ |
struct drm_property *tmds_pll_property; |
}; |
struct radeon_native_mode { |
/* preferred mode */ |
uint32_t panel_xres, panel_yres; |
uint32_t hoverplus, hsync_width; |
uint32_t hblank; |
uint32_t voverplus, vsync_width; |
uint32_t vblank; |
uint32_t dotclock; |
uint32_t flags; |
}; |
#define MAX_H_CODE_TIMING_LEN 32 |
#define MAX_V_CODE_TIMING_LEN 32 |
/* need to store these as reading |
back code tables is excessive */ |
struct radeon_tv_regs { |
uint32_t tv_uv_adr; |
uint32_t timing_cntl; |
uint32_t hrestart; |
uint32_t vrestart; |
uint32_t frestart; |
uint16_t h_code_timing[MAX_H_CODE_TIMING_LEN]; |
uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN]; |
}; |
struct radeon_crtc { |
struct drm_crtc base; |
int crtc_id; |
u16_t lut_r[256], lut_g[256], lut_b[256]; |
u16 lut_r[256], lut_g[256], lut_b[256]; |
bool enabled; |
bool can_tile; |
uint32_t crtc_offset; |
struct radeon_framebuffer *fbdev_fb; |
struct drm_mode_set mode_set; |
// struct drm_gem_object *cursor_bo; |
uint64_t cursor_addr; |
int cursor_width; |
int cursor_height; |
uint32_t legacy_display_base_addr; |
uint32_t legacy_cursor_offset; |
enum radeon_rmx_type rmx_type; |
fixed20_12 vsc; |
fixed20_12 hsc; |
struct radeon_native_mode native_mode; |
}; |
#define RADEON_USE_RMX 1 |
struct radeon_native_mode { |
/* preferred mode */ |
uint32_t panel_xres, panel_yres; |
uint32_t hoverplus, hsync_width; |
uint32_t hblank; |
uint32_t voverplus, vsync_width; |
uint32_t vblank; |
uint32_t dotclock; |
uint32_t flags; |
}; |
struct radeon_encoder_primary_dac { |
/* legacy primary dac */ |
uint32_t ps2_pdac_adj; |
225,7 → 257,13 |
uint32_t ntsc_tvdac_adj; |
uint32_t pal_tvdac_adj; |
int h_pos; |
int v_pos; |
int h_size; |
int supported_tv_stds; |
bool tv_on; |
enum radeon_tv_std tv_std; |
struct radeon_tv_regs tv; |
}; |
struct radeon_encoder_int_tmds { |
244,10 → 282,15 |
struct radeon_native_mode native_mode; |
}; |
struct radeon_encoder_atom_dac { |
enum radeon_tv_std tv_std; |
}; |
struct radeon_encoder { |
struct drm_encoder base; |
uint32_t encoder_id; |
uint32_t devices; |
uint32_t active_device; |
uint32_t flags; |
uint32_t pixel_clock; |
enum radeon_rmx_type rmx_type; |
265,8 → 308,12 |
uint32_t connector_id; |
uint32_t devices; |
struct radeon_i2c_chan *ddc_bus; |
int use_digital; |
bool use_digital; |
/* we need to mind the EDID between detect |
and get modes due to analog/digital/tvencoder */ |
struct edid *edid; |
void *con_priv; |
bool dac_load_detect; |
}; |
struct radeon_framebuffer { |
299,6 → 346,7 |
struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index); |
extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action); |
extern int atombios_get_encoder_mode(struct drm_encoder *encoder); |
extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); |
extern void radeon_crtc_load_lut(struct drm_crtc *crtc); |
extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
326,8 → 374,12 |
extern bool radeon_combios_get_clock_info(struct drm_device *dev); |
extern struct radeon_encoder_atom_dig * |
radeon_atombios_get_lvds_info(struct radeon_encoder *encoder); |
extern struct radeon_encoder_int_tmds * |
radeon_atombios_get_tmds_info(struct radeon_encoder *encoder); |
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, |
struct radeon_encoder_int_tmds *tmds); |
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, |
struct radeon_encoder_int_tmds *tmds); |
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder, |
struct radeon_encoder_int_tmds *tmds); |
extern struct radeon_encoder_primary_dac * |
radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder); |
extern struct radeon_encoder_tv_dac * |
334,8 → 386,6 |
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder); |
extern struct radeon_encoder_lvds * |
radeon_combios_get_lvds_info(struct radeon_encoder *encoder); |
extern struct radeon_encoder_int_tmds * |
radeon_combios_get_tmds_info(struct radeon_encoder *encoder); |
extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder); |
extern struct radeon_encoder_tv_dac * |
radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder); |
345,6 → 395,8 |
extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev); |
extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock); |
extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev); |
extern void radeon_save_bios_scratch_regs(struct radeon_device *rdev); |
extern void radeon_restore_bios_scratch_regs(struct radeon_device *rdev); |
extern void |
radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc); |
extern void |
382,16 → 434,22 |
void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); |
void radeon_combios_asic_init(struct drm_device *dev); |
extern int radeon_static_clocks_init(struct drm_device *dev); |
void radeon_init_disp_bw_legacy(struct drm_device *dev, |
struct drm_display_mode *mode1, |
uint32_t pixel_bytes1, |
struct drm_display_mode *mode2, |
uint32_t pixel_bytes2); |
void radeon_init_disp_bw_avivo(struct drm_device *dev, |
struct drm_display_mode *mode1, |
uint32_t pixel_bytes1, |
struct drm_display_mode *mode2, |
uint32_t pixel_bytes2); |
void radeon_init_disp_bandwidth(struct drm_device *dev); |
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode); |
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc); |
/* legacy tv */ |
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder, |
uint32_t *h_total_disp, uint32_t *h_sync_strt_wid, |
uint32_t *v_total_disp, uint32_t *v_sync_strt_wid); |
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder, |
uint32_t *htotal_cntl, uint32_t *ppll_ref_div, |
uint32_t *ppll_div_3, uint32_t *pixclks_cntl); |
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, |
uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div, |
uint32_t *p2pll_div_0, uint32_t *pixclks_cntl); |
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, |
struct drm_display_mode *mode, |
struct drm_display_mode *adjusted_mode); |
#endif |
/drivers/video/drm/radeon/radeon_object.c |
---|
29,9 → 29,8 |
* Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> |
* Dave Airlie |
*/ |
#include <list.h> |
#include <drmP.h> |
#include <linux/list.h> |
#include <drm/drmP.h> |
#include "radeon_drm.h" |
#include "radeon.h" |
#include <drm_mm.h> |
/drivers/video/drm/radeon/radeon_reg.h |
---|
982,12 → 982,15 |
# define RS400_TMDS2_PLLRST (1 << 1) |
#define RADEON_GEN_INT_CNTL 0x0040 |
# define RADEON_CRTC_VBLANK_MASK (1 << 0) |
# define RADEON_CRTC2_VBLANK_MASK (1 << 9) |
# define RADEON_SW_INT_ENABLE (1 << 25) |
#define RADEON_GEN_INT_STATUS 0x0044 |
# define RADEON_VSYNC_INT_AK (1 << 2) |
# define RADEON_VSYNC_INT (1 << 2) |
# define RADEON_VSYNC2_INT_AK (1 << 6) |
# define RADEON_VSYNC2_INT (1 << 6) |
# define AVIVO_DISPLAY_INT_STATUS (1 << 0) |
# define RADEON_CRTC_VBLANK_STAT (1 << 0) |
# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) |
# define RADEON_CRTC2_VBLANK_STAT (1 << 9) |
# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) |
# define RADEON_SW_INT_FIRE (1 << 26) |
# define RADEON_SW_INT_TEST (1 << 25) |
# define RADEON_SW_INT_TEST_ACK (1 << 25) |
1942,6 → 1945,11 |
# define RADEON_TXFORMAT_DXT1 (12 << 0) |
# define RADEON_TXFORMAT_DXT23 (14 << 0) |
# define RADEON_TXFORMAT_DXT45 (15 << 0) |
# define RADEON_TXFORMAT_SHADOW16 (16 << 0) |
# define RADEON_TXFORMAT_SHADOW32 (17 << 0) |
# define RADEON_TXFORMAT_DUDV88 (18 << 0) |
# define RADEON_TXFORMAT_LDUDV655 (19 << 0) |
# define RADEON_TXFORMAT_LDUDUV8888 (20 << 0) |
# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) |
# define RADEON_TXFORMAT_FORMAT_SHIFT 0 |
# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) |
2200,7 → 2208,7 |
# define RADEON_ROP_ENABLE (1 << 6) |
# define RADEON_STENCIL_ENABLE (1 << 7) |
# define RADEON_Z_ENABLE (1 << 8) |
# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9) |
# define RADEON_DEPTHXY_OFFSET_ENABLE (1 << 9) |
# define RADEON_RB3D_COLOR_FORMAT_SHIFT 10 |
# define RADEON_COLOR_FORMAT_ARGB1555 3 |
2334,6 → 2342,9 |
# define RADEON_RE_WIDTH_SHIFT 0 |
# define RADEON_RE_HEIGHT_SHIFT 16 |
#define RADEON_RB3D_ZPASS_DATA 0x3290 |
#define RADEON_RB3D_ZPASS_ADDR 0x3294 |
#define RADEON_SE_CNTL 0x1c4c |
# define RADEON_FFACE_CULL_CW (0 << 0) |
# define RADEON_FFACE_CULL_CCW (1 << 0) |
2767,7 → 2778,12 |
# define R200_TXFORMAT_DXT1 (12 << 0) |
# define R200_TXFORMAT_DXT23 (14 << 0) |
# define R200_TXFORMAT_DXT45 (15 << 0) |
# define R200_TXFORMAT_DVDU88 (18 << 0) |
# define R200_TXFORMAT_LDVDU655 (19 << 0) |
# define R200_TXFORMAT_LDVDU8888 (20 << 0) |
# define R200_TXFORMAT_GR1616 (21 << 0) |
# define R200_TXFORMAT_ABGR8888 (22 << 0) |
# define R200_TXFORMAT_BGR111110 (23 << 0) |
# define R200_TXFORMAT_FORMAT_MASK (31 << 0) |
# define R200_TXFORMAT_FORMAT_SHIFT 0 |
# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) |
2812,6 → 2828,13 |
#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */ |
#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */ |
#define R200_PP_CUBIC_FACES_0 0x2c18 |
#define R200_PP_CUBIC_FACES_1 0x2c38 |
#define R200_PP_CUBIC_FACES_2 0x2c58 |
#define R200_PP_CUBIC_FACES_3 0x2c78 |
#define R200_PP_CUBIC_FACES_4 0x2c98 |
#define R200_PP_CUBIC_FACES_5 0x2cb8 |
#define R200_PP_TXOFFSET_0 0x2d00 |
# define R200_TXO_ENDIAN_NO_SWAP (0 << 0) |
# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) |
2823,11 → 2846,44 |
# define R200_TXO_MICRO_TILE (1 << 3) |
# define R200_TXO_OFFSET_MASK 0xffffffe0 |
# define R200_TXO_OFFSET_SHIFT 5 |
#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 |
#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 |
#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c |
#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 |
#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 |
#define R200_PP_TXOFFSET_1 0x2d18 |
#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c |
#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 |
#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 |
#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 |
#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c |
#define R200_PP_TXOFFSET_2 0x2d30 |
#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 |
#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 |
#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c |
#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 |
#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 |
#define R200_PP_TXOFFSET_3 0x2d48 |
#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c |
#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 |
#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 |
#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 |
#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c |
#define R200_PP_TXOFFSET_4 0x2d60 |
#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 |
#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 |
#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c |
#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 |
#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 |
#define R200_PP_TXOFFSET_5 0x2d78 |
#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c |
#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 |
#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 |
#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 |
#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c |
#define R200_PP_TFACTOR_0 0x2ee0 |
#define R200_PP_TFACTOR_1 0x2ee4 |
3169,6 → 3225,11 |
# define R200_FORCE_INORDER_PROC (1<<31) |
#define R200_PP_CNTL_X 0x2cc4 |
#define R200_PP_TXMULTI_CTL_0 0x2c1c |
#define R200_PP_TXMULTI_CTL_1 0x2c3c |
#define R200_PP_TXMULTI_CTL_2 0x2c5c |
#define R200_PP_TXMULTI_CTL_3 0x2c7c |
#define R200_PP_TXMULTI_CTL_4 0x2c9c |
#define R200_PP_TXMULTI_CTL_5 0x2cbc |
#define R200_SE_VTX_STATE_CNTL 0x2180 |
# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16) |
3194,6 → 3255,24 |
#define RADEON_CP_RB_WPTR 0x0714 |
#define RADEON_CP_RB_RPTR_WR 0x071c |
#define RADEON_SCRATCH_UMSK 0x0770 |
#define RADEON_SCRATCH_ADDR 0x0774 |
#define R600_CP_RB_BASE 0xc100 |
#define R600_CP_RB_CNTL 0xc104 |
# define R600_RB_BUFSZ(x) ((x) << 0) |
# define R600_RB_BLKSZ(x) ((x) << 8) |
# define R600_RB_NO_UPDATE (1 << 27) |
# define R600_RB_RPTR_WR_ENA (1 << 31) |
#define R600_CP_RB_RPTR_WR 0xc108 |
#define R600_CP_RB_RPTR_ADDR 0xc10c |
#define R600_CP_RB_RPTR_ADDR_HI 0xc110 |
#define R600_CP_RB_WPTR 0xc114 |
#define R600_CP_RB_WPTR_ADDR 0xc118 |
#define R600_CP_RB_WPTR_ADDR_HI 0xc11c |
#define R600_CP_RB_RPTR 0x8700 |
#define R600_CP_RB_WPTR_DELAY 0x8704 |
#define RADEON_CP_IB_BASE 0x0738 |
#define RADEON_CP_IB_BUFSZ 0x073c |
3401,7 → 3480,9 |
# define RADEON_RGB_CONVERT_BY_PASS (1 << 10) |
# define RADEON_UVRAM_READ_MARGIN_SHIFT 16 |
# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20 |
# define RADEON_RGB_ATTEN_SEL(x) ((x) << 24) |
# define RADEON_TVOUT_SCALE_EN (1 << 26) |
# define RADEON_RGB_ATTEN_VAL(x) ((x) << 28) |
#define RADEON_TV_SYNC_CNTL 0x0808 |
# define RADEON_SYNC_OE (1 << 0) |
# define RADEON_SYNC_OUT (1 << 1) |
3568,4 → 3649,6 |
#define RADEON_SCRATCH_REG4 0x15f0 |
#define RADEON_SCRATCH_REG5 0x15f4 |
#define RV530_GB_PIPE_SELECT2 0x4124 |
#endif |
/drivers/video/drm/radeon/radeon_ring.c |
---|
25,7 → 25,7 |
* Alex Deucher |
* Jerome Glisse |
*/ |
//#include <linux/seq_file.h> |
#include <linux/seq_file.h> |
#include "drmP.h" |
#include "radeon_drm.h" |
#include "radeon_reg.h" |
32,7 → 32,6 |
#include "radeon.h" |
#include "atom.h" |
int radeon_debugfs_ib_init(struct radeon_device *rdev); |
/* |
60,10 → 59,12 |
set_bit(i, rdev->ib_pool.alloc_bm); |
rdev->ib_pool.ibs[i].length_dw = 0; |
*ib = &rdev->ib_pool.ibs[i]; |
mutex_unlock(&rdev->ib_pool.mutex); |
goto out; |
} |
if (list_empty(&rdev->ib_pool.scheduled_ibs)) { |
/* we go do nothings here */ |
mutex_unlock(&rdev->ib_pool.mutex); |
DRM_ERROR("all IB allocated none scheduled.\n"); |
r = -EINVAL; |
goto out; |
73,10 → 74,13 |
struct radeon_ib, list); |
if (nib->fence == NULL) { |
/* we go do nothings here */ |
mutex_unlock(&rdev->ib_pool.mutex); |
DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); |
r = -EINVAL; |
goto out; |
} |
mutex_unlock(&rdev->ib_pool.mutex); |
r = radeon_fence_wait(nib->fence, false); |
if (r) { |
DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, |
85,12 → 89,17 |
goto out; |
} |
radeon_fence_unref(&nib->fence); |
nib->length_dw = 0; |
/* scheduled list is accessed here */ |
mutex_lock(&rdev->ib_pool.mutex); |
list_del(&nib->list); |
INIT_LIST_HEAD(&nib->list); |
mutex_unlock(&rdev->ib_pool.mutex); |
*ib = nib; |
out: |
mutex_unlock(&rdev->ib_pool.mutex); |
if (r) { |
radeon_fence_unref(&fence); |
} else { |
115,60 → 124,36 |
} |
list_del(&tmp->list); |
INIT_LIST_HEAD(&tmp->list); |
if (tmp->fence) { |
if (tmp->fence) |
radeon_fence_unref(&tmp->fence); |
} |
tmp->length_dw = 0; |
clear_bit(tmp->idx, rdev->ib_pool.alloc_bm); |
mutex_unlock(&rdev->ib_pool.mutex); |
} |
static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib) |
{ |
while ((ib->length_dw & rdev->cp.align_mask)) { |
ib->ptr[ib->length_dw++] = PACKET2(0); |
} |
} |
static void radeon_ib_cpu_flush(struct radeon_device *rdev, |
struct radeon_ib *ib) |
{ |
unsigned long tmp; |
unsigned i; |
/* To force CPU cache flush ugly but seems reliable */ |
for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) { |
tmp = readl(&ib->ptr[i]); |
} |
} |
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) |
{ |
int r = 0; |
mutex_lock(&rdev->ib_pool.mutex); |
radeon_ib_align(rdev, ib); |
radeon_ib_cpu_flush(rdev, ib); |
if (!ib->length_dw || !rdev->cp.ready) { |
/* TODO: Nothings in the ib we should report. */ |
mutex_unlock(&rdev->ib_pool.mutex); |
DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); |
return -EINVAL; |
} |
/* 64 dwords should be enought for fence too */ |
/* 64 dwords should be enough for fence too */ |
r = radeon_ring_lock(rdev, 64); |
if (r) { |
DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); |
mutex_unlock(&rdev->ib_pool.mutex); |
return r; |
} |
radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1)); |
radeon_ring_write(rdev, ib->gpu_addr); |
radeon_ring_write(rdev, ib->length_dw); |
radeon_ring_ib_execute(rdev, ib); |
radeon_fence_emit(rdev, ib->fence); |
radeon_ring_unlock_commit(rdev); |
mutex_lock(&rdev->ib_pool.mutex); |
list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); |
mutex_unlock(&rdev->ib_pool.mutex); |
radeon_ring_unlock_commit(rdev); |
return 0; |
} |
#endif |
180,6 → 165,8 |
int i; |
int r = 0; |
if (rdev->ib_pool.robj) |
return 0; |
/* Allocate 1M object buffer */ |
INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs); |
r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, |
223,7 → 210,7 |
if (!rdev->ib_pool.ready) { |
return; |
} |
// mutex_lock(&rdev->ib_pool.mutex); |
mutex_lock(&rdev->ib_pool.mutex); |
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); |
if (rdev->ib_pool.robj) { |
// radeon_object_kunmap(rdev->ib_pool.robj); |
230,74 → 217,18 |
// radeon_object_unref(&rdev->ib_pool.robj); |
rdev->ib_pool.robj = NULL; |
} |
// mutex_unlock(&rdev->ib_pool.mutex); |
mutex_unlock(&rdev->ib_pool.mutex); |
} |
#if 0 |
int radeon_ib_test(struct radeon_device *rdev) |
{ |
struct radeon_ib *ib; |
uint32_t scratch; |
uint32_t tmp = 0; |
unsigned i; |
int r; |
r = radeon_scratch_get(rdev, &scratch); |
if (r) { |
DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); |
return r; |
} |
WREG32(scratch, 0xCAFEDEAD); |
r = radeon_ib_get(rdev, &ib); |
if (r) { |
return r; |
} |
ib->ptr[0] = PACKET0(scratch, 0); |
ib->ptr[1] = 0xDEADBEEF; |
ib->ptr[2] = PACKET2(0); |
ib->ptr[3] = PACKET2(0); |
ib->ptr[4] = PACKET2(0); |
ib->ptr[5] = PACKET2(0); |
ib->ptr[6] = PACKET2(0); |
ib->ptr[7] = PACKET2(0); |
ib->length_dw = 8; |
r = radeon_ib_schedule(rdev, ib); |
if (r) { |
radeon_scratch_free(rdev, scratch); |
radeon_ib_free(rdev, &ib); |
return r; |
} |
r = radeon_fence_wait(ib->fence, false); |
if (r) { |
return r; |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
tmp = RREG32(scratch); |
if (tmp == 0xDEADBEEF) { |
break; |
} |
DRM_UDELAY(1); |
} |
if (i < rdev->usec_timeout) { |
DRM_INFO("ib test succeeded in %u usecs\n", i); |
} else { |
DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n", |
scratch, tmp); |
r = -EINVAL; |
} |
radeon_scratch_free(rdev, scratch); |
radeon_ib_free(rdev, &ib); |
return r; |
} |
#endif |
/* |
* Ring. |
*/ |
void radeon_ring_free_size(struct radeon_device *rdev) |
{ |
if (rdev->family >= CHIP_R600) |
rdev->cp.rptr = RREG32(R600_CP_RB_RPTR); |
else |
rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); |
/* This works because ring_size is a power of 2 */ |
rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); |
315,14 → 246,12 |
/* Align requested size with padding so unlock_commit can |
* pad safely */ |
ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask; |
// mutex_lock(&rdev->cp.mutex); |
mutex_lock(&rdev->cp.mutex); |
while (ndw > (rdev->cp.ring_free_dw - 1)) { |
radeon_ring_free_size(rdev); |
if (ndw < rdev->cp.ring_free_dw) { |
break; |
} |
delay(1); |
// r = radeon_fence_wait_next(rdev); |
// if (r) { |
// mutex_unlock(&rdev->cp.mutex); |
343,79 → 272,26 |
count_dw_pad = (rdev->cp.align_mask + 1) - |
(rdev->cp.wptr & rdev->cp.align_mask); |
for (i = 0; i < count_dw_pad; i++) { |
radeon_ring_write(rdev, PACKET2(0)); |
radeon_ring_write(rdev, 2 << 30); |
} |
DRM_MEMORYBARRIER(); |
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr); |
(void)RREG32(RADEON_CP_RB_WPTR); |
// mutex_unlock(&rdev->cp.mutex); |
radeon_cp_commit(rdev); |
mutex_unlock(&rdev->cp.mutex); |
} |
void radeon_ring_unlock_undo(struct radeon_device *rdev) |
{ |
rdev->cp.wptr = rdev->cp.wptr_old; |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
} |
int radeon_ring_test(struct radeon_device *rdev) |
{ |
uint32_t scratch; |
uint32_t tmp = 0; |
unsigned i; |
int r; |
dbgprintf("%s\n",__FUNCTION__); |
r = radeon_scratch_get(rdev, &scratch); |
if (r) { |
DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); |
return r; |
} |
WREG32(scratch, 0xCAFEDEAD); |
r = radeon_ring_lock(rdev, 2); |
if (r) { |
DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); |
radeon_scratch_free(rdev, scratch); |
return r; |
} |
radeon_ring_write(rdev, PACKET0(scratch, 0)); |
radeon_ring_write(rdev, 0xDEADBEEF); |
radeon_ring_unlock_commit(rdev); |
for (i = 0; i < 100000; i++) { |
tmp = RREG32(scratch); |
if (tmp == 0xDEADBEEF) { |
break; |
} |
DRM_UDELAY(1); |
} |
if (i < 100000) { |
DRM_INFO("ring test succeeded in %d usecs\n", i); |
} else { |
DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n", |
scratch, tmp); |
r = -EINVAL; |
} |
radeon_scratch_free(rdev, scratch); |
dbgprintf("done %s\n",__FUNCTION__); |
return r; |
} |
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, |
int pages, u32_t *pagelist); |
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) |
{ |
int r; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
rdev->cp.ring_size = ring_size; |
/* Allocate ring buffer */ |
if (rdev->cp.ring_obj == NULL) { |
r = radeon_object_create(rdev, NULL, rdev->cp.ring_size, |
425,7 → 301,7 |
&rdev->cp.ring_obj); |
if (r) { |
DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r); |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
return r; |
} |
r = radeon_object_pin(rdev->cp.ring_obj, |
433,7 → 309,7 |
&rdev->cp.gpu_addr); |
if (r) { |
DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r); |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
return r; |
} |
r = radeon_object_kmap(rdev->cp.ring_obj, |
440,7 → 316,7 |
(void **)&rdev->cp.ring); |
if (r) { |
DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r); |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
return r; |
} |
} |
461,7 → 337,7 |
rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1; |
rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; |
dbgprintf("done %s\n",__FUNCTION__); |
LEAVE(); |
return 0; |
} |
468,7 → 344,7 |
void radeon_ring_fini(struct radeon_device *rdev) |
{ |
// mutex_lock(&rdev->cp.mutex); |
mutex_lock(&rdev->cp.mutex); |
if (rdev->cp.ring_obj) { |
// radeon_object_kunmap(rdev->cp.ring_obj); |
// radeon_object_unpin(rdev->cp.ring_obj); |
476,7 → 352,7 |
rdev->cp.ring = NULL; |
rdev->cp.ring_obj = NULL; |
} |
// mutex_unlock(&rdev->cp.mutex); |
mutex_unlock(&rdev->cp.mutex); |
} |
524,18 → 400,3 |
return 0; |
#endif |
} |
int drm_order(unsigned long size) |
{ |
int order; |
unsigned long tmp; |
for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ; |
if (size & (size - 1)) |
++order; |
return order; |
} |
/drivers/video/drm/radeon/radeon_share.h |
---|
0,0 → 1,39 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef __RADEON_SHARE_H__ |
#define __RADEON_SHARE_H__ |
void r100_vram_init_sizes(struct radeon_device *rdev); |
void rs690_line_buffer_adjust(struct radeon_device *rdev, |
struct drm_display_mode *mode1, |
struct drm_display_mode *mode2); |
void rv515_bandwidth_avivo_update(struct radeon_device *rdev); |
#endif |
/drivers/video/drm/radeon/rn50_reg_safe.h |
---|
0,0 → 1,28 |
static const unsigned rn50_reg_safe_bm[102] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, |
}; |
/drivers/video/drm/radeon/rs400.c |
---|
25,8 → 25,8 |
* Alex Deucher |
* Jerome Glisse |
*/ |
//#include <linux/seq_file.h> |
#include <drmP.h> |
#include <linux/seq_file.h> |
#include <drm/drmP.h> |
#include "radeon_reg.h" |
#include "radeon.h" |
62,7 → 62,7 |
break; |
default: |
DRM_ERROR("Unable to use IGP GART size %uM\n", |
rdev->mc.gtt_size >> 20); |
(unsigned)(rdev->mc.gtt_size >> 20)); |
DRM_ERROR("Valid GART size for IGP are 32M,64M,128M,256M,512M,1G,2G\n"); |
DRM_ERROR("Forcing to 32M GART size\n"); |
rdev->mc.gtt_size = 32 * 1024 * 1024; |
92,21 → 92,42 |
WREG32_MC(RS480_GART_CACHE_CNTRL, 0); |
} |
int rs400_gart_enable(struct radeon_device *rdev) |
int rs400_gart_init(struct radeon_device *rdev) |
{ |
uint32_t size_reg; |
uint32_t tmp; |
int r; |
if (rdev->gart.table.ram.ptr) { |
WARN(1, "RS400 GART already initialized.\n"); |
return 0; |
} |
/* Check gart size */ |
switch(rdev->mc.gtt_size / (1024 * 1024)) { |
case 32: |
case 64: |
case 128: |
case 256: |
case 512: |
case 1024: |
case 2048: |
break; |
default: |
return -EINVAL; |
} |
/* Initialize common gart structure */ |
r = radeon_gart_init(rdev); |
if (r) { |
if (r) |
return r; |
} |
if (rs400_debugfs_pcie_gart_info_init(rdev)) { |
if (rs400_debugfs_pcie_gart_info_init(rdev)) |
DRM_ERROR("Failed to register debugfs file for RS400 GART !\n"); |
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
return radeon_gart_table_ram_alloc(rdev); |
} |
int rs400_gart_enable(struct radeon_device *rdev) |
{ |
uint32_t size_reg; |
uint32_t tmp; |
tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); |
tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; |
WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); |
136,13 → 157,6 |
default: |
return -EINVAL; |
} |
if (rdev->gart.table.ram.ptr == NULL) { |
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
r = radeon_gart_table_ram_alloc(rdev); |
if (r) { |
return r; |
} |
} |
/* It should be fine to program it to max value */ |
if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { |
WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF); |
164,7 → 178,9 |
WREG32(RADEON_BUS_CNTL, tmp); |
} |
/* Table should be in 32bits address space so ignore bits above. */ |
tmp = rdev->gart.table_addr & 0xfffff000; |
tmp = (u32)rdev->gart.table_addr & 0xfffff000; |
tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4; |
WREG32_MC(RS480_GART_BASE, tmp); |
/* TODO: more tweaking here */ |
WREG32_MC(RS480_GART_FEATURE_ID, |
199,12 → 215,26 |
WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0); |
} |
void rs400_gart_fini(struct radeon_device *rdev) |
{ |
rs400_gart_disable(rdev); |
radeon_gart_table_ram_free(rdev); |
radeon_gart_fini(rdev); |
} |
int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) |
{ |
uint32_t entry; |
if (i < 0 || i > rdev->gart.num_gpu_pages) { |
return -EINVAL; |
} |
rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC); |
entry = (lower_32_bits(addr) & PAGE_MASK) | |
((upper_32_bits(addr) & 0xff) << 4) | |
0xc; |
entry = cpu_to_le32(entry); |
rdev->gart.table.ram.ptr[i] = entry; |
return 0; |
} |
223,10 → 253,9 |
rs400_gpu_init(rdev); |
rs400_gart_disable(rdev); |
rdev->mc.gtt_location = rdev->mc.vram_size; |
rdev->mc.gtt_location = rdev->mc.mc_vram_size; |
rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); |
rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
238,7 → 267,7 |
"programming pipes. Bad things might happen.\n"); |
} |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32(RADEON_MC_FB_LOCATION, tmp); |
247,14 → 276,12 |
(void)RREG32(RADEON_HOST_PATH_CNTL); |
WREG32(RADEON_HOST_PATH_CNTL, tmp); |
(void)RREG32(RADEON_HOST_PATH_CNTL); |
return 0; |
} |
void rs400_mc_fini(struct radeon_device *rdev) |
{ |
rs400_gart_disable(rdev); |
radeon_gart_table_ram_free(rdev); |
radeon_gart_fini(rdev); |
} |
284,21 → 311,12 |
*/ |
void rs400_vram_info(struct radeon_device *rdev) |
{ |
uint32_t tom; |
rs400_gart_adjust_size(rdev); |
/* DDR for all card after R300 & IGP */ |
rdev->mc.vram_is_ddr = true; |
rdev->mc.vram_width = 128; |
/* read NB_TOM to get the amount of ram stolen for the GPU */ |
tom = RREG32(RADEON_NB_TOM); |
rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); |
/* Could aper size report 0 ? */ |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
r100_vram_init_sizes(rdev); |
} |
/drivers/video/drm/radeon/rs600.c |
---|
28,7 → 28,10 |
#include "drmP.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "avivod.h" |
#include "rs600_reg_safe.h" |
/* rs600 depends on : */ |
void r100_hdp_reset(struct radeon_device *rdev); |
int r100_gui_wait_for_idle(struct radeon_device *rdev); |
223,7 → 226,7 |
printk(KERN_WARNING "Failed to wait MC idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32_MC(RS600_MC_FB_LOCATION, tmp); |
301,7 → 304,12 |
rdev->mc.vram_width = 128; |
} |
void rs600_bandwidth_update(struct radeon_device *rdev) |
{ |
/* FIXME: implement, should this be like rs690 ? */ |
} |
/* |
* Indirect registers accessor |
*/ |
/drivers/video/drm/radeon/rs600_reg_safe.h |
---|
0,0 → 1,57 |
static const unsigned rs600_reg_safe_bm[219] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, |
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, |
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF, |
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, |
0x00000000, 0x0000C100, 0x00000000, 0x00000000, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x0003FC01, 0xFFFFFCF8, 0xFF800B19, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
}; |
/drivers/video/drm/radeon/rs690.c |
---|
28,6 → 28,9 |
#include "drmP.h" |
#include "radeon_reg.h" |
#include "radeon.h" |
#include "rs690r.h" |
#include "atom.h" |
#include "atom-bits.h" |
/* rs690,rs740 depends on : */ |
void r100_hdp_reset(struct radeon_device *rdev); |
64,7 → 67,7 |
rs400_gart_disable(rdev); |
/* Setup GPU memory space */ |
rdev->mc.gtt_location = rdev->mc.vram_size; |
rdev->mc.gtt_location = rdev->mc.mc_vram_size; |
rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); |
rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
79,7 → 82,7 |
printk(KERN_WARNING "Failed to wait MC idle while " |
"programming pipes. Bad things might happen.\n"); |
} |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp); |
91,9 → 94,6 |
void rs690_mc_fini(struct radeon_device *rdev) |
{ |
rs400_gart_disable(rdev); |
radeon_gart_table_ram_free(rdev); |
radeon_gart_fini(rdev); |
} |
138,9 → 138,82 |
/* |
* VRAM info. |
*/ |
void rs690_pm_info(struct radeon_device *rdev) |
{ |
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); |
struct _ATOM_INTEGRATED_SYSTEM_INFO *info; |
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2; |
void *ptr; |
uint16_t data_offset; |
uint8_t frev, crev; |
fixed20_12 tmp; |
atom_parse_data_header(rdev->mode_info.atom_context, index, NULL, |
&frev, &crev, &data_offset); |
ptr = rdev->mode_info.atom_context->bios + data_offset; |
info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr; |
info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr; |
/* Get various system informations from bios */ |
switch (crev) { |
case 1: |
tmp.full = rfixed_const(100); |
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock); |
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); |
rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock)); |
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock)); |
rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth); |
break; |
case 2: |
tmp.full = rfixed_const(100); |
rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock); |
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp); |
rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock); |
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); |
rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq); |
rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp); |
rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth)); |
break; |
default: |
tmp.full = rfixed_const(100); |
/* We assume the slower possible clock ie worst case */ |
/* DDR 333Mhz */ |
rdev->pm.igp_sideport_mclk.full = rfixed_const(333); |
/* FIXME: system clock ? */ |
rdev->pm.igp_system_mclk.full = rfixed_const(100); |
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp); |
rdev->pm.igp_ht_link_clk.full = rfixed_const(200); |
rdev->pm.igp_ht_link_width.full = rfixed_const(8); |
DRM_ERROR("No integrated system info for your GPU, using safe default\n"); |
break; |
} |
/* Compute various bandwidth */ |
/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */ |
tmp.full = rfixed_const(4); |
rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp); |
/* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8 |
* = ht_clk * ht_width / 5 |
*/ |
tmp.full = rfixed_const(5); |
rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk, |
rdev->pm.igp_ht_link_width); |
rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp); |
if (tmp.full < rdev->pm.max_bandwidth.full) { |
/* HT link is a limiting factor */ |
rdev->pm.max_bandwidth.full = tmp.full; |
} |
/* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7 |
* = (sideport_clk * 14) / 10 |
*/ |
tmp.full = rfixed_const(14); |
rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp); |
tmp.full = rfixed_const(10); |
rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp); |
} |
void rs690_vram_info(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
fixed20_12 a; |
rs400_gart_adjust_size(rdev); |
/* DDR for all card after R300 & IGP */ |
152,14 → 225,411 |
} else { |
rdev->mc.vram_width = 64; |
} |
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
rdev->mc.mc_vram_size = rdev->mc.real_vram_size; |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
rs690_pm_info(rdev); |
/* FIXME: we should enforce default clock in case GPU is not in |
* default setup |
*/ |
a.full = rfixed_const(100); |
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); |
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); |
a.full = rfixed_const(16); |
/* core_bandwidth = sclk(Mhz) * 16 */ |
rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a); |
} |
void rs690_line_buffer_adjust(struct radeon_device *rdev, |
struct drm_display_mode *mode1, |
struct drm_display_mode *mode2) |
{ |
u32 tmp; |
/* |
* Line Buffer Setup |
* There is a single line buffer shared by both display controllers. |
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between |
* the display controllers. The paritioning can either be done |
* manually or via one of four preset allocations specified in bits 1:0: |
* 0 - line buffer is divided in half and shared between crtc |
* 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 |
* 2 - D1 gets the whole buffer |
* 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 |
* Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual |
* allocation mode. In manual allocation mode, D1 always starts at 0, |
* D1 end/2 is specified in bits 14:4; D2 allocation follows D1. |
*/ |
tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK; |
tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE; |
/* auto */ |
if (mode1 && mode2) { |
if (mode1->hdisplay > mode2->hdisplay) { |
if (mode1->hdisplay > 2560) |
tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; |
else |
tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
} else if (mode2->hdisplay > mode1->hdisplay) { |
if (mode2->hdisplay > 2560) |
tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
else |
tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
} else |
tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; |
} else if (mode1) { |
tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY; |
} else if (mode2) { |
tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; |
} |
WREG32(DC_LB_MEMORY_SPLIT, tmp); |
} |
struct rs690_watermark { |
u32 lb_request_fifo_depth; |
fixed20_12 num_line_pair; |
fixed20_12 estimated_width; |
fixed20_12 worst_case_latency; |
fixed20_12 consumption_rate; |
fixed20_12 active_time; |
fixed20_12 dbpp; |
fixed20_12 priority_mark_max; |
fixed20_12 priority_mark; |
fixed20_12 sclk; |
}; |
void rs690_crtc_bandwidth_compute(struct radeon_device *rdev, |
struct radeon_crtc *crtc, |
struct rs690_watermark *wm) |
{ |
struct drm_display_mode *mode = &crtc->base.mode; |
fixed20_12 a, b, c; |
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; |
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; |
/* FIXME: detect IGP with sideport memory, i don't think there is any |
* such product available |
*/ |
bool sideport = false; |
if (!crtc->base.enabled) { |
/* FIXME: wouldn't it better to set priority mark to maximum */ |
wm->lb_request_fifo_depth = 4; |
return; |
} |
if (crtc->vsc.full > rfixed_const(2)) |
wm->num_line_pair.full = rfixed_const(2); |
else |
wm->num_line_pair.full = rfixed_const(1); |
b.full = rfixed_const(mode->crtc_hdisplay); |
c.full = rfixed_const(256); |
a.full = rfixed_mul(wm->num_line_pair, b); |
request_fifo_depth.full = rfixed_div(a, c); |
if (a.full < rfixed_const(4)) { |
wm->lb_request_fifo_depth = 4; |
} else { |
wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth); |
} |
/* Determine consumption rate |
* pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) |
* vtaps = number of vertical taps, |
* vsc = vertical scaling ratio, defined as source/destination |
* hsc = horizontal scaling ration, defined as source/destination |
*/ |
a.full = rfixed_const(mode->clock); |
b.full = rfixed_const(1000); |
a.full = rfixed_div(a, b); |
pclk.full = rfixed_div(b, a); |
if (crtc->rmx_type != RMX_OFF) { |
b.full = rfixed_const(2); |
if (crtc->vsc.full > b.full) |
b.full = crtc->vsc.full; |
b.full = rfixed_mul(b, crtc->hsc); |
c.full = rfixed_const(2); |
b.full = rfixed_div(b, c); |
consumption_time.full = rfixed_div(pclk, b); |
} else { |
consumption_time.full = pclk.full; |
} |
a.full = rfixed_const(1); |
wm->consumption_rate.full = rfixed_div(a, consumption_time); |
/* Determine line time |
* LineTime = total time for one line of displayhtotal |
* LineTime = total number of horizontal pixels |
* pclk = pixel clock period(ns) |
*/ |
a.full = rfixed_const(crtc->base.mode.crtc_htotal); |
line_time.full = rfixed_mul(a, pclk); |
/* Determine active time |
* ActiveTime = time of active region of display within one line, |
* hactive = total number of horizontal active pixels |
* htotal = total number of horizontal pixels |
*/ |
a.full = rfixed_const(crtc->base.mode.crtc_htotal); |
b.full = rfixed_const(crtc->base.mode.crtc_hdisplay); |
wm->active_time.full = rfixed_mul(line_time, b); |
wm->active_time.full = rfixed_div(wm->active_time, a); |
/* Maximun bandwidth is the minimun bandwidth of all component */ |
rdev->pm.max_bandwidth = rdev->pm.core_bandwidth; |
if (sideport) { |
if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full && |
rdev->pm.sideport_bandwidth.full) |
rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth; |
read_delay_latency.full = rfixed_const(370 * 800 * 1000); |
read_delay_latency.full = rfixed_div(read_delay_latency, |
rdev->pm.igp_sideport_mclk); |
} else { |
if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full && |
rdev->pm.k8_bandwidth.full) |
rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth; |
if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full && |
rdev->pm.ht_bandwidth.full) |
rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth; |
read_delay_latency.full = rfixed_const(5000); |
} |
/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */ |
a.full = rfixed_const(16); |
rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a); |
a.full = rfixed_const(1000); |
rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk); |
/* Determine chunk time |
* ChunkTime = the time it takes the DCP to send one chunk of data |
* to the LB which consists of pipeline delay and inter chunk gap |
* sclk = system clock(ns) |
*/ |
a.full = rfixed_const(256 * 13); |
chunk_time.full = rfixed_mul(rdev->pm.sclk, a); |
a.full = rfixed_const(10); |
chunk_time.full = rfixed_div(chunk_time, a); |
/* Determine the worst case latency |
* NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) |
* WorstCaseLatency = worst case time from urgent to when the MC starts |
* to return data |
* READ_DELAY_IDLE_MAX = constant of 1us |
* ChunkTime = time it takes the DCP to send one chunk of data to the LB |
* which consists of pipeline delay and inter chunk gap |
*/ |
if (rfixed_trunc(wm->num_line_pair) > 1) { |
a.full = rfixed_const(3); |
wm->worst_case_latency.full = rfixed_mul(a, chunk_time); |
wm->worst_case_latency.full += read_delay_latency.full; |
} else { |
a.full = rfixed_const(2); |
wm->worst_case_latency.full = rfixed_mul(a, chunk_time); |
wm->worst_case_latency.full += read_delay_latency.full; |
} |
/* Determine the tolerable latency |
* TolerableLatency = Any given request has only 1 line time |
* for the data to be returned |
* LBRequestFifoDepth = Number of chunk requests the LB can |
* put into the request FIFO for a display |
* LineTime = total time for one line of display |
* ChunkTime = the time it takes the DCP to send one chunk |
* of data to the LB which consists of |
* pipeline delay and inter chunk gap |
*/ |
if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) { |
tolerable_latency.full = line_time.full; |
} else { |
tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2); |
tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; |
tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time); |
tolerable_latency.full = line_time.full - tolerable_latency.full; |
} |
/* We assume worst case 32bits (4 bytes) */ |
wm->dbpp.full = rfixed_const(4 * 8); |
/* Determine the maximum priority mark |
* width = viewport width in pixels |
*/ |
a.full = rfixed_const(16); |
wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); |
wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); |
/* Determine estimated width */ |
estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; |
estimated_width.full = rfixed_div(estimated_width, consumption_time); |
if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { |
wm->priority_mark.full = rfixed_const(10); |
} else { |
a.full = rfixed_const(16); |
wm->priority_mark.full = rfixed_div(estimated_width, a); |
wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; |
} |
} |
void rs690_bandwidth_update(struct radeon_device *rdev) |
{ |
struct drm_display_mode *mode0 = NULL; |
struct drm_display_mode *mode1 = NULL; |
struct rs690_watermark wm0; |
struct rs690_watermark wm1; |
u32 tmp; |
fixed20_12 priority_mark02, priority_mark12, fill_rate; |
fixed20_12 a, b; |
if (rdev->mode_info.crtcs[0]->base.enabled) |
mode0 = &rdev->mode_info.crtcs[0]->base.mode; |
if (rdev->mode_info.crtcs[1]->base.enabled) |
mode1 = &rdev->mode_info.crtcs[1]->base.mode; |
/* |
* Set display0/1 priority up in the memory controller for |
* modes if the user specifies HIGH for displaypriority |
* option. |
*/ |
if (rdev->disp_priority == 2) { |
tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER); |
tmp &= ~MC_DISP1R_INIT_LAT_MASK; |
tmp &= ~MC_DISP0R_INIT_LAT_MASK; |
if (mode1) |
tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT); |
if (mode0) |
tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT); |
WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp); |
} |
rs690_line_buffer_adjust(rdev, mode0, mode1); |
if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) |
WREG32(DCP_CONTROL, 0); |
if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880)) |
WREG32(DCP_CONTROL, 2); |
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); |
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); |
tmp = (wm0.lb_request_fifo_depth - 1); |
tmp |= (wm1.lb_request_fifo_depth - 1) << 16; |
WREG32(LB_MAX_REQ_OUTSTANDING, tmp); |
if (mode0 && mode1) { |
if (rfixed_trunc(wm0.dbpp) > 64) |
a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair); |
else |
a.full = wm0.num_line_pair.full; |
if (rfixed_trunc(wm1.dbpp) > 64) |
b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair); |
else |
b.full = wm1.num_line_pair.full; |
a.full += b.full; |
fill_rate.full = rfixed_div(wm0.sclk, a); |
if (wm0.consumption_rate.full > fill_rate.full) { |
b.full = wm0.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm0.active_time); |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
a.full = a.full + b.full; |
b.full = rfixed_const(16 * 1000); |
priority_mark02.full = rfixed_div(a, b); |
} else { |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark02.full = rfixed_div(a, b); |
} |
if (wm1.consumption_rate.full > fill_rate.full) { |
b.full = wm1.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm1.active_time); |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
a.full = a.full + b.full; |
b.full = rfixed_const(16 * 1000); |
priority_mark12.full = rfixed_div(a, b); |
} else { |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark12.full = rfixed_div(a, b); |
} |
if (wm0.priority_mark.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark.full; |
if (rfixed_trunc(priority_mark02) < 0) |
priority_mark02.full = 0; |
if (wm0.priority_mark_max.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark_max.full; |
if (wm1.priority_mark.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark.full; |
if (rfixed_trunc(priority_mark12) < 0) |
priority_mark12.full = 0; |
if (wm1.priority_mark_max.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark_max.full; |
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); |
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); |
} else if (mode0) { |
if (rfixed_trunc(wm0.dbpp) > 64) |
a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair); |
else |
a.full = wm0.num_line_pair.full; |
fill_rate.full = rfixed_div(wm0.sclk, a); |
if (wm0.consumption_rate.full > fill_rate.full) { |
b.full = wm0.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm0.active_time); |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
a.full = a.full + b.full; |
b.full = rfixed_const(16 * 1000); |
priority_mark02.full = rfixed_div(a, b); |
} else { |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark02.full = rfixed_div(a, b); |
} |
if (wm0.priority_mark.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark.full; |
if (rfixed_trunc(priority_mark02) < 0) |
priority_mark02.full = 0; |
if (wm0.priority_mark_max.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark_max.full; |
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); |
WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); |
} else { |
if (rfixed_trunc(wm1.dbpp) > 64) |
a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair); |
else |
a.full = wm1.num_line_pair.full; |
fill_rate.full = rfixed_div(wm1.sclk, a); |
if (wm1.consumption_rate.full > fill_rate.full) { |
b.full = wm1.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm1.active_time); |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
a.full = a.full + b.full; |
b.full = rfixed_const(16 * 1000); |
priority_mark12.full = rfixed_div(a, b); |
} else { |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark12.full = rfixed_div(a, b); |
} |
if (wm1.priority_mark.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark.full; |
if (rfixed_trunc(priority_mark12) < 0) |
priority_mark12.full = 0; |
if (wm1.priority_mark_max.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark_max.full; |
WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); |
WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); |
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); |
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); |
} |
} |
/* |
* Indirect registers accessor |
*/ |
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg) |
/drivers/video/drm/radeon/rs690r.h |
---|
0,0 → 1,99 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef RS690R_H |
#define RS690R_H |
/* RS690/RS740 registers */ |
#define MC_INDEX 0x0078 |
# define MC_INDEX_MASK 0x1FF |
# define MC_INDEX_WR_EN (1 << 9) |
# define MC_INDEX_WR_ACK 0x7F |
#define MC_DATA 0x007C |
#define HDP_FB_LOCATION 0x0134 |
#define DC_LB_MEMORY_SPLIT 0x6520 |
#define DC_LB_MEMORY_SPLIT_MASK 0x00000003 |
#define DC_LB_MEMORY_SPLIT_SHIFT 0 |
#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 |
#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 |
#define DC_LB_MEMORY_SPLIT_D1_ONLY 2 |
#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 |
#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) |
#define DC_LB_DISP1_END_ADR_SHIFT 4 |
#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0 |
#define D1MODE_PRIORITY_A_CNT 0x6548 |
#define MODE_PRIORITY_MARK_MASK 0x00007FFF |
#define MODE_PRIORITY_OFF (1 << 16) |
#define MODE_PRIORITY_ALWAYS_ON (1 << 20) |
#define MODE_PRIORITY_FORCE_MASK (1 << 24) |
#define D1MODE_PRIORITY_B_CNT 0x654C |
#define LB_MAX_REQ_OUTSTANDING 0x6D58 |
#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F |
#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0 |
#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000 |
#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16 |
#define DCP_CONTROL 0x6C9C |
#define D2MODE_PRIORITY_A_CNT 0x6D48 |
#define D2MODE_PRIORITY_B_CNT 0x6D4C |
/* MC indirect registers */ |
#define MC_STATUS_IDLE (1 << 0) |
#define MC_MISC_CNTL 0x18 |
#define DISABLE_GTW (1 << 1) |
#define GART_INDEX_REG_EN (1 << 12) |
#define BLOCK_GFX_D3_EN (1 << 14) |
#define GART_FEATURE_ID 0x2B |
#define HANG_EN (1 << 11) |
#define TLB_ENABLE (1 << 18) |
#define P2P_ENABLE (1 << 19) |
#define GTW_LAC_EN (1 << 25) |
#define LEVEL2_GART (0 << 30) |
#define LEVEL1_GART (1 << 30) |
#define PDC_EN (1 << 31) |
#define GART_BASE 0x2C |
#define GART_CACHE_CNTRL 0x2E |
# define GART_CACHE_INVALIDATE (1 << 0) |
#define MC_STATUS 0x90 |
#define MCCFG_FB_LOCATION 0x100 |
#define MC_FB_START_MASK 0x0000FFFF |
#define MC_FB_START_SHIFT 0 |
#define MC_FB_TOP_MASK 0xFFFF0000 |
#define MC_FB_TOP_SHIFT 16 |
#define MCCFG_AGP_LOCATION 0x101 |
#define MC_AGP_START_MASK 0x0000FFFF |
#define MC_AGP_START_SHIFT 0 |
#define MC_AGP_TOP_MASK 0xFFFF0000 |
#define MC_AGP_TOP_SHIFT 16 |
#define MCCFG_AGP_BASE 0x102 |
#define MCCFG_AGP_BASE_2 0x103 |
#define MC_INIT_MISC_LAT_TIMER 0x104 |
#define MC_DISP0R_INIT_LAT_SHIFT 8 |
#define MC_DISP0R_INIT_LAT_MASK 0x00000F00 |
#define MC_DISP1R_INIT_LAT_SHIFT 12 |
#define MC_DISP1R_INIT_LAT_MASK 0x0000F000 |
#endif |
/drivers/video/drm/radeon/rv515.c |
---|
25,11 → 25,12 |
* Alex Deucher |
* Jerome Glisse |
*/ |
//#include <linux/seq_file.h> |
#include <linux/seq_file.h> |
#include "drmP.h" |
#include "radeon_reg.h" |
#include "rv515d.h" |
#include "radeon.h" |
#include "rv515_reg_safe.h" |
/* rv515 depends on : */ |
void r100_hdp_reset(struct radeon_device *rdev); |
int r100_cp_reset(struct radeon_device *rdev); |
36,8 → 37,6 |
int r100_rb2d_reset(struct radeon_device *rdev); |
int r100_gui_wait_for_idle(struct radeon_device *rdev); |
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); |
int rv370_pcie_gart_enable(struct radeon_device *rdev); |
void rv370_pcie_gart_disable(struct radeon_device *rdev); |
void r420_pipes_init(struct radeon_device *rdev); |
void rs600_mc_disable_clients(struct radeon_device *rdev); |
void rs600_disable_vga(struct radeon_device *rdev); |
52,6 → 51,7 |
void rv515_gpu_init(struct radeon_device *rdev); |
int rv515_mc_wait_for_idle(struct radeon_device *rdev); |
/* |
* MC |
*/ |
76,16 → 76,16 |
/* Setup GPU memory space */ |
rdev->mc.vram_location = 0xFFFFFFFFUL; |
rdev->mc.gtt_location = 0xFFFFFFFFUL; |
if (rdev->flags & RADEON_IS_AGP) { |
r = radeon_agp_init(rdev); |
if (r) { |
printk(KERN_WARNING "[drm] Disabling AGP\n"); |
rdev->flags &= ~RADEON_IS_AGP; |
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
} else { |
rdev->mc.gtt_location = rdev->mc.agp_base; |
} |
} |
// if (rdev->flags & RADEON_IS_AGP) { |
// r = radeon_agp_init(rdev); |
// if (r) { |
// printk(KERN_WARNING "[drm] Disabling AGP\n"); |
// rdev->flags &= ~RADEON_IS_AGP; |
// rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
// } else { |
// rdev->mc.gtt_location = rdev->mc.agp_base; |
// } |
// } |
r = radeon_mc_setup(rdev); |
if (r) { |
return r; |
98,26 → 98,26 |
"programming pipes. Bad things might happen.\n"); |
} |
/* Write VRAM size in case we are limiting it */ |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); |
tmp = REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); |
tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32(0x134, tmp); |
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; |
tmp = REG_SET(RV515_MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32_MC(RV515_MC_FB_LOCATION, tmp); |
WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); |
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1; |
tmp = REG_SET(MC_FB_TOP, tmp >> 16); |
tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16); |
WREG32_MC(MC_FB_LOCATION, tmp); |
WREG32(HDP_FB_LOCATION, rdev->mc.vram_location >> 16); |
WREG32(0x310, rdev->mc.vram_location); |
if (rdev->flags & RADEON_IS_AGP) { |
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; |
tmp = REG_SET(RV515_MC_AGP_TOP, tmp >> 16); |
tmp |= REG_SET(RV515_MC_AGP_START, rdev->mc.gtt_location >> 16); |
WREG32_MC(RV515_MC_AGP_LOCATION, tmp); |
WREG32_MC(RV515_MC_AGP_BASE, rdev->mc.agp_base); |
WREG32_MC(RV515_MC_AGP_BASE_2, 0); |
tmp = REG_SET(MC_AGP_TOP, tmp >> 16); |
tmp |= REG_SET(MC_AGP_START, rdev->mc.gtt_location >> 16); |
WREG32_MC(MC_AGP_LOCATION, tmp); |
WREG32_MC(MC_AGP_BASE, rdev->mc.agp_base); |
WREG32_MC(MC_AGP_BASE_2, 0); |
} else { |
WREG32_MC(RV515_MC_AGP_LOCATION, 0x0FFFFFFF); |
WREG32_MC(RV515_MC_AGP_BASE, 0); |
WREG32_MC(RV515_MC_AGP_BASE_2, 0); |
WREG32_MC(MC_AGP_LOCATION, 0x0FFFFFFF); |
WREG32_MC(MC_AGP_BASE, 0); |
WREG32_MC(MC_AGP_BASE_2, 0); |
} |
return 0; |
} |
124,9 → 124,6 |
void rv515_mc_fini(struct radeon_device *rdev) |
{ |
rv370_pcie_gart_disable(rdev); |
radeon_gart_table_vram_free(rdev); |
radeon_gart_fini(rdev); |
} |
135,101 → 132,74 |
*/ |
void rv515_ring_start(struct radeon_device *rdev) |
{ |
unsigned gb_tile_config; |
int r; |
dbgprintf("%s\n",__FUNCTION__); |
/* Sub pixel 1/12 so we can have 4K rendering according to doc */ |
gb_tile_config = R300_ENABLE_TILING | R300_TILE_SIZE_16; |
switch (rdev->num_gb_pipes) { |
case 2: |
gb_tile_config |= R300_PIPE_COUNT_R300; |
break; |
case 3: |
gb_tile_config |= R300_PIPE_COUNT_R420_3P; |
break; |
case 4: |
gb_tile_config |= R300_PIPE_COUNT_R420; |
break; |
case 1: |
default: |
gb_tile_config |= R300_PIPE_COUNT_RV350; |
break; |
} |
ENTER(); |
r = radeon_ring_lock(rdev, 64); |
if (r) { |
return; |
} |
radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); |
radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0)); |
radeon_ring_write(rdev, |
RADEON_ISYNC_ANY2D_IDLE3D | |
RADEON_ISYNC_ANY3D_IDLE2D | |
RADEON_ISYNC_WAIT_IDLEGUI | |
RADEON_ISYNC_CPSCRATCH_IDLEGUI); |
radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0)); |
radeon_ring_write(rdev, gb_tile_config); |
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); |
radeon_ring_write(rdev, |
RADEON_WAIT_2D_IDLECLEAN | |
RADEON_WAIT_3D_IDLECLEAN); |
ISYNC_ANY2D_IDLE3D | |
ISYNC_ANY3D_IDLE2D | |
ISYNC_WAIT_IDLEGUI | |
ISYNC_CPSCRATCH_IDLEGUI); |
radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); |
radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); |
radeon_ring_write(rdev, PACKET0(0x170C, 0)); |
radeon_ring_write(rdev, 1 << 31); |
radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0)); |
radeon_ring_write(rdev, PACKET0(GB_SELECT, 0)); |
radeon_ring_write(rdev, 0); |
radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0)); |
radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0)); |
radeon_ring_write(rdev, 0); |
radeon_ring_write(rdev, PACKET0(0x42C8, 0)); |
radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1); |
radeon_ring_write(rdev, PACKET0(R500_VAP_INDEX_OFFSET, 0)); |
radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0)); |
radeon_ring_write(rdev, 0); |
radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); |
radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); |
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); |
radeon_ring_write(rdev, |
RADEON_WAIT_2D_IDLECLEAN | |
RADEON_WAIT_3D_IDLECLEAN); |
radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0)); |
radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE); |
radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE); |
radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); |
radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); |
radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0)); |
radeon_ring_write(rdev, 0); |
radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); |
radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); |
radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0)); |
radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE); |
radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0)); |
radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE); |
radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0)); |
radeon_ring_write(rdev, |
((6 << R300_MS_X0_SHIFT) | |
(6 << R300_MS_Y0_SHIFT) | |
(6 << R300_MS_X1_SHIFT) | |
(6 << R300_MS_Y1_SHIFT) | |
(6 << R300_MS_X2_SHIFT) | |
(6 << R300_MS_Y2_SHIFT) | |
(6 << R300_MSBD0_Y_SHIFT) | |
(6 << R300_MSBD0_X_SHIFT))); |
radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0)); |
((6 << MS_X0_SHIFT) | |
(6 << MS_Y0_SHIFT) | |
(6 << MS_X1_SHIFT) | |
(6 << MS_Y1_SHIFT) | |
(6 << MS_X2_SHIFT) | |
(6 << MS_Y2_SHIFT) | |
(6 << MSBD0_Y_SHIFT) | |
(6 << MSBD0_X_SHIFT))); |
radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0)); |
radeon_ring_write(rdev, |
((6 << R300_MS_X3_SHIFT) | |
(6 << R300_MS_Y3_SHIFT) | |
(6 << R300_MS_X4_SHIFT) | |
(6 << R300_MS_Y4_SHIFT) | |
(6 << R300_MS_X5_SHIFT) | |
(6 << R300_MS_Y5_SHIFT) | |
(6 << R300_MSBD1_SHIFT))); |
radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0)); |
radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); |
radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0)); |
radeon_ring_write(rdev, |
R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); |
radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0)); |
radeon_ring_write(rdev, |
R300_GEOMETRY_ROUND_NEAREST | |
R300_COLOR_ROUND_NEAREST); |
((6 << MS_X3_SHIFT) | |
(6 << MS_Y3_SHIFT) | |
(6 << MS_X4_SHIFT) | |
(6 << MS_Y4_SHIFT) | |
(6 << MS_X5_SHIFT) | |
(6 << MS_Y5_SHIFT) | |
(6 << MSBD1_SHIFT))); |
radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0)); |
radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL); |
radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0)); |
radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE); |
radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0)); |
radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST); |
radeon_ring_write(rdev, PACKET0(0x20C8, 0)); |
radeon_ring_write(rdev, 0); |
radeon_ring_unlock_commit(rdev); |
dbgprintf("done %s\n",__FUNCTION__); |
LEAVE(); |
} |
245,8 → 215,8 |
for (i = 0; i < rdev->usec_timeout; i++) { |
/* read MC_STATUS */ |
tmp = RREG32_MC(RV515_MC_STATUS); |
if (tmp & RV515_MC_STATUS_IDLE) { |
tmp = RREG32_MC(MC_STATUS); |
if (tmp & MC_STATUS_IDLE) { |
return 0; |
} |
DRM_UDELAY(1); |
285,7 → 255,6 |
} |
} |
int rv515_ga_reset(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
292,25 → 261,25 |
bool reinit_cp; |
int i; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
reinit_cp = rdev->cp.ready; |
rdev->cp.ready = false; |
for (i = 0; i < rdev->usec_timeout; i++) { |
WREG32(RADEON_CP_CSQ_MODE, 0); |
WREG32(RADEON_CP_CSQ_CNTL, 0); |
WREG32(RADEON_RBBM_SOFT_RESET, 0x32005); |
(void)RREG32(RADEON_RBBM_SOFT_RESET); |
WREG32(CP_CSQ_MODE, 0); |
WREG32(CP_CSQ_CNTL, 0); |
WREG32(RBBM_SOFT_RESET, 0x32005); |
(void)RREG32(RBBM_SOFT_RESET); |
udelay(200); |
WREG32(RADEON_RBBM_SOFT_RESET, 0); |
WREG32(RBBM_SOFT_RESET, 0); |
/* Wait to prevent race in RBBM_STATUS */ |
mdelay(1); |
tmp = RREG32(RADEON_RBBM_STATUS); |
tmp = RREG32(RBBM_STATUS); |
if (tmp & ((1 << 20) | (1 << 26))) { |
DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp); |
/* GA still busy soft reset it */ |
WREG32(0x429C, 0x200); |
WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0); |
WREG32(VAP_PVS_STATE_FLUSH_REG, 0); |
WREG32(0x43E0, 0); |
WREG32(0x43E4, 0); |
WREG32(0x24AC, 0); |
317,13 → 286,13 |
} |
/* Wait to prevent race in RBBM_STATUS */ |
mdelay(1); |
tmp = RREG32(RADEON_RBBM_STATUS); |
tmp = RREG32(RBBM_STATUS); |
if (!(tmp & ((1 << 20) | (1 << 26)))) { |
break; |
} |
} |
for (i = 0; i < rdev->usec_timeout; i++) { |
tmp = RREG32(RADEON_RBBM_STATUS); |
tmp = RREG32(RBBM_STATUS); |
if (!(tmp & ((1 << 20) | (1 << 26)))) { |
DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n", |
tmp); |
337,7 → 306,7 |
} |
DRM_UDELAY(1); |
} |
tmp = RREG32(RADEON_RBBM_STATUS); |
tmp = RREG32(RBBM_STATUS); |
DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp); |
return -1; |
} |
346,10 → 315,10 |
{ |
uint32_t status; |
dbgprintf("%s\n",__FUNCTION__); |
ENTER(); |
/* reset order likely matter */ |
status = RREG32(RADEON_RBBM_STATUS); |
status = RREG32(RBBM_STATUS); |
/* reset HDP */ |
r100_hdp_reset(rdev); |
/* reset rb2d */ |
361,12 → 330,12 |
rv515_ga_reset(rdev); |
} |
/* reset CP */ |
status = RREG32(RADEON_RBBM_STATUS); |
status = RREG32(RBBM_STATUS); |
if (status & (1 << 16)) { |
r100_cp_reset(rdev); |
} |
/* Check if GPU is idle */ |
status = RREG32(RADEON_RBBM_STATUS); |
status = RREG32(RBBM_STATUS); |
if (status & (1 << 31)) { |
DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); |
return -1; |
385,8 → 354,7 |
rdev->mc.vram_width = 128; |
rdev->mc.vram_is_ddr = true; |
tmp = RREG32_MC(RV515_MC_CNTL); |
tmp &= RV515_MEM_NUM_CHANNELS_MASK; |
tmp = RREG32_MC(RV515_MC_CNTL) & MEM_NUM_CHANNELS_MASK; |
switch (tmp) { |
case 0: |
rdev->mc.vram_width = 64; |
402,11 → 370,17 |
void rv515_vram_info(struct radeon_device *rdev) |
{ |
fixed20_12 a; |
rv515_vram_get_type(rdev); |
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); |
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); |
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); |
r100_vram_init_sizes(rdev); |
/* FIXME: we should enforce default clock in case GPU is not in |
* default setup |
*/ |
a.full = rfixed_const(100); |
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); |
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); |
} |
417,38 → 391,19 |
{ |
uint32_t r; |
WREG32(R520_MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); |
r = RREG32(R520_MC_IND_DATA); |
WREG32(R520_MC_IND_INDEX, 0); |
WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); |
r = RREG32(MC_IND_DATA); |
WREG32(MC_IND_INDEX, 0); |
return r; |
} |
void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
{ |
WREG32(R520_MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); |
WREG32(R520_MC_IND_DATA, (v)); |
WREG32(R520_MC_IND_INDEX, 0); |
WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); |
WREG32(MC_IND_DATA, (v)); |
WREG32(MC_IND_INDEX, 0); |
} |
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg) |
{ |
uint32_t r; |
WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff)); |
(void)RREG32(RADEON_PCIE_INDEX); |
r = RREG32(RADEON_PCIE_DATA); |
return r; |
} |
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
{ |
WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff)); |
(void)RREG32(RADEON_PCIE_INDEX); |
WREG32(RADEON_PCIE_DATA, (v)); |
(void)RREG32(RADEON_PCIE_DATA); |
} |
/* |
* Debugfs info |
*/ |
460,13 → 415,13 |
struct radeon_device *rdev = dev->dev_private; |
uint32_t tmp; |
tmp = RREG32(R400_GB_PIPE_SELECT); |
tmp = RREG32(GB_PIPE_SELECT); |
seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); |
tmp = RREG32(R500_SU_REG_DEST); |
tmp = RREG32(SU_REG_DEST); |
seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp); |
tmp = RREG32(R300_GB_TILE_CONFIG); |
tmp = RREG32(GB_TILE_CONFIG); |
seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); |
tmp = RREG32(R300_DST_PIPE_CONFIG); |
tmp = RREG32(DST_PIPE_CONFIG); |
seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); |
return 0; |
} |
513,60 → 468,564 |
#endif |
} |
/* |
* Asic initialization |
*/ |
static const unsigned r500_reg_safe_bm[159] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, |
0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF, |
0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF, |
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, |
0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x0003FC01, 0x3FFFFCF8, 0xFE800B19, |
int rv515_init(struct radeon_device *rdev) |
{ |
ENTER(); |
rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm; |
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rv515_reg_safe_bm); |
return 0; |
} |
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *crtc) |
{ |
int index_reg = 0x6578 + crtc->crtc_offset; |
int data_reg = 0x657c + crtc->crtc_offset; |
WREG32(0x659C + crtc->crtc_offset, 0x0); |
WREG32(0x6594 + crtc->crtc_offset, 0x705); |
WREG32(0x65A4 + crtc->crtc_offset, 0x10001); |
WREG32(0x65D8 + crtc->crtc_offset, 0x0); |
WREG32(0x65B0 + crtc->crtc_offset, 0x0); |
WREG32(0x65C0 + crtc->crtc_offset, 0x0); |
WREG32(0x65D4 + crtc->crtc_offset, 0x0); |
WREG32(index_reg, 0x0); |
WREG32(data_reg, 0x841880A8); |
WREG32(index_reg, 0x1); |
WREG32(data_reg, 0x84208680); |
WREG32(index_reg, 0x2); |
WREG32(data_reg, 0xBFF880B0); |
WREG32(index_reg, 0x100); |
WREG32(data_reg, 0x83D88088); |
WREG32(index_reg, 0x101); |
WREG32(data_reg, 0x84608680); |
WREG32(index_reg, 0x102); |
WREG32(data_reg, 0xBFF080D0); |
WREG32(index_reg, 0x200); |
WREG32(data_reg, 0x83988068); |
WREG32(index_reg, 0x201); |
WREG32(data_reg, 0x84A08680); |
WREG32(index_reg, 0x202); |
WREG32(data_reg, 0xBFF080F8); |
WREG32(index_reg, 0x300); |
WREG32(data_reg, 0x83588058); |
WREG32(index_reg, 0x301); |
WREG32(data_reg, 0x84E08660); |
WREG32(index_reg, 0x302); |
WREG32(data_reg, 0xBFF88120); |
WREG32(index_reg, 0x400); |
WREG32(data_reg, 0x83188040); |
WREG32(index_reg, 0x401); |
WREG32(data_reg, 0x85008660); |
WREG32(index_reg, 0x402); |
WREG32(data_reg, 0xBFF88150); |
WREG32(index_reg, 0x500); |
WREG32(data_reg, 0x82D88030); |
WREG32(index_reg, 0x501); |
WREG32(data_reg, 0x85408640); |
WREG32(index_reg, 0x502); |
WREG32(data_reg, 0xBFF88180); |
WREG32(index_reg, 0x600); |
WREG32(data_reg, 0x82A08018); |
WREG32(index_reg, 0x601); |
WREG32(data_reg, 0x85808620); |
WREG32(index_reg, 0x602); |
WREG32(data_reg, 0xBFF081B8); |
WREG32(index_reg, 0x700); |
WREG32(data_reg, 0x82608010); |
WREG32(index_reg, 0x701); |
WREG32(data_reg, 0x85A08600); |
WREG32(index_reg, 0x702); |
WREG32(data_reg, 0x800081F0); |
WREG32(index_reg, 0x800); |
WREG32(data_reg, 0x8228BFF8); |
WREG32(index_reg, 0x801); |
WREG32(data_reg, 0x85E085E0); |
WREG32(index_reg, 0x802); |
WREG32(data_reg, 0xBFF88228); |
WREG32(index_reg, 0x10000); |
WREG32(data_reg, 0x82A8BF00); |
WREG32(index_reg, 0x10001); |
WREG32(data_reg, 0x82A08CC0); |
WREG32(index_reg, 0x10002); |
WREG32(data_reg, 0x8008BEF8); |
WREG32(index_reg, 0x10100); |
WREG32(data_reg, 0x81F0BF28); |
WREG32(index_reg, 0x10101); |
WREG32(data_reg, 0x83608CA0); |
WREG32(index_reg, 0x10102); |
WREG32(data_reg, 0x8018BED0); |
WREG32(index_reg, 0x10200); |
WREG32(data_reg, 0x8148BF38); |
WREG32(index_reg, 0x10201); |
WREG32(data_reg, 0x84408C80); |
WREG32(index_reg, 0x10202); |
WREG32(data_reg, 0x8008BEB8); |
WREG32(index_reg, 0x10300); |
WREG32(data_reg, 0x80B0BF78); |
WREG32(index_reg, 0x10301); |
WREG32(data_reg, 0x85008C20); |
WREG32(index_reg, 0x10302); |
WREG32(data_reg, 0x8020BEA0); |
WREG32(index_reg, 0x10400); |
WREG32(data_reg, 0x8028BF90); |
WREG32(index_reg, 0x10401); |
WREG32(data_reg, 0x85E08BC0); |
WREG32(index_reg, 0x10402); |
WREG32(data_reg, 0x8018BE90); |
WREG32(index_reg, 0x10500); |
WREG32(data_reg, 0xBFB8BFB0); |
WREG32(index_reg, 0x10501); |
WREG32(data_reg, 0x86C08B40); |
WREG32(index_reg, 0x10502); |
WREG32(data_reg, 0x8010BE90); |
WREG32(index_reg, 0x10600); |
WREG32(data_reg, 0xBF58BFC8); |
WREG32(index_reg, 0x10601); |
WREG32(data_reg, 0x87A08AA0); |
WREG32(index_reg, 0x10602); |
WREG32(data_reg, 0x8010BE98); |
WREG32(index_reg, 0x10700); |
WREG32(data_reg, 0xBF10BFF0); |
WREG32(index_reg, 0x10701); |
WREG32(data_reg, 0x886089E0); |
WREG32(index_reg, 0x10702); |
WREG32(data_reg, 0x8018BEB0); |
WREG32(index_reg, 0x10800); |
WREG32(data_reg, 0xBED8BFE8); |
WREG32(index_reg, 0x10801); |
WREG32(data_reg, 0x89408940); |
WREG32(index_reg, 0x10802); |
WREG32(data_reg, 0xBFE8BED8); |
WREG32(index_reg, 0x20000); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x20001); |
WREG32(data_reg, 0x90008000); |
WREG32(index_reg, 0x20002); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x20003); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x20100); |
WREG32(data_reg, 0x80108000); |
WREG32(index_reg, 0x20101); |
WREG32(data_reg, 0x8FE0BF70); |
WREG32(index_reg, 0x20102); |
WREG32(data_reg, 0xBFE880C0); |
WREG32(index_reg, 0x20103); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x20200); |
WREG32(data_reg, 0x8018BFF8); |
WREG32(index_reg, 0x20201); |
WREG32(data_reg, 0x8F80BF08); |
WREG32(index_reg, 0x20202); |
WREG32(data_reg, 0xBFD081A0); |
WREG32(index_reg, 0x20203); |
WREG32(data_reg, 0xBFF88000); |
WREG32(index_reg, 0x20300); |
WREG32(data_reg, 0x80188000); |
WREG32(index_reg, 0x20301); |
WREG32(data_reg, 0x8EE0BEC0); |
WREG32(index_reg, 0x20302); |
WREG32(data_reg, 0xBFB082A0); |
WREG32(index_reg, 0x20303); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x20400); |
WREG32(data_reg, 0x80188000); |
WREG32(index_reg, 0x20401); |
WREG32(data_reg, 0x8E00BEA0); |
WREG32(index_reg, 0x20402); |
WREG32(data_reg, 0xBF8883C0); |
WREG32(index_reg, 0x20403); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x20500); |
WREG32(data_reg, 0x80188000); |
WREG32(index_reg, 0x20501); |
WREG32(data_reg, 0x8D00BE90); |
WREG32(index_reg, 0x20502); |
WREG32(data_reg, 0xBF588500); |
WREG32(index_reg, 0x20503); |
WREG32(data_reg, 0x80008008); |
WREG32(index_reg, 0x20600); |
WREG32(data_reg, 0x80188000); |
WREG32(index_reg, 0x20601); |
WREG32(data_reg, 0x8BC0BE98); |
WREG32(index_reg, 0x20602); |
WREG32(data_reg, 0xBF308660); |
WREG32(index_reg, 0x20603); |
WREG32(data_reg, 0x80008008); |
WREG32(index_reg, 0x20700); |
WREG32(data_reg, 0x80108000); |
WREG32(index_reg, 0x20701); |
WREG32(data_reg, 0x8A80BEB0); |
WREG32(index_reg, 0x20702); |
WREG32(data_reg, 0xBF0087C0); |
WREG32(index_reg, 0x20703); |
WREG32(data_reg, 0x80008008); |
WREG32(index_reg, 0x20800); |
WREG32(data_reg, 0x80108000); |
WREG32(index_reg, 0x20801); |
WREG32(data_reg, 0x8920BED0); |
WREG32(index_reg, 0x20802); |
WREG32(data_reg, 0xBED08920); |
WREG32(index_reg, 0x20803); |
WREG32(data_reg, 0x80008010); |
WREG32(index_reg, 0x30000); |
WREG32(data_reg, 0x90008000); |
WREG32(index_reg, 0x30001); |
WREG32(data_reg, 0x80008000); |
WREG32(index_reg, 0x30100); |
WREG32(data_reg, 0x8FE0BF90); |
WREG32(index_reg, 0x30101); |
WREG32(data_reg, 0xBFF880A0); |
WREG32(index_reg, 0x30200); |
WREG32(data_reg, 0x8F60BF40); |
WREG32(index_reg, 0x30201); |
WREG32(data_reg, 0xBFE88180); |
WREG32(index_reg, 0x30300); |
WREG32(data_reg, 0x8EC0BF00); |
WREG32(index_reg, 0x30301); |
WREG32(data_reg, 0xBFC88280); |
WREG32(index_reg, 0x30400); |
WREG32(data_reg, 0x8DE0BEE0); |
WREG32(index_reg, 0x30401); |
WREG32(data_reg, 0xBFA083A0); |
WREG32(index_reg, 0x30500); |
WREG32(data_reg, 0x8CE0BED0); |
WREG32(index_reg, 0x30501); |
WREG32(data_reg, 0xBF7884E0); |
WREG32(index_reg, 0x30600); |
WREG32(data_reg, 0x8BA0BED8); |
WREG32(index_reg, 0x30601); |
WREG32(data_reg, 0xBF508640); |
WREG32(index_reg, 0x30700); |
WREG32(data_reg, 0x8A60BEE8); |
WREG32(index_reg, 0x30701); |
WREG32(data_reg, 0xBF2087A0); |
WREG32(index_reg, 0x30800); |
WREG32(data_reg, 0x8900BF00); |
WREG32(index_reg, 0x30801); |
WREG32(data_reg, 0xBF008900); |
} |
struct rv515_watermark { |
u32 lb_request_fifo_depth; |
fixed20_12 num_line_pair; |
fixed20_12 estimated_width; |
fixed20_12 worst_case_latency; |
fixed20_12 consumption_rate; |
fixed20_12 active_time; |
fixed20_12 dbpp; |
fixed20_12 priority_mark_max; |
fixed20_12 priority_mark; |
fixed20_12 sclk; |
}; |
void rv515_crtc_bandwidth_compute(struct radeon_device *rdev, |
struct radeon_crtc *crtc, |
struct rv515_watermark *wm) |
{ |
struct drm_display_mode *mode = &crtc->base.mode; |
fixed20_12 a, b, c; |
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width; |
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency; |
if (!crtc->base.enabled) { |
/* FIXME: wouldn't it better to set priority mark to maximum */ |
wm->lb_request_fifo_depth = 4; |
return; |
} |
int rv515_init(struct radeon_device *rdev) |
if (crtc->vsc.full > rfixed_const(2)) |
wm->num_line_pair.full = rfixed_const(2); |
else |
wm->num_line_pair.full = rfixed_const(1); |
b.full = rfixed_const(mode->crtc_hdisplay); |
c.full = rfixed_const(256); |
a.full = rfixed_mul(wm->num_line_pair, b); |
request_fifo_depth.full = rfixed_div(a, c); |
if (a.full < rfixed_const(4)) { |
wm->lb_request_fifo_depth = 4; |
} else { |
wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth); |
} |
/* Determine consumption rate |
* pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000) |
* vtaps = number of vertical taps, |
* vsc = vertical scaling ratio, defined as source/destination |
* hsc = horizontal scaling ration, defined as source/destination |
*/ |
a.full = rfixed_const(mode->clock); |
b.full = rfixed_const(1000); |
a.full = rfixed_div(a, b); |
pclk.full = rfixed_div(b, a); |
if (crtc->rmx_type != RMX_OFF) { |
b.full = rfixed_const(2); |
if (crtc->vsc.full > b.full) |
b.full = crtc->vsc.full; |
b.full = rfixed_mul(b, crtc->hsc); |
c.full = rfixed_const(2); |
b.full = rfixed_div(b, c); |
consumption_time.full = rfixed_div(pclk, b); |
} else { |
consumption_time.full = pclk.full; |
} |
a.full = rfixed_const(1); |
wm->consumption_rate.full = rfixed_div(a, consumption_time); |
/* Determine line time |
* LineTime = total time for one line of displayhtotal |
* LineTime = total number of horizontal pixels |
* pclk = pixel clock period(ns) |
*/ |
a.full = rfixed_const(crtc->base.mode.crtc_htotal); |
line_time.full = rfixed_mul(a, pclk); |
/* Determine active time |
* ActiveTime = time of active region of display within one line, |
* hactive = total number of horizontal active pixels |
* htotal = total number of horizontal pixels |
*/ |
a.full = rfixed_const(crtc->base.mode.crtc_htotal); |
b.full = rfixed_const(crtc->base.mode.crtc_hdisplay); |
wm->active_time.full = rfixed_mul(line_time, b); |
wm->active_time.full = rfixed_div(wm->active_time, a); |
/* Determine chunk time |
* ChunkTime = the time it takes the DCP to send one chunk of data |
* to the LB which consists of pipeline delay and inter chunk gap |
* sclk = system clock(Mhz) |
*/ |
a.full = rfixed_const(600 * 1000); |
chunk_time.full = rfixed_div(a, rdev->pm.sclk); |
read_delay_latency.full = rfixed_const(1000); |
/* Determine the worst case latency |
* NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines) |
* WorstCaseLatency = worst case time from urgent to when the MC starts |
* to return data |
* READ_DELAY_IDLE_MAX = constant of 1us |
* ChunkTime = time it takes the DCP to send one chunk of data to the LB |
* which consists of pipeline delay and inter chunk gap |
*/ |
if (rfixed_trunc(wm->num_line_pair) > 1) { |
a.full = rfixed_const(3); |
wm->worst_case_latency.full = rfixed_mul(a, chunk_time); |
wm->worst_case_latency.full += read_delay_latency.full; |
} else { |
wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full; |
} |
/* Determine the tolerable latency |
* TolerableLatency = Any given request has only 1 line time |
* for the data to be returned |
* LBRequestFifoDepth = Number of chunk requests the LB can |
* put into the request FIFO for a display |
* LineTime = total time for one line of display |
* ChunkTime = the time it takes the DCP to send one chunk |
* of data to the LB which consists of |
* pipeline delay and inter chunk gap |
*/ |
if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) { |
tolerable_latency.full = line_time.full; |
} else { |
tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2); |
tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full; |
tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time); |
tolerable_latency.full = line_time.full - tolerable_latency.full; |
} |
/* We assume worst case 32bits (4 bytes) */ |
wm->dbpp.full = rfixed_const(2 * 16); |
/* Determine the maximum priority mark |
* width = viewport width in pixels |
*/ |
a.full = rfixed_const(16); |
wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay); |
wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a); |
/* Determine estimated width */ |
estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full; |
estimated_width.full = rfixed_div(estimated_width, consumption_time); |
if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) { |
wm->priority_mark.full = rfixed_const(10); |
} else { |
a.full = rfixed_const(16); |
wm->priority_mark.full = rfixed_div(estimated_width, a); |
wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full; |
} |
} |
void rv515_bandwidth_avivo_update(struct radeon_device *rdev) |
{ |
dbgprintf("%s\n",__FUNCTION__); |
struct drm_display_mode *mode0 = NULL; |
struct drm_display_mode *mode1 = NULL; |
struct rv515_watermark wm0; |
struct rv515_watermark wm1; |
u32 tmp; |
fixed20_12 priority_mark02, priority_mark12, fill_rate; |
fixed20_12 a, b; |
rdev->config.r300.reg_safe_bm = r500_reg_safe_bm; |
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm); |
return 0; |
if (rdev->mode_info.crtcs[0]->base.enabled) |
mode0 = &rdev->mode_info.crtcs[0]->base.mode; |
if (rdev->mode_info.crtcs[1]->base.enabled) |
mode1 = &rdev->mode_info.crtcs[1]->base.mode; |
rs690_line_buffer_adjust(rdev, mode0, mode1); |
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0); |
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1); |
tmp = wm0.lb_request_fifo_depth; |
tmp |= wm1.lb_request_fifo_depth << 16; |
WREG32(LB_MAX_REQ_OUTSTANDING, tmp); |
if (mode0 && mode1) { |
if (rfixed_trunc(wm0.dbpp) > 64) |
a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair); |
else |
a.full = wm0.num_line_pair.full; |
if (rfixed_trunc(wm1.dbpp) > 64) |
b.full = rfixed_div(wm1.dbpp, wm1.num_line_pair); |
else |
b.full = wm1.num_line_pair.full; |
a.full += b.full; |
fill_rate.full = rfixed_div(wm0.sclk, a); |
if (wm0.consumption_rate.full > fill_rate.full) { |
b.full = wm0.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm0.active_time); |
a.full = rfixed_const(16); |
b.full = rfixed_div(b, a); |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
priority_mark02.full = a.full + b.full; |
} else { |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark02.full = rfixed_div(a, b); |
} |
if (wm1.consumption_rate.full > fill_rate.full) { |
b.full = wm1.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm1.active_time); |
a.full = rfixed_const(16); |
b.full = rfixed_div(b, a); |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
priority_mark12.full = a.full + b.full; |
} else { |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark12.full = rfixed_div(a, b); |
} |
if (wm0.priority_mark.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark.full; |
if (rfixed_trunc(priority_mark02) < 0) |
priority_mark02.full = 0; |
if (wm0.priority_mark_max.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark_max.full; |
if (wm1.priority_mark.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark.full; |
if (rfixed_trunc(priority_mark12) < 0) |
priority_mark12.full = 0; |
if (wm1.priority_mark_max.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark_max.full; |
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); |
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); |
} else if (mode0) { |
if (rfixed_trunc(wm0.dbpp) > 64) |
a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair); |
else |
a.full = wm0.num_line_pair.full; |
fill_rate.full = rfixed_div(wm0.sclk, a); |
if (wm0.consumption_rate.full > fill_rate.full) { |
b.full = wm0.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm0.active_time); |
a.full = rfixed_const(16); |
b.full = rfixed_div(b, a); |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
priority_mark02.full = a.full + b.full; |
} else { |
a.full = rfixed_mul(wm0.worst_case_latency, |
wm0.consumption_rate); |
b.full = rfixed_const(16); |
priority_mark02.full = rfixed_div(a, b); |
} |
if (wm0.priority_mark.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark.full; |
if (rfixed_trunc(priority_mark02) < 0) |
priority_mark02.full = 0; |
if (wm0.priority_mark_max.full > priority_mark02.full) |
priority_mark02.full = wm0.priority_mark_max.full; |
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02)); |
WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); |
WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); |
} else { |
if (rfixed_trunc(wm1.dbpp) > 64) |
a.full = rfixed_div(wm1.dbpp, wm1.num_line_pair); |
else |
a.full = wm1.num_line_pair.full; |
fill_rate.full = rfixed_div(wm1.sclk, a); |
if (wm1.consumption_rate.full > fill_rate.full) { |
b.full = wm1.consumption_rate.full - fill_rate.full; |
b.full = rfixed_mul(b, wm1.active_time); |
a.full = rfixed_const(16); |
b.full = rfixed_div(b, a); |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
priority_mark12.full = a.full + b.full; |
} else { |
a.full = rfixed_mul(wm1.worst_case_latency, |
wm1.consumption_rate); |
b.full = rfixed_const(16 * 1000); |
priority_mark12.full = rfixed_div(a, b); |
} |
if (wm1.priority_mark.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark.full; |
if (rfixed_trunc(priority_mark12) < 0) |
priority_mark12.full = 0; |
if (wm1.priority_mark_max.full > priority_mark12.full) |
priority_mark12.full = wm1.priority_mark_max.full; |
WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF); |
WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF); |
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12)); |
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12)); |
} |
} |
void rv515_bandwidth_update(struct radeon_device *rdev) |
{ |
uint32_t tmp; |
struct drm_display_mode *mode0 = NULL; |
struct drm_display_mode *mode1 = NULL; |
if (rdev->mode_info.crtcs[0]->base.enabled) |
mode0 = &rdev->mode_info.crtcs[0]->base.mode; |
if (rdev->mode_info.crtcs[1]->base.enabled) |
mode1 = &rdev->mode_info.crtcs[1]->base.mode; |
/* |
* Set display0/1 priority up in the memory controller for |
* modes if the user specifies HIGH for displaypriority |
* option. |
*/ |
if (rdev->disp_priority == 2) { |
tmp = RREG32_MC(MC_MISC_LAT_TIMER); |
tmp &= ~MC_DISP1R_INIT_LAT_MASK; |
tmp &= ~MC_DISP0R_INIT_LAT_MASK; |
if (mode1) |
tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT); |
if (mode0) |
tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT); |
WREG32_MC(MC_MISC_LAT_TIMER, tmp); |
} |
rv515_bandwidth_avivo_update(rdev); |
} |
/drivers/video/drm/radeon/rv515_reg_safe.h |
---|
0,0 → 1,57 |
static const unsigned rv515_reg_safe_bm[219] = { |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, |
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, |
0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF, |
0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF, |
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, |
0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF, |
0x00000000, 0x00000000, 0x00000000, 0x00000000, |
0x0003FC01, 0x3FFFFCF8, 0xFF800B19, 0xFFDFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
}; |
/drivers/video/drm/radeon/rv515d.h |
---|
0,0 → 1,220 |
/* |
* Copyright 2008 Advanced Micro Devices, Inc. |
* Copyright 2008 Red Hat Inc. |
* Copyright 2009 Jerome Glisse. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included in |
* all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: Dave Airlie |
* Alex Deucher |
* Jerome Glisse |
*/ |
#ifndef __RV515D_H__ |
#define __RV515D_H__ |
/* |
* RV515 registers |
*/ |
#define PCIE_INDEX 0x0030 |
#define PCIE_DATA 0x0034 |
#define MC_IND_INDEX 0x0070 |
#define MC_IND_WR_EN (1 << 24) |
#define MC_IND_DATA 0x0074 |
#define RBBM_SOFT_RESET 0x00F0 |
#define CONFIG_MEMSIZE 0x00F8 |
#define HDP_FB_LOCATION 0x0134 |
#define CP_CSQ_CNTL 0x0740 |
#define CP_CSQ_MODE 0x0744 |
#define CP_CSQ_ADDR 0x07F0 |
#define CP_CSQ_DATA 0x07F4 |
#define CP_CSQ_STAT 0x07F8 |
#define CP_CSQ2_STAT 0x07FC |
#define RBBM_STATUS 0x0E40 |
#define DST_PIPE_CONFIG 0x170C |
#define WAIT_UNTIL 0x1720 |
#define WAIT_2D_IDLE (1 << 14) |
#define WAIT_3D_IDLE (1 << 15) |
#define WAIT_2D_IDLECLEAN (1 << 16) |
#define WAIT_3D_IDLECLEAN (1 << 17) |
#define ISYNC_CNTL 0x1724 |
#define ISYNC_ANY2D_IDLE3D (1 << 0) |
#define ISYNC_ANY3D_IDLE2D (1 << 1) |
#define ISYNC_TRIG2D_IDLE3D (1 << 2) |
#define ISYNC_TRIG3D_IDLE2D (1 << 3) |
#define ISYNC_WAIT_IDLEGUI (1 << 4) |
#define ISYNC_CPSCRATCH_IDLEGUI (1 << 5) |
#define VAP_INDEX_OFFSET 0x208C |
#define VAP_PVS_STATE_FLUSH_REG 0x2284 |
#define GB_ENABLE 0x4008 |
#define GB_MSPOS0 0x4010 |
#define MS_X0_SHIFT 0 |
#define MS_Y0_SHIFT 4 |
#define MS_X1_SHIFT 8 |
#define MS_Y1_SHIFT 12 |
#define MS_X2_SHIFT 16 |
#define MS_Y2_SHIFT 20 |
#define MSBD0_Y_SHIFT 24 |
#define MSBD0_X_SHIFT 28 |
#define GB_MSPOS1 0x4014 |
#define MS_X3_SHIFT 0 |
#define MS_Y3_SHIFT 4 |
#define MS_X4_SHIFT 8 |
#define MS_Y4_SHIFT 12 |
#define MS_X5_SHIFT 16 |
#define MS_Y5_SHIFT 20 |
#define MSBD1_SHIFT 24 |
#define GB_TILE_CONFIG 0x4018 |
#define ENABLE_TILING (1 << 0) |
#define PIPE_COUNT_MASK 0x0000000E |
#define PIPE_COUNT_SHIFT 1 |
#define TILE_SIZE_8 (0 << 4) |
#define TILE_SIZE_16 (1 << 4) |
#define TILE_SIZE_32 (2 << 4) |
#define SUBPIXEL_1_12 (0 << 16) |
#define SUBPIXEL_1_16 (1 << 16) |
#define GB_SELECT 0x401C |
#define GB_AA_CONFIG 0x4020 |
#define GB_PIPE_SELECT 0x402C |
#define GA_ENHANCE 0x4274 |
#define GA_DEADLOCK_CNTL (1 << 0) |
#define GA_FASTSYNC_CNTL (1 << 1) |
#define GA_POLY_MODE 0x4288 |
#define FRONT_PTYPE_POINT (0 << 4) |
#define FRONT_PTYPE_LINE (1 << 4) |
#define FRONT_PTYPE_TRIANGE (2 << 4) |
#define BACK_PTYPE_POINT (0 << 7) |
#define BACK_PTYPE_LINE (1 << 7) |
#define BACK_PTYPE_TRIANGE (2 << 7) |
#define GA_ROUND_MODE 0x428C |
#define GEOMETRY_ROUND_TRUNC (0 << 0) |
#define GEOMETRY_ROUND_NEAREST (1 << 0) |
#define COLOR_ROUND_TRUNC (0 << 2) |
#define COLOR_ROUND_NEAREST (1 << 2) |
#define SU_REG_DEST 0x42C8 |
#define RB3D_DSTCACHE_CTLSTAT 0x4E4C |
#define RB3D_DC_FLUSH (2 << 0) |
#define RB3D_DC_FREE (2 << 2) |
#define RB3D_DC_FINISH (1 << 4) |
#define ZB_ZCACHE_CTLSTAT 0x4F18 |
#define ZC_FLUSH (1 << 0) |
#define ZC_FREE (1 << 1) |
#define DC_LB_MEMORY_SPLIT 0x6520 |
#define DC_LB_MEMORY_SPLIT_MASK 0x00000003 |
#define DC_LB_MEMORY_SPLIT_SHIFT 0 |
#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 |
#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 |
#define DC_LB_MEMORY_SPLIT_D1_ONLY 2 |
#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 |
#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) |
#define DC_LB_DISP1_END_ADR_SHIFT 4 |
#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0 |
#define D1MODE_PRIORITY_A_CNT 0x6548 |
#define MODE_PRIORITY_MARK_MASK 0x00007FFF |
#define MODE_PRIORITY_OFF (1 << 16) |
#define MODE_PRIORITY_ALWAYS_ON (1 << 20) |
#define MODE_PRIORITY_FORCE_MASK (1 << 24) |
#define D1MODE_PRIORITY_B_CNT 0x654C |
#define LB_MAX_REQ_OUTSTANDING 0x6D58 |
#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F |
#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0 |
#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000 |
#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16 |
#define D2MODE_PRIORITY_A_CNT 0x6D48 |
#define D2MODE_PRIORITY_B_CNT 0x6D4C |
/* ix[MC] registers */ |
#define MC_FB_LOCATION 0x01 |
#define MC_FB_START_MASK 0x0000FFFF |
#define MC_FB_START_SHIFT 0 |
#define MC_FB_TOP_MASK 0xFFFF0000 |
#define MC_FB_TOP_SHIFT 16 |
#define MC_AGP_LOCATION 0x02 |
#define MC_AGP_START_MASK 0x0000FFFF |
#define MC_AGP_START_SHIFT 0 |
#define MC_AGP_TOP_MASK 0xFFFF0000 |
#define MC_AGP_TOP_SHIFT 16 |
#define MC_AGP_BASE 0x03 |
#define MC_AGP_BASE_2 0x04 |
#define MC_CNTL 0x5 |
#define MEM_NUM_CHANNELS_MASK 0x00000003 |
#define MC_STATUS 0x08 |
#define MC_STATUS_IDLE (1 << 4) |
#define MC_MISC_LAT_TIMER 0x09 |
#define MC_CPR_INIT_LAT_MASK 0x0000000F |
#define MC_VF_INIT_LAT_MASK 0x000000F0 |
#define MC_DISP0R_INIT_LAT_MASK 0x00000F00 |
#define MC_DISP0R_INIT_LAT_SHIFT 8 |
#define MC_DISP1R_INIT_LAT_MASK 0x0000F000 |
#define MC_DISP1R_INIT_LAT_SHIFT 12 |
#define MC_FIXED_INIT_LAT_MASK 0x000F0000 |
#define MC_E2R_INIT_LAT_MASK 0x00F00000 |
#define SAME_PAGE_PRIO_MASK 0x0F000000 |
#define MC_GLOBW_INIT_LAT_MASK 0xF0000000 |
/* |
* PM4 packet |
*/ |
#define CP_PACKET0 0x00000000 |
#define PACKET0_BASE_INDEX_SHIFT 0 |
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) |
#define PACKET0_COUNT_SHIFT 16 |
#define PACKET0_COUNT_MASK (0x3fff << 16) |
#define CP_PACKET1 0x40000000 |
#define CP_PACKET2 0x80000000 |
#define PACKET2_PAD_SHIFT 0 |
#define PACKET2_PAD_MASK (0x3fffffff << 0) |
#define CP_PACKET3 0xC0000000 |
#define PACKET3_IT_OPCODE_SHIFT 8 |
#define PACKET3_IT_OPCODE_MASK (0xff << 8) |
#define PACKET3_COUNT_SHIFT 16 |
#define PACKET3_COUNT_MASK (0x3fff << 16) |
/* PACKET3 op code */ |
#define PACKET3_NOP 0x10 |
#define PACKET3_3D_DRAW_VBUF 0x28 |
#define PACKET3_3D_DRAW_IMMD 0x29 |
#define PACKET3_3D_DRAW_INDX 0x2A |
#define PACKET3_3D_LOAD_VBPNTR 0x2F |
#define PACKET3_INDX_BUFFER 0x33 |
#define PACKET3_3D_DRAW_VBUF_2 0x34 |
#define PACKET3_3D_DRAW_IMMD_2 0x35 |
#define PACKET3_3D_DRAW_INDX_2 0x36 |
#define PACKET3_BITBLT_MULTI 0x9B |
#define PACKET0(reg, n) (CP_PACKET0 | \ |
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ |
REG_SET(PACKET0_COUNT, (n))) |
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) |
#define PACKET3(op, n) (CP_PACKET3 | \ |
REG_SET(PACKET3_IT_OPCODE, (op)) | \ |
REG_SET(PACKET3_COUNT, (n))) |
#define PACKET_TYPE0 0 |
#define PACKET_TYPE1 1 |
#define PACKET_TYPE2 2 |
#define PACKET_TYPE3 3 |
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) |
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) |
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) |
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) |
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) |
#endif |