Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1129 → Rev 1179

/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