Commit e15daf6c authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (25 commits)
  drm/radeon/kms: Convert R520 to new init path and associated cleanup
  drm/radeon/kms: Convert RV515 to new init path and associated cleanup
  drm: fix radeon DRM warnings when !CONFIG_DEBUG_FS
  drm: fix drm_fb_helper warning when !CONFIG_MAGIC_SYSRQ
  drm/r600: fix memory leak introduced with 64k malloc avoidance fix.
  drm/kms: make fb helper work for all drivers.
  drm/radeon/r600: fix offset handling in CS parser
  drm/radeon/kms/r600: fix forcing pci mode on agp cards
  drm/radeon/kms: fix for the extra pages copying.
  drm/radeon/kms/r600: add support for vline relocs
  drm/radeon/kms: fix some bugs in vline reloc
  drm/radeon/kms/r600: clamp vram to aperture size
  drm/kms: protect against fb helper not being created.
  drm/r600: get values from the passed in IB not the copy.
  drm: create gitignore file for radeon
  drm/radeon/kms: remove unneeded master create/destroy functions.
  drm/kms: start adding command line interface using fb.
  fb: change rules for global rules match.
  drm/radeon/kms: don't require up to 64k allocations. (v2)
  drm/radeon/kms: enable dac load detection by default.
  ...

