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
This diff is collapsed.
...@@ -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);
......
This diff is collapsed.
...@@ -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;
} }
This diff is collapsed.
...@@ -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)
......
This diff is collapsed.
...@@ -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) &&
......
This diff is collapsed.
...@@ -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)) {
......
This diff is collapsed.
This diff is collapsed.
...@@ -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