Trivial conflicts in drivers/gpu/drm/radeon/radeon_asic.h due to adding
'->vga_set_state' function pointers.
parents 07892acf f0ed1f65
...@@ -482,6 +482,7 @@ void drm_connector_cleanup(struct drm_connector *connector) ...@@ -482,6 +482,7 @@ void drm_connector_cleanup(struct drm_connector *connector)
list_for_each_entry_safe(mode, t, &connector->user_modes, head) list_for_each_entry_safe(mode, t, &connector->user_modes, head)
drm_mode_remove(connector, mode); drm_mode_remove(connector, mode);
kfree(connector->fb_helper_private);
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
drm_mode_object_put(dev, &connector->base); drm_mode_object_put(dev, &connector->base);
list_del(&connector->head); list_del(&connector->head);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "drmP.h" #include "drmP.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
#include "drm_fb_helper.h"
static void drm_mode_validate_flag(struct drm_connector *connector, static void drm_mode_validate_flag(struct drm_connector *connector,
int flags) int flags)
...@@ -90,7 +91,15 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, ...@@ -90,7 +91,15 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
list_for_each_entry_safe(mode, t, &connector->modes, head) list_for_each_entry_safe(mode, t, &connector->modes, head)
mode->status = MODE_UNVERIFIED; mode->status = MODE_UNVERIFIED;
connector->status = connector->funcs->detect(connector); if (connector->force) {
if (connector->force == DRM_FORCE_ON)
connector->status = connector_status_connected;
else
connector->status = connector_status_disconnected;
if (connector->funcs->force)
connector->funcs->force(connector);
} else
connector->status = connector->funcs->detect(connector);
if (connector->status == connector_status_disconnected) { if (connector->status == connector_status_disconnected) {
DRM_DEBUG_KMS("%s is disconnected\n", DRM_DEBUG_KMS("%s is disconnected\n",
...@@ -267,6 +276,65 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con ...@@ -267,6 +276,65 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con
return NULL; return NULL;
} }
static bool drm_has_cmdline_mode(struct drm_connector *connector)
{
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode;
if (!fb_help_conn)
return false;
cmdline_mode = &fb_help_conn->cmdline_mode;
return cmdline_mode->specified;
}
static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height)
{
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode;
struct drm_display_mode *mode = NULL;
if (!fb_help_conn)
return mode;
cmdline_mode = &fb_help_conn->cmdline_mode;
if (cmdline_mode->specified == false)
return mode;
/* attempt to find a matching mode in the list of modes
* we have gotten so far, if not add a CVT mode that conforms
*/
if (cmdline_mode->rb || cmdline_mode->margins)
goto create_mode;
list_for_each_entry(mode, &connector->modes, head) {
/* check width/height */
if (mode->hdisplay != cmdline_mode->xres ||
mode->vdisplay != cmdline_mode->yres)
continue;
if (cmdline_mode->refresh_specified) {
if (mode->vrefresh != cmdline_mode->refresh)
continue;
}
if (cmdline_mode->interlace) {
if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
continue;
}
return mode;
}
create_mode:
mode = drm_cvt_mode(connector->dev, cmdline_mode->xres,
cmdline_mode->yres,
cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
cmdline_mode->rb, cmdline_mode->interlace,
cmdline_mode->margins);
list_add(&mode->head, &connector->modes);
return mode;
}
static bool drm_connector_enabled(struct drm_connector *connector, bool strict) static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
{ {
bool enable; bool enable;
...@@ -317,10 +385,16 @@ static bool drm_target_preferred(struct drm_device *dev, ...@@ -317,10 +385,16 @@ static bool drm_target_preferred(struct drm_device *dev,
continue; continue;
} }
DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
connector->base.id); connector->base.id);
modes[i] = drm_has_preferred_mode(connector, width, height); /* got for command line mode first */
modes[i] = drm_pick_cmdline_mode(connector, width, height);
if (!modes[i]) {
DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
connector->base.id);
modes[i] = drm_has_preferred_mode(connector, width, height);
}
/* No preferred modes, pick one off the list */ /* No preferred modes, pick one off the list */
if (!modes[i] && !list_empty(&connector->modes)) { if (!modes[i] && !list_empty(&connector->modes)) {
list_for_each_entry(modes[i], &connector->modes, head) list_for_each_entry(modes[i], &connector->modes, head)
...@@ -369,6 +443,8 @@ static int drm_pick_crtcs(struct drm_device *dev, ...@@ -369,6 +443,8 @@ static int drm_pick_crtcs(struct drm_device *dev,
my_score = 1; my_score = 1;
if (connector->status == connector_status_connected) if (connector->status == connector_status_connected)
my_score++; my_score++;
if (drm_has_cmdline_mode(connector))
my_score++;
if (drm_has_preferred_mode(connector, width, height)) if (drm_has_preferred_mode(connector, width, height))
my_score++; my_score++;
...@@ -943,6 +1019,8 @@ bool drm_helper_initial_config(struct drm_device *dev) ...@@ -943,6 +1019,8 @@ bool drm_helper_initial_config(struct drm_device *dev)
{ {
int count = 0; int count = 0;
drm_fb_helper_parse_command_line(dev);
count = drm_helper_probe_connector_modes(dev, count = drm_helper_probe_connector_modes(dev,
dev->mode_config.max_width, dev->mode_config.max_width,
dev->mode_config.max_height); dev->mode_config.max_height);
...@@ -950,7 +1028,7 @@ bool drm_helper_initial_config(struct drm_device *dev) ...@@ -950,7 +1028,7 @@ bool drm_helper_initial_config(struct drm_device *dev)
/* /*
* we shouldn't end up with no modes here. * we shouldn't end up with no modes here.
*/ */
WARN(!count, "Connected connector with 0 modes\n"); WARN(!count, "No connectors reported connected with modes\n");
drm_setup_crtcs(dev); drm_setup_crtcs(dev);
......
...@@ -109,7 +109,9 @@ static struct edid_quirk { ...@@ -109,7 +109,9 @@ static struct edid_quirk {
/* Valid EDID header has these bytes */ /* Valid EDID header has these bytes */
static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; static const u8 edid_header[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
};
/** /**
* edid_is_valid - sanity check EDID data * edid_is_valid - sanity check EDID data
...@@ -500,6 +502,19 @@ static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, ...@@ -500,6 +502,19 @@ static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
} }
return mode; return mode;
} }
/*
* 0 is reserved. The spec says 0x01 fill for unused timings. Some old
* monitors fill with ascii space (0x20) instead.
*/
static int
bad_std_timing(u8 a, u8 b)
{
return (a == 0x00 && b == 0x00) ||
(a == 0x01 && b == 0x01) ||
(a == 0x20 && b == 0x20);
}
/** /**
* drm_mode_std - convert standard mode info (width, height, refresh) into mode * drm_mode_std - convert standard mode info (width, height, refresh) into mode
* @t: standard timing params * @t: standard timing params
...@@ -513,6 +528,7 @@ static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, ...@@ -513,6 +528,7 @@ static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
*/ */
struct drm_display_mode *drm_mode_std(struct drm_device *dev, struct drm_display_mode *drm_mode_std(struct drm_device *dev,
struct std_timing *t, struct std_timing *t,
int revision,
int timing_level) int timing_level)
{ {
struct drm_display_mode *mode; struct drm_display_mode *mode;
...@@ -523,14 +539,20 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, ...@@ -523,14 +539,20 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK) unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
>> EDID_TIMING_VFREQ_SHIFT; >> EDID_TIMING_VFREQ_SHIFT;
if (bad_std_timing(t->hsize, t->vfreq_aspect))
return NULL;
/* According to the EDID spec, the hdisplay = hsize * 8 + 248 */ /* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
hsize = t->hsize * 8 + 248; hsize = t->hsize * 8 + 248;
/* vrefresh_rate = vfreq + 60 */ /* vrefresh_rate = vfreq + 60 */
vrefresh_rate = vfreq + 60; vrefresh_rate = vfreq + 60;
/* the vdisplay is calculated based on the aspect ratio */ /* the vdisplay is calculated based on the aspect ratio */
if (aspect_ratio == 0) if (aspect_ratio == 0) {
vsize = (hsize * 10) / 16; if (revision < 3)
else if (aspect_ratio == 1) vsize = hsize;
else
vsize = (hsize * 10) / 16;
} else if (aspect_ratio == 1)
vsize = (hsize * 3) / 4; vsize = (hsize * 3) / 4;
else if (aspect_ratio == 2) else if (aspect_ratio == 2)
vsize = (hsize * 4) / 5; vsize = (hsize * 4) / 5;
...@@ -538,7 +560,8 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, ...@@ -538,7 +560,8 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
vsize = (hsize * 9) / 16; vsize = (hsize * 9) / 16;
/* HDTV hack */ /* HDTV hack */
if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) { if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) {
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
false);
mode->hdisplay = 1366; mode->hdisplay = 1366;
mode->vsync_start = mode->vsync_start - 1; mode->vsync_start = mode->vsync_start - 1;
mode->vsync_end = mode->vsync_end - 1; mode->vsync_end = mode->vsync_end - 1;
...@@ -557,7 +580,8 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev, ...@@ -557,7 +580,8 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
break; break;
case LEVEL_CVT: case LEVEL_CVT:
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
false);
break; break;
} }
return mode; return mode;
...@@ -779,7 +803,7 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid ...@@ -779,7 +803,7 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
continue; continue;
newmode = drm_mode_std(dev, &edid->standard_timings[i], newmode = drm_mode_std(dev, &edid->standard_timings[i],
timing_level); edid->revision, timing_level);
if (newmode) { if (newmode) {
drm_mode_probed_add(connector, newmode); drm_mode_probed_add(connector, newmode);
modes++; modes++;
...@@ -829,13 +853,13 @@ static int add_detailed_info(struct drm_connector *connector, ...@@ -829,13 +853,13 @@ static int add_detailed_info(struct drm_connector *connector,
case EDID_DETAIL_MONITOR_CPDATA: case EDID_DETAIL_MONITOR_CPDATA:
break; break;
case EDID_DETAIL_STD_MODES: case EDID_DETAIL_STD_MODES:
/* Five modes per detailed section */ for (j = 0; j < 6; i++) {
for (j = 0; j < 5; i++) {
struct std_timing *std; struct std_timing *std;
struct drm_display_mode *newmode; struct drm_display_mode *newmode;
std = &data->data.timings[j]; std = &data->data.timings[j];
newmode = drm_mode_std(dev, std, newmode = drm_mode_std(dev, std,
edid->revision,
timing_level); timing_level);
if (newmode) { if (newmode) {
drm_mode_probed_add(connector, newmode); drm_mode_probed_add(connector, newmode);
...@@ -964,7 +988,9 @@ static int add_detailed_info_eedid(struct drm_connector *connector, ...@@ -964,7 +988,9 @@ static int add_detailed_info_eedid(struct drm_connector *connector,
struct drm_display_mode *newmode; struct drm_display_mode *newmode;
std = &data->data.timings[j]; std = &data->data.timings[j];
newmode = drm_mode_std(dev, std, timing_level); newmode = drm_mode_std(dev, std,
edid->revision,
timing_level);
if (newmode) { if (newmode) {
drm_mode_probed_add(connector, newmode); drm_mode_probed_add(connector, newmode);
modes++; modes++;
......
...@@ -40,6 +40,199 @@ MODULE_LICENSE("GPL and additional rights"); ...@@ -40,6 +40,199 @@ MODULE_LICENSE("GPL and additional rights");
static LIST_HEAD(kernel_fb_helper_list); static LIST_HEAD(kernel_fb_helper_list);
int drm_fb_helper_add_connector(struct drm_connector *connector)
{
connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
if (!connector->fb_helper_private)
return -ENOMEM;
return 0;
}
EXPORT_SYMBOL(drm_fb_helper_add_connector);
static int my_atoi(const char *name)
{
int val = 0;
for (;; name++) {
switch (*name) {
case '0' ... '9':
val = 10*val+(*name-'0');
break;
default:
return val;
}
}
}
/**
* drm_fb_helper_connector_parse_command_line - parse command line for connector
* @connector - connector to parse line for
* @mode_option - per connector mode option
*
* This parses the connector specific then generic command lines for
* modes and options to configure the connector.
*
* This uses the same parameters as the fb modedb.c, except for extra
* <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
*
* enable/enable Digital/disable bit at the end
*/
static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *connector,
const char *mode_option)
{
const char *name;
unsigned int namelen;
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
int i;
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode;
if (!fb_help_conn)
return false;
cmdline_mode = &fb_help_conn->cmdline_mode;
if (!mode_option)
mode_option = fb_mode_option;
if (!mode_option) {
cmdline_mode->specified = false;
return false;
}
name = mode_option;
namelen = strlen(name);
for (i = namelen-1; i >= 0; i--) {
switch (name[i]) {
case '@':
namelen = i;
if (!refresh_specified && !bpp_specified &&
!yres_specified) {
refresh = my_atoi(&name[i+1]);
refresh_specified = 1;
if (cvt || rb)
cvt = 0;
} else
goto done;
break;
case '-':
namelen = i;
if (!bpp_specified && !yres_specified) {
bpp = my_atoi(&name[i+1]);
bpp_specified = 1;
if (cvt || rb)
cvt = 0;
} else
goto done;
break;
case 'x':
if (!yres_specified) {
yres = my_atoi(&name[i+1]);
yres_specified = 1;
} else
goto done;
case '0' ... '9':
break;
case 'M':
if (!yres_specified)
cvt = 1;
break;
case 'R':
if (!cvt)
rb = 1;
break;
case 'm':
if (!cvt)
margins = 1;
break;
case 'i':
if (!cvt)
interlace = 1;
break;
case 'e':
force = DRM_FORCE_ON;
break;
case 'D':
if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) ||
(connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
force = DRM_FORCE_ON;
else
force = DRM_FORCE_ON_DIGITAL;
break;
case 'd':
force = DRM_FORCE_OFF;
break;
default:
goto done;
}
}
if (i < 0 && yres_specified) {
xres = my_atoi(name);
res_specified = 1;
}
done:
DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
drm_get_connector_name(connector), xres, yres,
(refresh) ? refresh : 60, (rb) ? " reduced blanking" :
"", (margins) ? " with margins" : "", (interlace) ?
" interlaced" : "");
if (force) {
const char *s;
switch (force) {
case DRM_FORCE_OFF: s = "OFF"; break;
case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
default:
case DRM_FORCE_ON: s = "ON"; break;
}
DRM_INFO("forcing %s connector %s\n",
drm_get_connector_name(connector), s);
connector->force = force;
}
if (res_specified) {
cmdline_mode->specified = true;
cmdline_mode->xres = xres;
cmdline_mode->yres = yres;
}
if (refresh_specified) {
cmdline_mode->refresh_specified = true;
cmdline_mode->refresh = refresh;
}
if (bpp_specified) {
cmdline_mode->bpp_specified = true;
cmdline_mode->bpp = bpp;
}
cmdline_mode->rb = rb ? true : false;
cmdline_mode->cvt = cvt ? true : false;
cmdline_mode->interlace = interlace ? true : false;
return true;
}
int drm_fb_helper_parse_command_line(struct drm_device *dev)
{
struct drm_connector *connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
char *option = NULL;
/* do something on return - turn off connector maybe */
if (fb_get_options(drm_get_connector_name(connector), &option))
continue;
drm_fb_helper_connector_parse_command_line(connector, option);
}
return 0;
}
bool drm_fb_helper_force_kernel_mode(void) bool drm_fb_helper_force_kernel_mode(void)
{ {
int i = 0; int i = 0;
...@@ -87,6 +280,7 @@ void drm_fb_helper_restore(void) ...@@ -87,6 +280,7 @@ void drm_fb_helper_restore(void)
} }
EXPORT_SYMBOL(drm_fb_helper_restore); EXPORT_SYMBOL(drm_fb_helper_restore);
#ifdef CONFIG_MAGIC_SYSRQ
static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
{ {
drm_fb_helper_restore(); drm_fb_helper_restore();
...@@ -103,6 +297,7 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { ...@@ -103,6 +297,7 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
.help_msg = "force-fb(V)", .help_msg = "force-fb(V)",
.action_msg = "Restore framebuffer console", .action_msg = "Restore framebuffer console",
}; };
#endif
static void drm_fb_helper_on(struct fb_info *info) static void drm_fb_helper_on(struct fb_info *info)
{ {
...@@ -484,6 +679,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, ...@@ -484,6 +679,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
uint32_t fb_height, uint32_t fb_height,
uint32_t surface_width, uint32_t surface_width,
uint32_t surface_height, uint32_t surface_height,
uint32_t surface_depth,
uint32_t surface_bpp,
struct drm_framebuffer **fb_ptr)) struct drm_framebuffer **fb_ptr))
{ {
struct drm_crtc *crtc; struct drm_crtc *crtc;
...@@ -497,8 +694,43 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, ...@@ -497,8 +694,43 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_mode_set *modeset = NULL; struct drm_mode_set *modeset = NULL;
struct drm_fb_helper *fb_helper; struct drm_fb_helper *fb_helper;
uint32_t surface_depth = 24, surface_bpp = 32;
/* first up get a count of crtcs now in use and new min/maxes width/heights */ /* first up get a count of crtcs now in use and new min/maxes width/heights */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
struct drm_fb_helper_cmdline_mode *cmdline_mode;
if (!fb_help_conn)
continue;
cmdline_mode = &fb_help_conn->cmdline_mode;
if (cmdline_mode->bpp_specified) {
switch (cmdline_mode->bpp) {
case 8:
surface_depth = surface_bpp = 8;
break;
case 15:
surface_depth = 15;
surface_bpp = 16;
break;
case 16:
surface_depth = surface_bpp = 16;
break;
case 24:
surface_depth = surface_bpp = 24;
break;
case 32:
surface_depth = 24;
surface_bpp = 32;
break;
}
break;
}
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (drm_helper_crtc_in_use(crtc)) { if (drm_helper_crtc_in_use(crtc)) {
if (crtc->desired_mode) { if (crtc->desired_mode) {
...@@ -527,7 +759,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, ...@@ -527,7 +759,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
/* do we have an fb already? */ /* do we have an fb already? */
if (list_empty(&dev->mode_config.fb_kernel_list)) { if (list_empty(&dev->mode_config.fb_kernel_list)) {
ret = (*fb_create)(dev, fb_width, fb_height, surface_width, ret = (*fb_create)(dev, fb_width, fb_height, surface_width,
surface_height, &fb); surface_height, surface_depth, surface_bpp,
&fb);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
new_fb = 1; new_fb = 1;
......
...@@ -88,7 +88,7 @@ EXPORT_SYMBOL(drm_mode_debug_printmodeline); ...@@ -88,7 +88,7 @@ EXPORT_SYMBOL(drm_mode_debug_printmodeline);
#define HV_FACTOR 1000 #define HV_FACTOR 1000
struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
int vdisplay, int vrefresh, int vdisplay, int vrefresh,
bool reduced, bool interlaced) bool reduced, bool interlaced, bool margins)
{ {
/* 1) top/bottom margin size (% of height) - default: 1.8, */ /* 1) top/bottom margin size (% of height) - default: 1.8, */
#define CVT_MARGIN_PERCENTAGE 18 #define CVT_MARGIN_PERCENTAGE 18
...@@ -101,7 +101,6 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, ...@@ -101,7 +101,6 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
/* Pixel Clock step (kHz) */ /* Pixel Clock step (kHz) */
#define CVT_CLOCK_STEP 250 #define CVT_CLOCK_STEP 250
struct drm_display_mode *drm_mode; struct drm_display_mode *drm_mode;
bool margins = false;
unsigned int vfieldrate, hperiod; unsigned int vfieldrate, hperiod;
int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
int interlace; int interlace;
......
...@@ -110,6 +110,7 @@ EXPORT_SYMBOL(intelfb_resize); ...@@ -110,6 +110,7 @@ EXPORT_SYMBOL(intelfb_resize);
static int intelfb_create(struct drm_device *dev, uint32_t fb_width, static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
uint32_t fb_height, uint32_t surface_width, uint32_t fb_height, uint32_t surface_width,
uint32_t surface_height, uint32_t surface_height,
uint32_t surface_depth, uint32_t surface_bpp,
struct drm_framebuffer **fb_p) struct drm_framebuffer **fb_p)
{ {
struct fb_info *info; struct fb_info *info;
...@@ -125,9 +126,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, ...@@ -125,9 +126,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
mode_cmd.width = surface_width; mode_cmd.width = surface_width;
mode_cmd.height = surface_height; mode_cmd.height = surface_height;
mode_cmd.bpp = 32; mode_cmd.bpp = surface_bpp;
mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
mode_cmd.depth = 24; mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height; size = mode_cmd.pitch * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE); size = ALIGN(size, PAGE_SIZE);
......
...@@ -57,13 +57,4 @@ ...@@ -57,13 +57,4 @@
#define VGA_RENDER_CONTROL 0x0300 #define VGA_RENDER_CONTROL 0x0300
#define VGA_VSTATUS_CNTL_MASK 0x00030000 #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 #endif
...@@ -863,13 +863,11 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p, ...@@ -863,13 +863,11 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
void r100_cs_dump_packet(struct radeon_cs_parser *p, void r100_cs_dump_packet(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt) struct radeon_cs_packet *pkt)
{ {
struct radeon_cs_chunk *ib_chunk;
volatile uint32_t *ib; volatile uint32_t *ib;
unsigned i; unsigned i;
unsigned idx; unsigned idx;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx; idx = pkt->idx;
for (i = 0; i <= (pkt->count + 1); i++, idx++) { for (i = 0; i <= (pkt->count + 1); i++, idx++) {
DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
...@@ -896,7 +894,7 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p, ...@@ -896,7 +894,7 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p,
idx, ib_chunk->length_dw); idx, ib_chunk->length_dw);
return -EINVAL; return -EINVAL;
} }
header = ib_chunk->kdata[idx]; header = radeon_get_ib_value(p, idx);
pkt->idx = idx; pkt->idx = idx;
pkt->type = CP_PACKET_GET_TYPE(header); pkt->type = CP_PACKET_GET_TYPE(header);
pkt->count = CP_PACKET_GET_COUNT(header); pkt->count = CP_PACKET_GET_COUNT(header);
...@@ -939,7 +937,6 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p, ...@@ -939,7 +937,6 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p,
*/ */
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
{ {
struct radeon_cs_chunk *ib_chunk;
struct drm_mode_object *obj; struct drm_mode_object *obj;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc; struct radeon_crtc *radeon_crtc;
...@@ -947,8 +944,9 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) ...@@ -947,8 +944,9 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
int crtc_id; int crtc_id;
int r; int r;
uint32_t header, h_idx, reg; uint32_t header, h_idx, reg;
volatile uint32_t *ib;
ib_chunk = &p->chunks[p->chunk_ib_idx]; ib = p->ib->ptr;
/* parse the wait until */ /* parse the wait until */
r = r100_cs_packet_parse(p, &waitreloc, p->idx); r = r100_cs_packet_parse(p, &waitreloc, p->idx);
...@@ -963,24 +961,24 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) ...@@ -963,24 +961,24 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
return r; return r;
} }
if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) { if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) {
DRM_ERROR("vline wait had illegal wait until\n"); DRM_ERROR("vline wait had illegal wait until\n");
r = -EINVAL; r = -EINVAL;
return r; return r;
} }
/* jump over the NOP */ /* jump over the NOP */
r = r100_cs_packet_parse(p, &p3reloc, p->idx); r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2);
if (r) if (r)
return r; return r;
h_idx = p->idx - 2; h_idx = p->idx - 2;
p->idx += waitreloc.count; p->idx += waitreloc.count + 2;
p->idx += p3reloc.count; p->idx += p3reloc.count + 2;
header = ib_chunk->kdata[h_idx]; header = radeon_get_ib_value(p, h_idx);
crtc_id = ib_chunk->kdata[h_idx + 5]; crtc_id = radeon_get_ib_value(p, h_idx + 5);
reg = ib_chunk->kdata[h_idx] >> 2; reg = header >> 2;
mutex_lock(&p->rdev->ddev->mode_config.mutex); mutex_lock(&p->rdev->ddev->mode_config.mutex);
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) { if (!obj) {
...@@ -994,16 +992,16 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) ...@@ -994,16 +992,16 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
if (!crtc->enabled) { if (!crtc->enabled) {
/* if the CRTC isn't enabled - we need to nop out the wait until */ /* if the CRTC isn't enabled - we need to nop out the wait until */
ib_chunk->kdata[h_idx + 2] = PACKET2(0); ib[h_idx + 2] = PACKET2(0);
ib_chunk->kdata[h_idx + 3] = PACKET2(0); ib[h_idx + 3] = PACKET2(0);
} else if (crtc_id == 1) { } else if (crtc_id == 1) {
switch (reg) { switch (reg) {
case AVIVO_D1MODE_VLINE_START_END: case AVIVO_D1MODE_VLINE_START_END:
header &= R300_CP_PACKET0_REG_MASK; header &= ~R300_CP_PACKET0_REG_MASK;
header |= AVIVO_D2MODE_VLINE_START_END >> 2; header |= AVIVO_D2MODE_VLINE_START_END >> 2;
break; break;
case RADEON_CRTC_GUI_TRIG_VLINE: case RADEON_CRTC_GUI_TRIG_VLINE:
header &= R300_CP_PACKET0_REG_MASK; header &= ~R300_CP_PACKET0_REG_MASK;
header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2;
break; break;
default: default:
...@@ -1011,8 +1009,8 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) ...@@ -1011,8 +1009,8 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
r = -EINVAL; r = -EINVAL;
goto out; goto out;
} }
ib_chunk->kdata[h_idx] = header; ib[h_idx] = header;
ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
} }
out: out:
mutex_unlock(&p->rdev->ddev->mode_config.mutex); mutex_unlock(&p->rdev->ddev->mode_config.mutex);
...@@ -1033,7 +1031,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) ...@@ -1033,7 +1031,6 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc) struct radeon_cs_reloc **cs_reloc)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_chunk *relocs_chunk; struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc; struct radeon_cs_packet p3reloc;
unsigned idx; unsigned idx;
...@@ -1044,7 +1041,6 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, ...@@ -1044,7 +1041,6 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
*cs_reloc = NULL; *cs_reloc = NULL;
ib_chunk = &p->chunks[p->chunk_ib_idx];
relocs_chunk = &p->chunks[p->chunk_relocs_idx]; relocs_chunk = &p->chunks[p->chunk_relocs_idx];
r = r100_cs_packet_parse(p, &p3reloc, p->idx); r = r100_cs_packet_parse(p, &p3reloc, p->idx);
if (r) { if (r) {
...@@ -1057,7 +1053,7 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, ...@@ -1057,7 +1053,7 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, &p3reloc); r100_cs_dump_packet(p, &p3reloc);
return -EINVAL; return -EINVAL;
} }
idx = ib_chunk->kdata[p3reloc.idx + 1]; idx = radeon_get_ib_value(p, p3reloc.idx + 1);
if (idx >= relocs_chunk->length_dw) { if (idx >= relocs_chunk->length_dw) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
idx, relocs_chunk->length_dw); idx, relocs_chunk->length_dw);
...@@ -1126,7 +1122,6 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1126,7 +1122,6 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg) unsigned idx, unsigned reg)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r100_cs_track *track; struct r100_cs_track *track;
volatile uint32_t *ib; volatile uint32_t *ib;
...@@ -1134,11 +1129,13 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1134,11 +1129,13 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
int r; int r;
int i, face; int i, face;
u32 tile_flags = 0; u32 tile_flags = 0;
u32 idx_value;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track; track = (struct r100_cs_track *)p->track;
idx_value = radeon_get_ib_value(p, idx);
switch (reg) { switch (reg) {
case RADEON_CRTC_GUI_TRIG_VLINE: case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p); r = r100_cs_packet_parse_vline(p);
...@@ -1166,8 +1163,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1166,8 +1163,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
return r; return r;
} }
track->zb.robj = reloc->robj; track->zb.robj = reloc->robj;
track->zb.offset = ib_chunk->kdata[idx]; track->zb.offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case RADEON_RB3D_COLOROFFSET: case RADEON_RB3D_COLOROFFSET:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -1178,8 +1175,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1178,8 +1175,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
return r; return r;
} }
track->cb[0].robj = reloc->robj; track->cb[0].robj = reloc->robj;
track->cb[0].offset = ib_chunk->kdata[idx]; track->cb[0].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case RADEON_PP_TXOFFSET_0: case RADEON_PP_TXOFFSET_0:
case RADEON_PP_TXOFFSET_1: case RADEON_PP_TXOFFSET_1:
...@@ -1192,7 +1189,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1192,7 +1189,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj; track->textures[i].robj = reloc->robj;
break; break;
case RADEON_PP_CUBIC_OFFSET_T0_0: case RADEON_PP_CUBIC_OFFSET_T0_0:
...@@ -1208,8 +1205,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1208,8 +1205,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
track->textures[0].cube_info[i].offset = ib_chunk->kdata[idx]; track->textures[0].cube_info[i].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[0].cube_info[i].robj = reloc->robj; track->textures[0].cube_info[i].robj = reloc->robj;
break; break;
case RADEON_PP_CUBIC_OFFSET_T1_0: case RADEON_PP_CUBIC_OFFSET_T1_0:
...@@ -1225,8 +1222,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1225,8 +1222,8 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
track->textures[1].cube_info[i].offset = ib_chunk->kdata[idx]; track->textures[1].cube_info[i].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[1].cube_info[i].robj = reloc->robj; track->textures[1].cube_info[i].robj = reloc->robj;
break; break;
case RADEON_PP_CUBIC_OFFSET_T2_0: case RADEON_PP_CUBIC_OFFSET_T2_0:
...@@ -1242,12 +1239,12 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1242,12 +1239,12 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
track->textures[2].cube_info[i].offset = ib_chunk->kdata[idx]; track->textures[2].cube_info[i].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[2].cube_info[i].robj = reloc->robj; track->textures[2].cube_info[i].robj = reloc->robj;
break; break;
case RADEON_RE_WIDTH_HEIGHT: case RADEON_RE_WIDTH_HEIGHT:
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF); track->maxy = ((idx_value >> 16) & 0x7FF);
break; break;
case RADEON_RB3D_COLORPITCH: case RADEON_RB3D_COLORPITCH:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -1263,17 +1260,17 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1263,17 +1260,17 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags; tmp |= tile_flags;
ib[idx] = tmp; ib[idx] = tmp;
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK; track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
break; break;
case RADEON_RB3D_DEPTHPITCH: case RADEON_RB3D_DEPTHPITCH:
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK; track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
break; break;
case RADEON_RB3D_CNTL: case RADEON_RB3D_CNTL:
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
case 7: case 7:
case 8: case 8:
case 9: case 9:
...@@ -1291,13 +1288,13 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1291,13 +1288,13 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
break; break;
default: default:
DRM_ERROR("Invalid color buffer format (%d) !\n", DRM_ERROR("Invalid color buffer format (%d) !\n",
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
return -EINVAL; return -EINVAL;
} }
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE); track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
break; break;
case RADEON_RB3D_ZSTENCILCNTL: case RADEON_RB3D_ZSTENCILCNTL:
switch (ib_chunk->kdata[idx] & 0xf) { switch (idx_value & 0xf) {
case 0: case 0:
track->zb.cpp = 2; track->zb.cpp = 2;
break; break;
...@@ -1321,44 +1318,44 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1321,44 +1318,44 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case RADEON_PP_CNTL: case RADEON_PP_CNTL:
{ {
uint32_t temp = ib_chunk->kdata[idx] >> 4; uint32_t temp = idx_value >> 4;
for (i = 0; i < track->num_texture; i++) for (i = 0; i < track->num_texture; i++)
track->textures[i].enabled = !!(temp & (1 << i)); track->textures[i].enabled = !!(temp & (1 << i));
} }
break; break;
case RADEON_SE_VF_CNTL: case RADEON_SE_VF_CNTL:
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = idx_value;
break; break;
case RADEON_SE_VTX_FMT: case RADEON_SE_VTX_FMT:
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx]); track->vtx_size = r100_get_vtx_size(idx_value);
break; break;
case RADEON_PP_TEX_SIZE_0: case RADEON_PP_TEX_SIZE_0:
case RADEON_PP_TEX_SIZE_1: case RADEON_PP_TEX_SIZE_1:
case RADEON_PP_TEX_SIZE_2: case RADEON_PP_TEX_SIZE_2:
i = (reg - RADEON_PP_TEX_SIZE_0) / 8; i = (reg - RADEON_PP_TEX_SIZE_0) / 8;
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1; track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
break; break;
case RADEON_PP_TEX_PITCH_0: case RADEON_PP_TEX_PITCH_0:
case RADEON_PP_TEX_PITCH_1: case RADEON_PP_TEX_PITCH_1:
case RADEON_PP_TEX_PITCH_2: case RADEON_PP_TEX_PITCH_2:
i = (reg - RADEON_PP_TEX_PITCH_0) / 8; i = (reg - RADEON_PP_TEX_PITCH_0) / 8;
track->textures[i].pitch = ib_chunk->kdata[idx] + 32; track->textures[i].pitch = idx_value + 32;
break; break;
case RADEON_PP_TXFILTER_0: case RADEON_PP_TXFILTER_0:
case RADEON_PP_TXFILTER_1: case RADEON_PP_TXFILTER_1:
case RADEON_PP_TXFILTER_2: case RADEON_PP_TXFILTER_2:
i = (reg - RADEON_PP_TXFILTER_0) / 24; i = (reg - RADEON_PP_TXFILTER_0) / 24;
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & RADEON_MAX_MIP_LEVEL_MASK) track->textures[i].num_levels = ((idx_value & RADEON_MAX_MIP_LEVEL_MASK)
>> RADEON_MAX_MIP_LEVEL_SHIFT); >> RADEON_MAX_MIP_LEVEL_SHIFT);
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7; tmp = (idx_value >> 23) & 0x7;
if (tmp == 2 || tmp == 6) if (tmp == 2 || tmp == 6)
track->textures[i].roundup_w = false; track->textures[i].roundup_w = false;
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7; tmp = (idx_value >> 27) & 0x7;
if (tmp == 2 || tmp == 6) if (tmp == 2 || tmp == 6)
track->textures[i].roundup_h = false; track->textures[i].roundup_h = false;
break; break;
...@@ -1366,16 +1363,16 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1366,16 +1363,16 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
case RADEON_PP_TXFORMAT_1: case RADEON_PP_TXFORMAT_1:
case RADEON_PP_TXFORMAT_2: case RADEON_PP_TXFORMAT_2:
i = (reg - RADEON_PP_TXFORMAT_0) / 24; i = (reg - RADEON_PP_TXFORMAT_0) / 24;
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_NON_POWER2) { if (idx_value & RADEON_TXFORMAT_NON_POWER2) {
track->textures[i].use_pitch = 1; track->textures[i].use_pitch = 1;
} else { } else {
track->textures[i].use_pitch = 0; 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].width = 1 << ((idx_value >> 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); track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
} }
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE)
track->textures[i].tex_coord_type = 2; track->textures[i].tex_coord_type = 2;
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) { switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
case RADEON_TXFORMAT_I8: case RADEON_TXFORMAT_I8:
case RADEON_TXFORMAT_RGB332: case RADEON_TXFORMAT_RGB332:
case RADEON_TXFORMAT_Y8: case RADEON_TXFORMAT_Y8:
...@@ -1402,13 +1399,13 @@ static int r100_packet0_check(struct radeon_cs_parser *p, ...@@ -1402,13 +1399,13 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
track->textures[i].cpp = 4; track->textures[i].cpp = 4;
break; break;
} }
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf); track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf); track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
break; break;
case RADEON_PP_CUBIC_FACES_0: case RADEON_PP_CUBIC_FACES_0:
case RADEON_PP_CUBIC_FACES_1: case RADEON_PP_CUBIC_FACES_1:
case RADEON_PP_CUBIC_FACES_2: case RADEON_PP_CUBIC_FACES_2:
tmp = ib_chunk->kdata[idx]; tmp = idx_value;
i = (reg - RADEON_PP_CUBIC_FACES_0) / 4; i = (reg - RADEON_PP_CUBIC_FACES_0) / 4;
for (face = 0; face < 4; face++) { for (face = 0; face < 4; face++) {
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
...@@ -1427,15 +1424,14 @@ int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, ...@@ -1427,15 +1424,14 @@ int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
struct radeon_object *robj) struct radeon_object *robj)
{ {
struct radeon_cs_chunk *ib_chunk;
unsigned idx; unsigned idx;
u32 value;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1; idx = pkt->idx + 1;
if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) { value = radeon_get_ib_value(p, idx + 2);
if ((value + 1) > radeon_object_size(robj)) {
DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
"(need %u have %lu) !\n", "(need %u have %lu) !\n",
ib_chunk->kdata[idx+2] + 1, value + 1,
radeon_object_size(robj)); radeon_object_size(robj));
return -EINVAL; return -EINVAL;
} }
...@@ -1445,59 +1441,20 @@ int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, ...@@ -1445,59 +1441,20 @@ int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
static int r100_packet3_check(struct radeon_cs_parser *p, static int r100_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt) struct radeon_cs_packet *pkt)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r100_cs_track *track; struct r100_cs_track *track;
unsigned idx; unsigned idx;
unsigned i, c;
volatile uint32_t *ib; volatile uint32_t *ib;
int r; int r;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1; idx = pkt->idx + 1;
track = (struct r100_cs_track *)p->track; track = (struct r100_cs_track *)p->track;
switch (pkt->opcode) { switch (pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR: case PACKET3_3D_LOAD_VBPNTR:
c = ib_chunk->kdata[idx++]; r = r100_packet3_load_vbpntr(p, pkt, idx);
track->num_arrays = c; if (r)
for (i = 0; i < (c - 1); i += 2, idx += 3) { return r;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
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",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
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);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
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; break;
case PACKET3_INDX_BUFFER: case PACKET3_INDX_BUFFER:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -1506,7 +1463,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p, ...@@ -1506,7 +1463,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset);
r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
if (r) { if (r) {
return r; return r;
...@@ -1520,27 +1477,27 @@ static int r100_packet3_check(struct radeon_cs_parser *p, ...@@ -1520,27 +1477,27 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset);
track->num_arrays = 1; track->num_arrays = 1;
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx+2]); track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 2));
track->arrays[0].robj = reloc->robj; track->arrays[0].robj = reloc->robj;
track->arrays[0].esize = track->vtx_size; track->arrays[0].esize = track->vtx_size;
track->max_indx = ib_chunk->kdata[idx+1]; track->max_indx = radeon_get_ib_value(p, idx+1);
track->vap_vf_cntl = ib_chunk->kdata[idx+3]; track->vap_vf_cntl = radeon_get_ib_value(p, idx+3);
track->immd_dwords = pkt->count - 1; track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
return r; return r;
break; break;
case PACKET3_3D_DRAW_IMMD: case PACKET3_3D_DRAW_IMMD:
if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) { if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL; return -EINVAL;
} }
track->vap_vf_cntl = ib_chunk->kdata[idx+1]; track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
track->immd_dwords = pkt->count - 1; track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
...@@ -1548,11 +1505,11 @@ static int r100_packet3_check(struct radeon_cs_parser *p, ...@@ -1548,11 +1505,11 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
break; break;
/* triggers drawing using in-packet vertex data */ /* triggers drawing using in-packet vertex data */
case PACKET3_3D_DRAW_IMMD_2: case PACKET3_3D_DRAW_IMMD_2:
if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) { if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL; return -EINVAL;
} }
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = radeon_get_ib_value(p, idx);
track->immd_dwords = pkt->count; track->immd_dwords = pkt->count;
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
...@@ -1560,28 +1517,28 @@ static int r100_packet3_check(struct radeon_cs_parser *p, ...@@ -1560,28 +1517,28 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
break; break;
/* triggers drawing using in-packet vertex data */ /* triggers drawing using in-packet vertex data */
case PACKET3_3D_DRAW_VBUF_2: case PACKET3_3D_DRAW_VBUF_2:
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
return r; return r;
break; break;
/* triggers drawing of vertex buffers setup elsewhere */ /* triggers drawing of vertex buffers setup elsewhere */
case PACKET3_3D_DRAW_INDX_2: case PACKET3_3D_DRAW_INDX_2:
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
return r; return r;
break; break;
/* triggers drawing using indices to vertex buffer */ /* triggers drawing using indices to vertex buffer */
case PACKET3_3D_DRAW_VBUF: case PACKET3_3D_DRAW_VBUF:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
return r; return r;
break; break;
/* triggers drawing of vertex buffers setup elsewhere */ /* triggers drawing of vertex buffers setup elsewhere */
case PACKET3_3D_DRAW_INDX: case PACKET3_3D_DRAW_INDX:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) if (r)
return r; return r;
......
...@@ -84,6 +84,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -84,6 +84,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg); unsigned idx, unsigned reg);
static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p, static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx, unsigned idx,
...@@ -93,9 +95,7 @@ static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p, ...@@ -93,9 +95,7 @@ static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
u32 tile_flags = 0; u32 tile_flags = 0;
u32 tmp; u32 tmp;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct radeon_cs_chunk *ib_chunk; u32 value;
ib_chunk = &p->chunks[p->chunk_ib_idx];
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
if (r) { if (r) {
...@@ -104,7 +104,8 @@ static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p, ...@@ -104,7 +104,8 @@ static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
tmp = ib_chunk->kdata[idx] & 0x003fffff; value = radeon_get_ib_value(p, idx);
tmp = value & 0x003fffff;
tmp += (((u32)reloc->lobj.gpu_offset) >> 10); tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
...@@ -119,6 +120,64 @@ static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p, ...@@ -119,6 +120,64 @@ static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
} }
tmp |= tile_flags; tmp |= tile_flags;
p->ib->ptr[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp; p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
return 0; return 0;
} }
static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
int idx)
{
unsigned c, i;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
int r = 0;
volatile uint32_t *ib;
u32 idx_value;
ib = p->ib->ptr;
track = (struct r100_cs_track *)p->track;
c = radeon_get_ib_value(p, idx++) & 0x1F;
track->num_arrays = c;
for (i = 0; i < (c - 1); i+=2, idx+=3) {
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
return r;
}
idx_value = radeon_get_ib_value(p, idx);
ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
track->arrays[i + 0].esize = idx_value >> 8;
track->arrays[i + 0].robj = reloc->robj;
track->arrays[i + 0].esize &= 0x7F;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
return r;
}
ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
track->arrays[i + 1].robj = reloc->robj;
track->arrays[i + 1].esize = idx_value >> 24;
track->arrays[i + 1].esize &= 0x7F;
}
if (c & 1) {
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
return r;
}
idx_value = radeon_get_ib_value(p, idx);
ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
track->arrays[i + 0].robj = reloc->robj;
track->arrays[i + 0].esize = idx_value >> 8;
track->arrays[i + 0].esize &= 0x7F;
}
return r;
}
...@@ -96,7 +96,6 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -96,7 +96,6 @@ int r200_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg) unsigned idx, unsigned reg)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r100_cs_track *track; struct r100_cs_track *track;
volatile uint32_t *ib; volatile uint32_t *ib;
...@@ -105,11 +104,11 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -105,11 +104,11 @@ int r200_packet0_check(struct radeon_cs_parser *p,
int i; int i;
int face; int face;
u32 tile_flags = 0; u32 tile_flags = 0;
u32 idx_value;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track; track = (struct r100_cs_track *)p->track;
idx_value = radeon_get_ib_value(p, idx);
switch (reg) { switch (reg) {
case RADEON_CRTC_GUI_TRIG_VLINE: case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p); r = r100_cs_packet_parse_vline(p);
...@@ -137,8 +136,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -137,8 +136,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
return r; return r;
} }
track->zb.robj = reloc->robj; track->zb.robj = reloc->robj;
track->zb.offset = ib_chunk->kdata[idx]; track->zb.offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case RADEON_RB3D_COLOROFFSET: case RADEON_RB3D_COLOROFFSET:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -149,8 +148,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -149,8 +148,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
return r; return r;
} }
track->cb[0].robj = reloc->robj; track->cb[0].robj = reloc->robj;
track->cb[0].offset = ib_chunk->kdata[idx]; track->cb[0].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case R200_PP_TXOFFSET_0: case R200_PP_TXOFFSET_0:
case R200_PP_TXOFFSET_1: case R200_PP_TXOFFSET_1:
...@@ -166,7 +165,7 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -166,7 +165,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj; track->textures[i].robj = reloc->robj;
break; break;
case R200_PP_CUBIC_OFFSET_F1_0: case R200_PP_CUBIC_OFFSET_F1_0:
...@@ -208,12 +207,12 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -208,12 +207,12 @@ int r200_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
track->textures[i].cube_info[face - 1].offset = ib_chunk->kdata[idx]; track->textures[i].cube_info[face - 1].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].cube_info[face - 1].robj = reloc->robj; track->textures[i].cube_info[face - 1].robj = reloc->robj;
break; break;
case RADEON_RE_WIDTH_HEIGHT: case RADEON_RE_WIDTH_HEIGHT:
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF); track->maxy = ((idx_value >> 16) & 0x7FF);
break; break;
case RADEON_RB3D_COLORPITCH: case RADEON_RB3D_COLORPITCH:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -229,17 +228,17 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -229,17 +228,17 @@ int r200_packet0_check(struct radeon_cs_parser *p,
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags; tmp |= tile_flags;
ib[idx] = tmp; ib[idx] = tmp;
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK; track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
break; break;
case RADEON_RB3D_DEPTHPITCH: case RADEON_RB3D_DEPTHPITCH:
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK; track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
break; break;
case RADEON_RB3D_CNTL: case RADEON_RB3D_CNTL:
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
case 7: case 7:
case 8: case 8:
case 9: case 9:
...@@ -257,18 +256,18 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -257,18 +256,18 @@ int r200_packet0_check(struct radeon_cs_parser *p,
break; break;
default: default:
DRM_ERROR("Invalid color buffer format (%d) !\n", DRM_ERROR("Invalid color buffer format (%d) !\n",
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
return -EINVAL; return -EINVAL;
} }
if (ib_chunk->kdata[idx] & RADEON_DEPTHXY_OFFSET_ENABLE) { if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
DRM_ERROR("No support for depth xy offset in kms\n"); DRM_ERROR("No support for depth xy offset in kms\n");
return -EINVAL; return -EINVAL;
} }
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE); track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
break; break;
case RADEON_RB3D_ZSTENCILCNTL: case RADEON_RB3D_ZSTENCILCNTL:
switch (ib_chunk->kdata[idx] & 0xf) { switch (idx_value & 0xf) {
case 0: case 0:
track->zb.cpp = 2; track->zb.cpp = 2;
break; break;
...@@ -292,27 +291,27 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -292,27 +291,27 @@ int r200_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case RADEON_PP_CNTL: case RADEON_PP_CNTL:
{ {
uint32_t temp = ib_chunk->kdata[idx] >> 4; uint32_t temp = idx_value >> 4;
for (i = 0; i < track->num_texture; i++) for (i = 0; i < track->num_texture; i++)
track->textures[i].enabled = !!(temp & (1 << i)); track->textures[i].enabled = !!(temp & (1 << i));
} }
break; break;
case RADEON_SE_VF_CNTL: case RADEON_SE_VF_CNTL:
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = idx_value;
break; break;
case 0x210c: case 0x210c:
/* VAP_VF_MAX_VTX_INDX */ /* VAP_VF_MAX_VTX_INDX */
track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL; track->max_indx = idx_value & 0x00FFFFFFUL;
break; break;
case R200_SE_VTX_FMT_0: case R200_SE_VTX_FMT_0:
track->vtx_size = r200_get_vtx_size_0(ib_chunk->kdata[idx]); track->vtx_size = r200_get_vtx_size_0(idx_value);
break; break;
case R200_SE_VTX_FMT_1: case R200_SE_VTX_FMT_1:
track->vtx_size += r200_get_vtx_size_1(ib_chunk->kdata[idx]); track->vtx_size += r200_get_vtx_size_1(idx_value);
break; break;
case R200_PP_TXSIZE_0: case R200_PP_TXSIZE_0:
case R200_PP_TXSIZE_1: case R200_PP_TXSIZE_1:
...@@ -321,8 +320,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -321,8 +320,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_PP_TXSIZE_4: case R200_PP_TXSIZE_4:
case R200_PP_TXSIZE_5: case R200_PP_TXSIZE_5:
i = (reg - R200_PP_TXSIZE_0) / 32; i = (reg - R200_PP_TXSIZE_0) / 32;
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1; track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
break; break;
case R200_PP_TXPITCH_0: case R200_PP_TXPITCH_0:
case R200_PP_TXPITCH_1: case R200_PP_TXPITCH_1:
...@@ -331,7 +330,7 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -331,7 +330,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_PP_TXPITCH_4: case R200_PP_TXPITCH_4:
case R200_PP_TXPITCH_5: case R200_PP_TXPITCH_5:
i = (reg - R200_PP_TXPITCH_0) / 32; i = (reg - R200_PP_TXPITCH_0) / 32;
track->textures[i].pitch = ib_chunk->kdata[idx] + 32; track->textures[i].pitch = idx_value + 32;
break; break;
case R200_PP_TXFILTER_0: case R200_PP_TXFILTER_0:
case R200_PP_TXFILTER_1: case R200_PP_TXFILTER_1:
...@@ -340,12 +339,12 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -340,12 +339,12 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_PP_TXFILTER_4: case R200_PP_TXFILTER_4:
case R200_PP_TXFILTER_5: case R200_PP_TXFILTER_5:
i = (reg - R200_PP_TXFILTER_0) / 32; i = (reg - R200_PP_TXFILTER_0) / 32;
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & R200_MAX_MIP_LEVEL_MASK) track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
>> R200_MAX_MIP_LEVEL_SHIFT); >> R200_MAX_MIP_LEVEL_SHIFT);
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7; tmp = (idx_value >> 23) & 0x7;
if (tmp == 2 || tmp == 6) if (tmp == 2 || tmp == 6)
track->textures[i].roundup_w = false; track->textures[i].roundup_w = false;
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7; tmp = (idx_value >> 27) & 0x7;
if (tmp == 2 || tmp == 6) if (tmp == 2 || tmp == 6)
track->textures[i].roundup_h = false; track->textures[i].roundup_h = false;
break; break;
...@@ -364,8 +363,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -364,8 +363,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_PP_TXFORMAT_X_4: case R200_PP_TXFORMAT_X_4:
case R200_PP_TXFORMAT_X_5: case R200_PP_TXFORMAT_X_5:
i = (reg - R200_PP_TXFORMAT_X_0) / 32; i = (reg - R200_PP_TXFORMAT_X_0) / 32;
track->textures[i].txdepth = ib_chunk->kdata[idx] & 0x7; track->textures[i].txdepth = idx_value & 0x7;
tmp = (ib_chunk->kdata[idx] >> 16) & 0x3; tmp = (idx_value >> 16) & 0x3;
/* 2D, 3D, CUBE */ /* 2D, 3D, CUBE */
switch (tmp) { switch (tmp) {
case 0: case 0:
...@@ -389,14 +388,14 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -389,14 +388,14 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_PP_TXFORMAT_4: case R200_PP_TXFORMAT_4:
case R200_PP_TXFORMAT_5: case R200_PP_TXFORMAT_5:
i = (reg - R200_PP_TXFORMAT_0) / 32; i = (reg - R200_PP_TXFORMAT_0) / 32;
if (ib_chunk->kdata[idx] & R200_TXFORMAT_NON_POWER2) { if (idx_value & R200_TXFORMAT_NON_POWER2) {
track->textures[i].use_pitch = 1; track->textures[i].use_pitch = 1;
} else { } else {
track->textures[i].use_pitch = 0; 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].width = 1 << ((idx_value >> 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); track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
} }
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) { switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
case R200_TXFORMAT_I8: case R200_TXFORMAT_I8:
case R200_TXFORMAT_RGB332: case R200_TXFORMAT_RGB332:
case R200_TXFORMAT_Y8: case R200_TXFORMAT_Y8:
...@@ -424,8 +423,8 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -424,8 +423,8 @@ int r200_packet0_check(struct radeon_cs_parser *p,
track->textures[i].cpp = 4; track->textures[i].cpp = 4;
break; break;
} }
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf); track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf); track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
break; break;
case R200_PP_CUBIC_FACES_0: case R200_PP_CUBIC_FACES_0:
case R200_PP_CUBIC_FACES_1: case R200_PP_CUBIC_FACES_1:
...@@ -433,7 +432,7 @@ int r200_packet0_check(struct radeon_cs_parser *p, ...@@ -433,7 +432,7 @@ int r200_packet0_check(struct radeon_cs_parser *p,
case R200_PP_CUBIC_FACES_3: case R200_PP_CUBIC_FACES_3:
case R200_PP_CUBIC_FACES_4: case R200_PP_CUBIC_FACES_4:
case R200_PP_CUBIC_FACES_5: case R200_PP_CUBIC_FACES_5:
tmp = ib_chunk->kdata[idx]; tmp = idx_value;
i = (reg - R200_PP_CUBIC_FACES_0) / 32; i = (reg - R200_PP_CUBIC_FACES_0) / 32;
for (face = 0; face < 4; face++) { for (face = 0; face < 4; face++) {
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
......
...@@ -697,17 +697,18 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -697,17 +697,18 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg) unsigned idx, unsigned reg)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r100_cs_track *track; struct r100_cs_track *track;
volatile uint32_t *ib; volatile uint32_t *ib;
uint32_t tmp, tile_flags = 0; uint32_t tmp, tile_flags = 0;
unsigned i; unsigned i;
int r; int r;
u32 idx_value;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track; track = (struct r100_cs_track *)p->track;
idx_value = radeon_get_ib_value(p, idx);
switch(reg) { switch(reg) {
case AVIVO_D1MODE_VLINE_START_END: case AVIVO_D1MODE_VLINE_START_END:
case RADEON_CRTC_GUI_TRIG_VLINE: case RADEON_CRTC_GUI_TRIG_VLINE:
...@@ -738,8 +739,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -738,8 +739,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
return r; return r;
} }
track->cb[i].robj = reloc->robj; track->cb[i].robj = reloc->robj;
track->cb[i].offset = ib_chunk->kdata[idx]; track->cb[i].offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case R300_ZB_DEPTHOFFSET: case R300_ZB_DEPTHOFFSET:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -750,8 +751,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -750,8 +751,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
return r; return r;
} }
track->zb.robj = reloc->robj; track->zb.robj = reloc->robj;
track->zb.offset = ib_chunk->kdata[idx]; track->zb.offset = idx_value;
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case R300_TX_OFFSET_0: case R300_TX_OFFSET_0:
case R300_TX_OFFSET_0+4: case R300_TX_OFFSET_0+4:
...@@ -777,32 +778,32 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -777,32 +778,32 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj; track->textures[i].robj = reloc->robj;
break; break;
/* Tracked registers */ /* Tracked registers */
case 0x2084: case 0x2084:
/* VAP_VF_CNTL */ /* VAP_VF_CNTL */
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = idx_value;
break; break;
case 0x20B4: case 0x20B4:
/* VAP_VTX_SIZE */ /* VAP_VTX_SIZE */
track->vtx_size = ib_chunk->kdata[idx] & 0x7F; track->vtx_size = idx_value & 0x7F;
break; break;
case 0x2134: case 0x2134:
/* VAP_VF_MAX_VTX_INDX */ /* VAP_VF_MAX_VTX_INDX */
track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL; track->max_indx = idx_value & 0x00FFFFFFUL;
break; break;
case 0x43E4: case 0x43E4:
/* SC_SCISSOR1 */ /* SC_SCISSOR1 */
track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1; track->maxy = ((idx_value >> 13) & 0x1FFF) + 1;
if (p->rdev->family < CHIP_RV515) { if (p->rdev->family < CHIP_RV515) {
track->maxy -= 1440; track->maxy -= 1440;
} }
break; break;
case 0x4E00: case 0x4E00:
/* RB3D_CCTL */ /* RB3D_CCTL */
track->num_cb = ((ib_chunk->kdata[idx] >> 5) & 0x3) + 1; track->num_cb = ((idx_value >> 5) & 0x3) + 1;
break; break;
case 0x4E38: case 0x4E38:
case 0x4E3C: case 0x4E3C:
...@@ -825,13 +826,13 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -825,13 +826,13 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_COLOR_MICROTILE_ENABLE; tile_flags |= R300_COLOR_MICROTILE_ENABLE;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags; tmp |= tile_flags;
ib[idx] = tmp; ib[idx] = tmp;
i = (reg - 0x4E38) >> 2; i = (reg - 0x4E38) >> 2;
track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; track->cb[i].pitch = idx_value & 0x3FFE;
switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { switch (((idx_value >> 21) & 0xF)) {
case 9: case 9:
case 11: case 11:
case 12: case 12:
...@@ -854,13 +855,13 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -854,13 +855,13 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
break; break;
default: default:
DRM_ERROR("Invalid color buffer format (%d) !\n", DRM_ERROR("Invalid color buffer format (%d) !\n",
((ib_chunk->kdata[idx] >> 21) & 0xF)); ((idx_value >> 21) & 0xF));
return -EINVAL; return -EINVAL;
} }
break; break;
case 0x4F00: case 0x4F00:
/* ZB_CNTL */ /* ZB_CNTL */
if (ib_chunk->kdata[idx] & 2) { if (idx_value & 2) {
track->z_enabled = true; track->z_enabled = true;
} else { } else {
track->z_enabled = false; track->z_enabled = false;
...@@ -868,7 +869,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -868,7 +869,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
break; break;
case 0x4F10: case 0x4F10:
/* ZB_FORMAT */ /* ZB_FORMAT */
switch ((ib_chunk->kdata[idx] & 0xF)) { switch ((idx_value & 0xF)) {
case 0: case 0:
case 1: case 1:
track->zb.cpp = 2; track->zb.cpp = 2;
...@@ -878,7 +879,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -878,7 +879,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
break; break;
default: default:
DRM_ERROR("Invalid z buffer format (%d) !\n", DRM_ERROR("Invalid z buffer format (%d) !\n",
(ib_chunk->kdata[idx] & 0xF)); (idx_value & 0xF));
return -EINVAL; return -EINVAL;
} }
break; break;
...@@ -897,17 +898,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -897,17 +898,17 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_DEPTHMICROTILE_TILED;; tile_flags |= R300_DEPTHMICROTILE_TILED;;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16); tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags; tmp |= tile_flags;
ib[idx] = tmp; ib[idx] = tmp;
track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; track->zb.pitch = idx_value & 0x3FFC;
break; break;
case 0x4104: case 0x4104:
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
bool enabled; bool enabled;
enabled = !!(ib_chunk->kdata[idx] & (1 << i)); enabled = !!(idx_value & (1 << i));
track->textures[i].enabled = enabled; track->textures[i].enabled = enabled;
} }
break; break;
...@@ -929,9 +930,9 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -929,9 +930,9 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case 0x44FC: case 0x44FC:
/* TX_FORMAT1_[0-15] */ /* TX_FORMAT1_[0-15] */
i = (reg - 0x44C0) >> 2; i = (reg - 0x44C0) >> 2;
tmp = (ib_chunk->kdata[idx] >> 25) & 0x3; tmp = (idx_value >> 25) & 0x3;
track->textures[i].tex_coord_type = tmp; track->textures[i].tex_coord_type = tmp;
switch ((ib_chunk->kdata[idx] & 0x1F)) { switch ((idx_value & 0x1F)) {
case R300_TX_FORMAT_X8: case R300_TX_FORMAT_X8:
case R300_TX_FORMAT_Y4X4: case R300_TX_FORMAT_Y4X4:
case R300_TX_FORMAT_Z3Y3X2: case R300_TX_FORMAT_Z3Y3X2:
...@@ -971,7 +972,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -971,7 +972,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
break; break;
default: default:
DRM_ERROR("Invalid texture format %u\n", DRM_ERROR("Invalid texture format %u\n",
(ib_chunk->kdata[idx] & 0x1F)); (idx_value & 0x1F));
return -EINVAL; return -EINVAL;
break; break;
} }
...@@ -994,11 +995,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -994,11 +995,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case 0x443C: case 0x443C:
/* TX_FILTER0_[0-15] */ /* TX_FILTER0_[0-15] */
i = (reg - 0x4400) >> 2; i = (reg - 0x4400) >> 2;
tmp = ib_chunk->kdata[idx] & 0x7; tmp = idx_value & 0x7;
if (tmp == 2 || tmp == 4 || tmp == 6) { if (tmp == 2 || tmp == 4 || tmp == 6) {
track->textures[i].roundup_w = false; track->textures[i].roundup_w = false;
} }
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7; tmp = (idx_value >> 3) & 0x7;
if (tmp == 2 || tmp == 4 || tmp == 6) { if (tmp == 2 || tmp == 4 || tmp == 6) {
track->textures[i].roundup_h = false; track->textures[i].roundup_h = false;
} }
...@@ -1021,12 +1022,12 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1021,12 +1022,12 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case 0x453C: case 0x453C:
/* TX_FORMAT2_[0-15] */ /* TX_FORMAT2_[0-15] */
i = (reg - 0x4500) >> 2; i = (reg - 0x4500) >> 2;
tmp = ib_chunk->kdata[idx] & 0x3FFF; tmp = idx_value & 0x3FFF;
track->textures[i].pitch = tmp + 1; track->textures[i].pitch = tmp + 1;
if (p->rdev->family >= CHIP_RV515) { if (p->rdev->family >= CHIP_RV515) {
tmp = ((ib_chunk->kdata[idx] >> 15) & 1) << 11; tmp = ((idx_value >> 15) & 1) << 11;
track->textures[i].width_11 = tmp; track->textures[i].width_11 = tmp;
tmp = ((ib_chunk->kdata[idx] >> 16) & 1) << 11; tmp = ((idx_value >> 16) & 1) << 11;
track->textures[i].height_11 = tmp; track->textures[i].height_11 = tmp;
} }
break; break;
...@@ -1048,15 +1049,15 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1048,15 +1049,15 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
case 0x44BC: case 0x44BC:
/* TX_FORMAT0_[0-15] */ /* TX_FORMAT0_[0-15] */
i = (reg - 0x4480) >> 2; i = (reg - 0x4480) >> 2;
tmp = ib_chunk->kdata[idx] & 0x7FF; tmp = idx_value & 0x7FF;
track->textures[i].width = tmp + 1; track->textures[i].width = tmp + 1;
tmp = (ib_chunk->kdata[idx] >> 11) & 0x7FF; tmp = (idx_value >> 11) & 0x7FF;
track->textures[i].height = tmp + 1; track->textures[i].height = tmp + 1;
tmp = (ib_chunk->kdata[idx] >> 26) & 0xF; tmp = (idx_value >> 26) & 0xF;
track->textures[i].num_levels = tmp; track->textures[i].num_levels = tmp;
tmp = ib_chunk->kdata[idx] & (1 << 31); tmp = idx_value & (1 << 31);
track->textures[i].use_pitch = !!tmp; track->textures[i].use_pitch = !!tmp;
tmp = (ib_chunk->kdata[idx] >> 22) & 0xF; tmp = (idx_value >> 22) & 0xF;
track->textures[i].txdepth = tmp; track->textures[i].txdepth = tmp;
break; break;
case R300_ZB_ZPASS_ADDR: case R300_ZB_ZPASS_ADDR:
...@@ -1067,7 +1068,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1067,7 +1068,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break; break;
case 0x4be8: case 0x4be8:
/* valid register only on RV530 */ /* valid register only on RV530 */
...@@ -1085,60 +1086,20 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1085,60 +1086,20 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
static int r300_packet3_check(struct radeon_cs_parser *p, static int r300_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt) struct radeon_cs_packet *pkt)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r100_cs_track *track; struct r100_cs_track *track;
volatile uint32_t *ib; volatile uint32_t *ib;
unsigned idx; unsigned idx;
unsigned i, c;
int r; int r;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1; idx = pkt->idx + 1;
track = (struct r100_cs_track *)p->track; track = (struct r100_cs_track *)p->track;
switch(pkt->opcode) { switch(pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR: case PACKET3_3D_LOAD_VBPNTR:
c = ib_chunk->kdata[idx++] & 0x1F; r = r100_packet3_load_vbpntr(p, pkt, idx);
track->num_arrays = c; if (r)
for (i = 0; i < (c - 1); i+=2, idx+=3) { return r;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
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",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
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);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
pkt->opcode);
r100_cs_dump_packet(p, pkt);
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; break;
case PACKET3_INDX_BUFFER: case PACKET3_INDX_BUFFER:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -1147,7 +1108,7 @@ static int r300_packet3_check(struct radeon_cs_parser *p, ...@@ -1147,7 +1108,7 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
r100_cs_dump_packet(p, pkt); r100_cs_dump_packet(p, pkt);
return r; return r;
} }
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
if (r) { if (r) {
return r; return r;
...@@ -1158,11 +1119,11 @@ static int r300_packet3_check(struct radeon_cs_parser *p, ...@@ -1158,11 +1119,11 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
/* Number of dwords is vtx_size * (num_vertices - 1) /* Number of dwords is vtx_size * (num_vertices - 1)
* PRIM_WALK must be equal to 3 vertex data in embedded * PRIM_WALK must be equal to 3 vertex data in embedded
* in cmd stream */ * in cmd stream */
if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) { if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL; return -EINVAL;
} }
track->vap_vf_cntl = ib_chunk->kdata[idx+1]; track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
track->immd_dwords = pkt->count - 1; track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) { if (r) {
...@@ -1173,11 +1134,11 @@ static int r300_packet3_check(struct radeon_cs_parser *p, ...@@ -1173,11 +1134,11 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
/* Number of dwords is vtx_size * (num_vertices - 1) /* Number of dwords is vtx_size * (num_vertices - 1)
* PRIM_WALK must be equal to 3 vertex data in embedded * PRIM_WALK must be equal to 3 vertex data in embedded
* in cmd stream */ * in cmd stream */
if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) { if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL; return -EINVAL;
} }
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = radeon_get_ib_value(p, idx);
track->immd_dwords = pkt->count; track->immd_dwords = pkt->count;
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) { if (r) {
...@@ -1185,28 +1146,28 @@ static int r300_packet3_check(struct radeon_cs_parser *p, ...@@ -1185,28 +1146,28 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
} }
break; break;
case PACKET3_3D_DRAW_VBUF: case PACKET3_3D_DRAW_VBUF:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) { if (r) {
return r; return r;
} }
break; break;
case PACKET3_3D_DRAW_VBUF_2: case PACKET3_3D_DRAW_VBUF_2:
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) { if (r) {
return r; return r;
} }
break; break;
case PACKET3_3D_DRAW_INDX: case PACKET3_3D_DRAW_INDX:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1]; track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) { if (r) {
return r; return r;
} }
break; break;
case PACKET3_3D_DRAW_INDX_2: case PACKET3_3D_DRAW_INDX_2:
track->vap_vf_cntl = ib_chunk->kdata[idx]; track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track); r = r100_cs_track_check(p->rdev, track);
if (r) { if (r) {
return r; return r;
......
...@@ -445,6 +445,8 @@ ...@@ -445,6 +445,8 @@
#define AVIVO_D1MODE_VBLANK_STATUS 0x6534 #define AVIVO_D1MODE_VBLANK_STATUS 0x6534
# define AVIVO_VBLANK_ACK (1 << 4) # define AVIVO_VBLANK_ACK (1 << 4)
#define AVIVO_D1MODE_VLINE_START_END 0x6538 #define AVIVO_D1MODE_VLINE_START_END 0x6538
#define AVIVO_D1MODE_VLINE_STATUS 0x653c
# define AVIVO_D1MODE_VLINE_STAT (1 << 12)
#define AVIVO_DxMODE_INT_MASK 0x6540 #define AVIVO_DxMODE_INT_MASK 0x6540
# define AVIVO_D1MODE_INT_MASK (1 << 0) # define AVIVO_D1MODE_INT_MASK (1 << 0)
# define AVIVO_D2MODE_INT_MASK (1 << 8) # define AVIVO_D2MODE_INT_MASK (1 << 8)
...@@ -502,6 +504,7 @@ ...@@ -502,6 +504,7 @@
#define AVIVO_D2MODE_VBLANK_STATUS 0x6d34 #define AVIVO_D2MODE_VBLANK_STATUS 0x6d34
#define AVIVO_D2MODE_VLINE_START_END 0x6d38 #define AVIVO_D2MODE_VLINE_START_END 0x6d38
#define AVIVO_D2MODE_VLINE_STATUS 0x6d3c
#define AVIVO_D2MODE_VIEWPORT_START 0x6d80 #define AVIVO_D2MODE_VIEWPORT_START 0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84
#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88
......
...@@ -26,108 +26,13 @@ ...@@ -26,108 +26,13 @@
* Jerome Glisse * Jerome Glisse
*/ */
#include "drmP.h" #include "drmP.h"
#include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "atom.h"
#include "r520d.h"
/* r520,rv530,rv560,rv570,r580 depends on : */ /* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */
void r100_hdp_reset(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);
int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
/* This files gather functions specifics to: static int r520_mc_wait_for_idle(struct radeon_device *rdev)
* r520,rv530,rv560,rv570,r580
*
* Some of these functions might be used by newer ASICs.
*/
void r520_gpu_init(struct radeon_device *rdev);
int r520_mc_wait_for_idle(struct radeon_device *rdev);
/*
* MC
*/
int r520_mc_init(struct radeon_device *rdev)
{
uint32_t tmp;
int r;
if (r100_debugfs_rbbm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for RBBM !\n");
}
if (rv515_debugfs_pipes_info_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for pipes !\n");
}
if (rv515_debugfs_ga_info_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for pipes !\n");
}
r520_gpu_init(rdev);
rv370_pcie_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;
}
/* Program GPU memory space */
rs600_mc_disable_clients(rdev);
if (r520_mc_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
}
/* Write VRAM size in case we are limiting it */
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);
WREG32(RS690_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(R520_MC_AGP_TOP, tmp >> 16);
tmp |= REG_SET(R520_MC_AGP_START, rdev->mc.gtt_location >> 16);
WREG32_MC(R520_MC_AGP_LOCATION, tmp);
WREG32_MC(R520_MC_AGP_BASE, rdev->mc.agp_base);
WREG32_MC(R520_MC_AGP_BASE_2, 0);
} else {
WREG32_MC(R520_MC_AGP_LOCATION, 0x0FFFFFFF);
WREG32_MC(R520_MC_AGP_BASE, 0);
WREG32_MC(R520_MC_AGP_BASE_2, 0);
}
return 0;
}
void r520_mc_fini(struct radeon_device *rdev)
{
}
/*
* Global GPU functions
*/
void r520_errata(struct radeon_device *rdev)
{
rdev->pll_errata = 0;
}
int r520_mc_wait_for_idle(struct radeon_device *rdev)
{ {
unsigned i; unsigned i;
uint32_t tmp; uint32_t tmp;
...@@ -143,12 +48,12 @@ int r520_mc_wait_for_idle(struct radeon_device *rdev) ...@@ -143,12 +48,12 @@ int r520_mc_wait_for_idle(struct radeon_device *rdev)
return -1; return -1;
} }
void r520_gpu_init(struct radeon_device *rdev) static void r520_gpu_init(struct radeon_device *rdev)
{ {
unsigned pipe_select_current, gb_pipe_select, tmp; unsigned pipe_select_current, gb_pipe_select, tmp;
r100_hdp_reset(rdev); r100_hdp_reset(rdev);
rs600_disable_vga(rdev); rv515_vga_render_disable(rdev);
/* /*
* DST_PIPE_CONFIG 0x170C * DST_PIPE_CONFIG 0x170C
* GB_TILE_CONFIG 0x4018 * GB_TILE_CONFIG 0x4018
...@@ -186,10 +91,6 @@ void r520_gpu_init(struct radeon_device *rdev) ...@@ -186,10 +91,6 @@ void r520_gpu_init(struct radeon_device *rdev)
} }
} }
/*
* VRAM info
*/
static void r520_vram_get_type(struct radeon_device *rdev) static void r520_vram_get_type(struct radeon_device *rdev)
{ {
uint32_t tmp; uint32_t tmp;
...@@ -233,7 +134,168 @@ void r520_vram_info(struct radeon_device *rdev) ...@@ -233,7 +134,168 @@ void r520_vram_info(struct radeon_device *rdev)
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
} }
void r520_bandwidth_update(struct radeon_device *rdev) void r520_mc_program(struct radeon_device *rdev)
{
struct rv515_mc_save save;
/* Stops all mc clients */
rv515_mc_stop(rdev, &save);
/* Wait for mc idle */
if (r520_mc_wait_for_idle(rdev))
dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
/* Write VRAM size in case we are limiting it */
WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
/* Program MC, should be a 32bits limited address space */
WREG32_MC(R_000004_MC_FB_LOCATION,
S_000004_MC_FB_START(rdev->mc.vram_start >> 16) |
S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16));
WREG32(R_000134_HDP_FB_LOCATION,
S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
if (rdev->flags & RADEON_IS_AGP) {
WREG32_MC(R_000005_MC_AGP_LOCATION,
S_000005_MC_AGP_START(rdev->mc.gtt_start >> 16) |
S_000005_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
WREG32_MC(R_000006_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
WREG32_MC(R_000007_AGP_BASE_2,
S_000007_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base)));
} else {
WREG32_MC(R_000005_MC_AGP_LOCATION, 0xFFFFFFFF);
WREG32_MC(R_000006_AGP_BASE, 0);
WREG32_MC(R_000007_AGP_BASE_2, 0);
}
rv515_mc_resume(rdev, &save);
}
static int r520_startup(struct radeon_device *rdev)
{
int r;
r520_mc_program(rdev);
/* Resume clock */
rv515_clock_startup(rdev);
/* Initialize GPU configuration (# pipes, ...) */
r520_gpu_init(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;
}
/* 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 r520_resume(struct radeon_device *rdev)
{ {
rv515_bandwidth_avivo_update(rdev); /* Make sur GART are not working */
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_disable(rdev);
/* Resume clock before doing reset */
rv515_clock_startup(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));
}
/* post */
atom_asic_init(rdev->mode_info.atom_context);
/* Resume clock after posting */
rv515_clock_startup(rdev);
return r520_startup(rdev);
}
int r520_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 {
dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n");
return -EINVAL;
}
/* 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");
atom_asic_init(rdev->mode_info.atom_context);
}
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Get vram informations */
r520_vram_info(rdev);
/* Initialize memory controller (also test AGP) */
r = r420_mc_init(rdev);
if (r)
return r;
rv515_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;
r = rv370_pcie_gart_init(rdev);
if (r)
return r;
rv515_set_safe_registers(rdev);
rdev->accel_working = true;
r = r520_startup(rdev);
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rv515_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;
} }
/*
* 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 __R520D_H__
#define __R520D_H__
/* Registers */
#define R_0000F8_CONFIG_MEMSIZE 0x0000F8
#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0)
#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_0000F8_CONFIG_MEMSIZE 0x00000000
#define R_000134_HDP_FB_LOCATION 0x000134
#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0)
#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF)
#define C_000134_HDP_FB_START 0xFFFF0000
#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_RBBM_HIBUSY(x) (((x) & 0x1) << 28)
#define G_000E40_RBBM_HIBUSY(x) (((x) >> 28) & 0x1)
#define C_000E40_RBBM_HIBUSY 0xEFFFFFFF
#define S_000E40_SKID_CFBUSY(x) (((x) & 0x1) << 29)
#define G_000E40_SKID_CFBUSY(x) (((x) >> 29) & 0x1)
#define C_000E40_SKID_CFBUSY 0xDFFFFFFF
#define S_000E40_VAP_VF_BUSY(x) (((x) & 0x1) << 30)
#define G_000E40_VAP_VF_BUSY(x) (((x) >> 30) & 0x1)
#define C_000E40_VAP_VF_BUSY 0xBFFFFFFF
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
#define R_000004_MC_FB_LOCATION 0x000004
#define S_000004_MC_FB_START(x) (((x) & 0xFFFF) << 0)
#define G_000004_MC_FB_START(x) (((x) >> 0) & 0xFFFF)
#define C_000004_MC_FB_START 0xFFFF0000
#define S_000004_MC_FB_TOP(x) (((x) & 0xFFFF) << 16)
#define G_000004_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF)
#define C_000004_MC_FB_TOP 0x0000FFFF
#define R_000005_MC_AGP_LOCATION 0x000005
#define S_000005_MC_AGP_START(x) (((x) & 0xFFFF) << 0)
#define G_000005_MC_AGP_START(x) (((x) >> 0) & 0xFFFF)
#define C_000005_MC_AGP_START 0xFFFF0000
#define S_000005_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16)
#define G_000005_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF)
#define C_000005_MC_AGP_TOP 0x0000FFFF
#define R_000006_AGP_BASE 0x000006
#define S_000006_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
#define G_000006_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_000006_AGP_BASE_ADDR 0x00000000
#define R_000007_AGP_BASE_2 0x000007
#define S_000007_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0)
#define G_000007_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF)
#define C_000007_AGP_BASE_ADDR_2 0xFFFFFFF0
#endif
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
#include "radeon.h" #include "radeon.h"
#include "radeon_mode.h" #include "radeon_mode.h"
#include "r600d.h" #include "r600d.h"
#include "avivod.h"
#include "atom.h" #include "atom.h"
#include "avivod.h"
#define PFP_UCODE_SIZE 576 #define PFP_UCODE_SIZE 576
#define PM4_UCODE_SIZE 1792 #define PM4_UCODE_SIZE 1792
...@@ -342,7 +342,7 @@ static void r600_mc_resume(struct radeon_device *rdev) ...@@ -342,7 +342,7 @@ static void r600_mc_resume(struct radeon_device *rdev)
/* we need to own VRAM, so turn off the VGA renderer here /* we need to own VRAM, so turn off the VGA renderer here
* to stop it overwriting our objects */ * to stop it overwriting our objects */
radeon_avivo_vga_render_disable(rdev); rv515_vga_render_disable(rdev);
} }
int r600_mc_init(struct radeon_device *rdev) int r600_mc_init(struct radeon_device *rdev)
...@@ -380,6 +380,13 @@ int r600_mc_init(struct radeon_device *rdev) ...@@ -380,6 +380,13 @@ int r600_mc_init(struct radeon_device *rdev)
/* Setup GPU memory space */ /* Setup GPU memory space */
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
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;
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
if (r) if (r)
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "drmP.h" #include "drmP.h"
#include "radeon.h" #include "radeon.h"
#include "r600d.h" #include "r600d.h"
#include "avivod.h"
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc); struct radeon_cs_reloc **cs_reloc);
...@@ -57,7 +56,7 @@ int r600_cs_packet_parse(struct radeon_cs_parser *p, ...@@ -57,7 +56,7 @@ int r600_cs_packet_parse(struct radeon_cs_parser *p,
idx, ib_chunk->length_dw); idx, ib_chunk->length_dw);
return -EINVAL; return -EINVAL;
} }
header = ib_chunk->kdata[idx]; header = radeon_get_ib_value(p, idx);
pkt->idx = idx; pkt->idx = idx;
pkt->type = CP_PACKET_GET_TYPE(header); pkt->type = CP_PACKET_GET_TYPE(header);
pkt->count = CP_PACKET_GET_COUNT(header); pkt->count = CP_PACKET_GET_COUNT(header);
...@@ -98,7 +97,6 @@ int r600_cs_packet_parse(struct radeon_cs_parser *p, ...@@ -98,7 +97,6 @@ int r600_cs_packet_parse(struct radeon_cs_parser *p,
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc) struct radeon_cs_reloc **cs_reloc)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_chunk *relocs_chunk; struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc; struct radeon_cs_packet p3reloc;
unsigned idx; unsigned idx;
...@@ -109,7 +107,6 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, ...@@ -109,7 +107,6 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
*cs_reloc = NULL; *cs_reloc = NULL;
ib_chunk = &p->chunks[p->chunk_ib_idx];
relocs_chunk = &p->chunks[p->chunk_relocs_idx]; relocs_chunk = &p->chunks[p->chunk_relocs_idx];
r = r600_cs_packet_parse(p, &p3reloc, p->idx); r = r600_cs_packet_parse(p, &p3reloc, p->idx);
if (r) { if (r) {
...@@ -121,7 +118,7 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, ...@@ -121,7 +118,7 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
p3reloc.idx); p3reloc.idx);
return -EINVAL; return -EINVAL;
} }
idx = ib_chunk->kdata[p3reloc.idx + 1]; idx = radeon_get_ib_value(p, p3reloc.idx + 1);
if (idx >= relocs_chunk->length_dw) { if (idx >= relocs_chunk->length_dw) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
idx, relocs_chunk->length_dw); idx, relocs_chunk->length_dw);
...@@ -146,7 +143,6 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, ...@@ -146,7 +143,6 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc) struct radeon_cs_reloc **cs_reloc)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_chunk *relocs_chunk; struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc; struct radeon_cs_packet p3reloc;
unsigned idx; unsigned idx;
...@@ -157,7 +153,6 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, ...@@ -157,7 +153,6 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
*cs_reloc = NULL; *cs_reloc = NULL;
ib_chunk = &p->chunks[p->chunk_ib_idx];
relocs_chunk = &p->chunks[p->chunk_relocs_idx]; relocs_chunk = &p->chunks[p->chunk_relocs_idx];
r = r600_cs_packet_parse(p, &p3reloc, p->idx); r = r600_cs_packet_parse(p, &p3reloc, p->idx);
if (r) { if (r) {
...@@ -169,7 +164,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, ...@@ -169,7 +164,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
p3reloc.idx); p3reloc.idx);
return -EINVAL; return -EINVAL;
} }
idx = ib_chunk->kdata[p3reloc.idx + 1]; idx = radeon_get_ib_value(p, p3reloc.idx + 1);
if (idx >= relocs_chunk->length_dw) { if (idx >= relocs_chunk->length_dw) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
idx, relocs_chunk->length_dw); idx, relocs_chunk->length_dw);
...@@ -181,13 +176,136 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, ...@@ -181,13 +176,136 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
return 0; return 0;
} }
/**
* r600_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
* PACKET3 - WAIT_REG_MEM poll vline status reg
* RELOC (P3) - crtc_id in reloc.
*
* This function parses this and relocates the VLINE START END
* and WAIT_REG_MEM packets to the correct crtc.
* It also detects a switched off crtc and nulls out the
* wait in that case.
*/
static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
{
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
struct radeon_cs_packet p3reloc, wait_reg_mem;
int crtc_id;
int r;
uint32_t header, h_idx, reg, wait_reg_mem_info;
volatile uint32_t *ib;
ib = p->ib->ptr;
/* parse the WAIT_REG_MEM */
r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
if (r)
return r;
/* check its a WAIT_REG_MEM */
if (wait_reg_mem.type != PACKET_TYPE3 ||
wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
r = -EINVAL;
return r;
}
wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
/* bit 4 is reg (0) or mem (1) */
if (wait_reg_mem_info & 0x10) {
DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
r = -EINVAL;
return r;
}
/* waiting for value to be equal */
if ((wait_reg_mem_info & 0x7) != 0x3) {
DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
r = -EINVAL;
return r;
}
if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
r = -EINVAL;
return r;
}
if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
r = -EINVAL;
return r;
}
/* jump over the NOP */
r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
if (r)
return r;
h_idx = p->idx - 2;
p->idx += wait_reg_mem.count + 2;
p->idx += p3reloc.count + 2;
header = radeon_get_ib_value(p, h_idx);
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
reg = header >> 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_REG_MEM */
ib[h_idx + 2] = PACKET2(0);
ib[h_idx + 3] = PACKET2(0);
ib[h_idx + 4] = PACKET2(0);
ib[h_idx + 5] = PACKET2(0);
ib[h_idx + 6] = PACKET2(0);
ib[h_idx + 7] = PACKET2(0);
ib[h_idx + 8] = PACKET2(0);
} else if (crtc_id == 1) {
switch (reg) {
case AVIVO_D1MODE_VLINE_START_END:
header &= ~R600_CP_PACKET0_REG_MASK;
header |= AVIVO_D2MODE_VLINE_START_END >> 2;
break;
default:
DRM_ERROR("unknown crtc reloc\n");
r = -EINVAL;
goto out;
}
ib[h_idx] = header;
ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
}
out:
mutex_unlock(&p->rdev->ddev->mode_config.mutex);
return r;
}
static int r600_packet0_check(struct radeon_cs_parser *p, static int r600_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg) unsigned idx, unsigned reg)
{ {
int r;
switch (reg) { switch (reg) {
case AVIVO_D1MODE_VLINE_START_END: case AVIVO_D1MODE_VLINE_START_END:
case AVIVO_D2MODE_VLINE_START_END: r = r600_cs_packet_parse_vline(p);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
return r;
}
break; break;
default: default:
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
...@@ -218,17 +336,18 @@ static int r600_cs_parse_packet0(struct radeon_cs_parser *p, ...@@ -218,17 +336,18 @@ static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
static int r600_packet3_check(struct radeon_cs_parser *p, static int r600_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt) struct radeon_cs_packet *pkt)
{ {
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
volatile u32 *ib; volatile u32 *ib;
unsigned idx; unsigned idx;
unsigned i; unsigned i;
unsigned start_reg, end_reg, reg; unsigned start_reg, end_reg, reg;
int r; int r;
u32 idx_value;
ib = p->ib->ptr; ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1; idx = pkt->idx + 1;
idx_value = radeon_get_ib_value(p, idx);
switch (pkt->opcode) { switch (pkt->opcode) {
case PACKET3_START_3D_CMDBUF: case PACKET3_START_3D_CMDBUF:
if (p->family >= CHIP_RV770 || pkt->count) { if (p->family >= CHIP_RV770 || pkt->count) {
...@@ -259,8 +378,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -259,8 +378,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad DRAW_INDEX\n"); DRM_ERROR("bad DRAW_INDEX\n");
return -EINVAL; return -EINVAL;
} }
ib[idx+0] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+1] = upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
break; break;
case PACKET3_DRAW_INDEX_AUTO: case PACKET3_DRAW_INDEX_AUTO:
if (pkt->count != 1) { if (pkt->count != 1) {
...@@ -281,14 +400,14 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -281,14 +400,14 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
/* bit 4 is reg (0) or mem (1) */ /* bit 4 is reg (0) or mem (1) */
if (ib_chunk->kdata[idx+0] & 0x10) { if (idx_value & 0x10) {
r = r600_cs_packet_next_reloc(p, &reloc); r = r600_cs_packet_next_reloc(p, &reloc);
if (r) { if (r) {
DRM_ERROR("bad WAIT_REG_MEM\n"); DRM_ERROR("bad WAIT_REG_MEM\n");
return -EINVAL; return -EINVAL;
} }
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] = upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
} }
break; break;
case PACKET3_SURFACE_SYNC: case PACKET3_SURFACE_SYNC:
...@@ -297,8 +416,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -297,8 +416,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
/* 0xffffffff/0x0 is flush all cache flag */ /* 0xffffffff/0x0 is flush all cache flag */
if (ib_chunk->kdata[idx+1] != 0xffffffff || if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
ib_chunk->kdata[idx+2] != 0) { radeon_get_ib_value(p, idx + 2) != 0) {
r = r600_cs_packet_next_reloc(p, &reloc); r = r600_cs_packet_next_reloc(p, &reloc);
if (r) { if (r) {
DRM_ERROR("bad SURFACE_SYNC\n"); DRM_ERROR("bad SURFACE_SYNC\n");
...@@ -319,7 +438,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -319,7 +438,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
} }
break; break;
case PACKET3_EVENT_WRITE_EOP: case PACKET3_EVENT_WRITE_EOP:
...@@ -333,10 +452,10 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -333,10 +452,10 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
break; break;
case PACKET3_SET_CONFIG_REG: case PACKET3_SET_CONFIG_REG:
start_reg = (ib[idx+0] << 2) + PACKET3_SET_CONFIG_REG_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) || if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
(start_reg >= PACKET3_SET_CONFIG_REG_END) || (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
...@@ -356,7 +475,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -356,7 +475,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
} }
break; break;
case PACKET3_SET_CONTEXT_REG: case PACKET3_SET_CONTEXT_REG:
start_reg = (ib[idx+0] << 2) + PACKET3_SET_CONTEXT_REG_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) || if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
(start_reg >= PACKET3_SET_CONTEXT_REG_END) || (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
...@@ -421,7 +540,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -421,7 +540,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad SET_RESOURCE\n"); DRM_ERROR("bad SET_RESOURCE\n");
return -EINVAL; return -EINVAL;
} }
start_reg = (ib[idx+0] << 2) + PACKET3_SET_RESOURCE_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) || if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
(start_reg >= PACKET3_SET_RESOURCE_END) || (start_reg >= PACKET3_SET_RESOURCE_END) ||
...@@ -430,7 +549,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -430,7 +549,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
for (i = 0; i < (pkt->count / 7); i++) { for (i = 0; i < (pkt->count / 7); i++) {
switch (G__SQ_VTX_CONSTANT_TYPE(ib[idx+(i*7)+6+1])) { switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
case SQ_TEX_VTX_VALID_TEXTURE: case SQ_TEX_VTX_VALID_TEXTURE:
/* tex base */ /* tex base */
r = r600_cs_packet_next_reloc(p, &reloc); r = r600_cs_packet_next_reloc(p, &reloc);
...@@ -455,7 +574,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -455,7 +574,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
return -EINVAL; return -EINVAL;
} }
ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
ib[idx+1+(i*7)+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff; ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
break; break;
case SQ_TEX_VTX_INVALID_TEXTURE: case SQ_TEX_VTX_INVALID_TEXTURE:
case SQ_TEX_VTX_INVALID_BUFFER: case SQ_TEX_VTX_INVALID_BUFFER:
...@@ -466,7 +585,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -466,7 +585,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
} }
break; break;
case PACKET3_SET_ALU_CONST: case PACKET3_SET_ALU_CONST:
start_reg = (ib[idx+0] << 2) + PACKET3_SET_ALU_CONST_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) || if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_ALU_CONST_END) || (start_reg >= PACKET3_SET_ALU_CONST_END) ||
...@@ -476,7 +595,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -476,7 +595,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
} }
break; break;
case PACKET3_SET_BOOL_CONST: case PACKET3_SET_BOOL_CONST:
start_reg = (ib[idx+0] << 2) + PACKET3_SET_BOOL_CONST_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) || if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_BOOL_CONST_END) || (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
...@@ -486,7 +605,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -486,7 +605,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
} }
break; break;
case PACKET3_SET_LOOP_CONST: case PACKET3_SET_LOOP_CONST:
start_reg = (ib[idx+0] << 2) + PACKET3_SET_LOOP_CONST_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) || if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_LOOP_CONST_END) || (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
...@@ -496,7 +615,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -496,7 +615,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
} }
break; break;
case PACKET3_SET_CTL_CONST: case PACKET3_SET_CTL_CONST:
start_reg = (ib[idx+0] << 2) + PACKET3_SET_CTL_CONST_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) || if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_CTL_CONST_END) || (start_reg >= PACKET3_SET_CTL_CONST_END) ||
...@@ -510,7 +629,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, ...@@ -510,7 +629,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
DRM_ERROR("bad SET_SAMPLER\n"); DRM_ERROR("bad SET_SAMPLER\n");
return -EINVAL; return -EINVAL;
} }
start_reg = (ib[idx+0] << 2) + PACKET3_SET_SAMPLER_OFFSET; start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4; end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) || if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
(start_reg >= PACKET3_SET_SAMPLER_END) || (start_reg >= PACKET3_SET_SAMPLER_END) ||
...@@ -602,6 +721,8 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error) ...@@ -602,6 +721,8 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
kfree(parser->relocs); kfree(parser->relocs);
for (i = 0; i < parser->nchunks; i++) { for (i = 0; i < parser->nchunks; i++) {
kfree(parser->chunks[i].kdata); kfree(parser->chunks[i].kdata);
kfree(parser->chunks[i].kpage[0]);
kfree(parser->chunks[i].kpage[1]);
} }
kfree(parser->chunks); kfree(parser->chunks);
kfree(parser->chunks_array); kfree(parser->chunks_array);
...@@ -639,7 +760,6 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, ...@@ -639,7 +760,6 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
* uncached). */ * uncached). */
ib_chunk = &parser.chunks[parser.chunk_ib_idx]; ib_chunk = &parser.chunks[parser.chunk_ib_idx];
parser.ib->length_dw = ib_chunk->length_dw; parser.ib->length_dw = ib_chunk->length_dw;
memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
*l = parser.ib->length_dw; *l = parser.ib->length_dw;
r = r600_cs_parse(&parser); r = r600_cs_parse(&parser);
if (r) { if (r) {
...@@ -647,6 +767,12 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, ...@@ -647,6 +767,12 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
r600_cs_parser_fini(&parser, r); r600_cs_parser_fini(&parser, r);
return r; return r;
} }
r = radeon_cs_finish_pages(&parser);
if (r) {
DRM_ERROR("Invalid command stream !\n");
r600_cs_parser_fini(&parser, r);
return r;
}
r600_cs_parser_fini(&parser, r); r600_cs_parser_fini(&parser, r);
return r; return r;
} }
......
...@@ -44,6 +44,24 @@ ...@@ -44,6 +44,24 @@
* - TESTING, TESTING, TESTING * - TESTING, TESTING, TESTING
*/ */
/* Initialization path:
* We expect that acceleration initialization might fail for various
* reasons even thought we work hard to make it works on most
* configurations. In order to still have a working userspace in such
* situation the init path must succeed up to the memory controller
* initialization point. Failure before this point are considered as
* fatal error. Here is the init callchain :
* radeon_device_init perform common structure, mutex initialization
* asic_init setup the GPU memory layout and perform all
* one time initialization (failure in this
* function are considered fatal)
* asic_startup setup the GPU acceleration, in order to
* follow guideline the first thing this
* function should do is setting the GPU
* memory controller (only MC setup failure
* are considered as fatal)
*/
#include <asm/atomic.h> #include <asm/atomic.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -342,7 +360,7 @@ struct radeon_ib { ...@@ -342,7 +360,7 @@ struct radeon_ib {
unsigned long idx; unsigned long idx;
uint64_t gpu_addr; uint64_t gpu_addr;
struct radeon_fence *fence; struct radeon_fence *fence;
volatile uint32_t *ptr; uint32_t *ptr;
uint32_t length_dw; uint32_t length_dw;
}; };
...@@ -415,7 +433,12 @@ struct radeon_cs_reloc { ...@@ -415,7 +433,12 @@ struct radeon_cs_reloc {
struct radeon_cs_chunk { struct radeon_cs_chunk {
uint32_t chunk_id; uint32_t chunk_id;
uint32_t length_dw; uint32_t length_dw;
int kpage_idx[2];
uint32_t *kpage[2];
uint32_t *kdata; uint32_t *kdata;
void __user *user_ptr;
int last_copied_page;
int last_page_index;
}; };
struct radeon_cs_parser { struct radeon_cs_parser {
...@@ -438,8 +461,38 @@ struct radeon_cs_parser { ...@@ -438,8 +461,38 @@ struct radeon_cs_parser {
struct radeon_ib *ib; struct radeon_ib *ib;
void *track; void *track;
unsigned family; unsigned family;
int parser_error;
}; };
extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
static inline u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
{
struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
u32 pg_idx, pg_offset;
u32 idx_value = 0;
int new_page;
pg_idx = (idx * 4) / PAGE_SIZE;
pg_offset = (idx * 4) % PAGE_SIZE;
if (ibc->kpage_idx[0] == pg_idx)
return ibc->kpage[0][pg_offset/4];
if (ibc->kpage_idx[1] == pg_idx)
return ibc->kpage[1][pg_offset/4];
new_page = radeon_cs_update_pages(p, pg_idx);
if (new_page < 0) {
p->parser_error = new_page;
return 0;
}
idx_value = ibc->kpage[new_page][pg_offset/4];
return idx_value;
}
struct radeon_cs_packet { struct radeon_cs_packet {
unsigned idx; unsigned idx;
unsigned type; unsigned type;
...@@ -943,6 +996,7 @@ extern void radeon_clocks_fini(struct radeon_device *rdev); ...@@ -943,6 +996,7 @@ extern void radeon_clocks_fini(struct radeon_device *rdev);
extern void radeon_scratch_init(struct radeon_device *rdev); extern void radeon_scratch_init(struct radeon_device *rdev);
extern void radeon_surface_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); extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
struct r100_mc_save { struct r100_mc_save {
...@@ -974,6 +1028,9 @@ extern void r100_vram_init_sizes(struct radeon_device *rdev); ...@@ -974,6 +1028,9 @@ extern void r100_vram_init_sizes(struct radeon_device *rdev);
extern void r100_wb_disable(struct radeon_device *rdev); extern void r100_wb_disable(struct radeon_device *rdev);
extern void r100_wb_fini(struct radeon_device *rdev); extern void r100_wb_fini(struct radeon_device *rdev);
extern int r100_wb_init(struct radeon_device *rdev); extern int r100_wb_init(struct radeon_device *rdev);
extern void r100_hdp_reset(struct radeon_device *rdev);
extern int r100_rb2d_reset(struct radeon_device *rdev);
extern int r100_cp_reset(struct radeon_device *rdev);
/* r300,r350,rv350,rv370,rv380 */ /* r300,r350,rv350,rv370,rv380 */
extern void r300_set_reg_safe(struct radeon_device *rdev); extern void r300_set_reg_safe(struct radeon_device *rdev);
...@@ -985,12 +1042,29 @@ extern int rv370_pcie_gart_enable(struct radeon_device *rdev); ...@@ -985,12 +1042,29 @@ extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
extern void rv370_pcie_gart_disable(struct radeon_device *rdev); extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
/* r420,r423,rv410 */ /* r420,r423,rv410 */
extern int r420_mc_init(struct radeon_device *rdev);
extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg); 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 void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev); extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
extern void r420_pipes_init(struct radeon_device *rdev);
/* rv515 */ /* rv515 */
struct rv515_mc_save {
u32 d1vga_control;
u32 d2vga_control;
u32 vga_render_control;
u32 vga_hdp_control;
u32 d1crtc_control;
u32 d2crtc_control;
};
extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev); extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
extern void rv515_vga_render_disable(struct radeon_device *rdev);
extern void rv515_set_safe_registers(struct radeon_device *rdev);
extern void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save);
extern void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save);
extern void rv515_clock_startup(struct radeon_device *rdev);
extern void rv515_debugfs(struct radeon_device *rdev);
extern int rv515_suspend(struct radeon_device *rdev);
/* rs690, rs740 */ /* rs690, rs740 */
extern void rs690_line_buffer_adjust(struct radeon_device *rdev, extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
......
...@@ -420,41 +420,43 @@ static struct radeon_asic rs690_asic = { ...@@ -420,41 +420,43 @@ static struct radeon_asic rs690_asic = {
* rv515 * rv515
*/ */
int rv515_init(struct radeon_device *rdev); int rv515_init(struct radeon_device *rdev);
void rv515_errata(struct radeon_device *rdev); void rv515_fini(struct radeon_device *rdev);
void rv515_vram_info(struct radeon_device *rdev);
int rv515_gpu_reset(struct radeon_device *rdev); int rv515_gpu_reset(struct radeon_device *rdev);
int rv515_mc_init(struct radeon_device *rdev);
void rv515_mc_fini(struct radeon_device *rdev);
uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_ring_start(struct radeon_device *rdev); void rv515_ring_start(struct radeon_device *rdev);
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); 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_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_bandwidth_update(struct radeon_device *rdev); void rv515_bandwidth_update(struct radeon_device *rdev);
int rv515_resume(struct radeon_device *rdev);
int rv515_suspend(struct radeon_device *rdev);
static struct radeon_asic rv515_asic = { static struct radeon_asic rv515_asic = {
.init = &rv515_init, .init = &rv515_init,
.errata = &rv515_errata, .fini = &rv515_fini,
.vram_info = &rv515_vram_info, .suspend = &rv515_suspend,
.resume = &rv515_resume,
.errata = NULL,
.vram_info = NULL,
.vga_set_state = &r100_vga_set_state, .vga_set_state = &r100_vga_set_state,
.gpu_reset = &rv515_gpu_reset, .gpu_reset = &rv515_gpu_reset,
.mc_init = &rv515_mc_init, .mc_init = NULL,
.mc_fini = &rv515_mc_fini, .mc_fini = NULL,
.wb_init = &r100_wb_init, .wb_init = NULL,
.wb_fini = &r100_wb_fini, .wb_fini = NULL,
.gart_init = &rv370_pcie_gart_init, .gart_init = &rv370_pcie_gart_init,
.gart_fini = &rv370_pcie_gart_fini, .gart_fini = &rv370_pcie_gart_fini,
.gart_enable = &rv370_pcie_gart_enable, .gart_enable = NULL,
.gart_disable = &rv370_pcie_gart_disable, .gart_disable = NULL,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush, .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page, .gart_set_page = &rv370_pcie_gart_set_page,
.cp_init = &r100_cp_init, .cp_init = NULL,
.cp_fini = &r100_cp_fini, .cp_fini = NULL,
.cp_disable = &r100_cp_disable, .cp_disable = NULL,
.cp_commit = &r100_cp_commit, .cp_commit = &r100_cp_commit,
.ring_start = &rv515_ring_start, .ring_start = &rv515_ring_start,
.ring_test = &r100_ring_test, .ring_test = &r100_ring_test,
.ring_ib_execute = &r100_ring_ib_execute, .ring_ib_execute = &r100_ring_ib_execute,
.ib_test = &r100_ib_test, .ib_test = NULL,
.irq_set = &rs600_irq_set, .irq_set = &rs600_irq_set,
.irq_process = &rs600_irq_process, .irq_process = &rs600_irq_process,
.get_vblank_counter = &rs600_get_vblank_counter, .get_vblank_counter = &rs600_get_vblank_counter,
...@@ -476,35 +478,35 @@ static struct radeon_asic rv515_asic = { ...@@ -476,35 +478,35 @@ static struct radeon_asic rv515_asic = {
/* /*
* r520,rv530,rv560,rv570,r580 * r520,rv530,rv560,rv570,r580
*/ */
void r520_errata(struct radeon_device *rdev); int r520_init(struct radeon_device *rdev);
void r520_vram_info(struct radeon_device *rdev); int r520_resume(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 = { static struct radeon_asic r520_asic = {
.init = &rv515_init, .init = &r520_init,
.errata = &r520_errata, .fini = &rv515_fini,
.vram_info = &r520_vram_info, .suspend = &rv515_suspend,
.resume = &r520_resume,
.errata = NULL,
.vram_info = NULL,
.vga_set_state = &r100_vga_set_state, .vga_set_state = &r100_vga_set_state,
.gpu_reset = &rv515_gpu_reset, .gpu_reset = &rv515_gpu_reset,
.mc_init = &r520_mc_init, .mc_init = NULL,
.mc_fini = &r520_mc_fini, .mc_fini = NULL,
.wb_init = &r100_wb_init, .wb_init = NULL,
.wb_fini = &r100_wb_fini, .wb_fini = NULL,
.gart_init = &rv370_pcie_gart_init, .gart_init = NULL,
.gart_fini = &rv370_pcie_gart_fini, .gart_fini = NULL,
.gart_enable = &rv370_pcie_gart_enable, .gart_enable = NULL,
.gart_disable = &rv370_pcie_gart_disable, .gart_disable = NULL,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush, .gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page, .gart_set_page = &rv370_pcie_gart_set_page,
.cp_init = &r100_cp_init, .cp_init = NULL,
.cp_fini = &r100_cp_fini, .cp_fini = NULL,
.cp_disable = &r100_cp_disable, .cp_disable = NULL,
.cp_commit = &r100_cp_commit, .cp_commit = &r100_cp_commit,
.ring_start = &rv515_ring_start, .ring_start = &rv515_ring_start,
.ring_test = &r100_ring_test, .ring_test = &r100_ring_test,
.ring_ib_execute = &r100_ring_ib_execute, .ring_ib_execute = &r100_ring_ib_execute,
.ib_test = &r100_ib_test, .ib_test = NULL,
.irq_set = &rs600_irq_set, .irq_set = &rs600_irq_set,
.irq_process = &rs600_irq_process, .irq_process = &rs600_irq_process,
.get_vblank_counter = &rs600_get_vblank_counter, .get_vblank_counter = &rs600_get_vblank_counter,
...@@ -519,7 +521,7 @@ static struct radeon_asic r520_asic = { ...@@ -519,7 +521,7 @@ static struct radeon_asic r520_asic = {
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg, .set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg, .clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r520_bandwidth_update, .bandwidth_update = &rv515_bandwidth_update,
}; };
/* /*
...@@ -596,7 +598,7 @@ static struct radeon_asic r600_asic = { ...@@ -596,7 +598,7 @@ static struct radeon_asic r600_asic = {
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r600_set_surface_reg, .set_surface_reg = r600_set_surface_reg,
.clear_surface_reg = r600_clear_surface_reg, .clear_surface_reg = r600_clear_surface_reg,
.bandwidth_update = &r520_bandwidth_update, .bandwidth_update = &rv515_bandwidth_update,
}; };
/* /*
...@@ -646,7 +648,7 @@ static struct radeon_asic rv770_asic = { ...@@ -646,7 +648,7 @@ static struct radeon_asic rv770_asic = {
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r600_set_surface_reg, .set_surface_reg = r600_set_surface_reg,
.clear_surface_reg = r600_clear_surface_reg, .clear_surface_reg = r600_clear_surface_reg,
.bandwidth_update = &r520_bandwidth_update, .bandwidth_update = &rv515_bandwidth_update,
}; };
#endif #endif
...@@ -272,12 +272,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ...@@ -272,12 +272,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
(le16_to_cpu(path->usConnObjectId) & (le16_to_cpu(path->usConnObjectId) &
OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
if ((le16_to_cpu(path->usDeviceTag) == /* TODO CV support */
ATOM_DEVICE_TV1_SUPPORT) if (le16_to_cpu(path->usDeviceTag) ==
|| (le16_to_cpu(path->usDeviceTag) == ATOM_DEVICE_CV_SUPPORT)
ATOM_DEVICE_TV2_SUPPORT)
|| (le16_to_cpu(path->usDeviceTag) ==
ATOM_DEVICE_CV_SUPPORT))
continue; continue;
if ((rdev->family == CHIP_RS780) && if ((rdev->family == CHIP_RS780) &&
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "drmP.h" #include "drmP.h"
#include "drm_edid.h" #include "drm_edid.h"
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
#include "drm_fb_helper.h"
#include "radeon_drm.h" #include "radeon_drm.h"
#include "radeon.h" #include "radeon.h"
#include "atom.h" #include "atom.h"
...@@ -245,7 +246,7 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn ...@@ -245,7 +246,7 @@ static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_conn
if (common_modes[i].w < 320 || common_modes[i].h < 200) if (common_modes[i].w < 320 || common_modes[i].h < 200)
continue; continue;
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false); mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
} }
} }
...@@ -559,7 +560,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector) ...@@ -559,7 +560,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector)
radeon_add_common_modes(encoder, connector); radeon_add_common_modes(encoder, connector);
else { else {
/* only 800x600 is supported right now on pre-avivo chips */ /* only 800x600 is supported right now on pre-avivo chips */
tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false); tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false);
tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, tv_mode); drm_mode_probed_add(connector, tv_mode);
} }
...@@ -743,6 +744,15 @@ struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) ...@@ -743,6 +744,15 @@ struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
return NULL; return NULL;
} }
static void radeon_dvi_force(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
if (connector->force == DRM_FORCE_ON)
radeon_connector->use_digital = false;
if (connector->force == DRM_FORCE_ON_DIGITAL)
radeon_connector->use_digital = true;
}
struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
.get_modes = radeon_dvi_get_modes, .get_modes = radeon_dvi_get_modes,
.mode_valid = radeon_vga_mode_valid, .mode_valid = radeon_vga_mode_valid,
...@@ -755,6 +765,7 @@ struct drm_connector_funcs radeon_dvi_connector_funcs = { ...@@ -755,6 +765,7 @@ struct drm_connector_funcs radeon_dvi_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_connector_set_property, .set_property = radeon_connector_set_property,
.destroy = radeon_connector_destroy, .destroy = radeon_connector_destroy,
.force = radeon_dvi_force,
}; };
void void
...@@ -771,6 +782,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -771,6 +782,7 @@ radeon_add_atom_connector(struct drm_device *dev,
struct radeon_connector *radeon_connector; struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *radeon_dig_connector; struct radeon_connector_atom_dig *radeon_dig_connector;
uint32_t subpixel_order = SubPixelNone; uint32_t subpixel_order = SubPixelNone;
int ret;
/* fixme - tv/cv/din */ /* fixme - tv/cv/din */
if (connector_type == DRM_MODE_CONNECTOR_Unknown) if (connector_type == DRM_MODE_CONNECTOR_Unknown)
...@@ -796,24 +808,30 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -796,24 +808,30 @@ radeon_add_atom_connector(struct drm_device *dev,
switch (connector_type) { switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
goto failed; goto failed;
} }
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
break; break;
case DRM_MODE_CONNECTOR_DVIA: case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
goto failed; goto failed;
} }
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
...@@ -827,7 +845,9 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -827,7 +845,9 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -837,6 +857,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -837,6 +857,7 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.coherent_mode_property, rdev->mode_info.coherent_mode_property,
1); 1);
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
...@@ -850,7 +871,9 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -850,7 +871,9 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -869,7 +892,9 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -869,7 +892,9 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -882,11 +907,14 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -882,11 +907,14 @@ radeon_add_atom_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_9PinDIN: case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) { if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); 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); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
if (ret)
goto failed;
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
} }
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break; break;
case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_LVDS:
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
...@@ -896,7 +924,9 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -896,7 +924,9 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector; radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
...@@ -932,6 +962,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -932,6 +962,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
struct drm_connector *connector; struct drm_connector *connector;
struct radeon_connector *radeon_connector; struct radeon_connector *radeon_connector;
uint32_t subpixel_order = SubPixelNone; uint32_t subpixel_order = SubPixelNone;
int ret;
/* fixme - tv/cv/din */ /* fixme - tv/cv/din */
if (connector_type == DRM_MODE_CONNECTOR_Unknown) if (connector_type == DRM_MODE_CONNECTOR_Unknown)
...@@ -957,24 +988,30 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -957,24 +988,30 @@ radeon_add_legacy_connector(struct drm_device *dev,
switch (connector_type) { switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
goto failed; goto failed;
} }
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
break; break;
case DRM_MODE_CONNECTOR_DVIA: case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
goto failed; goto failed;
} }
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
...@@ -982,11 +1019,14 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -982,11 +1019,14 @@ radeon_add_legacy_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_DVID:
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
goto failed; goto failed;
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
...@@ -998,7 +1038,10 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -998,7 +1038,10 @@ radeon_add_legacy_connector(struct drm_device *dev,
case DRM_MODE_CONNECTOR_9PinDIN: case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) { if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); 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); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
if (ret)
goto failed;
radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base, drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
...@@ -1006,7 +1049,9 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1006,7 +1049,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
break; break;
case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_LVDS:
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
if (ret)
goto failed;
if (i2c_bus->valid) { if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
if (!radeon_connector->ddc_bus) if (!radeon_connector->ddc_bus)
......
...@@ -142,15 +142,31 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) ...@@ -142,15 +142,31 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
} }
p->chunks[i].length_dw = user_chunk.length_dw; p->chunks[i].length_dw = user_chunk.length_dw;
cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data;
size = p->chunks[i].length_dw * sizeof(uint32_t); cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
p->chunks[i].kdata = kmalloc(size, GFP_KERNEL); if (p->chunks[i].chunk_id != RADEON_CHUNK_ID_IB) {
if (p->chunks[i].kdata == NULL) { size = p->chunks[i].length_dw * sizeof(uint32_t);
return -ENOMEM; p->chunks[i].kdata = kmalloc(size, GFP_KERNEL);
} if (p->chunks[i].kdata == NULL) {
if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) { return -ENOMEM;
return -EFAULT; }
if (DRM_COPY_FROM_USER(p->chunks[i].kdata,
p->chunks[i].user_ptr, size)) {
return -EFAULT;
}
} else {
p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (p->chunks[i].kpage[0] == NULL || p->chunks[i].kpage[1] == NULL) {
kfree(p->chunks[i].kpage[0]);
kfree(p->chunks[i].kpage[1]);
return -ENOMEM;
}
p->chunks[i].kpage_idx[0] = -1;
p->chunks[i].kpage_idx[1] = -1;
p->chunks[i].last_copied_page = -1;
p->chunks[i].last_page_index = ((p->chunks[i].length_dw * 4) - 1) / PAGE_SIZE;
} }
} }
if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) { if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) {
...@@ -190,6 +206,8 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) ...@@ -190,6 +206,8 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
kfree(parser->relocs_ptr); kfree(parser->relocs_ptr);
for (i = 0; i < parser->nchunks; i++) { for (i = 0; i < parser->nchunks; i++) {
kfree(parser->chunks[i].kdata); kfree(parser->chunks[i].kdata);
kfree(parser->chunks[i].kpage[0]);
kfree(parser->chunks[i].kpage[1]);
} }
kfree(parser->chunks); kfree(parser->chunks);
kfree(parser->chunks_array); kfree(parser->chunks_array);
...@@ -238,8 +256,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -238,8 +256,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
* uncached). */ * uncached). */
ib_chunk = &parser.chunks[parser.chunk_ib_idx]; ib_chunk = &parser.chunks[parser.chunk_ib_idx];
parser.ib->length_dw = ib_chunk->length_dw; parser.ib->length_dw = ib_chunk->length_dw;
memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
r = radeon_cs_parse(&parser); r = radeon_cs_parse(&parser);
if (r || parser.parser_error) {
DRM_ERROR("Invalid command stream !\n");
radeon_cs_parser_fini(&parser, r);
mutex_unlock(&rdev->cs_mutex);
return r;
}
r = radeon_cs_finish_pages(&parser);
if (r) { if (r) {
DRM_ERROR("Invalid command stream !\n"); DRM_ERROR("Invalid command stream !\n");
radeon_cs_parser_fini(&parser, r); radeon_cs_parser_fini(&parser, r);
...@@ -254,3 +278,64 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -254,3 +278,64 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
mutex_unlock(&rdev->cs_mutex); mutex_unlock(&rdev->cs_mutex);
return r; return r;
} }
int radeon_cs_finish_pages(struct radeon_cs_parser *p)
{
struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
int i;
int size = PAGE_SIZE;
for (i = ibc->last_copied_page + 1; i <= ibc->last_page_index; i++) {
if (i == ibc->last_page_index) {
size = (ibc->length_dw * 4) % PAGE_SIZE;
if (size == 0)
size = PAGE_SIZE;
}
if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
ibc->user_ptr + (i * PAGE_SIZE),
size))
return -EFAULT;
}
return 0;
}
int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
{
int new_page;
struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
int i;
int size = PAGE_SIZE;
for (i = ibc->last_copied_page + 1; i < pg_idx; i++) {
if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
ibc->user_ptr + (i * PAGE_SIZE),
PAGE_SIZE)) {
p->parser_error = -EFAULT;
return 0;
}
}
new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1;
if (pg_idx == ibc->last_page_index) {
size = (ibc->length_dw * 4) % PAGE_SIZE;
if (size == 0)
size = PAGE_SIZE;
}
if (DRM_COPY_FROM_USER(ibc->kpage[new_page],
ibc->user_ptr + (pg_idx * PAGE_SIZE),
size)) {
p->parser_error = -EFAULT;
return 0;
}
/* copy to IB here */
memcpy((void *)(p->ib->ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size);
ibc->last_copied_page = pg_idx;
ibc->kpage_idx[new_page] = pg_idx;
return new_page;
}
...@@ -532,10 +532,13 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -532,10 +532,13 @@ int radeon_device_init(struct radeon_device *rdev,
if (radeon_agpmode == -1) { if (radeon_agpmode == -1) {
rdev->flags &= ~RADEON_IS_AGP; rdev->flags &= ~RADEON_IS_AGP;
if (rdev->family >= CHIP_RV515 || if (rdev->family >= CHIP_R600) {
rdev->family == CHIP_RV380 || DRM_INFO("Forcing AGP to PCIE mode\n");
rdev->family == CHIP_RV410 || rdev->flags |= RADEON_IS_PCIE;
rdev->family == CHIP_R423) { } else 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"); DRM_INFO("Forcing AGP to PCIE mode\n");
rdev->flags |= RADEON_IS_PCIE; rdev->flags |= RADEON_IS_PCIE;
rdev->asic->gart_init = &rv370_pcie_gart_init; rdev->asic->gart_init = &rv370_pcie_gart_init;
......
...@@ -62,9 +62,6 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev); ...@@ -62,9 +62,6 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
int radeon_driver_irq_postinstall_kms(struct drm_device *dev); int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
void radeon_driver_irq_uninstall_kms(struct drm_device *dev); void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS); irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS);
int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master);
void radeon_master_destroy_kms(struct drm_device *dev,
struct drm_master *master);
int radeon_dma_ioctl_kms(struct drm_device *dev, void *data, int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
int radeon_gem_object_init(struct drm_gem_object *obj); int radeon_gem_object_init(struct drm_gem_object *obj);
...@@ -260,8 +257,6 @@ static struct drm_driver kms_driver = { ...@@ -260,8 +257,6 @@ static struct drm_driver kms_driver = {
.get_vblank_counter = radeon_get_vblank_counter_kms, .get_vblank_counter = radeon_get_vblank_counter_kms,
.enable_vblank = radeon_enable_vblank_kms, .enable_vblank = radeon_enable_vblank_kms,
.disable_vblank = radeon_disable_vblank_kms, .disable_vblank = radeon_disable_vblank_kms,
.master_create = radeon_master_create_kms,
.master_destroy = radeon_master_destroy_kms,
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
.debugfs_init = radeon_debugfs_init, .debugfs_init = radeon_debugfs_init,
.debugfs_cleanup = radeon_debugfs_cleanup, .debugfs_cleanup = radeon_debugfs_cleanup,
......
...@@ -128,6 +128,7 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { ...@@ -128,6 +128,7 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
int radeonfb_create(struct drm_device *dev, int radeonfb_create(struct drm_device *dev,
uint32_t fb_width, uint32_t fb_height, uint32_t fb_width, uint32_t fb_height,
uint32_t surface_width, uint32_t surface_height, uint32_t surface_width, uint32_t surface_height,
uint32_t surface_depth, uint32_t surface_bpp,
struct drm_framebuffer **fb_p) struct drm_framebuffer **fb_p)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -148,10 +149,10 @@ int radeonfb_create(struct drm_device *dev, ...@@ -148,10 +149,10 @@ int radeonfb_create(struct drm_device *dev,
mode_cmd.width = surface_width; mode_cmd.width = surface_width;
mode_cmd.height = surface_height; mode_cmd.height = surface_height;
mode_cmd.bpp = 32; mode_cmd.bpp = surface_bpp;
/* need to align pitch with crtc limits */ /* need to align pitch with crtc limits */
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
mode_cmd.depth = 24; mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height; size = mode_cmd.pitch * mode_cmd.height;
aligned_size = ALIGN(size, PAGE_SIZE); aligned_size = ALIGN(size, PAGE_SIZE);
...@@ -290,13 +291,26 @@ int radeonfb_create(struct drm_device *dev, ...@@ -290,13 +291,26 @@ int radeonfb_create(struct drm_device *dev,
return ret; return ret;
} }
static char *mode_option;
int radeon_parse_options(char *options)
{
char *this_opt;
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
mode_option = this_opt;
}
return 0;
}
int radeonfb_probe(struct drm_device *dev) int radeonfb_probe(struct drm_device *dev)
{ {
int ret; return drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
return ret;
} }
EXPORT_SYMBOL(radeonfb_probe);
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
{ {
......
...@@ -200,55 +200,6 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) ...@@ -200,55 +200,6 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
} }
/*
* For multiple master (like multiple X).
*/
struct drm_radeon_master_private {
drm_local_map_t *sarea;
drm_radeon_sarea_t *sarea_priv;
};
int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master)
{
struct drm_radeon_master_private *master_priv;
unsigned long sareapage;
int ret;
master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
if (master_priv == NULL) {
return -ENOMEM;
}
/* prebuild the SAREA */
sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
ret = drm_addmap(dev, 0, sareapage, _DRM_SHM,
_DRM_CONTAINS_LOCK,
&master_priv->sarea);
if (ret) {
DRM_ERROR("SAREA setup failed\n");
return ret;
}
master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
master_priv->sarea_priv->pfCurrentPage = 0;
master->driver_priv = master_priv;
return 0;
}
void radeon_master_destroy_kms(struct drm_device *dev,
struct drm_master *master)
{
struct drm_radeon_master_private *master_priv = master->driver_priv;
if (master_priv == NULL) {
return;
}
if (master_priv->sarea) {
drm_rmmap_locked(dev, master_priv->sarea);
}
kfree(master_priv);
master->driver_priv = NULL;
}
/* /*
* IOCTL. * IOCTL.
*/ */
......
...@@ -3333,6 +3333,7 @@ ...@@ -3333,6 +3333,7 @@
# define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) # define RADEON_CP_PACKET_MAX_DWORDS (1 << 12)
# define RADEON_CP_PACKET0_REG_MASK 0x000007ff # define RADEON_CP_PACKET0_REG_MASK 0x000007ff
# define R300_CP_PACKET0_REG_MASK 0x00001fff # define R300_CP_PACKET0_REG_MASK 0x00001fff
# define R600_CP_PACKET0_REG_MASK 0x0000ffff
# define RADEON_CP_PACKET1_REG0_MASK 0x000007ff # define RADEON_CP_PACKET1_REG0_MASK 0x000007ff
# define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 # define RADEON_CP_PACKET1_REG1_MASK 0x003ff800
......
...@@ -689,9 +689,6 @@ struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev) ...@@ -689,9 +689,6 @@ struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev)
#define RADEON_DEBUGFS_MEM_TYPES 2 #define RADEON_DEBUGFS_MEM_TYPES 2
static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES];
static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES][32];
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
static int radeon_mm_dump_table(struct seq_file *m, void *data) static int radeon_mm_dump_table(struct seq_file *m, void *data)
{ {
...@@ -711,9 +708,11 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data) ...@@ -711,9 +708,11 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data)
static int radeon_ttm_debugfs_init(struct radeon_device *rdev) static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
{ {
#if defined(CONFIG_DEBUG_FS)
static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES];
static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES][32];
unsigned i; unsigned i;
#if defined(CONFIG_DEBUG_FS)
for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) { for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) {
if (i == 0) if (i == 0)
sprintf(radeon_mem_types_names[i], "radeon_vram_mm"); sprintf(radeon_mem_types_names[i], "radeon_vram_mm");
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "drmP.h" #include "drmP.h"
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "avivod.h"
#include "rs600_reg_safe.h" #include "rs600_reg_safe.h"
...@@ -45,7 +44,6 @@ void r420_pipes_init(struct radeon_device *rdev); ...@@ -45,7 +44,6 @@ void r420_pipes_init(struct radeon_device *rdev);
*/ */
void rs600_gpu_init(struct radeon_device *rdev); void rs600_gpu_init(struct radeon_device *rdev);
int rs600_mc_wait_for_idle(struct radeon_device *rdev); int rs600_mc_wait_for_idle(struct radeon_device *rdev);
void rs600_disable_vga(struct radeon_device *rdev);
/* /*
...@@ -198,7 +196,7 @@ void rs600_mc_disable_clients(struct radeon_device *rdev) ...@@ -198,7 +196,7 @@ void rs600_mc_disable_clients(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
radeon_avivo_vga_render_disable(rdev); rv515_vga_render_disable(rdev);
tmp = RREG32(AVIVO_D1VGA_CONTROL); tmp = RREG32(AVIVO_D1VGA_CONTROL);
WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
...@@ -346,20 +344,6 @@ u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc) ...@@ -346,20 +344,6 @@ u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc)
/* /*
* Global GPU functions * Global GPU functions
*/ */
void rs600_disable_vga(struct radeon_device *rdev)
{
unsigned tmp;
WREG32(0x330, 0);
WREG32(0x338, 0);
tmp = RREG32(0x300);
tmp &= ~(3 << 16);
WREG32(0x300, tmp);
WREG32(0x308, (1 << 8));
WREG32(0x310, rdev->mc.vram_location);
WREG32(0x594, 0);
}
int rs600_mc_wait_for_idle(struct radeon_device *rdev) int rs600_mc_wait_for_idle(struct radeon_device *rdev)
{ {
unsigned i; unsigned i;
...@@ -385,7 +369,7 @@ void rs600_gpu_init(struct radeon_device *rdev) ...@@ -385,7 +369,7 @@ void rs600_gpu_init(struct radeon_device *rdev)
{ {
/* FIXME: HDP same place on rs600 ? */ /* FIXME: HDP same place on rs600 ? */
r100_hdp_reset(rdev); r100_hdp_reset(rdev);
rs600_disable_vga(rdev); rv515_vga_render_disable(rdev);
/* FIXME: is this correct ? */ /* FIXME: is this correct ? */
r420_pipes_init(rdev); r420_pipes_init(rdev);
if (rs600_mc_wait_for_idle(rdev)) { if (rs600_mc_wait_for_idle(rdev)) {
......
...@@ -40,7 +40,6 @@ void rs400_gart_disable(struct radeon_device *rdev); ...@@ -40,7 +40,6 @@ void rs400_gart_disable(struct radeon_device *rdev);
int rs400_gart_enable(struct radeon_device *rdev); int rs400_gart_enable(struct radeon_device *rdev);
void rs400_gart_adjust_size(struct radeon_device *rdev); void rs400_gart_adjust_size(struct radeon_device *rdev);
void rs600_mc_disable_clients(struct radeon_device *rdev); void rs600_mc_disable_clients(struct radeon_device *rdev);
void rs600_disable_vga(struct radeon_device *rdev);
/* This files gather functions specifics to : /* This files gather functions specifics to :
* rs690,rs740 * rs690,rs740
...@@ -125,7 +124,7 @@ void rs690_gpu_init(struct radeon_device *rdev) ...@@ -125,7 +124,7 @@ void rs690_gpu_init(struct radeon_device *rdev)
{ {
/* FIXME: HDP same place on rs690 ? */ /* FIXME: HDP same place on rs690 ? */
r100_hdp_reset(rdev); r100_hdp_reset(rdev);
rs600_disable_vga(rdev); rv515_vga_render_disable(rdev);
/* FIXME: is this correct ? */ /* FIXME: is this correct ? */
r420_pipes_init(rdev); r420_pipes_init(rdev);
if (rs690_mc_wait_for_idle(rdev)) { if (rs690_mc_wait_for_idle(rdev)) {
......
...@@ -29,37 +29,17 @@ ...@@ -29,37 +29,17 @@
#include "drmP.h" #include "drmP.h"
#include "rv515d.h" #include "rv515d.h"
#include "radeon.h" #include "radeon.h"
#include "atom.h"
#include "rv515_reg_safe.h" #include "rv515_reg_safe.h"
/* rv515 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); /* This files gather functions specifics to: rv515 */
int r100_cp_reset(struct radeon_device *rdev);
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);
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);
/* This files gather functions specifics to:
* rv515
*
* Some of these functions might be used by newer ASICs.
*/
int rv515_debugfs_pipes_info_init(struct radeon_device *rdev); int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
int rv515_debugfs_ga_info_init(struct radeon_device *rdev); int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
void rv515_gpu_init(struct radeon_device *rdev); void rv515_gpu_init(struct radeon_device *rdev);
int rv515_mc_wait_for_idle(struct radeon_device *rdev); int rv515_mc_wait_for_idle(struct radeon_device *rdev);
void rv515_debugfs(struct radeon_device *rdev)
/*
* MC
*/
int rv515_mc_init(struct radeon_device *rdev)
{ {
uint32_t tmp;
int r;
if (r100_debugfs_rbbm_init(rdev)) { if (r100_debugfs_rbbm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for RBBM !\n"); DRM_ERROR("Failed to register debugfs file for RBBM !\n");
} }
...@@ -69,67 +49,8 @@ int rv515_mc_init(struct radeon_device *rdev) ...@@ -69,67 +49,8 @@ int rv515_mc_init(struct radeon_device *rdev)
if (rv515_debugfs_ga_info_init(rdev)) { if (rv515_debugfs_ga_info_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for pipes !\n"); DRM_ERROR("Failed to register debugfs file for pipes !\n");
} }
rv515_gpu_init(rdev);
rv370_pcie_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;
}
/* Program GPU memory space */
rs600_mc_disable_clients(rdev);
if (rv515_mc_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
}
/* Write VRAM size in case we are limiting it */
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.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(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(MC_AGP_LOCATION, 0x0FFFFFFF);
WREG32_MC(MC_AGP_BASE, 0);
WREG32_MC(MC_AGP_BASE_2, 0);
}
return 0;
}
void rv515_mc_fini(struct radeon_device *rdev)
{
} }
/*
* Global GPU functions
*/
void rv515_ring_start(struct radeon_device *rdev) void rv515_ring_start(struct radeon_device *rdev)
{ {
int r; int r;
...@@ -198,11 +119,6 @@ void rv515_ring_start(struct radeon_device *rdev) ...@@ -198,11 +119,6 @@ void rv515_ring_start(struct radeon_device *rdev)
radeon_ring_unlock_commit(rdev); radeon_ring_unlock_commit(rdev);
} }
void rv515_errata(struct radeon_device *rdev)
{
rdev->pll_errata = 0;
}
int rv515_mc_wait_for_idle(struct radeon_device *rdev) int rv515_mc_wait_for_idle(struct radeon_device *rdev)
{ {
unsigned i; unsigned i;
...@@ -219,6 +135,12 @@ int rv515_mc_wait_for_idle(struct radeon_device *rdev) ...@@ -219,6 +135,12 @@ int rv515_mc_wait_for_idle(struct radeon_device *rdev)
return -1; return -1;
} }
void rv515_vga_render_disable(struct radeon_device *rdev)
{
WREG32(R_000300_VGA_RENDER_CONTROL,
RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL);
}
void rv515_gpu_init(struct radeon_device *rdev) void rv515_gpu_init(struct radeon_device *rdev)
{ {
unsigned pipe_select_current, gb_pipe_select, tmp; unsigned pipe_select_current, gb_pipe_select, tmp;
...@@ -231,7 +153,7 @@ void rv515_gpu_init(struct radeon_device *rdev) ...@@ -231,7 +153,7 @@ void rv515_gpu_init(struct radeon_device *rdev)
"reseting GPU. Bad things might happen.\n"); "reseting GPU. Bad things might happen.\n");
} }
rs600_disable_vga(rdev); rv515_vga_render_disable(rdev);
r420_pipes_init(rdev); r420_pipes_init(rdev);
gb_pipe_select = RREG32(0x402C); gb_pipe_select = RREG32(0x402C);
...@@ -335,10 +257,6 @@ int rv515_gpu_reset(struct radeon_device *rdev) ...@@ -335,10 +257,6 @@ int rv515_gpu_reset(struct radeon_device *rdev)
return 0; return 0;
} }
/*
* VRAM info
*/
static void rv515_vram_get_type(struct radeon_device *rdev) static void rv515_vram_get_type(struct radeon_device *rdev)
{ {
uint32_t tmp; uint32_t tmp;
...@@ -374,10 +292,6 @@ void rv515_vram_info(struct radeon_device *rdev) ...@@ -374,10 +292,6 @@ void rv515_vram_info(struct radeon_device *rdev)
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
} }
/*
* Indirect registers accessor
*/
uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg) uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
{ {
uint32_t r; uint32_t r;
...@@ -395,9 +309,6 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) ...@@ -395,9 +309,6 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
WREG32(MC_IND_INDEX, 0); WREG32(MC_IND_INDEX, 0);
} }
/*
* Debugfs info
*/
#if defined(CONFIG_DEBUG_FS) #if defined(CONFIG_DEBUG_FS)
static int rv515_debugfs_pipes_info(struct seq_file *m, void *data) static int rv515_debugfs_pipes_info(struct seq_file *m, void *data)
{ {
...@@ -459,13 +370,258 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev) ...@@ -459,13 +370,258 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
#endif #endif
} }
/* void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
* Asic initialization {
*/ save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL);
int rv515_init(struct radeon_device *rdev) save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);
save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);
save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL);
save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);
/* Stop all video */
WREG32(R_000330_D1VGA_CONTROL, 0);
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
WREG32(R_000300_VGA_RENDER_CONTROL, 0);
WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
WREG32(R_006080_D1CRTC_CONTROL, 0);
WREG32(R_006880_D2CRTC_CONTROL, 0);
WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
}
void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
{
WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
WREG32(R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
WREG32(R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
/* Unlock host access */
WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
mdelay(1);
/* Restore video state */
WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control);
WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control);
WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control);
WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control);
WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
}
void rv515_mc_program(struct radeon_device *rdev)
{
struct rv515_mc_save save;
/* Stops all mc clients */
rv515_mc_stop(rdev, &save);
/* Wait for mc idle */
if (rv515_mc_wait_for_idle(rdev))
dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
/* Write VRAM size in case we are limiting it */
WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
/* Program MC, should be a 32bits limited address space */
WREG32_MC(R_000001_MC_FB_LOCATION,
S_000001_MC_FB_START(rdev->mc.vram_start >> 16) |
S_000001_MC_FB_TOP(rdev->mc.vram_end >> 16));
WREG32(R_000134_HDP_FB_LOCATION,
S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
if (rdev->flags & RADEON_IS_AGP) {
WREG32_MC(R_000002_MC_AGP_LOCATION,
S_000002_MC_AGP_START(rdev->mc.gtt_start >> 16) |
S_000002_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
WREG32_MC(R_000003_MC_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
WREG32_MC(R_000004_MC_AGP_BASE_2,
S_000004_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base)));
} else {
WREG32_MC(R_000002_MC_AGP_LOCATION, 0xFFFFFFFF);
WREG32_MC(R_000003_MC_AGP_BASE, 0);
WREG32_MC(R_000004_MC_AGP_BASE_2, 0);
}
rv515_mc_resume(rdev, &save);
}
void rv515_clock_startup(struct radeon_device *rdev)
{
if (radeon_dynclks != -1 && radeon_dynclks)
radeon_atom_set_clock_gating(rdev, 1);
/* We need to force on some of the block */
WREG32_PLL(R_00000F_CP_DYN_CNTL,
RREG32_PLL(R_00000F_CP_DYN_CNTL) | S_00000F_CP_FORCEON(1));
WREG32_PLL(R_000011_E2_DYN_CNTL,
RREG32_PLL(R_000011_E2_DYN_CNTL) | S_000011_E2_FORCEON(1));
WREG32_PLL(R_000013_IDCT_DYN_CNTL,
RREG32_PLL(R_000013_IDCT_DYN_CNTL) | S_000013_IDCT_FORCEON(1));
}
static int rv515_startup(struct radeon_device *rdev)
{
int r;
rv515_mc_program(rdev);
/* Resume clock */
rv515_clock_startup(rdev);
/* Initialize GPU configuration (# pipes, ...) */
rv515_gpu_init(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;
}
/* 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 rv515_resume(struct radeon_device *rdev)
{
/* Make sur GART are not working */
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_disable(rdev);
/* Resume clock before doing reset */
rv515_clock_startup(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));
}
/* post */
atom_asic_init(rdev->mode_info.atom_context);
/* Resume clock after posting */
rv515_clock_startup(rdev);
return rv515_startup(rdev);
}
int rv515_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);
return 0;
}
void rv515_set_safe_registers(struct radeon_device *rdev)
{ {
rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm; rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm;
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rv515_reg_safe_bm); rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rv515_reg_safe_bm);
}
void rv515_fini(struct radeon_device *rdev)
{
rv515_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_gem_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_object_fini(rdev);
radeon_atombios_fini(rdev);
kfree(rdev->bios);
rdev->bios = NULL;
}
int rv515_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 {
dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n");
return -EINVAL;
}
/* 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");
atom_asic_init(rdev->mode_info.atom_context);
}
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Get vram informations */
rv515_vram_info(rdev);
/* Initialize memory controller (also test AGP) */
r = r420_mc_init(rdev);
if (r)
return r;
rv515_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;
r = rv370_pcie_gart_init(rdev);
if (r)
return r;
rv515_set_safe_registers(rdev);
rdev->accel_working = true;
r = rv515_startup(rdev);
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
rv515_suspend(rdev);
r100_cp_fini(rdev);
r100_wb_fini(rdev);
r100_ib_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0; return 0;
} }
......
...@@ -216,5 +216,388 @@ ...@@ -216,5 +216,388 @@
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) #define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) #define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
#endif /* Registers */
#define R_0000F8_CONFIG_MEMSIZE 0x0000F8
#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0)
#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_0000F8_CONFIG_MEMSIZE 0x00000000
#define R_000134_HDP_FB_LOCATION 0x000134
#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0)
#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF)
#define C_000134_HDP_FB_START 0xFFFF0000
#define R_000300_VGA_RENDER_CONTROL 0x000300
#define S_000300_VGA_BLINK_RATE(x) (((x) & 0x1F) << 0)
#define G_000300_VGA_BLINK_RATE(x) (((x) >> 0) & 0x1F)
#define C_000300_VGA_BLINK_RATE 0xFFFFFFE0
#define S_000300_VGA_BLINK_MODE(x) (((x) & 0x3) << 5)
#define G_000300_VGA_BLINK_MODE(x) (((x) >> 5) & 0x3)
#define C_000300_VGA_BLINK_MODE 0xFFFFFF9F
#define S_000300_VGA_CURSOR_BLINK_INVERT(x) (((x) & 0x1) << 7)
#define G_000300_VGA_CURSOR_BLINK_INVERT(x) (((x) >> 7) & 0x1)
#define C_000300_VGA_CURSOR_BLINK_INVERT 0xFFFFFF7F
#define S_000300_VGA_EXTD_ADDR_COUNT_ENABLE(x) (((x) & 0x1) << 8)
#define G_000300_VGA_EXTD_ADDR_COUNT_ENABLE(x) (((x) >> 8) & 0x1)
#define C_000300_VGA_EXTD_ADDR_COUNT_ENABLE 0xFFFFFEFF
#define S_000300_VGA_VSTATUS_CNTL(x) (((x) & 0x3) << 16)
#define G_000300_VGA_VSTATUS_CNTL(x) (((x) >> 16) & 0x3)
#define C_000300_VGA_VSTATUS_CNTL 0xFFFCFFFF
#define S_000300_VGA_LOCK_8DOT(x) (((x) & 0x1) << 24)
#define G_000300_VGA_LOCK_8DOT(x) (((x) >> 24) & 0x1)
#define C_000300_VGA_LOCK_8DOT 0xFEFFFFFF
#define S_000300_VGAREG_LINECMP_COMPATIBILITY_SEL(x) (((x) & 0x1) << 25)
#define G_000300_VGAREG_LINECMP_COMPATIBILITY_SEL(x) (((x) >> 25) & 0x1)
#define C_000300_VGAREG_LINECMP_COMPATIBILITY_SEL 0xFDFFFFFF
#define R_000310_VGA_MEMORY_BASE_ADDRESS 0x000310
#define S_000310_VGA_MEMORY_BASE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
#define G_000310_VGA_MEMORY_BASE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_000310_VGA_MEMORY_BASE_ADDRESS 0x00000000
#define R_000328_VGA_HDP_CONTROL 0x000328
#define S_000328_VGA_MEM_PAGE_SELECT_EN(x) (((x) & 0x1) << 0)
#define G_000328_VGA_MEM_PAGE_SELECT_EN(x) (((x) >> 0) & 0x1)
#define C_000328_VGA_MEM_PAGE_SELECT_EN 0xFFFFFFFE
#define S_000328_VGA_RBBM_LOCK_DISABLE(x) (((x) & 0x1) << 8)
#define G_000328_VGA_RBBM_LOCK_DISABLE(x) (((x) >> 8) & 0x1)
#define C_000328_VGA_RBBM_LOCK_DISABLE 0xFFFFFEFF
#define S_000328_VGA_SOFT_RESET(x) (((x) & 0x1) << 16)
#define G_000328_VGA_SOFT_RESET(x) (((x) >> 16) & 0x1)
#define C_000328_VGA_SOFT_RESET 0xFFFEFFFF
#define S_000328_VGA_TEST_RESET_CONTROL(x) (((x) & 0x1) << 24)
#define G_000328_VGA_TEST_RESET_CONTROL(x) (((x) >> 24) & 0x1)
#define C_000328_VGA_TEST_RESET_CONTROL 0xFEFFFFFF
#define R_000330_D1VGA_CONTROL 0x000330
#define S_000330_D1VGA_MODE_ENABLE(x) (((x) & 0x1) << 0)
#define G_000330_D1VGA_MODE_ENABLE(x) (((x) >> 0) & 0x1)
#define C_000330_D1VGA_MODE_ENABLE 0xFFFFFFFE
#define S_000330_D1VGA_TIMING_SELECT(x) (((x) & 0x1) << 8)
#define G_000330_D1VGA_TIMING_SELECT(x) (((x) >> 8) & 0x1)
#define C_000330_D1VGA_TIMING_SELECT 0xFFFFFEFF
#define S_000330_D1VGA_SYNC_POLARITY_SELECT(x) (((x) & 0x1) << 9)
#define G_000330_D1VGA_SYNC_POLARITY_SELECT(x) (((x) >> 9) & 0x1)
#define C_000330_D1VGA_SYNC_POLARITY_SELECT 0xFFFFFDFF
#define S_000330_D1VGA_OVERSCAN_TIMING_SELECT(x) (((x) & 0x1) << 10)
#define G_000330_D1VGA_OVERSCAN_TIMING_SELECT(x) (((x) >> 10) & 0x1)
#define C_000330_D1VGA_OVERSCAN_TIMING_SELECT 0xFFFFFBFF
#define S_000330_D1VGA_OVERSCAN_COLOR_EN(x) (((x) & 0x1) << 16)
#define G_000330_D1VGA_OVERSCAN_COLOR_EN(x) (((x) >> 16) & 0x1)
#define C_000330_D1VGA_OVERSCAN_COLOR_EN 0xFFFEFFFF
#define S_000330_D1VGA_ROTATE(x) (((x) & 0x3) << 24)
#define G_000330_D1VGA_ROTATE(x) (((x) >> 24) & 0x3)
#define C_000330_D1VGA_ROTATE 0xFCFFFFFF
#define R_000338_D2VGA_CONTROL 0x000338
#define S_000338_D2VGA_MODE_ENABLE(x) (((x) & 0x1) << 0)
#define G_000338_D2VGA_MODE_ENABLE(x) (((x) >> 0) & 0x1)
#define C_000338_D2VGA_MODE_ENABLE 0xFFFFFFFE
#define S_000338_D2VGA_TIMING_SELECT(x) (((x) & 0x1) << 8)
#define G_000338_D2VGA_TIMING_SELECT(x) (((x) >> 8) & 0x1)
#define C_000338_D2VGA_TIMING_SELECT 0xFFFFFEFF
#define S_000338_D2VGA_SYNC_POLARITY_SELECT(x) (((x) & 0x1) << 9)
#define G_000338_D2VGA_SYNC_POLARITY_SELECT(x) (((x) >> 9) & 0x1)
#define C_000338_D2VGA_SYNC_POLARITY_SELECT 0xFFFFFDFF
#define S_000338_D2VGA_OVERSCAN_TIMING_SELECT(x) (((x) & 0x1) << 10)
#define G_000338_D2VGA_OVERSCAN_TIMING_SELECT(x) (((x) >> 10) & 0x1)
#define C_000338_D2VGA_OVERSCAN_TIMING_SELECT 0xFFFFFBFF
#define S_000338_D2VGA_OVERSCAN_COLOR_EN(x) (((x) & 0x1) << 16)
#define G_000338_D2VGA_OVERSCAN_COLOR_EN(x) (((x) >> 16) & 0x1)
#define C_000338_D2VGA_OVERSCAN_COLOR_EN 0xFFFEFFFF
#define S_000338_D2VGA_ROTATE(x) (((x) & 0x3) << 24)
#define G_000338_D2VGA_ROTATE(x) (((x) >> 24) & 0x3)
#define C_000338_D2VGA_ROTATE 0xFCFFFFFF
#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_RBBM_HIBUSY(x) (((x) & 0x1) << 28)
#define G_000E40_RBBM_HIBUSY(x) (((x) >> 28) & 0x1)
#define C_000E40_RBBM_HIBUSY 0xEFFFFFFF
#define S_000E40_SKID_CFBUSY(x) (((x) & 0x1) << 29)
#define G_000E40_SKID_CFBUSY(x) (((x) >> 29) & 0x1)
#define C_000E40_SKID_CFBUSY 0xDFFFFFFF
#define S_000E40_VAP_VF_BUSY(x) (((x) & 0x1) << 30)
#define G_000E40_VAP_VF_BUSY(x) (((x) >> 30) & 0x1)
#define C_000E40_VAP_VF_BUSY 0xBFFFFFFF
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
#define R_006080_D1CRTC_CONTROL 0x006080
#define S_006080_D1CRTC_MASTER_EN(x) (((x) & 0x1) << 0)
#define G_006080_D1CRTC_MASTER_EN(x) (((x) >> 0) & 0x1)
#define C_006080_D1CRTC_MASTER_EN 0xFFFFFFFE
#define S_006080_D1CRTC_SYNC_RESET_SEL(x) (((x) & 0x1) << 4)
#define G_006080_D1CRTC_SYNC_RESET_SEL(x) (((x) >> 4) & 0x1)
#define C_006080_D1CRTC_SYNC_RESET_SEL 0xFFFFFFEF
#define S_006080_D1CRTC_DISABLE_POINT_CNTL(x) (((x) & 0x3) << 8)
#define G_006080_D1CRTC_DISABLE_POINT_CNTL(x) (((x) >> 8) & 0x3)
#define C_006080_D1CRTC_DISABLE_POINT_CNTL 0xFFFFFCFF
#define S_006080_D1CRTC_CURRENT_MASTER_EN_STATE(x) (((x) & 0x1) << 16)
#define G_006080_D1CRTC_CURRENT_MASTER_EN_STATE(x) (((x) >> 16) & 0x1)
#define C_006080_D1CRTC_CURRENT_MASTER_EN_STATE 0xFFFEFFFF
#define S_006080_D1CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) & 0x1) << 24)
#define G_006080_D1CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) >> 24) & 0x1)
#define C_006080_D1CRTC_DISP_READ_REQUEST_DISABLE 0xFEFFFFFF
#define R_0060E8_D1CRTC_UPDATE_LOCK 0x0060E8
#define S_0060E8_D1CRTC_UPDATE_LOCK(x) (((x) & 0x1) << 0)
#define G_0060E8_D1CRTC_UPDATE_LOCK(x) (((x) >> 0) & 0x1)
#define C_0060E8_D1CRTC_UPDATE_LOCK 0xFFFFFFFE
#define R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x006110
#define S_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
#define G_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x00000000
#define R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x006118
#define S_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
#define G_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x00000000
#define R_006880_D2CRTC_CONTROL 0x006880
#define S_006880_D2CRTC_MASTER_EN(x) (((x) & 0x1) << 0)
#define G_006880_D2CRTC_MASTER_EN(x) (((x) >> 0) & 0x1)
#define C_006880_D2CRTC_MASTER_EN 0xFFFFFFFE
#define S_006880_D2CRTC_SYNC_RESET_SEL(x) (((x) & 0x1) << 4)
#define G_006880_D2CRTC_SYNC_RESET_SEL(x) (((x) >> 4) & 0x1)
#define C_006880_D2CRTC_SYNC_RESET_SEL 0xFFFFFFEF
#define S_006880_D2CRTC_DISABLE_POINT_CNTL(x) (((x) & 0x3) << 8)
#define G_006880_D2CRTC_DISABLE_POINT_CNTL(x) (((x) >> 8) & 0x3)
#define C_006880_D2CRTC_DISABLE_POINT_CNTL 0xFFFFFCFF
#define S_006880_D2CRTC_CURRENT_MASTER_EN_STATE(x) (((x) & 0x1) << 16)
#define G_006880_D2CRTC_CURRENT_MASTER_EN_STATE(x) (((x) >> 16) & 0x1)
#define C_006880_D2CRTC_CURRENT_MASTER_EN_STATE 0xFFFEFFFF
#define S_006880_D2CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) & 0x1) << 24)
#define G_006880_D2CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) >> 24) & 0x1)
#define C_006880_D2CRTC_DISP_READ_REQUEST_DISABLE 0xFEFFFFFF
#define R_0068E8_D2CRTC_UPDATE_LOCK 0x0068E8
#define S_0068E8_D2CRTC_UPDATE_LOCK(x) (((x) & 0x1) << 0)
#define G_0068E8_D2CRTC_UPDATE_LOCK(x) (((x) >> 0) & 0x1)
#define C_0068E8_D2CRTC_UPDATE_LOCK 0xFFFFFFFE
#define R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x006910
#define S_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
#define G_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x00000000
#define R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x006918
#define S_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
#define G_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x00000000
#define R_000001_MC_FB_LOCATION 0x000001
#define S_000001_MC_FB_START(x) (((x) & 0xFFFF) << 0)
#define G_000001_MC_FB_START(x) (((x) >> 0) & 0xFFFF)
#define C_000001_MC_FB_START 0xFFFF0000
#define S_000001_MC_FB_TOP(x) (((x) & 0xFFFF) << 16)
#define G_000001_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF)
#define C_000001_MC_FB_TOP 0x0000FFFF
#define R_000002_MC_AGP_LOCATION 0x000002
#define S_000002_MC_AGP_START(x) (((x) & 0xFFFF) << 0)
#define G_000002_MC_AGP_START(x) (((x) >> 0) & 0xFFFF)
#define C_000002_MC_AGP_START 0xFFFF0000
#define S_000002_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16)
#define G_000002_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF)
#define C_000002_MC_AGP_TOP 0x0000FFFF
#define R_000003_MC_AGP_BASE 0x000003
#define S_000003_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
#define G_000003_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_000003_AGP_BASE_ADDR 0x00000000
#define R_000004_MC_AGP_BASE_2 0x000004
#define S_000004_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0)
#define G_000004_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF)
#define C_000004_AGP_BASE_ADDR_2 0xFFFFFFF0
#define R_00000F_CP_DYN_CNTL 0x00000F
#define S_00000F_CP_FORCEON(x) (((x) & 0x1) << 0)
#define G_00000F_CP_FORCEON(x) (((x) >> 0) & 0x1)
#define C_00000F_CP_FORCEON 0xFFFFFFFE
#define S_00000F_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1)
#define G_00000F_CP_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1)
#define C_00000F_CP_MAX_DYN_STOP_LAT 0xFFFFFFFD
#define S_00000F_CP_CLOCK_STATUS(x) (((x) & 0x1) << 2)
#define G_00000F_CP_CLOCK_STATUS(x) (((x) >> 2) & 0x1)
#define C_00000F_CP_CLOCK_STATUS 0xFFFFFFFB
#define S_00000F_CP_PROG_SHUTOFF(x) (((x) & 0x1) << 3)
#define G_00000F_CP_PROG_SHUTOFF(x) (((x) >> 3) & 0x1)
#define C_00000F_CP_PROG_SHUTOFF 0xFFFFFFF7
#define S_00000F_CP_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4)
#define G_00000F_CP_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF)
#define C_00000F_CP_PROG_DELAY_VALUE 0xFFFFF00F
#define S_00000F_CP_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12)
#define G_00000F_CP_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF)
#define C_00000F_CP_LOWER_POWER_IDLE 0xFFF00FFF
#define S_00000F_CP_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20)
#define G_00000F_CP_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1)
#define C_00000F_CP_LOWER_POWER_IGNORE 0xFFEFFFFF
#define S_00000F_CP_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21)
#define G_00000F_CP_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1)
#define C_00000F_CP_NORMAL_POWER_IGNORE 0xFFDFFFFF
#define S_00000F_SPARE(x) (((x) & 0x3) << 22)
#define G_00000F_SPARE(x) (((x) >> 22) & 0x3)
#define C_00000F_SPARE 0xFF3FFFFF
#define S_00000F_CP_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24)
#define G_00000F_CP_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF)
#define C_00000F_CP_NORMAL_POWER_BUSY 0x00FFFFFF
#define R_000011_E2_DYN_CNTL 0x000011
#define S_000011_E2_FORCEON(x) (((x) & 0x1) << 0)
#define G_000011_E2_FORCEON(x) (((x) >> 0) & 0x1)
#define C_000011_E2_FORCEON 0xFFFFFFFE
#define S_000011_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1)
#define G_000011_E2_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1)
#define C_000011_E2_MAX_DYN_STOP_LAT 0xFFFFFFFD
#define S_000011_E2_CLOCK_STATUS(x) (((x) & 0x1) << 2)
#define G_000011_E2_CLOCK_STATUS(x) (((x) >> 2) & 0x1)
#define C_000011_E2_CLOCK_STATUS 0xFFFFFFFB
#define S_000011_E2_PROG_SHUTOFF(x) (((x) & 0x1) << 3)
#define G_000011_E2_PROG_SHUTOFF(x) (((x) >> 3) & 0x1)
#define C_000011_E2_PROG_SHUTOFF 0xFFFFFFF7
#define S_000011_E2_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4)
#define G_000011_E2_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF)
#define C_000011_E2_PROG_DELAY_VALUE 0xFFFFF00F
#define S_000011_E2_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12)
#define G_000011_E2_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF)
#define C_000011_E2_LOWER_POWER_IDLE 0xFFF00FFF
#define S_000011_E2_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20)
#define G_000011_E2_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1)
#define C_000011_E2_LOWER_POWER_IGNORE 0xFFEFFFFF
#define S_000011_E2_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21)
#define G_000011_E2_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1)
#define C_000011_E2_NORMAL_POWER_IGNORE 0xFFDFFFFF
#define S_000011_SPARE(x) (((x) & 0x3) << 22)
#define G_000011_SPARE(x) (((x) >> 22) & 0x3)
#define C_000011_SPARE 0xFF3FFFFF
#define S_000011_E2_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24)
#define G_000011_E2_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF)
#define C_000011_E2_NORMAL_POWER_BUSY 0x00FFFFFF
#define R_000013_IDCT_DYN_CNTL 0x000013
#define S_000013_IDCT_FORCEON(x) (((x) & 0x1) << 0)
#define G_000013_IDCT_FORCEON(x) (((x) >> 0) & 0x1)
#define C_000013_IDCT_FORCEON 0xFFFFFFFE
#define S_000013_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1)
#define G_000013_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1)
#define C_000013_IDCT_MAX_DYN_STOP_LAT 0xFFFFFFFD
#define S_000013_IDCT_CLOCK_STATUS(x) (((x) & 0x1) << 2)
#define G_000013_IDCT_CLOCK_STATUS(x) (((x) >> 2) & 0x1)
#define C_000013_IDCT_CLOCK_STATUS 0xFFFFFFFB
#define S_000013_IDCT_PROG_SHUTOFF(x) (((x) & 0x1) << 3)
#define G_000013_IDCT_PROG_SHUTOFF(x) (((x) >> 3) & 0x1)
#define C_000013_IDCT_PROG_SHUTOFF 0xFFFFFFF7
#define S_000013_IDCT_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4)
#define G_000013_IDCT_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF)
#define C_000013_IDCT_PROG_DELAY_VALUE 0xFFFFF00F
#define S_000013_IDCT_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12)
#define G_000013_IDCT_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF)
#define C_000013_IDCT_LOWER_POWER_IDLE 0xFFF00FFF
#define S_000013_IDCT_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20)
#define G_000013_IDCT_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1)
#define C_000013_IDCT_LOWER_POWER_IGNORE 0xFFEFFFFF
#define S_000013_IDCT_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21)
#define G_000013_IDCT_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1)
#define C_000013_IDCT_NORMAL_POWER_IGNORE 0xFFDFFFFF
#define S_000013_SPARE(x) (((x) & 0x3) << 22)
#define G_000013_SPARE(x) (((x) >> 22) & 0x3)
#define C_000013_SPARE 0xFF3FFFFF
#define S_000013_IDCT_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24)
#define G_000013_IDCT_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF)
#define C_000013_IDCT_NORMAL_POWER_BUSY 0x00FFFFFF
#endif
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#include "radeon.h" #include "radeon.h"
#include "radeon_drm.h" #include "radeon_drm.h"
#include "rv770d.h" #include "rv770d.h"
#include "avivod.h"
#include "atom.h" #include "atom.h"
#include "avivod.h"
#define R700_PFP_UCODE_SIZE 848 #define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360 #define R700_PM4_UCODE_SIZE 1360
...@@ -231,7 +231,7 @@ static void rv770_mc_resume(struct radeon_device *rdev) ...@@ -231,7 +231,7 @@ static void rv770_mc_resume(struct radeon_device *rdev)
/* we need to own VRAM, so turn off the VGA renderer here /* we need to own VRAM, so turn off the VGA renderer here
* to stop it overwriting our objects */ * to stop it overwriting our objects */
radeon_avivo_vga_render_disable(rdev); rv515_vga_render_disable(rdev);
} }
...@@ -801,6 +801,13 @@ int rv770_mc_init(struct radeon_device *rdev) ...@@ -801,6 +801,13 @@ int rv770_mc_init(struct radeon_device *rdev)
/* Setup GPU memory space */ /* Setup GPU memory space */
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
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;
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev); r = radeon_agp_init(rdev);
if (r) if (r)
......
...@@ -1800,7 +1800,7 @@ static int __init video_setup(char *options) ...@@ -1800,7 +1800,7 @@ static int __init video_setup(char *options)
global = 1; global = 1;
} }
if (!global && !strstr(options, "fb:")) { if (!global && !strchr(options, ':')) {
fb_mode_option = options; fb_mode_option = options;
global = 1; global = 1;
} }
......
...@@ -387,6 +387,7 @@ struct drm_crtc { ...@@ -387,6 +387,7 @@ struct drm_crtc {
* @get_modes: get mode list for this connector * @get_modes: get mode list for this connector
* @set_property: property for this connector may need update * @set_property: property for this connector may need update
* @destroy: make object go away * @destroy: make object go away
* @force: notify the driver the connector is forced on
* *
* Each CRTC may have one or more connectors attached to it. The functions * Each CRTC may have one or more connectors attached to it. The functions
* below allow the core DRM code to control connectors, enumerate available modes, * below allow the core DRM code to control connectors, enumerate available modes,
...@@ -401,6 +402,7 @@ struct drm_connector_funcs { ...@@ -401,6 +402,7 @@ struct drm_connector_funcs {
int (*set_property)(struct drm_connector *connector, struct drm_property *property, int (*set_property)(struct drm_connector *connector, struct drm_property *property,
uint64_t val); uint64_t val);
void (*destroy)(struct drm_connector *connector); void (*destroy)(struct drm_connector *connector);
void (*force)(struct drm_connector *connector);
}; };
struct drm_encoder_funcs { struct drm_encoder_funcs {
...@@ -429,6 +431,13 @@ struct drm_encoder { ...@@ -429,6 +431,13 @@ struct drm_encoder {
void *helper_private; void *helper_private;
}; };
enum drm_connector_force {
DRM_FORCE_UNSPECIFIED,
DRM_FORCE_OFF,
DRM_FORCE_ON, /* force on analog part normally */
DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
};
/** /**
* drm_connector - central DRM connector control structure * drm_connector - central DRM connector control structure
* @crtc: CRTC this connector is currently connected to, NULL if none * @crtc: CRTC this connector is currently connected to, NULL if none
...@@ -478,9 +487,12 @@ struct drm_connector { ...@@ -478,9 +487,12 @@ struct drm_connector {
void *helper_private; void *helper_private;
/* forced on connector */
enum drm_connector_force force;
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
uint32_t force_encoder_id; uint32_t force_encoder_id;
struct drm_encoder *encoder; /* currently active encoder */ struct drm_encoder *encoder; /* currently active encoder */
void *fb_helper_private;
}; };
/** /**
...@@ -746,7 +758,7 @@ extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, ...@@ -746,7 +758,7 @@ extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
extern bool drm_detect_hdmi_monitor(struct edid *edid); extern bool drm_detect_hdmi_monitor(struct edid *edid);
extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh, int hdisplay, int vdisplay, int vrefresh,
bool reduced, bool interlaced); bool reduced, bool interlaced, bool margins);
extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh, int hdisplay, int vdisplay, int vrefresh,
bool interlaced, int margins); bool interlaced, int margins);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/fb.h> #include <linux/fb.h>
#include "drm_fb_helper.h"
struct drm_crtc_helper_funcs { struct drm_crtc_helper_funcs {
/* /*
* Control power levels on the CRTC. If the mode passed in is * Control power levels on the CRTC. If the mode passed in is
...@@ -119,10 +120,11 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder, ...@@ -119,10 +120,11 @@ static inline void drm_encoder_helper_add(struct drm_encoder *encoder,
encoder->helper_private = (void *)funcs; encoder->helper_private = (void *)funcs;
} }
static inline void drm_connector_helper_add(struct drm_connector *connector, static inline int drm_connector_helper_add(struct drm_connector *connector,
const struct drm_connector_helper_funcs *funcs) const struct drm_connector_helper_funcs *funcs)
{ {
connector->helper_private = (void *)funcs; connector->helper_private = (void *)funcs;
return drm_fb_helper_add_connector(connector);
} }
extern int drm_helper_resume_force_mode(struct drm_device *dev); extern int drm_helper_resume_force_mode(struct drm_device *dev);
......
...@@ -35,11 +35,30 @@ struct drm_fb_helper_crtc { ...@@ -35,11 +35,30 @@ struct drm_fb_helper_crtc {
struct drm_mode_set mode_set; struct drm_mode_set mode_set;
}; };
struct drm_fb_helper_funcs { struct drm_fb_helper_funcs {
void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green, void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno); u16 blue, int regno);
}; };
/* mode specified on the command line */
struct drm_fb_helper_cmdline_mode {
bool specified;
bool refresh_specified;
bool bpp_specified;
int xres, yres;
int bpp;
int refresh;
bool rb;
bool interlace;
bool cvt;
bool margins;
};
struct drm_fb_helper_connector {
struct drm_fb_helper_cmdline_mode cmdline_mode;
};
struct drm_fb_helper { struct drm_fb_helper {
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_device *dev; struct drm_device *dev;
...@@ -57,6 +76,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev, ...@@ -57,6 +76,8 @@ int drm_fb_helper_single_fb_probe(struct drm_device *dev,
uint32_t fb_height, uint32_t fb_height,
uint32_t surface_width, uint32_t surface_width,
uint32_t surface_height, uint32_t surface_height,
uint32_t surface_depth,
uint32_t surface_bpp,
struct drm_framebuffer **fb_ptr)); struct drm_framebuffer **fb_ptr));
int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count,
int max_conn); int max_conn);
...@@ -79,4 +100,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb, ...@@ -79,4 +100,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb,
uint32_t fb_width, uint32_t fb_height); uint32_t fb_width, uint32_t fb_height);
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch); void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch);
int drm_fb_helper_add_connector(struct drm_connector *connector);
int drm_fb_helper_parse_command_line(struct drm_device *dev);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment