Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (133 commits) drm/vgaarb: add VGA arbitration support to the drm and kms. drm/radeon: some r420s have a CP race with the DMA engine. drm/radeon/r600/kms: rv670 is not DCE3 drm/radeon/kms: r420 idle after programming GA_ENHANCE drm/radeon/kms: more fixes to rv770 suspend/resume path. drm/radeon/kms: more alignment for rv770.c with r600.c drm/radeon/kms: rv770 blit init called too late. drm/radeon/kms: move around new init path code to avoid posting at init drm/radeon/r600: fix some issues with suspend/resume. drm/radeon/kms: disable VGA rendering engine before taking over VRAM drm/radeon/kms: Move radeon_get_clock_info() call out of radeon_clocks_init(). drm/radeon/kms: add initial connector properties drm/radeon/kms: Use surfaces for scanout / cursor byte swapping on big endian. drm/radeon/kms: don't fail if we fail to init GPU acceleration drm/r600/kms: fixup number of loops per blit calculation. drm/radeon/kms: reprogram format in set base. drm/radeon: avivo chips have no separate int bit for display drm/radeon/r600: don't do interrupts drm: fix _DRM_GEM addmap error message drm: update crtc x/y when only fb changes ... Fixed up trivial conflicts in firmware/Makefile due to network driver (cxgb3) and drm (mga/r128/radeon) firmware being listed next to each other.
This commit is contained in:
commit
44040f107e
165 changed files with 35603 additions and 41387 deletions
|
@ -18,6 +18,14 @@ menuconfig DRM
|
|||
details. You should also select and configure AGP
|
||||
(/dev/agpgart) support.
|
||||
|
||||
config DRM_KMS_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
select FB
|
||||
select FRAMEBUFFER_CONSOLE if !EMBEDDED
|
||||
help
|
||||
FB and CRTC helpers for KMS drivers.
|
||||
|
||||
config DRM_TTM
|
||||
tristate
|
||||
depends on DRM
|
||||
|
@ -36,6 +44,7 @@ config DRM_TDFX
|
|||
config DRM_R128
|
||||
tristate "ATI Rage 128"
|
||||
depends on DRM && PCI
|
||||
select FW_LOADER
|
||||
help
|
||||
Choose this option if you have an ATI Rage 128 graphics card. If M
|
||||
is selected, the module will be called r128. AGP support for
|
||||
|
@ -47,8 +56,9 @@ config DRM_RADEON
|
|||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
select FB
|
||||
select FRAMEBUFFER_CONSOLE if !EMBEDDED
|
||||
select FW_LOADER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_TTM
|
||||
help
|
||||
Choose this option if you have an ATI Radeon graphics card. There
|
||||
are both PCI and AGP versions. You don't need to choose this to
|
||||
|
@ -82,11 +92,10 @@ config DRM_I830
|
|||
config DRM_I915
|
||||
tristate "i915 driver"
|
||||
depends on AGP_INTEL
|
||||
select DRM_KMS_HELPER
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
select FB
|
||||
select FRAMEBUFFER_CONSOLE if !EMBEDDED
|
||||
# i915 depends on ACPI_VIDEO when ACPI is enabled
|
||||
# but for select to work, need to select ACPI_VIDEO's dependencies, ick
|
||||
select VIDEO_OUTPUT_CONTROL if ACPI
|
||||
|
@ -116,6 +125,7 @@ endchoice
|
|||
config DRM_MGA
|
||||
tristate "Matrox g200/g400"
|
||||
depends on DRM
|
||||
select FW_LOADER
|
||||
help
|
||||
Choose this option if you have a Matrox G200, G400 or G450 graphics
|
||||
card. If M is selected, the module will be called mga. AGP
|
||||
|
|
|
@ -10,11 +10,15 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
|
|||
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
|
||||
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
|
||||
drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
|
||||
drm_crtc.o drm_crtc_helper.o drm_modes.o drm_edid.o \
|
||||
drm_info.o drm_debugfs.o
|
||||
drm_crtc.o drm_modes.o drm_edid.o \
|
||||
drm_info.o drm_debugfs.o drm_encoder_slave.o
|
||||
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
|
||||
drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o
|
||||
|
||||
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
||||
|
||||
obj-$(CONFIG_DRM) += drm.o
|
||||
obj-$(CONFIG_DRM_TTM) += ttm/
|
||||
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
||||
|
|
|
@ -310,10 +310,10 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
|
|||
(unsigned long long)map->offset, map->size);
|
||||
|
||||
break;
|
||||
case _DRM_GEM:
|
||||
DRM_ERROR("tried to rmmap GEM object\n");
|
||||
break;
|
||||
}
|
||||
case _DRM_GEM:
|
||||
DRM_ERROR("tried to addmap GEM object\n");
|
||||
break;
|
||||
case _DRM_SCATTER_GATHER:
|
||||
if (!dev->sg) {
|
||||
kfree(map);
|
||||
|
|
|
@ -45,6 +45,23 @@ drm_clflush_page(struct page *page)
|
|||
clflush(page_virtual + i);
|
||||
kunmap_atomic(page_virtual, KM_USER0);
|
||||
}
|
||||
|
||||
static void drm_cache_flush_clflush(struct page *pages[],
|
||||
unsigned long num_pages)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
mb();
|
||||
for (i = 0; i < num_pages; i++)
|
||||
drm_clflush_page(*pages++);
|
||||
mb();
|
||||
}
|
||||
|
||||
static void
|
||||
drm_clflush_ipi_handler(void *null)
|
||||
{
|
||||
wbinvd();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
|
@ -53,17 +70,30 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
|
|||
|
||||
#if defined(CONFIG_X86)
|
||||
if (cpu_has_clflush) {
|
||||
unsigned long i;
|
||||
|
||||
mb();
|
||||
for (i = 0; i < num_pages; ++i)
|
||||
drm_clflush_page(*pages++);
|
||||
mb();
|
||||
|
||||
drm_cache_flush_clflush(pages, num_pages);
|
||||
return;
|
||||
}
|
||||
|
||||
wbinvd();
|
||||
if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0)
|
||||
printk(KERN_ERR "Timed out waiting for cache flush.\n");
|
||||
|
||||
#elif defined(__powerpc__)
|
||||
unsigned long i;
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
struct page *page = pages[i];
|
||||
void *page_virtual;
|
||||
|
||||
if (unlikely(page == NULL))
|
||||
continue;
|
||||
|
||||
page_virtual = kmap_atomic(page, KM_USER0);
|
||||
flush_dcache_range((unsigned long)page_virtual,
|
||||
(unsigned long)page_virtual + PAGE_SIZE);
|
||||
kunmap_atomic(page_virtual, KM_USER0);
|
||||
}
|
||||
#else
|
||||
printk(KERN_ERR "Architecture has no drm_cache.c support\n");
|
||||
WARN_ON_ONCE(1);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(drm_clflush_pages);
|
||||
|
|
|
@ -68,10 +68,10 @@ DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
|
|||
*/
|
||||
static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_SCALE_NON_GPU, "Non-GPU" },
|
||||
{ DRM_MODE_SCALE_FULLSCREEN, "Fullscreen" },
|
||||
{ DRM_MODE_SCALE_NO_SCALE, "No scale" },
|
||||
{ DRM_MODE_SCALE_ASPECT, "Aspect" },
|
||||
{ DRM_MODE_SCALE_NONE, "None" },
|
||||
{ DRM_MODE_SCALE_FULLSCREEN, "Full" },
|
||||
{ DRM_MODE_SCALE_CENTER, "Center" },
|
||||
{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
|
||||
|
@ -108,6 +108,7 @@ static struct drm_prop_enum_list drm_tv_select_enum_list[] =
|
|||
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
|
||||
};
|
||||
|
||||
DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
|
||||
|
@ -118,6 +119,7 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
|
|||
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
|
||||
};
|
||||
|
||||
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
|
||||
|
@ -146,6 +148,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
|
|||
{ DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
|
||||
{ DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
|
||||
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
|
||||
{ DRM_MODE_CONNECTOR_TV, "TV", 0 },
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list drm_encoder_enum_list[] =
|
||||
|
@ -165,6 +168,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder)
|
|||
encoder->base.id);
|
||||
return buf;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_encoder_name);
|
||||
|
||||
char *drm_get_connector_name(struct drm_connector *connector)
|
||||
{
|
||||
|
@ -699,6 +703,42 @@ int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
|
|||
drm_property_add_enum(dev->mode_config.tv_mode_property, i,
|
||||
i, modes[i]);
|
||||
|
||||
dev->mode_config.tv_brightness_property =
|
||||
drm_property_create(dev, DRM_MODE_PROP_RANGE,
|
||||
"brightness", 2);
|
||||
dev->mode_config.tv_brightness_property->values[0] = 0;
|
||||
dev->mode_config.tv_brightness_property->values[1] = 100;
|
||||
|
||||
dev->mode_config.tv_contrast_property =
|
||||
drm_property_create(dev, DRM_MODE_PROP_RANGE,
|
||||
"contrast", 2);
|
||||
dev->mode_config.tv_contrast_property->values[0] = 0;
|
||||
dev->mode_config.tv_contrast_property->values[1] = 100;
|
||||
|
||||
dev->mode_config.tv_flicker_reduction_property =
|
||||
drm_property_create(dev, DRM_MODE_PROP_RANGE,
|
||||
"flicker reduction", 2);
|
||||
dev->mode_config.tv_flicker_reduction_property->values[0] = 0;
|
||||
dev->mode_config.tv_flicker_reduction_property->values[1] = 100;
|
||||
|
||||
dev->mode_config.tv_overscan_property =
|
||||
drm_property_create(dev, DRM_MODE_PROP_RANGE,
|
||||
"overscan", 2);
|
||||
dev->mode_config.tv_overscan_property->values[0] = 0;
|
||||
dev->mode_config.tv_overscan_property->values[1] = 100;
|
||||
|
||||
dev->mode_config.tv_saturation_property =
|
||||
drm_property_create(dev, DRM_MODE_PROP_RANGE,
|
||||
"saturation", 2);
|
||||
dev->mode_config.tv_saturation_property->values[0] = 0;
|
||||
dev->mode_config.tv_saturation_property->values[1] = 100;
|
||||
|
||||
dev->mode_config.tv_hue_property =
|
||||
drm_property_create(dev, DRM_MODE_PROP_RANGE,
|
||||
"hue", 2);
|
||||
dev->mode_config.tv_hue_property->values[0] = 0;
|
||||
dev->mode_config.tv_hue_property->values[1] = 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_create_tv_properties);
|
||||
|
@ -1044,7 +1084,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
|||
if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list,
|
||||
head) {
|
||||
DRM_DEBUG("CRTC ID is %d\n", crtc->base.id);
|
||||
DRM_DEBUG_KMS("CRTC ID is %d\n", crtc->base.id);
|
||||
if (put_user(crtc->base.id, crtc_id + copied)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
|
@ -1072,7 +1112,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
|||
list_for_each_entry(encoder,
|
||||
&dev->mode_config.encoder_list,
|
||||
head) {
|
||||
DRM_DEBUG("ENCODER ID is %d\n",
|
||||
DRM_DEBUG_KMS("ENCODER ID is %d\n",
|
||||
encoder->base.id);
|
||||
if (put_user(encoder->base.id, encoder_id +
|
||||
copied)) {
|
||||
|
@ -1103,7 +1143,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
|||
list_for_each_entry(connector,
|
||||
&dev->mode_config.connector_list,
|
||||
head) {
|
||||
DRM_DEBUG("CONNECTOR ID is %d\n",
|
||||
DRM_DEBUG_KMS("CONNECTOR ID is %d\n",
|
||||
connector->base.id);
|
||||
if (put_user(connector->base.id,
|
||||
connector_id + copied)) {
|
||||
|
@ -1127,7 +1167,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
|||
}
|
||||
card_res->count_connectors = connector_count;
|
||||
|
||||
DRM_DEBUG("Counted %d %d %d\n", card_res->count_crtcs,
|
||||
DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs,
|
||||
card_res->count_connectors, card_res->count_encoders);
|
||||
|
||||
out:
|
||||
|
@ -1230,7 +1270,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
|
|||
|
||||
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
|
||||
|
||||
DRM_DEBUG("connector id %d:\n", out_resp->connector_id);
|
||||
DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
|
@ -1406,7 +1446,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
obj = drm_mode_object_find(dev, crtc_req->crtc_id,
|
||||
DRM_MODE_OBJECT_CRTC);
|
||||
if (!obj) {
|
||||
DRM_DEBUG("Unknown CRTC ID %d\n", crtc_req->crtc_id);
|
||||
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1419,7 +1459,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
list_for_each_entry(crtcfb,
|
||||
&dev->mode_config.crtc_list, head) {
|
||||
if (crtcfb == crtc) {
|
||||
DRM_DEBUG("Using current fb for setmode\n");
|
||||
DRM_DEBUG_KMS("Using current fb for "
|
||||
"setmode\n");
|
||||
fb = crtc->fb;
|
||||
}
|
||||
}
|
||||
|
@ -1427,7 +1468,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
obj = drm_mode_object_find(dev, crtc_req->fb_id,
|
||||
DRM_MODE_OBJECT_FB);
|
||||
if (!obj) {
|
||||
DRM_DEBUG("Unknown FB ID%d\n", crtc_req->fb_id);
|
||||
DRM_DEBUG_KMS("Unknown FB ID%d\n",
|
||||
crtc_req->fb_id);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1440,13 +1482,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
}
|
||||
|
||||
if (crtc_req->count_connectors == 0 && mode) {
|
||||
DRM_DEBUG("Count connectors is 0 but mode set\n");
|
||||
DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
|
||||
DRM_DEBUG("Count connectors is %d but no mode or fb set\n",
|
||||
DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
|
||||
crtc_req->count_connectors);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
@ -1479,7 +1521,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
obj = drm_mode_object_find(dev, out_id,
|
||||
DRM_MODE_OBJECT_CONNECTOR);
|
||||
if (!obj) {
|
||||
DRM_DEBUG("Connector id %d unknown\n", out_id);
|
||||
DRM_DEBUG_KMS("Connector id %d unknown\n",
|
||||
out_id);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -1512,7 +1555,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
|
|||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (!req->flags) {
|
||||
DRM_ERROR("no operation set\n");
|
||||
|
@ -1522,7 +1565,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
|
|||
mutex_lock(&dev->mode_config.mutex);
|
||||
obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
|
||||
if (!obj) {
|
||||
DRM_DEBUG("Unknown CRTC ID %d\n", req->crtc_id);
|
||||
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -33,15 +33,6 @@
|
|||
#include "drm_crtc.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
|
||||
/*
|
||||
* Detailed mode info for 800x600@60Hz
|
||||
*/
|
||||
static struct drm_display_mode std_modes[] = {
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
|
||||
968, 1056, 0, 600, 601, 605, 628, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
};
|
||||
|
||||
static void drm_mode_validate_flag(struct drm_connector *connector,
|
||||
int flags)
|
||||
{
|
||||
|
@ -94,7 +85,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
|||
int count = 0;
|
||||
int mode_flags = 0;
|
||||
|
||||
DRM_DEBUG("%s\n", drm_get_connector_name(connector));
|
||||
DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
|
||||
/* set all modes to the unverified state */
|
||||
list_for_each_entry_safe(mode, t, &connector->modes, head)
|
||||
mode->status = MODE_UNVERIFIED;
|
||||
|
@ -102,15 +93,17 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
|||
connector->status = connector->funcs->detect(connector);
|
||||
|
||||
if (connector->status == connector_status_disconnected) {
|
||||
DRM_DEBUG("%s is disconnected\n",
|
||||
DRM_DEBUG_KMS("%s is disconnected\n",
|
||||
drm_get_connector_name(connector));
|
||||
/* TODO set EDID to NULL */
|
||||
return 0;
|
||||
goto prune;
|
||||
}
|
||||
|
||||
count = (*connector_funcs->get_modes)(connector);
|
||||
if (!count)
|
||||
return 0;
|
||||
if (!count) {
|
||||
count = drm_add_modes_noedid(connector, 800, 600);
|
||||
if (!count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
drm_mode_connector_list_update(connector);
|
||||
|
||||
|
@ -130,7 +123,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
|||
mode);
|
||||
}
|
||||
|
||||
|
||||
prune:
|
||||
drm_mode_prune_invalid(dev, &connector->modes, true);
|
||||
|
||||
if (list_empty(&connector->modes))
|
||||
|
@ -138,7 +131,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
|||
|
||||
drm_mode_sort(&connector->modes);
|
||||
|
||||
DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
|
||||
DRM_DEBUG_KMS("Probed modes for %s\n",
|
||||
drm_get_connector_name(connector));
|
||||
list_for_each_entry_safe(mode, t, &connector->modes, head) {
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
|
@ -165,39 +159,6 @@ int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_helper_probe_connector_modes);
|
||||
|
||||
static void drm_helper_add_std_modes(struct drm_device *dev,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_display_mode *mode, *t;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
|
||||
struct drm_display_mode *stdmode;
|
||||
|
||||
/*
|
||||
* When no valid EDID modes are available we end up
|
||||
* here and bailed in the past, now we add some standard
|
||||
* modes and move on.
|
||||
*/
|
||||
stdmode = drm_mode_duplicate(dev, &std_modes[i]);
|
||||
drm_mode_probed_add(connector, stdmode);
|
||||
drm_mode_list_concat(&connector->probed_modes,
|
||||
&connector->modes);
|
||||
|
||||
DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
|
||||
drm_get_connector_name(connector));
|
||||
}
|
||||
drm_mode_sort(&connector->modes);
|
||||
|
||||
DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
|
||||
list_for_each_entry_safe(mode, t, &connector->modes, head) {
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_helper_encoder_in_use - check if a given encoder is in use
|
||||
* @encoder: encoder to check
|
||||
|
@ -258,13 +219,27 @@ EXPORT_SYMBOL(drm_helper_crtc_in_use);
|
|||
void drm_helper_disable_unused_functions(struct drm_device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (!connector->encoder)
|
||||
continue;
|
||||
if (connector->status == connector_status_disconnected)
|
||||
connector->encoder = NULL;
|
||||
}
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (!drm_helper_encoder_in_use(encoder))
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
if (!drm_helper_encoder_in_use(encoder)) {
|
||||
if (encoder_funcs->disable)
|
||||
(*encoder_funcs->disable)(encoder);
|
||||
else
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
/* disconnector encoder from any connector */
|
||||
encoder->crtc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
|
@ -312,7 +287,7 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled)
|
|||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
enabled[i] = drm_connector_enabled(connector, true);
|
||||
DRM_DEBUG("connector %d enabled? %s\n", connector->base.id,
|
||||
DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
|
||||
enabled[i] ? "yes" : "no");
|
||||
any_enabled |= enabled[i];
|
||||
i++;
|
||||
|
@ -342,7 +317,7 @@ static bool drm_target_preferred(struct drm_device *dev,
|
|||
continue;
|
||||
}
|
||||
|
||||
DRM_DEBUG("looking for preferred mode on connector %d\n",
|
||||
DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
|
||||
connector->base.id);
|
||||
|
||||
modes[i] = drm_has_preferred_mode(connector, width, height);
|
||||
|
@ -351,7 +326,7 @@ static bool drm_target_preferred(struct drm_device *dev,
|
|||
list_for_each_entry(modes[i], &connector->modes, head)
|
||||
break;
|
||||
}
|
||||
DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
|
||||
DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
|
||||
"none");
|
||||
i++;
|
||||
}
|
||||
|
@ -409,7 +384,7 @@ static int drm_pick_crtcs(struct drm_device *dev,
|
|||
c = 0;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
|
||||
if ((connector->encoder->possible_crtcs & (1 << c)) == 0) {
|
||||
if ((encoder->possible_crtcs & (1 << c)) == 0) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
@ -452,7 +427,7 @@ static void drm_setup_crtcs(struct drm_device *dev)
|
|||
int width, height;
|
||||
int i, ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
width = dev->mode_config.max_width;
|
||||
height = dev->mode_config.max_height;
|
||||
|
@ -475,7 +450,7 @@ static void drm_setup_crtcs(struct drm_device *dev)
|
|||
if (!ret)
|
||||
DRM_ERROR("Unable to find initial modes\n");
|
||||
|
||||
DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
|
||||
DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height);
|
||||
|
||||
drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
|
||||
|
||||
|
@ -490,12 +465,14 @@ static void drm_setup_crtcs(struct drm_device *dev)
|
|||
}
|
||||
|
||||
if (mode && crtc) {
|
||||
DRM_DEBUG("desired mode %s set on crtc %d\n",
|
||||
DRM_DEBUG_KMS("desired mode %s set on crtc %d\n",
|
||||
mode->name, crtc->base.id);
|
||||
crtc->desired_mode = mode;
|
||||
connector->encoder->crtc = crtc;
|
||||
} else
|
||||
} else {
|
||||
connector->encoder->crtc = NULL;
|
||||
connector->encoder = NULL;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -702,18 +679,17 @@ EXPORT_SYMBOL(drm_crtc_helper_set_mode);
|
|||
int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct drm_crtc **save_crtcs, *new_crtc;
|
||||
struct drm_encoder **save_encoders, *new_encoder;
|
||||
struct drm_crtc *save_crtcs, *new_crtc, *crtc;
|
||||
struct drm_encoder *save_encoders, *new_encoder, *encoder;
|
||||
struct drm_framebuffer *old_fb = NULL;
|
||||
bool save_enabled;
|
||||
bool mode_changed = false; /* if true do a full mode set */
|
||||
bool fb_changed = false; /* if true and !mode_changed just do a flip */
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector *save_connectors, *connector;
|
||||
int count = 0, ro, fail = 0;
|
||||
struct drm_crtc_helper_funcs *crtc_funcs;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (!set)
|
||||
return -EINVAL;
|
||||
|
@ -726,37 +702,60 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
|
||||
crtc_funcs = set->crtc->helper_private;
|
||||
|
||||
DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n",
|
||||
DRM_DEBUG_KMS("crtc: %p %d fb: %p connectors: %p num_connectors:"
|
||||
" %d (x, y) (%i, %i)\n",
|
||||
set->crtc, set->crtc->base.id, set->fb, set->connectors,
|
||||
(int)set->num_connectors, set->x, set->y);
|
||||
|
||||
dev = set->crtc->dev;
|
||||
|
||||
/* save previous config */
|
||||
save_enabled = set->crtc->enabled;
|
||||
|
||||
/*
|
||||
* We do mode_config.num_connectors here since we'll look at the
|
||||
* CRTC and encoder associated with each connector later.
|
||||
*/
|
||||
save_crtcs = kzalloc(dev->mode_config.num_connector *
|
||||
sizeof(struct drm_crtc *), GFP_KERNEL);
|
||||
/* Allocate space for the backup of all (non-pointer) crtc, encoder and
|
||||
* connector data. */
|
||||
save_crtcs = kzalloc(dev->mode_config.num_crtc *
|
||||
sizeof(struct drm_crtc), GFP_KERNEL);
|
||||
if (!save_crtcs)
|
||||
return -ENOMEM;
|
||||
|
||||
save_encoders = kzalloc(dev->mode_config.num_connector *
|
||||
sizeof(struct drm_encoders *), GFP_KERNEL);
|
||||
save_encoders = kzalloc(dev->mode_config.num_encoder *
|
||||
sizeof(struct drm_encoder), GFP_KERNEL);
|
||||
if (!save_encoders) {
|
||||
kfree(save_crtcs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
save_connectors = kzalloc(dev->mode_config.num_connector *
|
||||
sizeof(struct drm_connector), GFP_KERNEL);
|
||||
if (!save_connectors) {
|
||||
kfree(save_crtcs);
|
||||
kfree(save_encoders);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Copy data. Note that driver private data is not affected.
|
||||
* Should anything bad happen only the expected state is
|
||||
* restored, not the drivers personal bookkeeping.
|
||||
*/
|
||||
count = 0;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
save_crtcs[count++] = *crtc;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
save_encoders[count++] = *encoder;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
save_connectors[count++] = *connector;
|
||||
}
|
||||
|
||||
/* We should be able to check here if the fb has the same properties
|
||||
* and then just flip_or_move it */
|
||||
if (set->crtc->fb != set->fb) {
|
||||
/* If we have no fb then treat it as a full mode set */
|
||||
if (set->crtc->fb == NULL) {
|
||||
DRM_DEBUG("crtc has no fb, full mode set\n");
|
||||
DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
|
||||
mode_changed = true;
|
||||
} else if (set->fb == NULL) {
|
||||
mode_changed = true;
|
||||
|
@ -772,7 +771,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
fb_changed = true;
|
||||
|
||||
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
|
||||
DRM_DEBUG("modes are different, full mode set\n");
|
||||
DRM_DEBUG_KMS("modes are different, full mode set\n");
|
||||
drm_mode_debug_printmodeline(&set->crtc->mode);
|
||||
drm_mode_debug_printmodeline(set->mode);
|
||||
mode_changed = true;
|
||||
|
@ -783,7 +782,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct drm_connector_helper_funcs *connector_funcs =
|
||||
connector->helper_private;
|
||||
save_encoders[count++] = connector->encoder;
|
||||
new_encoder = connector->encoder;
|
||||
for (ro = 0; ro < set->num_connectors; ro++) {
|
||||
if (set->connectors[ro] == connector) {
|
||||
|
@ -798,15 +796,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
}
|
||||
|
||||
if (new_encoder != connector->encoder) {
|
||||
DRM_DEBUG("encoder changed, full mode switch\n");
|
||||
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
|
||||
mode_changed = true;
|
||||
/* If the encoder is reused for another connector, then
|
||||
* the appropriate crtc will be set later.
|
||||
*/
|
||||
if (connector->encoder)
|
||||
connector->encoder->crtc = NULL;
|
||||
connector->encoder = new_encoder;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
ret = -EINVAL;
|
||||
goto fail_no_encoder;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
@ -814,8 +817,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
if (!connector->encoder)
|
||||
continue;
|
||||
|
||||
save_crtcs[count++] = connector->encoder->crtc;
|
||||
|
||||
if (connector->encoder->crtc == set->crtc)
|
||||
new_crtc = NULL;
|
||||
else
|
||||
|
@ -830,14 +831,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
if (new_crtc &&
|
||||
!drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
|
||||
ret = -EINVAL;
|
||||
goto fail_set_mode;
|
||||
goto fail;
|
||||
}
|
||||
if (new_crtc != connector->encoder->crtc) {
|
||||
DRM_DEBUG("crtc changed, full mode switch\n");
|
||||
DRM_DEBUG_KMS("crtc changed, full mode switch\n");
|
||||
mode_changed = true;
|
||||
connector->encoder->crtc = new_crtc;
|
||||
}
|
||||
DRM_DEBUG("setting connector %d crtc to %p\n",
|
||||
DRM_DEBUG_KMS("setting connector %d crtc to %p\n",
|
||||
connector->base.id, new_crtc);
|
||||
}
|
||||
|
||||
|
@ -850,7 +851,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
set->crtc->fb = set->fb;
|
||||
set->crtc->enabled = (set->mode != NULL);
|
||||
if (set->mode != NULL) {
|
||||
DRM_DEBUG("attempting to set mode from userspace\n");
|
||||
DRM_DEBUG_KMS("attempting to set mode from"
|
||||
" userspace\n");
|
||||
drm_mode_debug_printmodeline(set->mode);
|
||||
if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
|
||||
set->x, set->y,
|
||||
|
@ -858,7 +860,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
DRM_ERROR("failed to set mode on crtc %p\n",
|
||||
set->crtc);
|
||||
ret = -EINVAL;
|
||||
goto fail_set_mode;
|
||||
goto fail;
|
||||
}
|
||||
/* TODO are these needed? */
|
||||
set->crtc->desired_x = set->x;
|
||||
|
@ -867,43 +869,50 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
|||
}
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
} else if (fb_changed) {
|
||||
set->crtc->x = set->x;
|
||||
set->crtc->y = set->y;
|
||||
|
||||
old_fb = set->crtc->fb;
|
||||
if (set->crtc->fb != set->fb)
|
||||
set->crtc->fb = set->fb;
|
||||
ret = crtc_funcs->mode_set_base(set->crtc,
|
||||
set->x, set->y, old_fb);
|
||||
if (ret != 0)
|
||||
goto fail_set_mode;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
kfree(save_connectors);
|
||||
kfree(save_encoders);
|
||||
kfree(save_crtcs);
|
||||
return 0;
|
||||
|
||||
fail_set_mode:
|
||||
set->crtc->enabled = save_enabled;
|
||||
set->crtc->fb = old_fb;
|
||||
fail:
|
||||
/* Restore all previous data. */
|
||||
count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (!connector->encoder)
|
||||
continue;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
*crtc = save_crtcs[count++];
|
||||
}
|
||||
|
||||
connector->encoder->crtc = save_crtcs[count++];
|
||||
count = 0;
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
*encoder = save_encoders[count++];
|
||||
}
|
||||
fail_no_encoder:
|
||||
kfree(save_crtcs);
|
||||
|
||||
count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
connector->encoder = save_encoders[count++];
|
||||
*connector = save_connectors[count++];
|
||||
}
|
||||
|
||||
kfree(save_connectors);
|
||||
kfree(save_encoders);
|
||||
kfree(save_crtcs);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_helper_set_config);
|
||||
|
||||
bool drm_helper_plugged_event(struct drm_device *dev)
|
||||
{
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
drm_helper_probe_connector_modes(dev, dev->mode_config.max_width,
|
||||
dev->mode_config.max_height);
|
||||
|
@ -932,7 +941,6 @@ bool drm_helper_plugged_event(struct drm_device *dev)
|
|||
*/
|
||||
bool drm_helper_initial_config(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
int count = 0;
|
||||
|
||||
count = drm_helper_probe_connector_modes(dev,
|
||||
|
@ -940,16 +948,9 @@ bool drm_helper_initial_config(struct drm_device *dev)
|
|||
dev->mode_config.max_height);
|
||||
|
||||
/*
|
||||
* None of the available connectors had any modes, so add some
|
||||
* and try to light them up anyway
|
||||
* we shouldn't end up with no modes here.
|
||||
*/
|
||||
if (!count) {
|
||||
DRM_ERROR("connectors have no modes, using standard modes\n");
|
||||
list_for_each_entry(connector,
|
||||
&dev->mode_config.connector_list,
|
||||
head)
|
||||
drm_helper_add_std_modes(dev, connector);
|
||||
}
|
||||
WARN(!count, "Connected connector with 0 modes\n");
|
||||
|
||||
drm_setup_crtcs(dev);
|
||||
|
||||
|
|
|
@ -63,12 +63,12 @@ static struct drm_ioctl_desc drm_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER),
|
||||
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
|
||||
|
|
|
@ -60,6 +60,12 @@
|
|||
#define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5)
|
||||
/* use +hsync +vsync for detailed mode */
|
||||
#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6)
|
||||
/* define the number of Extension EDID block */
|
||||
#define MAX_EDID_EXT_NUM 4
|
||||
|
||||
#define LEVEL_DMT 0
|
||||
#define LEVEL_GTF 1
|
||||
#define LEVEL_CVT 2
|
||||
|
||||
static struct edid_quirk {
|
||||
char *vendor;
|
||||
|
@ -237,28 +243,291 @@ static void edid_fixup_preferred(struct drm_connector *connector,
|
|||
preferred_mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the Autogenerated from the DMT spec.
|
||||
* This table is copied from xfree86/modes/xf86EdidModes.c.
|
||||
* But the mode with Reduced blank feature is deleted.
|
||||
*/
|
||||
static struct drm_display_mode drm_dmt_modes[] = {
|
||||
/* 640x350@85Hz */
|
||||
{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
|
||||
736, 832, 0, 350, 382, 385, 445, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 640x400@85Hz */
|
||||
{ DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
|
||||
736, 832, 0, 400, 401, 404, 445, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 720x400@85Hz */
|
||||
{ DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756,
|
||||
828, 936, 0, 400, 401, 404, 446, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 640x480@60Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
|
||||
752, 800, 0, 480, 489, 492, 525, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 640x480@72Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664,
|
||||
704, 832, 0, 480, 489, 492, 520, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 640x480@75Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656,
|
||||
720, 840, 0, 480, 481, 484, 500, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 640x480@85Hz */
|
||||
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696,
|
||||
752, 832, 0, 480, 481, 484, 509, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 800x600@56Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824,
|
||||
896, 1024, 0, 600, 601, 603, 625, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 800x600@60Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
|
||||
968, 1056, 0, 600, 601, 605, 628, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 800x600@72Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856,
|
||||
976, 1040, 0, 600, 637, 643, 666, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 800x600@75Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816,
|
||||
896, 1056, 0, 600, 601, 604, 625, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 800x600@85Hz */
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832,
|
||||
896, 1048, 0, 600, 601, 604, 631, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 848x480@60Hz */
|
||||
{ DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864,
|
||||
976, 1088, 0, 480, 486, 494, 517, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1024x768@43Hz, interlace */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
|
||||
1208, 1264, 0, 768, 768, 772, 817, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
|
||||
DRM_MODE_FLAG_INTERLACE) },
|
||||
/* 1024x768@60Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
|
||||
1184, 1344, 0, 768, 771, 777, 806, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 1024x768@70Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048,
|
||||
1184, 1328, 0, 768, 771, 777, 806, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 1024x768@75Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040,
|
||||
1136, 1312, 0, 768, 769, 772, 800, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1024x768@85Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072,
|
||||
1072, 1376, 0, 768, 769, 772, 808, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1152x864@75Hz */
|
||||
{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
|
||||
1344, 1600, 0, 864, 865, 868, 900, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x768@60Hz */
|
||||
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
|
||||
1472, 1664, 0, 768, 771, 778, 798, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x768@75Hz */
|
||||
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360,
|
||||
1488, 1696, 0, 768, 771, 778, 805, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 1280x768@85Hz */
|
||||
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360,
|
||||
1496, 1712, 0, 768, 771, 778, 809, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x800@60Hz */
|
||||
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
|
||||
1480, 1680, 0, 800, 803, 809, 831, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 1280x800@75Hz */
|
||||
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360,
|
||||
1488, 1696, 0, 800, 803, 809, 838, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x800@85Hz */
|
||||
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360,
|
||||
1496, 1712, 0, 800, 803, 809, 843, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x960@60Hz */
|
||||
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
|
||||
1488, 1800, 0, 960, 961, 964, 1000, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x960@85Hz */
|
||||
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344,
|
||||
1504, 1728, 0, 960, 961, 964, 1011, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x1024@60Hz */
|
||||
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
|
||||
1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x1024@75Hz */
|
||||
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296,
|
||||
1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1280x1024@85Hz */
|
||||
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344,
|
||||
1504, 1728, 0, 1024, 1025, 1028, 1072, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1360x768@60Hz */
|
||||
{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
|
||||
1536, 1792, 0, 768, 771, 777, 795, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1440x1050@60Hz */
|
||||
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
|
||||
1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1440x1050@75Hz */
|
||||
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504,
|
||||
1648, 1896, 0, 1050, 1053, 1057, 1099, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1440x1050@85Hz */
|
||||
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504,
|
||||
1656, 1912, 0, 1050, 1053, 1057, 1105, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1440x900@60Hz */
|
||||
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
|
||||
1672, 1904, 0, 900, 903, 909, 934, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1440x900@75Hz */
|
||||
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536,
|
||||
1688, 1936, 0, 900, 903, 909, 942, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1440x900@85Hz */
|
||||
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544,
|
||||
1696, 1952, 0, 900, 903, 909, 948, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1600x1200@60Hz */
|
||||
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
|
||||
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1600x1200@65Hz */
|
||||
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664,
|
||||
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1600x1200@70Hz */
|
||||
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664,
|
||||
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1600x1200@75Hz */
|
||||
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 2025000, 1600, 1664,
|
||||
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1600x1200@85Hz */
|
||||
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664,
|
||||
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1680x1050@60Hz */
|
||||
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
|
||||
1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1680x1050@75Hz */
|
||||
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800,
|
||||
1976, 2272, 0, 1050, 1053, 1059, 1099, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1680x1050@85Hz */
|
||||
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808,
|
||||
1984, 2288, 0, 1050, 1053, 1059, 1105, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1792x1344@60Hz */
|
||||
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
|
||||
2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1729x1344@75Hz */
|
||||
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888,
|
||||
2104, 2456, 0, 1344, 1345, 1348, 1417, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1853x1392@60Hz */
|
||||
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
|
||||
2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1856x1392@75Hz */
|
||||
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984,
|
||||
2208, 2560, 0, 1392, 1395, 1399, 1500, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1920x1200@60Hz */
|
||||
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
|
||||
2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1920x1200@75Hz */
|
||||
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056,
|
||||
2264, 2608, 0, 1200, 1203, 1209, 1255, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1920x1200@85Hz */
|
||||
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064,
|
||||
2272, 2624, 0, 1200, 1203, 1209, 1262, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1920x1440@60Hz */
|
||||
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
|
||||
2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1920x1440@75Hz */
|
||||
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064,
|
||||
2288, 2640, 0, 1440, 1441, 1444, 1500, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 2560x1600@60Hz */
|
||||
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
|
||||
3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 2560x1600@75HZ */
|
||||
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768,
|
||||
3048, 3536, 0, 1600, 1603, 1609, 1672, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 2560x1600@85HZ */
|
||||
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768,
|
||||
3048, 3536, 0, 1600, 1603, 1609, 1682, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
};
|
||||
|
||||
static struct drm_display_mode *drm_find_dmt(struct drm_device *dev,
|
||||
int hsize, int vsize, int fresh)
|
||||
{
|
||||
int i, count;
|
||||
struct drm_display_mode *ptr, *mode;
|
||||
|
||||
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
|
||||
mode = NULL;
|
||||
for (i = 0; i < count; i++) {
|
||||
ptr = &drm_dmt_modes[i];
|
||||
if (hsize == ptr->hdisplay &&
|
||||
vsize == ptr->vdisplay &&
|
||||
fresh == drm_mode_vrefresh(ptr)) {
|
||||
/* get the expected default mode */
|
||||
mode = drm_mode_duplicate(dev, ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
/**
|
||||
* drm_mode_std - convert standard mode info (width, height, refresh) into mode
|
||||
* @t: standard timing params
|
||||
* @timing_level: standard timing level
|
||||
*
|
||||
* Take the standard timing params (in this case width, aspect, and refresh)
|
||||
* and convert them into a real mode using CVT.
|
||||
* and convert them into a real mode using CVT/GTF/DMT.
|
||||
*
|
||||
* Punts for now, but should eventually use the FB layer's CVT based mode
|
||||
* generation code.
|
||||
*/
|
||||
struct drm_display_mode *drm_mode_std(struct drm_device *dev,
|
||||
struct std_timing *t)
|
||||
struct std_timing *t,
|
||||
int timing_level)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
int hsize = t->hsize * 8 + 248, vsize;
|
||||
int hsize, vsize;
|
||||
int vrefresh_rate;
|
||||
unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
|
||||
>> EDID_TIMING_ASPECT_SHIFT;
|
||||
unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
|
||||
>> EDID_TIMING_VFREQ_SHIFT;
|
||||
|
||||
mode = drm_mode_create(dev);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
/* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
|
||||
hsize = t->hsize * 8 + 248;
|
||||
/* vrefresh_rate = vfreq + 60 */
|
||||
vrefresh_rate = vfreq + 60;
|
||||
/* the vdisplay is calculated based on the aspect ratio */
|
||||
if (aspect_ratio == 0)
|
||||
vsize = (hsize * 10) / 16;
|
||||
else if (aspect_ratio == 1)
|
||||
|
@ -267,9 +536,30 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
|
|||
vsize = (hsize * 4) / 5;
|
||||
else
|
||||
vsize = (hsize * 9) / 16;
|
||||
/* HDTV hack */
|
||||
if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) {
|
||||
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
|
||||
mode->hdisplay = 1366;
|
||||
mode->vsync_start = mode->vsync_start - 1;
|
||||
mode->vsync_end = mode->vsync_end - 1;
|
||||
return mode;
|
||||
}
|
||||
mode = NULL;
|
||||
/* check whether it can be found in default mode table */
|
||||
mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate);
|
||||
if (mode)
|
||||
return mode;
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
switch (timing_level) {
|
||||
case LEVEL_DMT:
|
||||
break;
|
||||
case LEVEL_GTF:
|
||||
mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
|
||||
break;
|
||||
case LEVEL_CVT:
|
||||
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
|
||||
break;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
@ -451,6 +741,19 @@ static int add_established_modes(struct drm_connector *connector, struct edid *e
|
|||
|
||||
return modes;
|
||||
}
|
||||
/**
|
||||
* stanard_timing_level - get std. timing level(CVT/GTF/DMT)
|
||||
* @edid: EDID block to scan
|
||||
*/
|
||||
static int standard_timing_level(struct edid *edid)
|
||||
{
|
||||
if (edid->revision >= 2) {
|
||||
if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
|
||||
return LEVEL_CVT;
|
||||
return LEVEL_GTF;
|
||||
}
|
||||
return LEVEL_DMT;
|
||||
}
|
||||
|
||||
/**
|
||||
* add_standard_modes - get std. modes from EDID and add them
|
||||
|
@ -463,6 +766,9 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
|
|||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
int i, modes = 0;
|
||||
int timing_level;
|
||||
|
||||
timing_level = standard_timing_level(edid);
|
||||
|
||||
for (i = 0; i < EDID_STD_TIMINGS; i++) {
|
||||
struct std_timing *t = &edid->standard_timings[i];
|
||||
|
@ -472,7 +778,8 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
|
|||
if (t->hsize == 1 && t->vfreq_aspect == 1)
|
||||
continue;
|
||||
|
||||
newmode = drm_mode_std(dev, &edid->standard_timings[i]);
|
||||
newmode = drm_mode_std(dev, &edid->standard_timings[i],
|
||||
timing_level);
|
||||
if (newmode) {
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
modes++;
|
||||
|
@ -496,6 +803,9 @@ static int add_detailed_info(struct drm_connector *connector,
|
|||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
int i, j, modes = 0;
|
||||
int timing_level;
|
||||
|
||||
timing_level = standard_timing_level(edid);
|
||||
|
||||
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
|
||||
struct detailed_timing *timing = &edid->detailed_timings[i];
|
||||
|
@ -525,7 +835,8 @@ static int add_detailed_info(struct drm_connector *connector,
|
|||
struct drm_display_mode *newmode;
|
||||
|
||||
std = &data->data.timings[j];
|
||||
newmode = drm_mode_std(dev, std);
|
||||
newmode = drm_mode_std(dev, std,
|
||||
timing_level);
|
||||
if (newmode) {
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
modes++;
|
||||
|
@ -551,6 +862,122 @@ static int add_detailed_info(struct drm_connector *connector,
|
|||
|
||||
return modes;
|
||||
}
|
||||
/**
|
||||
* add_detailed_mode_eedid - get detailed mode info from addtional timing
|
||||
* EDID block
|
||||
* @connector: attached connector
|
||||
* @edid: EDID block to scan(It is only to get addtional timing EDID block)
|
||||
* @quirks: quirks to apply
|
||||
*
|
||||
* Some of the detailed timing sections may contain mode information. Grab
|
||||
* it and add it to the list.
|
||||
*/
|
||||
static int add_detailed_info_eedid(struct drm_connector *connector,
|
||||
struct edid *edid, u32 quirks)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
int i, j, modes = 0;
|
||||
char *edid_ext = NULL;
|
||||
struct detailed_timing *timing;
|
||||
struct detailed_non_pixel *data;
|
||||
struct drm_display_mode *newmode;
|
||||
int edid_ext_num;
|
||||
int start_offset, end_offset;
|
||||
int timing_level;
|
||||
|
||||
if (edid->version == 1 && edid->revision < 3) {
|
||||
/* If the EDID version is less than 1.3, there is no
|
||||
* extension EDID.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (!edid->extensions) {
|
||||
/* if there is no extension EDID, it is unnecessary to
|
||||
* parse the E-EDID to get detailed info
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Chose real EDID extension number */
|
||||
edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
|
||||
MAX_EDID_EXT_NUM : edid->extensions;
|
||||
|
||||
/* Find CEA extension */
|
||||
for (i = 0; i < edid_ext_num; i++) {
|
||||
edid_ext = (char *)edid + EDID_LENGTH * (i + 1);
|
||||
/* This block is CEA extension */
|
||||
if (edid_ext[0] == 0x02)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == edid_ext_num) {
|
||||
/* if there is no additional timing EDID block, return */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the start offset of detailed timing block */
|
||||
start_offset = edid_ext[2];
|
||||
if (start_offset == 0) {
|
||||
/* If the start_offset is zero, it means that neither detailed
|
||||
* info nor data block exist. In such case it is also
|
||||
* unnecessary to parse the detailed timing info.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
timing_level = standard_timing_level(edid);
|
||||
end_offset = EDID_LENGTH;
|
||||
end_offset -= sizeof(struct detailed_timing);
|
||||
for (i = start_offset; i < end_offset;
|
||||
i += sizeof(struct detailed_timing)) {
|
||||
timing = (struct detailed_timing *)(edid_ext + i);
|
||||
data = &timing->data.other_data;
|
||||
/* Detailed mode timing */
|
||||
if (timing->pixel_clock) {
|
||||
newmode = drm_mode_detailed(dev, edid, timing, quirks);
|
||||
if (!newmode)
|
||||
continue;
|
||||
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
|
||||
modes++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Other timing or info */
|
||||
switch (data->type) {
|
||||
case EDID_DETAIL_MONITOR_SERIAL:
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_STRING:
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_RANGE:
|
||||
/* Get monitor range data */
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_NAME:
|
||||
break;
|
||||
case EDID_DETAIL_MONITOR_CPDATA:
|
||||
break;
|
||||
case EDID_DETAIL_STD_MODES:
|
||||
/* Five modes per detailed section */
|
||||
for (j = 0; j < 5; i++) {
|
||||
struct std_timing *std;
|
||||
struct drm_display_mode *newmode;
|
||||
|
||||
std = &data->data.timings[j];
|
||||
newmode = drm_mode_std(dev, std, timing_level);
|
||||
if (newmode) {
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
modes++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
#define DDC_ADDR 0x50
|
||||
/**
|
||||
|
@ -584,7 +1011,6 @@ int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
|
|||
if (i2c_transfer(adapter, msgs, 2) == 2)
|
||||
return 0;
|
||||
|
||||
dev_info(&adapter->dev, "unable to read EDID block.\n");
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_do_probe_ddc_edid);
|
||||
|
@ -597,8 +1023,6 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
|
|||
|
||||
ret = drm_do_probe_ddc_edid(adapter, buf, len);
|
||||
if (ret != 0) {
|
||||
dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
|
||||
drm_get_connector_name(connector));
|
||||
goto end;
|
||||
}
|
||||
if (!edid_is_valid((struct edid *)buf)) {
|
||||
|
@ -610,7 +1034,6 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define MAX_EDID_EXT_NUM 4
|
||||
/**
|
||||
* drm_get_edid - get EDID data, if available
|
||||
* @connector: connector we're probing
|
||||
|
@ -763,6 +1186,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
|||
num_modes += add_established_modes(connector, edid);
|
||||
num_modes += add_standard_modes(connector, edid);
|
||||
num_modes += add_detailed_info(connector, edid, quirks);
|
||||
num_modes += add_detailed_info_eedid(connector, edid, quirks);
|
||||
|
||||
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
|
||||
edid_fixup_preferred(connector, quirks);
|
||||
|
@ -788,3 +1212,49 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
|||
return num_modes;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_add_edid_modes);
|
||||
|
||||
/**
|
||||
* drm_add_modes_noedid - add modes for the connectors without EDID
|
||||
* @connector: connector we're probing
|
||||
* @hdisplay: the horizontal display limit
|
||||
* @vdisplay: the vertical display limit
|
||||
*
|
||||
* Add the specified modes to the connector's mode list. Only when the
|
||||
* hdisplay/vdisplay is not beyond the given limit, it will be added.
|
||||
*
|
||||
* Return number of modes added or 0 if we couldn't find any.
|
||||
*/
|
||||
int drm_add_modes_noedid(struct drm_connector *connector,
|
||||
int hdisplay, int vdisplay)
|
||||
{
|
||||
int i, count, num_modes = 0;
|
||||
struct drm_display_mode *mode, *ptr;
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
|
||||
if (hdisplay < 0)
|
||||
hdisplay = 0;
|
||||
if (vdisplay < 0)
|
||||
vdisplay = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ptr = &drm_dmt_modes[i];
|
||||
if (hdisplay && vdisplay) {
|
||||
/*
|
||||
* Only when two are valid, they will be used to check
|
||||
* whether the mode should be added to the mode list of
|
||||
* the connector.
|
||||
*/
|
||||
if (ptr->hdisplay > hdisplay ||
|
||||
ptr->vdisplay > vdisplay)
|
||||
continue;
|
||||
}
|
||||
mode = drm_mode_duplicate(dev, ptr);
|
||||
if (mode) {
|
||||
drm_mode_probed_add(connector, mode);
|
||||
num_modes++;
|
||||
}
|
||||
}
|
||||
return num_modes;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_add_modes_noedid);
|
||||
|
|
116
drivers/gpu/drm/drm_encoder_slave.c
Normal file
116
drivers/gpu/drm/drm_encoder_slave.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Francisco Jerez.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* 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 (including the
|
||||
* next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drm_encoder_slave.h"
|
||||
|
||||
/**
|
||||
* drm_i2c_encoder_init - Initialize an I2C slave encoder
|
||||
* @dev: DRM device.
|
||||
* @encoder: Encoder to be attached to the I2C device. You aren't
|
||||
* required to have called drm_encoder_init() before.
|
||||
* @adap: I2C adapter that will be used to communicate with
|
||||
* the device.
|
||||
* @info: Information that will be used to create the I2C device.
|
||||
* Required fields are @addr and @type.
|
||||
*
|
||||
* Create an I2C device on the specified bus (the module containing its
|
||||
* driver is transparently loaded) and attach it to the specified
|
||||
* &drm_encoder_slave. The @slave_funcs field will be initialized with
|
||||
* the hooks provided by the slave driver.
|
||||
*
|
||||
* Returns 0 on success or a negative errno on failure, in particular,
|
||||
* -ENODEV is returned when no matching driver is found.
|
||||
*/
|
||||
int drm_i2c_encoder_init(struct drm_device *dev,
|
||||
struct drm_encoder_slave *encoder,
|
||||
struct i2c_adapter *adap,
|
||||
const struct i2c_board_info *info)
|
||||
{
|
||||
char modalias[sizeof(I2C_MODULE_PREFIX)
|
||||
+ I2C_NAME_SIZE];
|
||||
struct module *module = NULL;
|
||||
struct i2c_client *client;
|
||||
struct drm_i2c_encoder_driver *encoder_drv;
|
||||
int err = 0;
|
||||
|
||||
snprintf(modalias, sizeof(modalias),
|
||||
"%s%s", I2C_MODULE_PREFIX, info->type);
|
||||
request_module(modalias);
|
||||
|
||||
client = i2c_new_device(adap, info);
|
||||
if (!client) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!client->driver) {
|
||||
err = -ENODEV;
|
||||
goto fail_unregister;
|
||||
}
|
||||
|
||||
module = client->driver->driver.owner;
|
||||
if (!try_module_get(module)) {
|
||||
err = -ENODEV;
|
||||
goto fail_unregister;
|
||||
}
|
||||
|
||||
encoder->bus_priv = client;
|
||||
|
||||
encoder_drv = to_drm_i2c_encoder_driver(client->driver);
|
||||
|
||||
err = encoder_drv->encoder_init(client, dev, encoder);
|
||||
if (err)
|
||||
goto fail_unregister;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unregister:
|
||||
i2c_unregister_device(client);
|
||||
module_put(module);
|
||||
fail:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_i2c_encoder_init);
|
||||
|
||||
/**
|
||||
* drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder
|
||||
* @drm_encoder: Encoder to be unregistered.
|
||||
*
|
||||
* This should be called from the @destroy method of an I2C slave
|
||||
* encoder driver once I2C access is no longer needed.
|
||||
*/
|
||||
void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
|
||||
{
|
||||
struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder);
|
||||
struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder);
|
||||
struct module *module = client->driver->driver.owner;
|
||||
|
||||
i2c_unregister_device(client);
|
||||
encoder->bus_priv = NULL;
|
||||
|
||||
module_put(module);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_i2c_encoder_destroy);
|
707
drivers/gpu/drm/drm_fb_helper.c
Normal file
707
drivers/gpu/drm/drm_fb_helper.c
Normal file
|
@ -0,0 +1,707 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2009 Red Hat Inc.
|
||||
* Copyright (c) 2006-2008 Intel Corporation
|
||||
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
|
||||
*
|
||||
* DRM framebuffer helper functions
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Dave Airlie <airlied@linux.ie>
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/fb.h>
|
||||
#include "drmP.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_fb_helper.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
|
||||
MODULE_AUTHOR("David Airlie, Jesse Barnes");
|
||||
MODULE_DESCRIPTION("DRM KMS helper");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
||||
static LIST_HEAD(kernel_fb_helper_list);
|
||||
|
||||
bool drm_fb_helper_force_kernel_mode(void)
|
||||
{
|
||||
int i = 0;
|
||||
bool ret, error = false;
|
||||
struct drm_fb_helper *helper;
|
||||
|
||||
if (list_empty(&kernel_fb_helper_list))
|
||||
return false;
|
||||
|
||||
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
|
||||
for (i = 0; i < helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
|
||||
ret = drm_crtc_helper_set_config(mode_set);
|
||||
if (ret)
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed,
|
||||
void *panic_str)
|
||||
{
|
||||
DRM_ERROR("panic occurred, switching back to text console\n");
|
||||
return drm_fb_helper_force_kernel_mode();
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_panic);
|
||||
|
||||
static struct notifier_block paniced = {
|
||||
.notifier_call = drm_fb_helper_panic,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_fb_helper_restore - restore the framebuffer console (kernel) config
|
||||
*
|
||||
* Restore's the kernel's fbcon mode, used for lastclose & panic paths.
|
||||
*/
|
||||
void drm_fb_helper_restore(void)
|
||||
{
|
||||
bool ret;
|
||||
ret = drm_fb_helper_force_kernel_mode();
|
||||
if (ret == true)
|
||||
DRM_ERROR("Failed to restore crtc configuration\n");
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_restore);
|
||||
|
||||
static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
|
||||
{
|
||||
drm_fb_helper_restore();
|
||||
}
|
||||
static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn);
|
||||
|
||||
static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3)
|
||||
{
|
||||
schedule_work(&drm_fb_helper_restore_work);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = {
|
||||
.handler = drm_fb_helper_sysrq,
|
||||
.help_msg = "force-fb(V)",
|
||||
.action_msg = "Restore framebuffer console",
|
||||
};
|
||||
|
||||
static void drm_fb_helper_on(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, turn the crtc on then,
|
||||
* find all associated encoders and turn them on.
|
||||
*/
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs =
|
||||
crtc->helper_private;
|
||||
|
||||
/* Only mess with CRTCs in this fb */
|
||||
if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
|
||||
!crtc->enabled)
|
||||
continue;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
/* Found a CRTC on this fb, now find encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, find all associated encoders
|
||||
* and turn them off, then turn off the CRTC.
|
||||
*/
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs =
|
||||
crtc->helper_private;
|
||||
|
||||
/* Only mess with CRTCs in this fb */
|
||||
if (crtc->base.id != fb_helper->crtc_info[i].crtc_id ||
|
||||
!crtc->enabled)
|
||||
continue;
|
||||
|
||||
/* Found a CRTC on this fb, now find encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
encoder_funcs->dpms(encoder, dpms_mode);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
}
|
||||
if (dpms_mode == DRM_MODE_DPMS_OFF) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
crtc_funcs->dpms(crtc, dpms_mode);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int drm_fb_helper_blank(int blank, struct fb_info *info)
|
||||
{
|
||||
switch (blank) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
drm_fb_helper_on(info);
|
||||
break;
|
||||
case FB_BLANK_NORMAL:
|
||||
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
case FB_BLANK_HSYNC_SUSPEND:
|
||||
drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
case FB_BLANK_VSYNC_SUSPEND:
|
||||
drm_fb_helper_off(info, DRM_MODE_DPMS_SUSPEND);
|
||||
break;
|
||||
case FB_BLANK_POWERDOWN:
|
||||
drm_fb_helper_off(info, DRM_MODE_DPMS_OFF);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_blank);
|
||||
|
||||
static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < helper->crtc_count; i++)
|
||||
kfree(helper->crtc_info[i].mode_set.connectors);
|
||||
kfree(helper->crtc_info);
|
||||
}
|
||||
|
||||
int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count, int max_conn_count)
|
||||
{
|
||||
struct drm_device *dev = helper->dev;
|
||||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
|
||||
if (!helper->crtc_info)
|
||||
return -ENOMEM;
|
||||
|
||||
helper->crtc_count = crtc_count;
|
||||
|
||||
for (i = 0; i < crtc_count; i++) {
|
||||
helper->crtc_info[i].mode_set.connectors =
|
||||
kcalloc(max_conn_count,
|
||||
sizeof(struct drm_connector *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!helper->crtc_info[i].mode_set.connectors) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
helper->crtc_info[i].mode_set.num_connectors = 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
helper->crtc_info[i].crtc_id = crtc->base.id;
|
||||
helper->crtc_info[i].mode_set.crtc = crtc;
|
||||
i++;
|
||||
}
|
||||
helper->conn_limit = max_conn_count;
|
||||
return 0;
|
||||
out_free:
|
||||
drm_fb_helper_crtc_free(helper);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
|
||||
|
||||
int drm_fb_helper_setcolreg(unsigned regno,
|
||||
unsigned red,
|
||||
unsigned green,
|
||||
unsigned blue,
|
||||
unsigned transp,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_crtc *crtc;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
|
||||
break;
|
||||
}
|
||||
if (i == fb_helper->crtc_count)
|
||||
continue;
|
||||
|
||||
if (regno > 255)
|
||||
return 1;
|
||||
|
||||
if (fb->depth == 8) {
|
||||
fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (regno < 16) {
|
||||
switch (fb->depth) {
|
||||
case 15:
|
||||
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
|
||||
((green & 0xf800) >> 6) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 16:
|
||||
fb->pseudo_palette[regno] = (red & 0xf800) |
|
||||
((green & 0xfc00) >> 5) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
fb->pseudo_palette[regno] =
|
||||
(((red >> 8) & 0xff) << info->var.red.offset) |
|
||||
(((green >> 8) & 0xff) << info->var.green.offset) |
|
||||
(((blue >> 8) & 0xff) << info->var.blue.offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_setcolreg);
|
||||
|
||||
int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
int depth;
|
||||
|
||||
if (var->pixclock == -1 || !var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
/* Need to resize the fb object !!! */
|
||||
if (var->xres > fb->width || var->yres > fb->height) {
|
||||
DRM_ERROR("Requested width/height is greater than current fb "
|
||||
"object %dx%d > %dx%d\n", var->xres, var->yres,
|
||||
fb->width, fb->height);
|
||||
DRM_ERROR("Need resizing code.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
var->red.offset = 0;
|
||||
var->green.offset = 0;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 5;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 1;
|
||||
var->transp.offset = 15;
|
||||
break;
|
||||
case 16:
|
||||
var->red.offset = 11;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 32:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 8;
|
||||
var->transp.offset = 24;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_check_var);
|
||||
|
||||
/* this will let fbcon do the mode init */
|
||||
int drm_fb_helper_set_par(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct drm_crtc *crtc;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (var->pixclock != -1) {
|
||||
DRM_ERROR("PIXEL CLCOK SET\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
|
||||
break;
|
||||
}
|
||||
if (i == fb_helper->crtc_count)
|
||||
continue;
|
||||
|
||||
if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_set_par);
|
||||
|
||||
int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
if (crtc->base.id == fb_helper->crtc_info[i].crtc_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == fb_helper->crtc_count)
|
||||
continue;
|
||||
|
||||
modeset = &fb_helper->crtc_info[i].mode_set;
|
||||
|
||||
modeset->x = var->xoffset;
|
||||
modeset->y = var->yoffset;
|
||||
|
||||
if (modeset->num_connectors) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = crtc->funcs->set_config(modeset);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (!ret) {
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_pan_display);
|
||||
|
||||
int drm_fb_helper_single_fb_probe(struct drm_device *dev,
|
||||
int (*fb_create)(struct drm_device *dev,
|
||||
uint32_t fb_width,
|
||||
uint32_t fb_height,
|
||||
uint32_t surface_width,
|
||||
uint32_t surface_height,
|
||||
struct drm_framebuffer **fb_ptr))
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
|
||||
unsigned int surface_width = 0, surface_height = 0;
|
||||
int new_fb = 0;
|
||||
int crtc_count = 0;
|
||||
int ret, i, conn_count = 0;
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_mode_set *modeset = NULL;
|
||||
struct drm_fb_helper *fb_helper;
|
||||
|
||||
/* first up get a count of crtcs now in use and new min/maxes width/heights */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (drm_helper_crtc_in_use(crtc)) {
|
||||
if (crtc->desired_mode) {
|
||||
if (crtc->desired_mode->hdisplay < fb_width)
|
||||
fb_width = crtc->desired_mode->hdisplay;
|
||||
|
||||
if (crtc->desired_mode->vdisplay < fb_height)
|
||||
fb_height = crtc->desired_mode->vdisplay;
|
||||
|
||||
if (crtc->desired_mode->hdisplay > surface_width)
|
||||
surface_width = crtc->desired_mode->hdisplay;
|
||||
|
||||
if (crtc->desired_mode->vdisplay > surface_height)
|
||||
surface_height = crtc->desired_mode->vdisplay;
|
||||
}
|
||||
crtc_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
|
||||
/* hmm everyone went away - assume VGA cable just fell out
|
||||
and will come back later. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do we have an fb already? */
|
||||
if (list_empty(&dev->mode_config.fb_kernel_list)) {
|
||||
ret = (*fb_create)(dev, fb_width, fb_height, surface_width,
|
||||
surface_height, &fb);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
new_fb = 1;
|
||||
} else {
|
||||
fb = list_first_entry(&dev->mode_config.fb_kernel_list,
|
||||
struct drm_framebuffer, filp_head);
|
||||
|
||||
/* if someone hotplugs something bigger than we have already allocated, we are pwned.
|
||||
As really we can't resize an fbdev that is in the wild currently due to fbdev
|
||||
not really being designed for the lower layers moving stuff around under it.
|
||||
- so in the grand style of things - punt. */
|
||||
if ((fb->width < surface_width) ||
|
||||
(fb->height < surface_height)) {
|
||||
DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
info = fb->fbdev;
|
||||
fb_helper = info->par;
|
||||
|
||||
crtc_count = 0;
|
||||
/* okay we need to setup new connector sets in the crtcs */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
modeset = &fb_helper->crtc_info[crtc_count].mode_set;
|
||||
modeset->fb = fb;
|
||||
conn_count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder)
|
||||
if (connector->encoder->crtc == modeset->crtc) {
|
||||
modeset->connectors[conn_count] = connector;
|
||||
conn_count++;
|
||||
if (conn_count > fb_helper->conn_limit)
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = conn_count; i < fb_helper->conn_limit; i++)
|
||||
modeset->connectors[i] = NULL;
|
||||
|
||||
modeset->crtc = crtc;
|
||||
crtc_count++;
|
||||
|
||||
modeset->num_connectors = conn_count;
|
||||
if (modeset->crtc->desired_mode) {
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = drm_mode_duplicate(dev,
|
||||
modeset->crtc->desired_mode);
|
||||
}
|
||||
}
|
||||
fb_helper->crtc_count = crtc_count;
|
||||
fb_helper->fb = fb;
|
||||
|
||||
if (new_fb) {
|
||||
info->var.pixclock = -1;
|
||||
if (register_framebuffer(info) < 0)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
drm_fb_helper_set_par(info);
|
||||
}
|
||||
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
|
||||
info->fix.id);
|
||||
|
||||
/* Switch back to kernel console on panic */
|
||||
/* multi card linked list maybe */
|
||||
if (list_empty(&kernel_fb_helper_list)) {
|
||||
printk(KERN_INFO "registered panic notifier\n");
|
||||
atomic_notifier_chain_register(&panic_notifier_list,
|
||||
&paniced);
|
||||
register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
|
||||
}
|
||||
list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
|
||||
|
||||
void drm_fb_helper_free(struct drm_fb_helper *helper)
|
||||
{
|
||||
list_del(&helper->kernel_fb_list);
|
||||
if (list_empty(&kernel_fb_helper_list)) {
|
||||
printk(KERN_INFO "unregistered panic notifier\n");
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list,
|
||||
&paniced);
|
||||
unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
|
||||
}
|
||||
drm_fb_helper_crtc_free(helper);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_free);
|
||||
|
||||
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch)
|
||||
{
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
info->fix.type_aux = 0;
|
||||
info->fix.xpanstep = 1; /* doing it in hw */
|
||||
info->fix.ypanstep = 1; /* doing it in hw */
|
||||
info->fix.ywrapstep = 0;
|
||||
info->fix.accel = FB_ACCEL_NONE;
|
||||
info->fix.type_aux = 0;
|
||||
|
||||
info->fix.line_length = pitch;
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_fill_fix);
|
||||
|
||||
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_framebuffer *fb,
|
||||
uint32_t fb_width, uint32_t fb_height)
|
||||
{
|
||||
info->pseudo_palette = fb->pseudo_palette;
|
||||
info->var.xres_virtual = fb->width;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->bits_per_pixel;
|
||||
info->var.xoffset = 0;
|
||||
info->var.yoffset = 0;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
info->var.height = -1;
|
||||
info->var.width = -1;
|
||||
|
||||
switch (fb->depth) {
|
||||
case 8:
|
||||
info->var.red.offset = 0;
|
||||
info->var.green.offset = 0;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8; /* 8bit DAC */
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 15:
|
||||
info->var.red.offset = 10;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 5;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 15;
|
||||
info->var.transp.length = 1;
|
||||
break;
|
||||
case 16:
|
||||
info->var.red.offset = 11;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 6;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 32:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
info->var.xres = fb_width;
|
||||
info->var.yres = fb_height;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_fill_var);
|
|
@ -164,7 +164,7 @@ EXPORT_SYMBOL(drm_gem_object_alloc);
|
|||
* Removes the mapping from handle to filp for this object.
|
||||
*/
|
||||
static int
|
||||
drm_gem_handle_delete(struct drm_file *filp, int handle)
|
||||
drm_gem_handle_delete(struct drm_file *filp, u32 handle)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct drm_gem_object *obj;
|
||||
|
@ -207,7 +207,7 @@ drm_gem_handle_delete(struct drm_file *filp, int handle)
|
|||
int
|
||||
drm_gem_handle_create(struct drm_file *file_priv,
|
||||
struct drm_gem_object *obj,
|
||||
int *handlep)
|
||||
u32 *handlep)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -221,7 +221,7 @@ again:
|
|||
|
||||
/* do the allocation under our spinlock */
|
||||
spin_lock(&file_priv->table_lock);
|
||||
ret = idr_get_new_above(&file_priv->object_idr, obj, 1, handlep);
|
||||
ret = idr_get_new_above(&file_priv->object_idr, obj, 1, (int *)handlep);
|
||||
spin_unlock(&file_priv->table_lock);
|
||||
if (ret == -EAGAIN)
|
||||
goto again;
|
||||
|
@ -237,7 +237,7 @@ EXPORT_SYMBOL(drm_gem_handle_create);
|
|||
/** Returns a reference to the object named by the handle. */
|
||||
struct drm_gem_object *
|
||||
drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
|
||||
int handle)
|
||||
u32 handle)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
|
@ -344,7 +344,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
|||
struct drm_gem_open *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
int handle;
|
||||
u32 handle;
|
||||
|
||||
if (!(dev->driver->driver_features & DRIVER_GEM))
|
||||
return -ENODEV;
|
||||
|
@ -539,7 +539,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
|
||||
vma->vm_ops = obj->dev->driver->gem_vm_ops;
|
||||
vma->vm_private_data = map->handle;
|
||||
/* FIXME: use pgprot_writecombine when available */
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
|
||||
/* Take a ref for this mapping of the object, so that the fault
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
|
||||
#include <linux/vgaarb.h>
|
||||
/**
|
||||
* Get interrupt from bus id.
|
||||
*
|
||||
|
@ -171,6 +172,26 @@ err:
|
|||
}
|
||||
EXPORT_SYMBOL(drm_vblank_init);
|
||||
|
||||
static void drm_irq_vgaarb_nokms(void *cookie, bool state)
|
||||
{
|
||||
struct drm_device *dev = cookie;
|
||||
|
||||
if (dev->driver->vgaarb_irq) {
|
||||
dev->driver->vgaarb_irq(dev, state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dev->irq_enabled)
|
||||
return;
|
||||
|
||||
if (state)
|
||||
dev->driver->irq_uninstall(dev);
|
||||
else {
|
||||
dev->driver->irq_preinstall(dev);
|
||||
dev->driver->irq_postinstall(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install IRQ handler.
|
||||
*
|
||||
|
@ -231,6 +252,9 @@ int drm_irq_install(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
vga_client_register(dev->pdev, (void *)dev, drm_irq_vgaarb_nokms, NULL);
|
||||
|
||||
/* After installing handler */
|
||||
ret = dev->driver->irq_postinstall(dev);
|
||||
if (ret < 0) {
|
||||
|
@ -279,6 +303,9 @@ int drm_irq_uninstall(struct drm_device * dev)
|
|||
|
||||
DRM_DEBUG("irq=%d\n", dev->pdev->irq);
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
|
||||
dev->driver->irq_uninstall(dev);
|
||||
|
||||
free_irq(dev->pdev->irq, dev);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "drmP.h"
|
||||
#include "drm_mm.h"
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#define MM_UNUSED_TARGET 4
|
||||
|
||||
|
@ -370,3 +371,23 @@ void drm_mm_takedown(struct drm_mm * mm)
|
|||
BUG_ON(mm->num_unused != 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_takedown);
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
|
||||
{
|
||||
struct drm_mm_node *entry;
|
||||
int total_used = 0, total_free = 0, total = 0;
|
||||
|
||||
list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
|
||||
seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
|
||||
total += entry->size;
|
||||
if (entry->free)
|
||||
total_free += entry->size;
|
||||
else
|
||||
total_used += entry->size;
|
||||
}
|
||||
seq_printf(m, "total: %d, used %d free %d\n", total, total_free, total_used);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_dump_table);
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* Copyright © 2007 Dave Airlie
|
||||
* Copyright © 2007-2008 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
* Copyright 2005-2006 Luc Verhaegen
|
||||
* Copyright (c) 2001, Andy Ritger aritger@nvidia.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -38,7 +40,6 @@
|
|||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
|
||||
#define DRM_MODESET_DEBUG "drm_mode"
|
||||
/**
|
||||
* drm_mode_debug_printmodeline - debug print a mode
|
||||
* @dev: DRM device
|
||||
|
@ -51,8 +52,8 @@
|
|||
*/
|
||||
void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
|
||||
{
|
||||
DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
|
||||
"Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
|
||||
DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
|
||||
"0x%x 0x%x\n",
|
||||
mode->base.id, mode->name, mode->vrefresh, mode->clock,
|
||||
mode->hdisplay, mode->hsync_start,
|
||||
mode->hsync_end, mode->htotal,
|
||||
|
@ -61,6 +62,420 @@ void drm_mode_debug_printmodeline(struct drm_display_mode *mode)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_mode_debug_printmodeline);
|
||||
|
||||
/**
|
||||
* drm_cvt_mode -create a modeline based on CVT algorithm
|
||||
* @dev: DRM device
|
||||
* @hdisplay: hdisplay size
|
||||
* @vdisplay: vdisplay size
|
||||
* @vrefresh : vrefresh rate
|
||||
* @reduced : Whether the GTF calculation is simplified
|
||||
* @interlaced:Whether the interlace is supported
|
||||
*
|
||||
* LOCKING:
|
||||
* none.
|
||||
*
|
||||
* return the modeline based on CVT algorithm
|
||||
*
|
||||
* This function is called to generate the modeline based on CVT algorithm
|
||||
* according to the hdisplay, vdisplay, vrefresh.
|
||||
* It is based from the VESA(TM) Coordinated Video Timing Generator by
|
||||
* Graham Loveridge April 9, 2003 available at
|
||||
* http://www.vesa.org/public/CVT/CVTd6r1.xls
|
||||
*
|
||||
* And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
|
||||
* What I have done is to translate it by using integer calculation.
|
||||
*/
|
||||
#define HV_FACTOR 1000
|
||||
struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
|
||||
int vdisplay, int vrefresh,
|
||||
bool reduced, bool interlaced)
|
||||
{
|
||||
/* 1) top/bottom margin size (% of height) - default: 1.8, */
|
||||
#define CVT_MARGIN_PERCENTAGE 18
|
||||
/* 2) character cell horizontal granularity (pixels) - default 8 */
|
||||
#define CVT_H_GRANULARITY 8
|
||||
/* 3) Minimum vertical porch (lines) - default 3 */
|
||||
#define CVT_MIN_V_PORCH 3
|
||||
/* 4) Minimum number of vertical back porch lines - default 6 */
|
||||
#define CVT_MIN_V_BPORCH 6
|
||||
/* Pixel Clock step (kHz) */
|
||||
#define CVT_CLOCK_STEP 250
|
||||
struct drm_display_mode *drm_mode;
|
||||
bool margins = false;
|
||||
unsigned int vfieldrate, hperiod;
|
||||
int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
|
||||
int interlace;
|
||||
|
||||
/* allocate the drm_display_mode structure. If failure, we will
|
||||
* return directly
|
||||
*/
|
||||
drm_mode = drm_mode_create(dev);
|
||||
if (!drm_mode)
|
||||
return NULL;
|
||||
|
||||
/* the CVT default refresh rate is 60Hz */
|
||||
if (!vrefresh)
|
||||
vrefresh = 60;
|
||||
|
||||
/* the required field fresh rate */
|
||||
if (interlaced)
|
||||
vfieldrate = vrefresh * 2;
|
||||
else
|
||||
vfieldrate = vrefresh;
|
||||
|
||||
/* horizontal pixels */
|
||||
hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY);
|
||||
|
||||
/* determine the left&right borders */
|
||||
hmargin = 0;
|
||||
if (margins) {
|
||||
hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
|
||||
hmargin -= hmargin % CVT_H_GRANULARITY;
|
||||
}
|
||||
/* find the total active pixels */
|
||||
drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin;
|
||||
|
||||
/* find the number of lines per field */
|
||||
if (interlaced)
|
||||
vdisplay_rnd = vdisplay / 2;
|
||||
else
|
||||
vdisplay_rnd = vdisplay;
|
||||
|
||||
/* find the top & bottom borders */
|
||||
vmargin = 0;
|
||||
if (margins)
|
||||
vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
|
||||
|
||||
drm_mode->vdisplay = vdisplay + 2 * vmargin;
|
||||
|
||||
/* Interlaced */
|
||||
if (interlaced)
|
||||
interlace = 1;
|
||||
else
|
||||
interlace = 0;
|
||||
|
||||
/* Determine VSync Width from aspect ratio */
|
||||
if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay))
|
||||
vsync = 4;
|
||||
else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay))
|
||||
vsync = 5;
|
||||
else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay))
|
||||
vsync = 6;
|
||||
else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay))
|
||||
vsync = 7;
|
||||
else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay))
|
||||
vsync = 7;
|
||||
else /* custom */
|
||||
vsync = 10;
|
||||
|
||||
if (!reduced) {
|
||||
/* simplify the GTF calculation */
|
||||
/* 4) Minimum time of vertical sync + back porch interval (µs)
|
||||
* default 550.0
|
||||
*/
|
||||
int tmp1, tmp2;
|
||||
#define CVT_MIN_VSYNC_BP 550
|
||||
/* 3) Nominal HSync width (% of line period) - default 8 */
|
||||
#define CVT_HSYNC_PERCENTAGE 8
|
||||
unsigned int hblank_percentage;
|
||||
int vsyncandback_porch, vback_porch, hblank;
|
||||
|
||||
/* estimated the horizontal period */
|
||||
tmp1 = HV_FACTOR * 1000000 -
|
||||
CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate;
|
||||
tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 +
|
||||
interlace;
|
||||
hperiod = tmp1 * 2 / (tmp2 * vfieldrate);
|
||||
|
||||
tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1;
|
||||
/* 9. Find number of lines in sync + backporch */
|
||||
if (tmp1 < (vsync + CVT_MIN_V_PORCH))
|
||||
vsyncandback_porch = vsync + CVT_MIN_V_PORCH;
|
||||
else
|
||||
vsyncandback_porch = tmp1;
|
||||
/* 10. Find number of lines in back porch */
|
||||
vback_porch = vsyncandback_porch - vsync;
|
||||
drm_mode->vtotal = vdisplay_rnd + 2 * vmargin +
|
||||
vsyncandback_porch + CVT_MIN_V_PORCH;
|
||||
/* 5) Definition of Horizontal blanking time limitation */
|
||||
/* Gradient (%/kHz) - default 600 */
|
||||
#define CVT_M_FACTOR 600
|
||||
/* Offset (%) - default 40 */
|
||||
#define CVT_C_FACTOR 40
|
||||
/* Blanking time scaling factor - default 128 */
|
||||
#define CVT_K_FACTOR 128
|
||||
/* Scaling factor weighting - default 20 */
|
||||
#define CVT_J_FACTOR 20
|
||||
#define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256)
|
||||
#define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
|
||||
CVT_J_FACTOR)
|
||||
/* 12. Find ideal blanking duty cycle from formula */
|
||||
hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME *
|
||||
hperiod / 1000;
|
||||
/* 13. Blanking time */
|
||||
if (hblank_percentage < 20 * HV_FACTOR)
|
||||
hblank_percentage = 20 * HV_FACTOR;
|
||||
hblank = drm_mode->hdisplay * hblank_percentage /
|
||||
(100 * HV_FACTOR - hblank_percentage);
|
||||
hblank -= hblank % (2 * CVT_H_GRANULARITY);
|
||||
/* 14. find the total pixes per line */
|
||||
drm_mode->htotal = drm_mode->hdisplay + hblank;
|
||||
drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2;
|
||||
drm_mode->hsync_start = drm_mode->hsync_end -
|
||||
(drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100;
|
||||
drm_mode->hsync_start += CVT_H_GRANULARITY -
|
||||
drm_mode->hsync_start % CVT_H_GRANULARITY;
|
||||
/* fill the Vsync values */
|
||||
drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH;
|
||||
drm_mode->vsync_end = drm_mode->vsync_start + vsync;
|
||||
} else {
|
||||
/* Reduced blanking */
|
||||
/* Minimum vertical blanking interval time (µs)- default 460 */
|
||||
#define CVT_RB_MIN_VBLANK 460
|
||||
/* Fixed number of clocks for horizontal sync */
|
||||
#define CVT_RB_H_SYNC 32
|
||||
/* Fixed number of clocks for horizontal blanking */
|
||||
#define CVT_RB_H_BLANK 160
|
||||
/* Fixed number of lines for vertical front porch - default 3*/
|
||||
#define CVT_RB_VFPORCH 3
|
||||
int vbilines;
|
||||
int tmp1, tmp2;
|
||||
/* 8. Estimate Horizontal period. */
|
||||
tmp1 = HV_FACTOR * 1000000 -
|
||||
CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate;
|
||||
tmp2 = vdisplay_rnd + 2 * vmargin;
|
||||
hperiod = tmp1 / (tmp2 * vfieldrate);
|
||||
/* 9. Find number of lines in vertical blanking */
|
||||
vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1;
|
||||
/* 10. Check if vertical blanking is sufficient */
|
||||
if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH))
|
||||
vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH;
|
||||
/* 11. Find total number of lines in vertical field */
|
||||
drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines;
|
||||
/* 12. Find total number of pixels in a line */
|
||||
drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
|
||||
/* Fill in HSync values */
|
||||
drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
|
||||
drm_mode->hsync_start = drm_mode->hsync_end = CVT_RB_H_SYNC;
|
||||
}
|
||||
/* 15/13. Find pixel clock frequency (kHz for xf86) */
|
||||
drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod;
|
||||
drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP;
|
||||
/* 18/16. Find actual vertical frame frequency */
|
||||
/* ignore - just set the mode flag for interlaced */
|
||||
if (interlaced)
|
||||
drm_mode->vtotal *= 2;
|
||||
/* Fill the mode line name */
|
||||
drm_mode_set_name(drm_mode);
|
||||
if (reduced)
|
||||
drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC |
|
||||
DRM_MODE_FLAG_NVSYNC);
|
||||
else
|
||||
drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
|
||||
DRM_MODE_FLAG_NHSYNC);
|
||||
if (interlaced)
|
||||
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
|
||||
|
||||
return drm_mode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_cvt_mode);
|
||||
|
||||
/**
|
||||
* drm_gtf_mode - create the modeline based on GTF algorithm
|
||||
*
|
||||
* @dev :drm device
|
||||
* @hdisplay :hdisplay size
|
||||
* @vdisplay :vdisplay size
|
||||
* @vrefresh :vrefresh rate.
|
||||
* @interlaced :whether the interlace is supported
|
||||
* @margins :whether the margin is supported
|
||||
*
|
||||
* LOCKING.
|
||||
* none.
|
||||
*
|
||||
* return the modeline based on GTF algorithm
|
||||
*
|
||||
* This function is to create the modeline based on the GTF algorithm.
|
||||
* Generalized Timing Formula is derived from:
|
||||
* GTF Spreadsheet by Andy Morrish (1/5/97)
|
||||
* available at http://www.vesa.org
|
||||
*
|
||||
* And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
|
||||
* What I have done is to translate it by using integer calculation.
|
||||
* I also refer to the function of fb_get_mode in the file of
|
||||
* drivers/video/fbmon.c
|
||||
*/
|
||||
struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay,
|
||||
int vdisplay, int vrefresh,
|
||||
bool interlaced, int margins)
|
||||
{
|
||||
/* 1) top/bottom margin size (% of height) - default: 1.8, */
|
||||
#define GTF_MARGIN_PERCENTAGE 18
|
||||
/* 2) character cell horizontal granularity (pixels) - default 8 */
|
||||
#define GTF_CELL_GRAN 8
|
||||
/* 3) Minimum vertical porch (lines) - default 3 */
|
||||
#define GTF_MIN_V_PORCH 1
|
||||
/* width of vsync in lines */
|
||||
#define V_SYNC_RQD 3
|
||||
/* width of hsync as % of total line */
|
||||
#define H_SYNC_PERCENT 8
|
||||
/* min time of vsync + back porch (microsec) */
|
||||
#define MIN_VSYNC_PLUS_BP 550
|
||||
/* blanking formula gradient */
|
||||
#define GTF_M 600
|
||||
/* blanking formula offset */
|
||||
#define GTF_C 40
|
||||
/* blanking formula scaling factor */
|
||||
#define GTF_K 128
|
||||
/* blanking formula scaling factor */
|
||||
#define GTF_J 20
|
||||
/* C' and M' are part of the Blanking Duty Cycle computation */
|
||||
#define GTF_C_PRIME (((GTF_C - GTF_J) * GTF_K / 256) + GTF_J)
|
||||
#define GTF_M_PRIME (GTF_K * GTF_M / 256)
|
||||
struct drm_display_mode *drm_mode;
|
||||
unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
|
||||
int top_margin, bottom_margin;
|
||||
int interlace;
|
||||
unsigned int hfreq_est;
|
||||
int vsync_plus_bp, vback_porch;
|
||||
unsigned int vtotal_lines, vfieldrate_est, hperiod;
|
||||
unsigned int vfield_rate, vframe_rate;
|
||||
int left_margin, right_margin;
|
||||
unsigned int total_active_pixels, ideal_duty_cycle;
|
||||
unsigned int hblank, total_pixels, pixel_freq;
|
||||
int hsync, hfront_porch, vodd_front_porch_lines;
|
||||
unsigned int tmp1, tmp2;
|
||||
|
||||
drm_mode = drm_mode_create(dev);
|
||||
if (!drm_mode)
|
||||
return NULL;
|
||||
|
||||
/* 1. In order to give correct results, the number of horizontal
|
||||
* pixels requested is first processed to ensure that it is divisible
|
||||
* by the character size, by rounding it to the nearest character
|
||||
* cell boundary:
|
||||
*/
|
||||
hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
|
||||
hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN;
|
||||
|
||||
/* 2. If interlace is requested, the number of vertical lines assumed
|
||||
* by the calculation must be halved, as the computation calculates
|
||||
* the number of vertical lines per field.
|
||||
*/
|
||||
if (interlaced)
|
||||
vdisplay_rnd = vdisplay / 2;
|
||||
else
|
||||
vdisplay_rnd = vdisplay;
|
||||
|
||||
/* 3. Find the frame rate required: */
|
||||
if (interlaced)
|
||||
vfieldrate_rqd = vrefresh * 2;
|
||||
else
|
||||
vfieldrate_rqd = vrefresh;
|
||||
|
||||
/* 4. Find number of lines in Top margin: */
|
||||
top_margin = 0;
|
||||
if (margins)
|
||||
top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
|
||||
1000;
|
||||
/* 5. Find number of lines in bottom margin: */
|
||||
bottom_margin = top_margin;
|
||||
|
||||
/* 6. If interlace is required, then set variable interlace: */
|
||||
if (interlaced)
|
||||
interlace = 1;
|
||||
else
|
||||
interlace = 0;
|
||||
|
||||
/* 7. Estimate the Horizontal frequency */
|
||||
{
|
||||
tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500;
|
||||
tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) *
|
||||
2 + interlace;
|
||||
hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1;
|
||||
}
|
||||
|
||||
/* 8. Find the number of lines in V sync + back porch */
|
||||
/* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
|
||||
vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000;
|
||||
vsync_plus_bp = (vsync_plus_bp + 500) / 1000;
|
||||
/* 9. Find the number of lines in V back porch alone: */
|
||||
vback_porch = vsync_plus_bp - V_SYNC_RQD;
|
||||
/* 10. Find the total number of lines in Vertical field period: */
|
||||
vtotal_lines = vdisplay_rnd + top_margin + bottom_margin +
|
||||
vsync_plus_bp + GTF_MIN_V_PORCH;
|
||||
/* 11. Estimate the Vertical field frequency: */
|
||||
vfieldrate_est = hfreq_est / vtotal_lines;
|
||||
/* 12. Find the actual horizontal period: */
|
||||
hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines);
|
||||
|
||||
/* 13. Find the actual Vertical field frequency: */
|
||||
vfield_rate = hfreq_est / vtotal_lines;
|
||||
/* 14. Find the Vertical frame frequency: */
|
||||
if (interlaced)
|
||||
vframe_rate = vfield_rate / 2;
|
||||
else
|
||||
vframe_rate = vfield_rate;
|
||||
/* 15. Find number of pixels in left margin: */
|
||||
if (margins)
|
||||
left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
|
||||
1000;
|
||||
else
|
||||
left_margin = 0;
|
||||
|
||||
/* 16.Find number of pixels in right margin: */
|
||||
right_margin = left_margin;
|
||||
/* 17.Find total number of active pixels in image and left and right */
|
||||
total_active_pixels = hdisplay_rnd + left_margin + right_margin;
|
||||
/* 18.Find the ideal blanking duty cycle from blanking duty cycle */
|
||||
ideal_duty_cycle = GTF_C_PRIME * 1000 -
|
||||
(GTF_M_PRIME * 1000000 / hfreq_est);
|
||||
/* 19.Find the number of pixels in the blanking time to the nearest
|
||||
* double character cell: */
|
||||
hblank = total_active_pixels * ideal_duty_cycle /
|
||||
(100000 - ideal_duty_cycle);
|
||||
hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN);
|
||||
hblank = hblank * 2 * GTF_CELL_GRAN;
|
||||
/* 20.Find total number of pixels: */
|
||||
total_pixels = total_active_pixels + hblank;
|
||||
/* 21.Find pixel clock frequency: */
|
||||
pixel_freq = total_pixels * hfreq_est / 1000;
|
||||
/* Stage 1 computations are now complete; I should really pass
|
||||
* the results to another function and do the Stage 2 computations,
|
||||
* but I only need a few more values so I'll just append the
|
||||
* computations here for now */
|
||||
/* 17. Find the number of pixels in the horizontal sync period: */
|
||||
hsync = H_SYNC_PERCENT * total_pixels / 100;
|
||||
hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
|
||||
hsync = hsync * GTF_CELL_GRAN;
|
||||
/* 18. Find the number of pixels in horizontal front porch period */
|
||||
hfront_porch = hblank / 2 - hsync;
|
||||
/* 36. Find the number of lines in the odd front porch period: */
|
||||
vodd_front_porch_lines = GTF_MIN_V_PORCH ;
|
||||
|
||||
/* finally, pack the results in the mode struct */
|
||||
drm_mode->hdisplay = hdisplay_rnd;
|
||||
drm_mode->hsync_start = hdisplay_rnd + hfront_porch;
|
||||
drm_mode->hsync_end = drm_mode->hsync_start + hsync;
|
||||
drm_mode->htotal = total_pixels;
|
||||
drm_mode->vdisplay = vdisplay_rnd;
|
||||
drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines;
|
||||
drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD;
|
||||
drm_mode->vtotal = vtotal_lines;
|
||||
|
||||
drm_mode->clock = pixel_freq;
|
||||
|
||||
drm_mode_set_name(drm_mode);
|
||||
drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
|
||||
|
||||
if (interlaced) {
|
||||
drm_mode->vtotal *= 2;
|
||||
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
|
||||
}
|
||||
|
||||
return drm_mode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gtf_mode);
|
||||
/**
|
||||
* drm_mode_set_name - set the name on a mode
|
||||
* @mode: name will be set in this mode
|
||||
|
@ -151,7 +566,9 @@ EXPORT_SYMBOL(drm_mode_height);
|
|||
* FIXME: why is this needed? shouldn't vrefresh be set already?
|
||||
*
|
||||
* RETURNS:
|
||||
* Vertical refresh rate of @mode x 1000. For precision reasons.
|
||||
* Vertical refresh rate. It will be the result of actual value plus 0.5.
|
||||
* If it is 70.288, it will return 70Hz.
|
||||
* If it is 59.6, it will return 60Hz.
|
||||
*/
|
||||
int drm_mode_vrefresh(struct drm_display_mode *mode)
|
||||
{
|
||||
|
@ -161,14 +578,13 @@ int drm_mode_vrefresh(struct drm_display_mode *mode)
|
|||
if (mode->vrefresh > 0)
|
||||
refresh = mode->vrefresh;
|
||||
else if (mode->htotal > 0 && mode->vtotal > 0) {
|
||||
int vtotal;
|
||||
vtotal = mode->vtotal;
|
||||
/* work out vrefresh the value will be x1000 */
|
||||
calc_val = (mode->clock * 1000);
|
||||
|
||||
calc_val /= mode->htotal;
|
||||
calc_val *= 1000;
|
||||
calc_val /= mode->vtotal;
|
||||
refresh = (calc_val + vtotal / 2) / vtotal;
|
||||
|
||||
refresh = calc_val;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
refresh *= 2;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
|
@ -403,8 +819,7 @@ void drm_mode_prune_invalid(struct drm_device *dev,
|
|||
list_del(&mode->head);
|
||||
if (verbose) {
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
DRM_DEBUG_MODE(DRM_MODESET_DEBUG,
|
||||
"Not using %s mode %d\n",
|
||||
DRM_DEBUG_KMS("Not using %s mode %d\n",
|
||||
mode->name, mode->status);
|
||||
}
|
||||
drm_mode_destroy(dev, mode);
|
||||
|
|
|
@ -106,20 +106,25 @@ int drm_proc_create_files(struct drm_info_list *files, int count,
|
|||
continue;
|
||||
|
||||
tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
|
||||
ent = create_proc_entry(files[i].name, S_IFREG | S_IRUGO, root);
|
||||
if (tmp == NULL) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
tmp->minor = minor;
|
||||
tmp->info_ent = &files[i];
|
||||
list_add(&tmp->list, &minor->proc_nodes.list);
|
||||
|
||||
ent = proc_create_data(files[i].name, S_IRUGO, root,
|
||||
&drm_proc_fops, tmp);
|
||||
if (!ent) {
|
||||
DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
|
||||
name, files[i].name);
|
||||
list_del(&tmp->list);
|
||||
kfree(tmp);
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ent->proc_fops = &drm_proc_fops;
|
||||
ent->data = tmp;
|
||||
tmp->minor = minor;
|
||||
tmp->info_ent = &files[i];
|
||||
list_add(&(tmp->list), &(minor->proc_nodes.list));
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/kdev_t.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "drm_sysfs.h"
|
||||
#include "drm_core.h"
|
||||
#include "drmP.h"
|
||||
|
||||
|
@ -253,6 +254,7 @@ static ssize_t subconnector_show(struct device *device,
|
|||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Component:
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
prop = dev->mode_config.tv_subconnector_property;
|
||||
is_tv = 1;
|
||||
break;
|
||||
|
@ -293,6 +295,7 @@ static ssize_t select_subconnector_show(struct device *device,
|
|||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Component:
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
prop = dev->mode_config.tv_select_subconnector_property;
|
||||
is_tv = 1;
|
||||
break;
|
||||
|
@ -391,6 +394,7 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
|
|||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Component:
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
for (i = 0; i < ARRAY_SIZE(connector_attrs_opt1); i++) {
|
||||
ret = device_create_file(&connector->kdev, &connector_attrs_opt1[i]);
|
||||
if (ret)
|
||||
|
@ -519,3 +523,27 @@ void drm_sysfs_device_remove(struct drm_minor *minor)
|
|||
{
|
||||
device_unregister(&minor->kdev);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* drm_class_device_register - Register a struct device in the drm class.
|
||||
*
|
||||
* @dev: pointer to struct device to register.
|
||||
*
|
||||
* @dev should have all relevant members pre-filled with the exception
|
||||
* of the class member. In particular, the device_type member must
|
||||
* be set.
|
||||
*/
|
||||
|
||||
int drm_class_device_register(struct device *dev)
|
||||
{
|
||||
dev->class = drm_class;
|
||||
return device_register(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_class_device_register);
|
||||
|
||||
void drm_class_device_unregister(struct device *dev)
|
||||
{
|
||||
return device_unregister(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_class_device_unregister);
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
ccflags-y := -Iinclude/drm
|
||||
i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
|
||||
i915_debugfs.o \
|
||||
i915_suspend.o \
|
||||
i915_gem.o \
|
||||
i915_gem_debug.o \
|
||||
i915_gem_debugfs.o \
|
||||
i915_gem_tiling.o \
|
||||
intel_display.o \
|
||||
intel_crt.o \
|
||||
|
|
|
@ -158,16 +158,37 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
seq_printf(m, "Interrupt enable: %08x\n",
|
||||
I915_READ(IER));
|
||||
seq_printf(m, "Interrupt identity: %08x\n",
|
||||
I915_READ(IIR));
|
||||
seq_printf(m, "Interrupt mask: %08x\n",
|
||||
I915_READ(IMR));
|
||||
seq_printf(m, "Pipe A stat: %08x\n",
|
||||
I915_READ(PIPEASTAT));
|
||||
seq_printf(m, "Pipe B stat: %08x\n",
|
||||
I915_READ(PIPEBSTAT));
|
||||
if (!IS_IGDNG(dev)) {
|
||||
seq_printf(m, "Interrupt enable: %08x\n",
|
||||
I915_READ(IER));
|
||||
seq_printf(m, "Interrupt identity: %08x\n",
|
||||
I915_READ(IIR));
|
||||
seq_printf(m, "Interrupt mask: %08x\n",
|
||||
I915_READ(IMR));
|
||||
seq_printf(m, "Pipe A stat: %08x\n",
|
||||
I915_READ(PIPEASTAT));
|
||||
seq_printf(m, "Pipe B stat: %08x\n",
|
||||
I915_READ(PIPEBSTAT));
|
||||
} else {
|
||||
seq_printf(m, "North Display Interrupt enable: %08x\n",
|
||||
I915_READ(DEIER));
|
||||
seq_printf(m, "North Display Interrupt identity: %08x\n",
|
||||
I915_READ(DEIIR));
|
||||
seq_printf(m, "North Display Interrupt mask: %08x\n",
|
||||
I915_READ(DEIMR));
|
||||
seq_printf(m, "South Display Interrupt enable: %08x\n",
|
||||
I915_READ(SDEIER));
|
||||
seq_printf(m, "South Display Interrupt identity: %08x\n",
|
||||
I915_READ(SDEIIR));
|
||||
seq_printf(m, "South Display Interrupt mask: %08x\n",
|
||||
I915_READ(SDEIMR));
|
||||
seq_printf(m, "Graphics Interrupt enable: %08x\n",
|
||||
I915_READ(GTIER));
|
||||
seq_printf(m, "Graphics Interrupt identity: %08x\n",
|
||||
I915_READ(GTIIR));
|
||||
seq_printf(m, "Graphics Interrupt mask: %08x\n",
|
||||
I915_READ(GTIMR));
|
||||
}
|
||||
seq_printf(m, "Interrupts received: %d\n",
|
||||
atomic_read(&dev_priv->irq_received));
|
||||
if (dev_priv->hw_status_page != NULL) {
|
||||
|
@ -312,15 +333,13 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
|
|||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
unsigned int head, tail, mask;
|
||||
unsigned int head, tail;
|
||||
|
||||
head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
|
||||
tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
|
||||
mask = dev_priv->ring.tail_mask;
|
||||
|
||||
seq_printf(m, "RingHead : %08x\n", head);
|
||||
seq_printf(m, "RingTail : %08x\n", tail);
|
||||
seq_printf(m, "RingMask : %08x\n", mask);
|
||||
seq_printf(m, "RingSize : %08lx\n", dev_priv->ring.Size);
|
||||
seq_printf(m, "Acthd : %08x\n", I915_READ(IS_I965G(dev) ? ACTHD_I965 : ACTHD));
|
||||
|
||||
|
@ -363,7 +382,37 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_info_list i915_gem_debugfs_list[] = {
|
||||
static int i915_registers_info(struct seq_file *m, void *data) {
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t reg;
|
||||
|
||||
#define DUMP_RANGE(start, end) \
|
||||
for (reg=start; reg < end; reg += 4) \
|
||||
seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg));
|
||||
|
||||
DUMP_RANGE(0x00000, 0x00fff); /* VGA registers */
|
||||
DUMP_RANGE(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */
|
||||
DUMP_RANGE(0x03000, 0x031ff); /* FENCE and PPGTT control registers */
|
||||
DUMP_RANGE(0x03200, 0x03fff); /* frame buffer compression registers */
|
||||
DUMP_RANGE(0x05000, 0x05fff); /* I/O control registers */
|
||||
DUMP_RANGE(0x06000, 0x06fff); /* clock control registers */
|
||||
DUMP_RANGE(0x07000, 0x07fff); /* 3D internal debug registers */
|
||||
DUMP_RANGE(0x07400, 0x088ff); /* GPE debug registers */
|
||||
DUMP_RANGE(0x0a000, 0x0afff); /* display palette registers */
|
||||
DUMP_RANGE(0x10000, 0x13fff); /* MMIO MCHBAR */
|
||||
DUMP_RANGE(0x30000, 0x3ffff); /* overlay registers */
|
||||
DUMP_RANGE(0x60000, 0x6ffff); /* display engine pipeline registers */
|
||||
DUMP_RANGE(0x70000, 0x72fff); /* display and cursor registers */
|
||||
DUMP_RANGE(0x73000, 0x73fff); /* performance counters */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_regs", i915_registers_info, 0},
|
||||
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
|
||||
{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
|
||||
{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
|
||||
|
@ -377,19 +426,19 @@ static struct drm_info_list i915_gem_debugfs_list[] = {
|
|||
{"i915_batchbuffers", i915_batchbuffer_info, 0},
|
||||
{"i915_error_state", i915_error_state, 0},
|
||||
};
|
||||
#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
|
||||
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
|
||||
|
||||
int i915_gem_debugfs_init(struct drm_minor *minor)
|
||||
int i915_debugfs_init(struct drm_minor *minor)
|
||||
{
|
||||
return drm_debugfs_create_files(i915_gem_debugfs_list,
|
||||
I915_GEM_DEBUGFS_ENTRIES,
|
||||
return drm_debugfs_create_files(i915_debugfs_list,
|
||||
I915_DEBUGFS_ENTRIES,
|
||||
minor->debugfs_root, minor);
|
||||
}
|
||||
|
||||
void i915_gem_debugfs_cleanup(struct drm_minor *minor)
|
||||
void i915_debugfs_cleanup(struct drm_minor *minor)
|
||||
{
|
||||
drm_debugfs_remove_files(i915_gem_debugfs_list,
|
||||
I915_GEM_DEBUGFS_ENTRIES, minor);
|
||||
drm_debugfs_remove_files(i915_debugfs_list,
|
||||
I915_DEBUGFS_ENTRIES, minor);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
|
@ -29,11 +29,11 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "drm_fb_helper.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define I915_DRV "i915_drv"
|
||||
#include <linux/vgaarb.h>
|
||||
|
||||
/* Really want an OS-independent resettable timer. Would like to have
|
||||
* this loop run for (eg) 3 sec, but have the timer reset every time
|
||||
|
@ -80,6 +80,34 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* As a ringbuffer is only allowed to wrap between instructions, fill
|
||||
* the tail with NOOPs.
|
||||
*/
|
||||
int i915_wrap_ring(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
volatile unsigned int *virt;
|
||||
int rem;
|
||||
|
||||
rem = dev_priv->ring.Size - dev_priv->ring.tail;
|
||||
if (dev_priv->ring.space < rem) {
|
||||
int ret = i915_wait_ring(dev, rem, __func__);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
dev_priv->ring.space -= rem;
|
||||
|
||||
virt = (unsigned int *)
|
||||
(dev_priv->ring.virtual_start + dev_priv->ring.tail);
|
||||
rem /= 4;
|
||||
while (rem--)
|
||||
*virt++ = MI_NOOP;
|
||||
|
||||
dev_priv->ring.tail = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the hardware status page for devices that need a physical address
|
||||
* in the register.
|
||||
|
@ -101,7 +129,7 @@ static int i915_init_phys_hws(struct drm_device *dev)
|
|||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
|
||||
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
|
||||
DRM_DEBUG_DRIVER("Enabled hardware status page\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -187,8 +215,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
|
|||
master_priv->sarea_priv = (drm_i915_sarea_t *)
|
||||
((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER(I915_DRV,
|
||||
"sarea not found assuming DRI2 userspace\n");
|
||||
DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
|
||||
}
|
||||
|
||||
if (init->ring_size != 0) {
|
||||
|
@ -200,7 +227,6 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
|
|||
}
|
||||
|
||||
dev_priv->ring.Size = init->ring_size;
|
||||
dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
|
||||
|
||||
dev_priv->ring.map.offset = init->ring_start;
|
||||
dev_priv->ring.map.size = init->ring_size;
|
||||
|
@ -238,7 +264,7 @@ static int i915_dma_resume(struct drm_device * dev)
|
|||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
|
||||
DRM_DEBUG_DRIVER("%s\n", __func__);
|
||||
|
||||
if (dev_priv->ring.map.handle == NULL) {
|
||||
DRM_ERROR("can not ioremap virtual address for"
|
||||
|
@ -251,14 +277,14 @@ static int i915_dma_resume(struct drm_device * dev)
|
|||
DRM_ERROR("Can not find hardware status page\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "hw status page @ %p\n",
|
||||
DRM_DEBUG_DRIVER("hw status page @ %p\n",
|
||||
dev_priv->hw_status_page);
|
||||
|
||||
if (dev_priv->status_gfx_addr != 0)
|
||||
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
||||
else
|
||||
I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "Enabled hardware status page\n");
|
||||
DRM_DEBUG_DRIVER("Enabled hardware status page\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -552,7 +578,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
|
|||
if (!master_priv->sarea_priv)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "%s: page=%d pfCurrentPage=%d\n",
|
||||
DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
|
||||
__func__,
|
||||
dev_priv->current_page,
|
||||
master_priv->sarea_priv->pf_current_page);
|
||||
|
@ -633,8 +659,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER(I915_DRV,
|
||||
"i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n",
|
||||
batch->start, batch->used, batch->num_cliprects);
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
@ -681,8 +706,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
|||
void *batch_data;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER(I915_DRV,
|
||||
"i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
|
||||
cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
@ -735,7 +759,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
|
|||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "%s\n", __func__);
|
||||
DRM_DEBUG_DRIVER("%s\n", __func__);
|
||||
|
||||
RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
|
@ -778,7 +802,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
|||
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "Unknown parameter %d\n",
|
||||
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
|
||||
param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -819,7 +843,7 @@ static int i915_setparam(struct drm_device *dev, void *data,
|
|||
dev_priv->fence_reg_start = param->value;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "unknown parameter %d\n",
|
||||
DRM_DEBUG_DRIVER("unknown parameter %d\n",
|
||||
param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -846,7 +870,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
|
||||
DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
|
||||
|
||||
dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
|
||||
|
||||
|
@ -868,13 +892,25 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
|||
|
||||
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
||||
I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "load hws HWS_PGA with gfx mem 0x%x\n",
|
||||
DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
|
||||
dev_priv->status_gfx_addr);
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "load hws at %p\n",
|
||||
DRM_DEBUG_DRIVER("load hws at %p\n",
|
||||
dev_priv->hw_status_page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_get_bridge_dev(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!dev_priv->bridge_dev) {
|
||||
DRM_ERROR("bridge device not found\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_probe_agp - get AGP bootup configuration
|
||||
* @pdev: PCI device
|
||||
|
@ -888,20 +924,13 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
|||
static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
|
||||
uint32_t *preallocated_size)
|
||||
{
|
||||
struct pci_dev *bridge_dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u16 tmp = 0;
|
||||
unsigned long overhead;
|
||||
unsigned long stolen;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_ERROR("bridge device not found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the fb aperture size and "stolen" memory amount. */
|
||||
pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
|
||||
pci_dev_put(bridge_dev);
|
||||
pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp);
|
||||
|
||||
*aperture_size = 1024 * 1024;
|
||||
*preallocated_size = 1024 * 1024;
|
||||
|
@ -984,6 +1013,19 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* true = enable decode, false = disable decoder */
|
||||
static unsigned int i915_vga_set_decode(void *cookie, bool state)
|
||||
{
|
||||
struct drm_device *dev = cookie;
|
||||
|
||||
intel_modeset_vga_set_state(dev, state);
|
||||
if (state)
|
||||
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
|
||||
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
|
||||
else
|
||||
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
|
||||
}
|
||||
|
||||
static int i915_load_modeset_init(struct drm_device *dev,
|
||||
unsigned long prealloc_size,
|
||||
unsigned long agp_size)
|
||||
|
@ -1029,6 +1071,11 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|||
if (ret)
|
||||
DRM_INFO("failed to find VBIOS tables\n");
|
||||
|
||||
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
|
||||
ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
|
||||
if (ret)
|
||||
goto destroy_ringbuffer;
|
||||
|
||||
ret = drm_irq_install(dev);
|
||||
if (ret)
|
||||
goto destroy_ringbuffer;
|
||||
|
@ -1153,11 +1200,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
base = drm_get_resource_start(dev, mmio_bar);
|
||||
size = drm_get_resource_len(dev, mmio_bar);
|
||||
|
||||
if (i915_get_bridge_dev(dev)) {
|
||||
ret = -EIO;
|
||||
goto free_priv;
|
||||
}
|
||||
|
||||
dev_priv->regs = ioremap(base, size);
|
||||
if (!dev_priv->regs) {
|
||||
DRM_ERROR("failed to map registers\n");
|
||||
ret = -EIO;
|
||||
goto free_priv;
|
||||
goto put_bridge;
|
||||
}
|
||||
|
||||
dev_priv->mm.gtt_mapping =
|
||||
|
@ -1269,6 +1321,8 @@ out_iomapfree:
|
|||
io_mapping_free(dev_priv->mm.gtt_mapping);
|
||||
out_rmmap:
|
||||
iounmap(dev_priv->regs);
|
||||
put_bridge:
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
free_priv:
|
||||
kfree(dev_priv);
|
||||
return ret;
|
||||
|
@ -1289,6 +1343,7 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
drm_irq_uninstall(dev);
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (dev->pdev->msi_enabled)
|
||||
|
@ -1312,6 +1367,7 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
i915_gem_lastclose(dev);
|
||||
}
|
||||
|
||||
pci_dev_put(dev_priv->bridge_dev);
|
||||
kfree(dev->dev_private);
|
||||
|
||||
return 0;
|
||||
|
@ -1321,7 +1377,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
|
|||
{
|
||||
struct drm_i915_file_private *i915_file_priv;
|
||||
|
||||
DRM_DEBUG_DRIVER(I915_DRV, "\n");
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
i915_file_priv = (struct drm_i915_file_private *)
|
||||
kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
|
||||
|
||||
|
@ -1352,7 +1408,7 @@ void i915_driver_lastclose(struct drm_device * dev)
|
|||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
intelfb_restore();
|
||||
drm_fb_helper_restore();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,15 @@
|
|||
#include <linux/console.h>
|
||||
#include "drm_crtc_helper.h"
|
||||
|
||||
static unsigned int i915_modeset = -1;
|
||||
static int i915_modeset = -1;
|
||||
module_param_named(modeset, i915_modeset, int, 0400);
|
||||
|
||||
unsigned int i915_fbpercrtc = 0;
|
||||
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
|
||||
|
||||
unsigned int i915_powersave = 1;
|
||||
module_param_named(powersave, i915_powersave, int, 0400);
|
||||
|
||||
static struct drm_driver driver;
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
|
@ -188,8 +191,8 @@ static struct drm_driver driver = {
|
|||
.master_create = i915_master_create,
|
||||
.master_destroy = i915_master_destroy,
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
.debugfs_init = i915_gem_debugfs_init,
|
||||
.debugfs_cleanup = i915_gem_debugfs_cleanup,
|
||||
.debugfs_init = i915_debugfs_init,
|
||||
.debugfs_cleanup = i915_debugfs_cleanup,
|
||||
#endif
|
||||
.gem_init_object = i915_gem_init_object,
|
||||
.gem_free_object = i915_gem_free_object,
|
||||
|
|
|
@ -85,7 +85,6 @@ struct drm_i915_gem_phys_object {
|
|||
};
|
||||
|
||||
typedef struct _drm_i915_ring_buffer {
|
||||
int tail_mask;
|
||||
unsigned long Size;
|
||||
u8 *virtual_start;
|
||||
int head;
|
||||
|
@ -156,6 +155,7 @@ typedef struct drm_i915_private {
|
|||
|
||||
void __iomem *regs;
|
||||
|
||||
struct pci_dev *bridge_dev;
|
||||
drm_i915_ring_buffer_t ring;
|
||||
|
||||
drm_dma_handle_t *status_page_dmah;
|
||||
|
@ -311,7 +311,7 @@ typedef struct drm_i915_private {
|
|||
u32 saveIMR;
|
||||
u32 saveCACHE_MODE_0;
|
||||
u32 saveD_STATE;
|
||||
u32 saveCG_2D_DIS;
|
||||
u32 saveDSPCLK_GATE_D;
|
||||
u32 saveMI_ARB_STATE;
|
||||
u32 saveSWF0[16];
|
||||
u32 saveSWF1[16];
|
||||
|
@ -443,6 +443,14 @@ typedef struct drm_i915_private {
|
|||
struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
|
||||
} mm;
|
||||
struct sdvo_device_mapping sdvo_mappings[2];
|
||||
|
||||
/* Reclocking support */
|
||||
bool render_reclock_avail;
|
||||
bool lvds_downclock_avail;
|
||||
struct work_struct idle_work;
|
||||
struct timer_list idle_timer;
|
||||
bool busy;
|
||||
u16 orig_clock;
|
||||
} drm_i915_private_t;
|
||||
|
||||
/** driver private structure attached to each drm_gem_object */
|
||||
|
@ -575,6 +583,7 @@ enum intel_chip_family {
|
|||
extern struct drm_ioctl_desc i915_ioctls[];
|
||||
extern int i915_max_ioctl;
|
||||
extern unsigned int i915_fbpercrtc;
|
||||
extern unsigned int i915_powersave;
|
||||
|
||||
extern int i915_master_create(struct drm_device *dev, struct drm_master *master);
|
||||
extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master);
|
||||
|
@ -730,8 +739,8 @@ void i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
|||
void i915_dump_lru(struct drm_device *dev, const char *where);
|
||||
|
||||
/* i915_debugfs.c */
|
||||
int i915_gem_debugfs_init(struct drm_minor *minor);
|
||||
void i915_gem_debugfs_cleanup(struct drm_minor *minor);
|
||||
int i915_debugfs_init(struct drm_minor *minor);
|
||||
void i915_debugfs_cleanup(struct drm_minor *minor);
|
||||
|
||||
/* i915_suspend.c */
|
||||
extern int i915_save_state(struct drm_device *dev);
|
||||
|
@ -757,6 +766,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
|
|||
/* modesetting */
|
||||
extern void intel_modeset_init(struct drm_device *dev);
|
||||
extern void intel_modeset_cleanup(struct drm_device *dev);
|
||||
extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
|
||||
|
||||
/**
|
||||
* Lock test for when it's just for synchronization of ring access.
|
||||
|
@ -781,33 +791,32 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
|
|||
|
||||
#define I915_VERBOSE 0
|
||||
|
||||
#define RING_LOCALS unsigned int outring, ringmask, outcount; \
|
||||
volatile char *virt;
|
||||
#define RING_LOCALS volatile unsigned int *ring_virt__;
|
||||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I915_VERBOSE) \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
|
||||
if (dev_priv->ring.space < (n)*4) \
|
||||
i915_wait_ring(dev, (n)*4, __func__); \
|
||||
outcount = 0; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start; \
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
int bytes__ = 4*(n); \
|
||||
if (I915_VERBOSE) DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n)); \
|
||||
/* a wrap must occur between instructions so pad beforehand */ \
|
||||
if (unlikely (dev_priv->ring.tail + bytes__ > dev_priv->ring.Size)) \
|
||||
i915_wrap_ring(dev); \
|
||||
if (unlikely (dev_priv->ring.space < bytes__)) \
|
||||
i915_wait_ring(dev, bytes__, __func__); \
|
||||
ring_virt__ = (unsigned int *) \
|
||||
(dev_priv->ring.virtual_start + dev_priv->ring.tail); \
|
||||
dev_priv->ring.tail += bytes__; \
|
||||
dev_priv->ring.tail &= dev_priv->ring.Size - 1; \
|
||||
dev_priv->ring.space -= bytes__; \
|
||||
} while (0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
#define OUT_RING(n) do { \
|
||||
if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = (n); \
|
||||
outcount++; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
*ring_virt__++ = (n); \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
dev_priv->ring.space -= outcount * 4; \
|
||||
I915_WRITE(PRB0_TAIL, outring); \
|
||||
if (I915_VERBOSE) \
|
||||
DRM_DEBUG("ADVANCE_LP_RING %x\n", dev_priv->ring.tail); \
|
||||
I915_WRITE(PRB0_TAIL, dev_priv->ring.tail); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
|
@ -830,6 +839,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
|
|||
#define I915_GEM_HWS_INDEX 0x20
|
||||
#define I915_BREADCRUMB_INDEX 0x21
|
||||
|
||||
extern int i915_wrap_ring(struct drm_device * dev);
|
||||
extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
|
||||
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
|
||||
|
@ -903,6 +913,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|||
/* dsparb controlled by hw only */
|
||||
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
|
||||
|
||||
#define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev))
|
||||
#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev))
|
||||
|
||||
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include <linux/swap.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
|
@ -111,7 +112,8 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
|
|||
{
|
||||
struct drm_i915_gem_create *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
int handle, ret;
|
||||
int ret;
|
||||
u32 handle;
|
||||
|
||||
args->size = roundup(args->size, PAGE_SIZE);
|
||||
|
||||
|
@ -981,6 +983,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_set_domain *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
uint32_t read_domains = args->read_domains;
|
||||
uint32_t write_domain = args->write_domain;
|
||||
int ret;
|
||||
|
@ -1004,15 +1007,17 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
|||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (obj == NULL)
|
||||
return -EBADF;
|
||||
obj_priv = obj->driver_private;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
intel_mark_busy(dev, obj);
|
||||
|
||||
#if WATCH_BUF
|
||||
DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
|
||||
obj, obj->size, read_domains, write_domain);
|
||||
#endif
|
||||
if (read_domains & I915_GEM_DOMAIN_GTT) {
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
|
||||
ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
|
||||
|
||||
/* Update the LRU on the fence for the CPU access that's
|
||||
|
@ -2776,6 +2781,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
|
|||
BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
|
||||
BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
|
||||
|
||||
intel_mark_busy(dev, obj);
|
||||
|
||||
#if WATCH_BUF
|
||||
DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
|
||||
__func__, obj,
|
||||
|
@ -4093,7 +4100,6 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
|
|||
|
||||
/* Set up the kernel mapping for the ring. */
|
||||
ring->Size = obj->size;
|
||||
ring->tail_mask = obj->size - 1;
|
||||
|
||||
ring->map.offset = dev->agp->base + obj_priv->gtt_offset;
|
||||
ring->map.size = obj->size;
|
||||
|
|
|
@ -94,23 +94,15 @@
|
|||
static int
|
||||
intel_alloc_mchbar_resource(struct drm_device *dev)
|
||||
{
|
||||
struct pci_dev *bridge_dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp_lo, temp_hi = 0;
|
||||
u64 mchbar_addr;
|
||||
int ret = 0;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_DEBUG("no bridge dev?!\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_read_config_dword(bridge_dev, reg + 4, &temp_hi);
|
||||
pci_read_config_dword(bridge_dev, reg, &temp_lo);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
|
||||
mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
||||
|
||||
/* If ACPI doesn't have it, assume we need to allocate it ourselves */
|
||||
|
@ -118,30 +110,28 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
|
|||
if (mchbar_addr &&
|
||||
pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
|
||||
ret = 0;
|
||||
goto out_put;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get some space for it */
|
||||
ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
|
||||
ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
|
||||
MCHBAR_SIZE, MCHBAR_SIZE,
|
||||
PCIBIOS_MIN_MEM,
|
||||
0, pcibios_align_resource,
|
||||
bridge_dev);
|
||||
dev_priv->bridge_dev);
|
||||
if (ret) {
|
||||
DRM_DEBUG("failed bus alloc: %d\n", ret);
|
||||
dev_priv->mch_res.start = 0;
|
||||
goto out_put;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I965G(dev))
|
||||
pci_write_config_dword(bridge_dev, reg + 4,
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
|
||||
upper_32_bits(dev_priv->mch_res.start));
|
||||
|
||||
pci_write_config_dword(bridge_dev, reg,
|
||||
pci_write_config_dword(dev_priv->bridge_dev, reg,
|
||||
lower_32_bits(dev_priv->mch_res.start));
|
||||
out_put:
|
||||
pci_dev_put(bridge_dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -150,44 +140,36 @@ out:
|
|||
static bool
|
||||
intel_setup_mchbar(struct drm_device *dev)
|
||||
{
|
||||
struct pci_dev *bridge_dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
bool need_disable = false, enabled;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_DEBUG("no bridge dev?!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
enabled = !!(temp & DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
enabled = temp & 1;
|
||||
}
|
||||
|
||||
/* If it's already enabled, don't have to do anything */
|
||||
if (enabled)
|
||||
goto out_put;
|
||||
goto out;
|
||||
|
||||
if (intel_alloc_mchbar_resource(dev))
|
||||
goto out_put;
|
||||
goto out;
|
||||
|
||||
need_disable = true;
|
||||
|
||||
/* Space is allocated or reserved, so enable it. */
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_write_config_dword(bridge_dev, DEVEN_REG,
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
|
||||
temp | DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
|
||||
pci_write_config_dword(bridge_dev, mchbar_reg, temp | 1);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
|
||||
}
|
||||
out_put:
|
||||
pci_dev_put(bridge_dev);
|
||||
out:
|
||||
return need_disable;
|
||||
}
|
||||
|
@ -196,25 +178,18 @@ static void
|
|||
intel_teardown_mchbar(struct drm_device *dev, bool disable)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct pci_dev *bridge_dev;
|
||||
int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
|
||||
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
|
||||
if (!bridge_dev) {
|
||||
DRM_DEBUG("no bridge dev?!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (disable) {
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(bridge_dev, DEVEN_REG, &temp);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
temp &= ~DEVEN_MCHBAR_EN;
|
||||
pci_write_config_dword(bridge_dev, DEVEN_REG, temp);
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
|
||||
} else {
|
||||
pci_read_config_dword(bridge_dev, mchbar_reg, &temp);
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
temp &= ~1;
|
||||
pci_write_config_dword(bridge_dev, mchbar_reg, temp);
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,7 +209,13 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
bool need_disable;
|
||||
|
||||
if (!IS_I9XX(dev)) {
|
||||
if (IS_IGDNG(dev)) {
|
||||
/* On IGDNG whatever DRAM config, GPU always do
|
||||
* same swizzling setup.
|
||||
*/
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_9;
|
||||
} else if (!IS_I9XX(dev)) {
|
||||
/* As far as we know, the 865 doesn't have these bit 6
|
||||
* swizzling issues.
|
||||
*/
|
||||
|
@ -317,13 +298,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
/* FIXME: check with memory config on IGDNG */
|
||||
if (IS_IGDNG(dev)) {
|
||||
DRM_ERROR("disable tiling on IGDNG...\n");
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
}
|
||||
|
||||
dev_priv->mm.bit_6_swizzle_x = swizzle_x;
|
||||
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
|
||||
}
|
||||
|
|
|
@ -565,6 +565,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
|
||||
I915_READ(PORT_HOTPLUG_STAT);
|
||||
|
||||
/* EOS interrupts occurs */
|
||||
if (IS_IGD(dev) &&
|
||||
(hotplug_status & CRT_EOS_INT_STATUS)) {
|
||||
u32 temp;
|
||||
|
||||
DRM_DEBUG("EOS interrupt occurs\n");
|
||||
/* status is already cleared */
|
||||
temp = I915_READ(ADPA);
|
||||
temp &= ~ADPA_DAC_ENABLE;
|
||||
I915_WRITE(ADPA, temp);
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
temp &= ~CRT_EOS_INT_EN;
|
||||
I915_WRITE(PORT_HOTPLUG_EN, temp);
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_STAT);
|
||||
if (temp & CRT_EOS_INT_STATUS)
|
||||
I915_WRITE(PORT_HOTPLUG_STAT,
|
||||
CRT_EOS_INT_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
I915_WRITE(IIR, iir);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
* fb aperture size and the amount of pre-reserved memory.
|
||||
*/
|
||||
#define INTEL_GMCH_CTRL 0x52
|
||||
#define INTEL_GMCH_VGA_DISABLE (1 << 1)
|
||||
#define INTEL_GMCH_ENABLED 0x4
|
||||
#define INTEL_GMCH_MEM_MASK 0x1
|
||||
#define INTEL_GMCH_MEM_64M 0x1
|
||||
|
@ -55,7 +56,7 @@
|
|||
/* PCI config space */
|
||||
|
||||
#define HPLLCC 0xc0 /* 855 only */
|
||||
#define GC_CLOCK_CONTROL_MASK (3 << 0)
|
||||
#define GC_CLOCK_CONTROL_MASK (0xf << 0)
|
||||
#define GC_CLOCK_133_200 (0 << 0)
|
||||
#define GC_CLOCK_100_200 (1 << 0)
|
||||
#define GC_CLOCK_100_133 (2 << 0)
|
||||
|
@ -65,6 +66,25 @@
|
|||
#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
|
||||
#define GC_DISPLAY_CLOCK_333_MHZ (4 << 4)
|
||||
#define GC_DISPLAY_CLOCK_MASK (7 << 4)
|
||||
#define GM45_GC_RENDER_CLOCK_MASK (0xf << 0)
|
||||
#define GM45_GC_RENDER_CLOCK_266_MHZ (8 << 0)
|
||||
#define GM45_GC_RENDER_CLOCK_320_MHZ (9 << 0)
|
||||
#define GM45_GC_RENDER_CLOCK_400_MHZ (0xb << 0)
|
||||
#define GM45_GC_RENDER_CLOCK_533_MHZ (0xc << 0)
|
||||
#define I965_GC_RENDER_CLOCK_MASK (0xf << 0)
|
||||
#define I965_GC_RENDER_CLOCK_267_MHZ (2 << 0)
|
||||
#define I965_GC_RENDER_CLOCK_333_MHZ (3 << 0)
|
||||
#define I965_GC_RENDER_CLOCK_444_MHZ (4 << 0)
|
||||
#define I965_GC_RENDER_CLOCK_533_MHZ (5 << 0)
|
||||
#define I945_GC_RENDER_CLOCK_MASK (7 << 0)
|
||||
#define I945_GC_RENDER_CLOCK_166_MHZ (0 << 0)
|
||||
#define I945_GC_RENDER_CLOCK_200_MHZ (1 << 0)
|
||||
#define I945_GC_RENDER_CLOCK_250_MHZ (3 << 0)
|
||||
#define I945_GC_RENDER_CLOCK_400_MHZ (5 << 0)
|
||||
#define I915_GC_RENDER_CLOCK_MASK (7 << 0)
|
||||
#define I915_GC_RENDER_CLOCK_166_MHZ (0 << 0)
|
||||
#define I915_GC_RENDER_CLOCK_200_MHZ (1 << 0)
|
||||
#define I915_GC_RENDER_CLOCK_333_MHZ (4 << 0)
|
||||
#define LBB 0xf4
|
||||
|
||||
/* VGA stuff */
|
||||
|
@ -553,9 +573,118 @@
|
|||
#define DPLLA_TEST_M_BYPASS (1 << 2)
|
||||
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
|
||||
#define D_STATE 0x6104
|
||||
#define CG_2D_DIS 0x6200
|
||||
#define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24)
|
||||
#define CG_3D_DIS 0x6204
|
||||
#define DSTATE_PLL_D3_OFF (1<<3)
|
||||
#define DSTATE_GFX_CLOCK_GATING (1<<1)
|
||||
#define DSTATE_DOT_CLOCK_GATING (1<<0)
|
||||
#define DSPCLK_GATE_D 0x6200
|
||||
# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */
|
||||
# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */
|
||||
# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */
|
||||
# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */
|
||||
# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */
|
||||
# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */
|
||||
# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */
|
||||
# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */
|
||||
# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */
|
||||
# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */
|
||||
# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */
|
||||
# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */
|
||||
# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */
|
||||
# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */
|
||||
# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */
|
||||
# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */
|
||||
# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */
|
||||
# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */
|
||||
# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */
|
||||
# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11)
|
||||
# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10)
|
||||
# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9)
|
||||
# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8)
|
||||
# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */
|
||||
# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */
|
||||
# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */
|
||||
# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5)
|
||||
# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4)
|
||||
/**
|
||||
* This bit must be set on the 830 to prevent hangs when turning off the
|
||||
* overlay scaler.
|
||||
*/
|
||||
# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3)
|
||||
# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2)
|
||||
# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1)
|
||||
# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */
|
||||
# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */
|
||||
|
||||
#define RENCLK_GATE_D1 0x6204
|
||||
# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */
|
||||
# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */
|
||||
# define PC_FE_CLOCK_GATE_DISABLE (1 << 11)
|
||||
# define PC_BE_CLOCK_GATE_DISABLE (1 << 10)
|
||||
# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9)
|
||||
# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8)
|
||||
# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7)
|
||||
# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6)
|
||||
# define MAG_CLOCK_GATE_DISABLE (1 << 5)
|
||||
/** This bit must be unset on 855,865 */
|
||||
# define MECI_CLOCK_GATE_DISABLE (1 << 4)
|
||||
# define DCMP_CLOCK_GATE_DISABLE (1 << 3)
|
||||
# define MEC_CLOCK_GATE_DISABLE (1 << 2)
|
||||
# define MECO_CLOCK_GATE_DISABLE (1 << 1)
|
||||
/** This bit must be set on 855,865. */
|
||||
# define SV_CLOCK_GATE_DISABLE (1 << 0)
|
||||
# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16)
|
||||
# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15)
|
||||
# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14)
|
||||
# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13)
|
||||
# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12)
|
||||
# define I915_WM_CLOCK_GATE_DISABLE (1 << 11)
|
||||
# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10)
|
||||
# define I915_PI_CLOCK_GATE_DISABLE (1 << 9)
|
||||
# define I915_DI_CLOCK_GATE_DISABLE (1 << 8)
|
||||
# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7)
|
||||
# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6)
|
||||
# define I915_SC_CLOCK_GATE_DISABLE (1 << 5)
|
||||
# define I915_FL_CLOCK_GATE_DISABLE (1 << 4)
|
||||
# define I915_DM_CLOCK_GATE_DISABLE (1 << 3)
|
||||
# define I915_PS_CLOCK_GATE_DISABLE (1 << 2)
|
||||
# define I915_CC_CLOCK_GATE_DISABLE (1 << 1)
|
||||
# define I915_BY_CLOCK_GATE_DISABLE (1 << 0)
|
||||
|
||||
# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30)
|
||||
/** This bit must always be set on 965G/965GM */
|
||||
# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29)
|
||||
# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28)
|
||||
# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27)
|
||||
# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26)
|
||||
# define I965_GW_CLOCK_GATE_DISABLE (1 << 25)
|
||||
# define I965_TD_CLOCK_GATE_DISABLE (1 << 24)
|
||||
/** This bit must always be set on 965G */
|
||||
# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23)
|
||||
# define I965_IC_CLOCK_GATE_DISABLE (1 << 22)
|
||||
# define I965_EU_CLOCK_GATE_DISABLE (1 << 21)
|
||||
# define I965_IF_CLOCK_GATE_DISABLE (1 << 20)
|
||||
# define I965_TC_CLOCK_GATE_DISABLE (1 << 19)
|
||||
# define I965_SO_CLOCK_GATE_DISABLE (1 << 17)
|
||||
# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16)
|
||||
# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15)
|
||||
# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14)
|
||||
# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13)
|
||||
# define I965_EM_CLOCK_GATE_DISABLE (1 << 12)
|
||||
# define I965_UC_CLOCK_GATE_DISABLE (1 << 11)
|
||||
# define I965_SI_CLOCK_GATE_DISABLE (1 << 6)
|
||||
# define I965_MT_CLOCK_GATE_DISABLE (1 << 5)
|
||||
# define I965_PL_CLOCK_GATE_DISABLE (1 << 4)
|
||||
# define I965_DG_CLOCK_GATE_DISABLE (1 << 3)
|
||||
# define I965_QC_CLOCK_GATE_DISABLE (1 << 2)
|
||||
# define I965_FT_CLOCK_GATE_DISABLE (1 << 1)
|
||||
# define I965_DM_CLOCK_GATE_DISABLE (1 << 0)
|
||||
|
||||
#define RENCLK_GATE_D2 0x6208
|
||||
#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9)
|
||||
#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7)
|
||||
#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6)
|
||||
#define RAMCLK_GATE_D 0x6210 /* CRL only */
|
||||
#define DEUC 0x6214 /* CRL only */
|
||||
|
||||
/*
|
||||
* Palette regs
|
||||
|
@ -683,6 +812,7 @@
|
|||
#define SDVOB_HOTPLUG_INT_EN (1 << 26)
|
||||
#define SDVOC_HOTPLUG_INT_EN (1 << 25)
|
||||
#define TV_HOTPLUG_INT_EN (1 << 18)
|
||||
#define CRT_EOS_INT_EN (1 << 10)
|
||||
#define CRT_HOTPLUG_INT_EN (1 << 9)
|
||||
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
|
||||
#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
|
||||
|
@ -717,6 +847,7 @@
|
|||
#define DPC_HOTPLUG_INT_STATUS (1 << 28)
|
||||
#define HDMID_HOTPLUG_INT_STATUS (1 << 27)
|
||||
#define DPD_HOTPLUG_INT_STATUS (1 << 27)
|
||||
#define CRT_EOS_INT_STATUS (1 << 12)
|
||||
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
|
||||
#define TV_HOTPLUG_INT_STATUS (1 << 10)
|
||||
#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
|
||||
|
@ -1586,6 +1717,7 @@
|
|||
#define PIPECONF_PROGRESSIVE (0 << 21)
|
||||
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
|
||||
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
|
||||
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
|
||||
#define PIPEASTAT 0x70024
|
||||
#define PIPE_FIFO_UNDERRUN_STATUS (1UL<<31)
|
||||
#define PIPE_CRC_ERROR_ENABLE (1UL<<29)
|
||||
|
@ -1733,6 +1865,7 @@
|
|||
#define DISPPLANE_NO_LINE_DOUBLE 0
|
||||
#define DISPPLANE_STEREO_POLARITY_FIRST 0
|
||||
#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
|
||||
#define DISPPLANE_TRICKLE_FEED_DISABLE (1<<14) /* IGDNG */
|
||||
#define DISPPLANE_TILED (1<<10)
|
||||
#define DSPAADDR 0x70184
|
||||
#define DSPASTRIDE 0x70188
|
||||
|
@ -1913,6 +2046,9 @@
|
|||
#define GTIIR 0x44018
|
||||
#define GTIER 0x4401c
|
||||
|
||||
#define DISP_ARB_CTL 0x45000
|
||||
#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
|
||||
|
||||
/* PCH */
|
||||
|
||||
/* south display engine interrupt */
|
||||
|
|
|
@ -461,7 +461,7 @@ int i915_save_state(struct drm_device *dev)
|
|||
|
||||
/* Clock gating state */
|
||||
dev_priv->saveD_STATE = I915_READ(D_STATE);
|
||||
dev_priv->saveCG_2D_DIS = I915_READ(CG_2D_DIS);
|
||||
dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
|
||||
|
||||
/* Cache mode state */
|
||||
dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
|
||||
|
@ -588,7 +588,7 @@ int i915_restore_state(struct drm_device *dev)
|
|||
|
||||
/* Clock gating state */
|
||||
I915_WRITE (D_STATE, dev_priv->saveD_STATE);
|
||||
I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS);
|
||||
I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
|
||||
|
||||
/* Cache mode state */
|
||||
I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
|
||||
|
|
|
@ -355,8 +355,14 @@ parse_driver_features(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
|
||||
driver = find_section(bdb, BDB_DRIVER_FEATURES);
|
||||
if (driver && driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
|
||||
if (!driver)
|
||||
return;
|
||||
|
||||
if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
|
||||
dev_priv->edp_support = 1;
|
||||
|
||||
if (driver->dual_frequency)
|
||||
dev_priv->render_reclock_avail = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,6 +64,34 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
|||
}
|
||||
|
||||
I915_WRITE(reg, temp);
|
||||
|
||||
if (IS_IGD(dev)) {
|
||||
if (mode == DRM_MODE_DPMS_OFF) {
|
||||
/* turn off DAC */
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
temp &= ~CRT_EOS_INT_EN;
|
||||
I915_WRITE(PORT_HOTPLUG_EN, temp);
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_STAT);
|
||||
if (temp & CRT_EOS_INT_STATUS)
|
||||
I915_WRITE(PORT_HOTPLUG_STAT,
|
||||
CRT_EOS_INT_STATUS);
|
||||
} else {
|
||||
/* turn on DAC. EOS interrupt must be enabled after DAC
|
||||
* is enabled, so it sounds not good to enable it in
|
||||
* i915_driver_irq_postinstall()
|
||||
* wait 12.5ms after DAC is enabled
|
||||
*/
|
||||
msleep(13);
|
||||
temp = I915_READ(PORT_HOTPLUG_STAT);
|
||||
if (temp & CRT_EOS_INT_STATUS)
|
||||
I915_WRITE(PORT_HOTPLUG_STAT,
|
||||
CRT_EOS_INT_STATUS);
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
temp |= CRT_EOS_INT_EN;
|
||||
I915_WRITE(PORT_HOTPLUG_EN, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_crt_mode_valid(struct drm_connector *connector,
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
|
||||
static void intel_update_watermarks(struct drm_device *dev);
|
||||
static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule);
|
||||
|
||||
typedef struct {
|
||||
/* given values */
|
||||
|
@ -67,6 +68,8 @@ struct intel_limit {
|
|||
intel_p2_t p2;
|
||||
bool (* find_pll)(const intel_limit_t *, struct drm_crtc *,
|
||||
int, int, intel_clock_t *);
|
||||
bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *,
|
||||
int, int, intel_clock_t *);
|
||||
};
|
||||
|
||||
#define I8XX_DOT_MIN 25000
|
||||
|
@ -261,6 +264,9 @@ static bool
|
|||
intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
static bool
|
||||
intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
static bool
|
||||
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock);
|
||||
static bool
|
||||
|
@ -286,6 +292,7 @@ static const intel_limit_t intel_limits_i8xx_dvo = {
|
|||
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
|
||||
.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
.find_reduced_pll = intel_find_best_reduced_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_i8xx_lvds = {
|
||||
|
@ -300,6 +307,7 @@ static const intel_limit_t intel_limits_i8xx_lvds = {
|
|||
.p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT,
|
||||
.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
.find_reduced_pll = intel_find_best_reduced_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_i9xx_sdvo = {
|
||||
|
@ -314,6 +322,7 @@ static const intel_limit_t intel_limits_i9xx_sdvo = {
|
|||
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
.find_reduced_pll = intel_find_best_reduced_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_i9xx_lvds = {
|
||||
|
@ -331,6 +340,7 @@ static const intel_limit_t intel_limits_i9xx_lvds = {
|
|||
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
.find_reduced_pll = intel_find_best_reduced_PLL,
|
||||
};
|
||||
|
||||
/* below parameter and function is for G4X Chipset Family*/
|
||||
|
@ -348,6 +358,7 @@ static const intel_limit_t intel_limits_g4x_sdvo = {
|
|||
.p2_fast = G4X_P2_SDVO_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
.find_reduced_pll = intel_g4x_find_best_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_g4x_hdmi = {
|
||||
|
@ -364,6 +375,7 @@ static const intel_limit_t intel_limits_g4x_hdmi = {
|
|||
.p2_fast = G4X_P2_HDMI_DAC_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
.find_reduced_pll = intel_g4x_find_best_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
|
||||
|
@ -388,6 +400,7 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
|
|||
.p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
.find_reduced_pll = intel_g4x_find_best_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
|
||||
|
@ -412,6 +425,7 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
|
|||
.p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
|
||||
},
|
||||
.find_pll = intel_g4x_find_best_PLL,
|
||||
.find_reduced_pll = intel_g4x_find_best_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_g4x_display_port = {
|
||||
|
@ -449,6 +463,7 @@ static const intel_limit_t intel_limits_igd_sdvo = {
|
|||
.p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
.find_reduced_pll = intel_find_best_reduced_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_igd_lvds = {
|
||||
|
@ -464,6 +479,7 @@ static const intel_limit_t intel_limits_igd_lvds = {
|
|||
.p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
|
||||
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW },
|
||||
.find_pll = intel_find_best_PLL,
|
||||
.find_reduced_pll = intel_find_best_reduced_PLL,
|
||||
};
|
||||
|
||||
static const intel_limit_t intel_limits_igdng_sdvo = {
|
||||
|
@ -688,15 +704,16 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|||
|
||||
memset (best_clock, 0, sizeof (*best_clock));
|
||||
|
||||
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
|
||||
for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
|
||||
/* m1 is always 0 in IGD */
|
||||
if (clock.m2 >= clock.m1 && !IS_IGD(dev))
|
||||
break;
|
||||
for (clock.n = limit->n.min; clock.n <= limit->n.max;
|
||||
clock.n++) {
|
||||
for (clock.p1 = limit->p1.min;
|
||||
clock.p1 <= limit->p1.max; clock.p1++) {
|
||||
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
|
||||
clock.m1++) {
|
||||
for (clock.m2 = limit->m2.min;
|
||||
clock.m2 <= limit->m2.max; clock.m2++) {
|
||||
/* m1 is always 0 in IGD */
|
||||
if (clock.m2 >= clock.m1 && !IS_IGD(dev))
|
||||
break;
|
||||
for (clock.n = limit->n.min;
|
||||
clock.n <= limit->n.max; clock.n++) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(dev, refclk, &clock);
|
||||
|
@ -717,6 +734,46 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|||
return (err != target);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock)
|
||||
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
intel_clock_t clock;
|
||||
int err = target;
|
||||
bool found = false;
|
||||
|
||||
memcpy(&clock, best_clock, sizeof(intel_clock_t));
|
||||
|
||||
for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) {
|
||||
for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) {
|
||||
/* m1 is always 0 in IGD */
|
||||
if (clock.m2 >= clock.m1 && !IS_IGD(dev))
|
||||
break;
|
||||
for (clock.n = limit->n.min; clock.n <= limit->n.max;
|
||||
clock.n++) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(dev, refclk, &clock);
|
||||
|
||||
if (!intel_PLL_is_valid(crtc, &clock))
|
||||
continue;
|
||||
|
||||
this_err = abs(clock.dot - target);
|
||||
if (this_err < err) {
|
||||
*best_clock = clock;
|
||||
err = this_err;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
||||
int target, int refclk, intel_clock_t *best_clock)
|
||||
|
@ -747,7 +804,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|||
max_n = limit->n.max;
|
||||
/* based on hardware requriment prefer smaller n to precision */
|
||||
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
||||
/* based on hardware requirment prefere larger m1,m2, p1 */
|
||||
/* based on hardware requirment prefere larger m1,m2 */
|
||||
for (clock.m1 = limit->m1.max;
|
||||
clock.m1 >= limit->m1.min; clock.m1--) {
|
||||
for (clock.m2 = limit->m2.max;
|
||||
|
@ -832,15 +889,14 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|||
|
||||
memset(best_clock, 0, sizeof(*best_clock));
|
||||
max_n = limit->n.max;
|
||||
/* based on hardware requriment prefer smaller n to precision */
|
||||
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
||||
/* based on hardware requirment prefere larger m1,m2, p1 */
|
||||
for (clock.m1 = limit->m1.max;
|
||||
clock.m1 >= limit->m1.min; clock.m1--) {
|
||||
for (clock.m2 = limit->m2.max;
|
||||
clock.m2 >= limit->m2.min; clock.m2--) {
|
||||
for (clock.p1 = limit->p1.max;
|
||||
clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
|
||||
/* based on hardware requriment prefer smaller n to precision */
|
||||
for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
|
||||
/* based on hardware requirment prefere larger m1,m2 */
|
||||
for (clock.m1 = limit->m1.max;
|
||||
clock.m1 >= limit->m1.min; clock.m1--) {
|
||||
for (clock.m2 = limit->m2.max;
|
||||
clock.m2 >= limit->m2.min; clock.m2--) {
|
||||
int this_err;
|
||||
|
||||
intel_clock(dev, refclk, &clock);
|
||||
|
@ -1008,6 +1064,10 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
dspcntr &= ~DISPPLANE_TILED;
|
||||
}
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
/* must disable */
|
||||
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
||||
|
||||
I915_WRITE(dspcntr_reg, dspcntr);
|
||||
|
||||
Start = obj_priv->gtt_offset;
|
||||
|
@ -1030,8 +1090,11 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
|
||||
if (old_fb) {
|
||||
intel_fb = to_intel_framebuffer(old_fb);
|
||||
obj_priv = intel_fb->obj->driver_private;
|
||||
i915_gem_object_unpin(intel_fb->obj);
|
||||
}
|
||||
intel_increase_pllclock(crtc, true);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
if (!dev->primary->master)
|
||||
|
@ -1581,6 +1644,8 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
else
|
||||
i9xx_crtc_dpms(crtc, mode);
|
||||
|
||||
intel_crtc->dpms_mode = mode;
|
||||
|
||||
if (!dev->primary->master)
|
||||
return;
|
||||
|
||||
|
@ -1603,8 +1668,6 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
intel_crtc->dpms_mode = mode;
|
||||
}
|
||||
|
||||
static void intel_crtc_prepare (struct drm_crtc *crtc)
|
||||
|
@ -2054,6 +2117,18 @@ static int intel_get_fifo_size(struct drm_device *dev, int plane)
|
|||
return size;
|
||||
}
|
||||
|
||||
static void g4x_update_wm(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 fw_blc_self = I915_READ(FW_BLC_SELF);
|
||||
|
||||
if (i915_powersave)
|
||||
fw_blc_self |= FW_BLC_SELF_EN;
|
||||
else
|
||||
fw_blc_self &= ~FW_BLC_SELF_EN;
|
||||
I915_WRITE(FW_BLC_SELF, fw_blc_self);
|
||||
}
|
||||
|
||||
static void i965_update_wm(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
@ -2105,7 +2180,8 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
|
|||
cwm = 2;
|
||||
|
||||
/* Calc sr entries for one plane configs */
|
||||
if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
|
||||
if (HAS_FW_BLC(dev) && sr_hdisplay &&
|
||||
(!planea_clock || !planeb_clock)) {
|
||||
/* self-refresh has much higher latency */
|
||||
const static int sr_latency_ns = 6000;
|
||||
|
||||
|
@ -2120,8 +2196,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
|
|||
srwm = total_size - sr_entries;
|
||||
if (srwm < 0)
|
||||
srwm = 1;
|
||||
if (IS_I9XX(dev))
|
||||
I915_WRITE(FW_BLC_SELF, (srwm & 0x3f));
|
||||
I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
|
||||
}
|
||||
|
||||
DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
|
||||
|
@ -2195,9 +2270,6 @@ static void intel_update_watermarks(struct drm_device *dev)
|
|||
unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
|
||||
int enabled = 0, pixel_size = 0;
|
||||
|
||||
if (DSPARB_HWCONTROL(dev))
|
||||
return;
|
||||
|
||||
/* Get the clock config from both planes */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
|
@ -2230,7 +2302,9 @@ static void intel_update_watermarks(struct drm_device *dev)
|
|||
else if (IS_IGD(dev))
|
||||
igd_disable_cxsr(dev);
|
||||
|
||||
if (IS_I965G(dev))
|
||||
if (IS_G4X(dev))
|
||||
g4x_update_wm(dev);
|
||||
else if (IS_I965G(dev))
|
||||
i965_update_wm(dev);
|
||||
else if (IS_I9XX(dev) || IS_MOBILE(dev))
|
||||
i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
|
||||
|
@ -2264,9 +2338,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
|
||||
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
|
||||
int refclk, num_outputs = 0;
|
||||
intel_clock_t clock;
|
||||
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
|
||||
bool ok, is_sdvo = false, is_dvo = false;
|
||||
intel_clock_t clock, reduced_clock;
|
||||
u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
|
||||
bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
|
||||
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
|
||||
bool is_edp = false;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
|
@ -2349,6 +2423,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (limit->find_reduced_pll && dev_priv->lvds_downclock_avail) {
|
||||
memcpy(&reduced_clock, &clock, sizeof(intel_clock_t));
|
||||
has_reduced_clock = limit->find_reduced_pll(limit, crtc,
|
||||
(adjusted_mode->clock*3/4),
|
||||
refclk,
|
||||
&reduced_clock);
|
||||
}
|
||||
|
||||
/* SDVO TV has fixed PLL values depend on its clock range,
|
||||
this mirrors vbios setting. */
|
||||
if (is_sdvo && is_tv) {
|
||||
|
@ -2394,10 +2476,17 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
link_bw, &m_n);
|
||||
}
|
||||
|
||||
if (IS_IGD(dev))
|
||||
if (IS_IGD(dev)) {
|
||||
fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
|
||||
else
|
||||
if (has_reduced_clock)
|
||||
fp2 = (1 << reduced_clock.n) << 16 |
|
||||
reduced_clock.m1 << 8 | reduced_clock.m2;
|
||||
} else {
|
||||
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
|
||||
if (has_reduced_clock)
|
||||
fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 |
|
||||
reduced_clock.m2;
|
||||
}
|
||||
|
||||
if (!IS_IGDNG(dev))
|
||||
dpll = DPLL_VGA_MODE_DIS;
|
||||
|
@ -2426,6 +2515,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
/* also FPA1 */
|
||||
if (IS_IGDNG(dev))
|
||||
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
||||
if (IS_G4X(dev) && has_reduced_clock)
|
||||
dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
||||
}
|
||||
switch (clock.p2) {
|
||||
case 5:
|
||||
|
@ -2573,6 +2664,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
udelay(150);
|
||||
}
|
||||
|
||||
if (is_lvds && has_reduced_clock && i915_powersave) {
|
||||
I915_WRITE(fp_reg + 4, fp2);
|
||||
intel_crtc->lowfreq_avail = true;
|
||||
if (HAS_PIPE_CXSR(dev)) {
|
||||
DRM_DEBUG("enabling CxSR downclocking\n");
|
||||
pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
|
||||
}
|
||||
} else {
|
||||
I915_WRITE(fp_reg + 4, fp);
|
||||
intel_crtc->lowfreq_avail = false;
|
||||
if (HAS_PIPE_CXSR(dev)) {
|
||||
DRM_DEBUG("disabling CxSR downclocking\n");
|
||||
pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
|
||||
((adjusted_mode->crtc_htotal - 1) << 16));
|
||||
I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
|
||||
|
@ -2616,6 +2723,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|||
|
||||
intel_wait_for_vblank(dev);
|
||||
|
||||
if (IS_IGDNG(dev)) {
|
||||
/* enable address swizzle for tiling buffer */
|
||||
temp = I915_READ(DISP_ARB_CTL);
|
||||
I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING);
|
||||
}
|
||||
|
||||
I915_WRITE(dspcntr_reg, dspcntr);
|
||||
|
||||
/* Flush the plane changes */
|
||||
|
@ -2769,10 +2882,16 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
|||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_framebuffer *intel_fb;
|
||||
int pipe = intel_crtc->pipe;
|
||||
uint32_t temp = 0;
|
||||
uint32_t adder;
|
||||
|
||||
if (crtc->fb) {
|
||||
intel_fb = to_intel_framebuffer(crtc->fb);
|
||||
intel_mark_busy(dev, intel_fb->obj);
|
||||
}
|
||||
|
||||
if (x < 0) {
|
||||
temp |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
|
||||
x = -x;
|
||||
|
@ -3070,12 +3189,319 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|||
return mode;
|
||||
}
|
||||
|
||||
#define GPU_IDLE_TIMEOUT 500 /* ms */
|
||||
|
||||
/* When this timer fires, we've been idle for awhile */
|
||||
static void intel_gpu_idle_timer(unsigned long arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *)arg;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG("idle timer fired, downclocking\n");
|
||||
|
||||
dev_priv->busy = false;
|
||||
|
||||
queue_work(dev_priv->wq, &dev_priv->idle_work);
|
||||
}
|
||||
|
||||
void intel_increase_renderclock(struct drm_device *dev, bool schedule)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
if (!dev_priv->render_reclock_avail) {
|
||||
DRM_DEBUG("not reclocking render clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Restore render clock frequency to original value */
|
||||
if (IS_G4X(dev) || IS_I9XX(dev))
|
||||
pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock);
|
||||
else if (IS_I85X(dev))
|
||||
pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock);
|
||||
DRM_DEBUG("increasing render clock frequency\n");
|
||||
|
||||
/* Schedule downclock */
|
||||
if (schedule)
|
||||
mod_timer(&dev_priv->idle_timer, jiffies +
|
||||
msecs_to_jiffies(GPU_IDLE_TIMEOUT));
|
||||
}
|
||||
|
||||
void intel_decrease_renderclock(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
if (!dev_priv->render_reclock_avail) {
|
||||
DRM_DEBUG("not reclocking render clock\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_G4X(dev)) {
|
||||
u16 gcfgc;
|
||||
|
||||
/* Adjust render clock... */
|
||||
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
||||
|
||||
/* Down to minimum... */
|
||||
gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK;
|
||||
gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ;
|
||||
|
||||
pci_write_config_word(dev->pdev, GCFGC, gcfgc);
|
||||
} else if (IS_I965G(dev)) {
|
||||
u16 gcfgc;
|
||||
|
||||
/* Adjust render clock... */
|
||||
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
||||
|
||||
/* Down to minimum... */
|
||||
gcfgc &= ~I965_GC_RENDER_CLOCK_MASK;
|
||||
gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ;
|
||||
|
||||
pci_write_config_word(dev->pdev, GCFGC, gcfgc);
|
||||
} else if (IS_I945G(dev) || IS_I945GM(dev)) {
|
||||
u16 gcfgc;
|
||||
|
||||
/* Adjust render clock... */
|
||||
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
||||
|
||||
/* Down to minimum... */
|
||||
gcfgc &= ~I945_GC_RENDER_CLOCK_MASK;
|
||||
gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ;
|
||||
|
||||
pci_write_config_word(dev->pdev, GCFGC, gcfgc);
|
||||
} else if (IS_I915G(dev)) {
|
||||
u16 gcfgc;
|
||||
|
||||
/* Adjust render clock... */
|
||||
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
||||
|
||||
/* Down to minimum... */
|
||||
gcfgc &= ~I915_GC_RENDER_CLOCK_MASK;
|
||||
gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ;
|
||||
|
||||
pci_write_config_word(dev->pdev, GCFGC, gcfgc);
|
||||
} else if (IS_I85X(dev)) {
|
||||
u16 hpllcc;
|
||||
|
||||
/* Adjust render clock... */
|
||||
pci_read_config_word(dev->pdev, HPLLCC, &hpllcc);
|
||||
|
||||
/* Up to maximum... */
|
||||
hpllcc &= ~GC_CLOCK_CONTROL_MASK;
|
||||
hpllcc |= GC_CLOCK_133_200;
|
||||
|
||||
pci_write_config_word(dev->pdev, HPLLCC, hpllcc);
|
||||
}
|
||||
DRM_DEBUG("decreasing render clock frequency\n");
|
||||
}
|
||||
|
||||
/* Note that no increase function is needed for this - increase_renderclock()
|
||||
* will also rewrite these bits
|
||||
*/
|
||||
void intel_decrease_displayclock(struct drm_device *dev)
|
||||
{
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) ||
|
||||
IS_I915GM(dev)) {
|
||||
u16 gcfgc;
|
||||
|
||||
/* Adjust render clock... */
|
||||
pci_read_config_word(dev->pdev, GCFGC, &gcfgc);
|
||||
|
||||
/* Down to minimum... */
|
||||
gcfgc &= ~0xf0;
|
||||
gcfgc |= 0x80;
|
||||
|
||||
pci_write_config_word(dev->pdev, GCFGC, gcfgc);
|
||||
}
|
||||
}
|
||||
|
||||
#define CRTC_IDLE_TIMEOUT 1000 /* ms */
|
||||
|
||||
static void intel_crtc_idle_timer(unsigned long arg)
|
||||
{
|
||||
struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
|
||||
struct drm_crtc *crtc = &intel_crtc->base;
|
||||
drm_i915_private_t *dev_priv = crtc->dev->dev_private;
|
||||
|
||||
DRM_DEBUG("idle timer fired, downclocking\n");
|
||||
|
||||
intel_crtc->busy = false;
|
||||
|
||||
queue_work(dev_priv->wq, &dev_priv->idle_work);
|
||||
}
|
||||
|
||||
static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll = I915_READ(dpll_reg);
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
if (!dev_priv->lvds_downclock_avail)
|
||||
return;
|
||||
|
||||
if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {
|
||||
DRM_DEBUG("upclocking LVDS\n");
|
||||
|
||||
/* Unlock panel regs */
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
|
||||
|
||||
dpll &= ~DISPLAY_RATE_SELECT_FPA1;
|
||||
I915_WRITE(dpll_reg, dpll);
|
||||
dpll = I915_READ(dpll_reg);
|
||||
intel_wait_for_vblank(dev);
|
||||
dpll = I915_READ(dpll_reg);
|
||||
if (dpll & DISPLAY_RATE_SELECT_FPA1)
|
||||
DRM_DEBUG("failed to upclock LVDS!\n");
|
||||
|
||||
/* ...and lock them again */
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
|
||||
}
|
||||
|
||||
/* Schedule downclock */
|
||||
if (schedule)
|
||||
mod_timer(&intel_crtc->idle_timer, jiffies +
|
||||
msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
|
||||
}
|
||||
|
||||
static void intel_decrease_pllclock(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int pipe = intel_crtc->pipe;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int dpll = I915_READ(dpll_reg);
|
||||
|
||||
if (IS_IGDNG(dev))
|
||||
return;
|
||||
|
||||
if (!dev_priv->lvds_downclock_avail)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Since this is called by a timer, we should never get here in
|
||||
* the manual case.
|
||||
*/
|
||||
if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
|
||||
DRM_DEBUG("downclocking LVDS\n");
|
||||
|
||||
/* Unlock panel regs */
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | (0xabcd << 16));
|
||||
|
||||
dpll |= DISPLAY_RATE_SELECT_FPA1;
|
||||
I915_WRITE(dpll_reg, dpll);
|
||||
dpll = I915_READ(dpll_reg);
|
||||
intel_wait_for_vblank(dev);
|
||||
dpll = I915_READ(dpll_reg);
|
||||
if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
|
||||
DRM_DEBUG("failed to downclock LVDS!\n");
|
||||
|
||||
/* ...and lock them again */
|
||||
I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_idle_update - adjust clocks for idleness
|
||||
* @work: work struct
|
||||
*
|
||||
* Either the GPU or display (or both) went idle. Check the busy status
|
||||
* here and adjust the CRTC and GPU clocks as necessary.
|
||||
*/
|
||||
static void intel_idle_update(struct work_struct *work)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
|
||||
idle_work);
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct intel_crtc *intel_crtc;
|
||||
|
||||
if (!i915_powersave)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/* GPU isn't processing, downclock it. */
|
||||
if (!dev_priv->busy) {
|
||||
intel_decrease_renderclock(dev);
|
||||
intel_decrease_displayclock(dev);
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
/* Skip inactive CRTCs */
|
||||
if (!crtc->fb)
|
||||
continue;
|
||||
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
if (!intel_crtc->busy)
|
||||
intel_decrease_pllclock(crtc);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_mark_busy - mark the GPU and possibly the display busy
|
||||
* @dev: drm device
|
||||
* @obj: object we're operating on
|
||||
*
|
||||
* Callers can use this function to indicate that the GPU is busy processing
|
||||
* commands. If @obj matches one of the CRTC objects (i.e. it's a scanout
|
||||
* buffer), we'll also mark the display as busy, so we know to increase its
|
||||
* clock frequency.
|
||||
*/
|
||||
void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = NULL;
|
||||
struct intel_framebuffer *intel_fb;
|
||||
struct intel_crtc *intel_crtc;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return;
|
||||
|
||||
dev_priv->busy = true;
|
||||
intel_increase_renderclock(dev, true);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (!crtc->fb)
|
||||
continue;
|
||||
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
intel_fb = to_intel_framebuffer(crtc->fb);
|
||||
if (intel_fb->obj == obj) {
|
||||
if (!intel_crtc->busy) {
|
||||
/* Non-busy -> busy, upclock */
|
||||
intel_increase_pllclock(crtc, true);
|
||||
intel_crtc->busy = true;
|
||||
} else {
|
||||
/* Busy -> busy, put off timer */
|
||||
mod_timer(&intel_crtc->idle_timer, jiffies +
|
||||
msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
if (intel_crtc->mode_set.mode)
|
||||
drm_mode_destroy(crtc->dev, intel_crtc->mode_set.mode);
|
||||
drm_crtc_cleanup(crtc);
|
||||
kfree(intel_crtc);
|
||||
}
|
||||
|
@ -3122,15 +3548,10 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
|
|||
intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
|
||||
drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
|
||||
|
||||
intel_crtc->mode_set.crtc = &intel_crtc->base;
|
||||
intel_crtc->mode_set.connectors = (struct drm_connector **)(intel_crtc + 1);
|
||||
intel_crtc->mode_set.num_connectors = 0;
|
||||
intel_crtc->busy = false;
|
||||
|
||||
if (i915_fbpercrtc) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
|
||||
(unsigned long)intel_crtc);
|
||||
}
|
||||
|
||||
int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
||||
|
@ -3138,30 +3559,26 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
|||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data;
|
||||
struct drm_crtc *crtc = NULL;
|
||||
int pipe = -1;
|
||||
struct drm_mode_object *drmmode_obj;
|
||||
struct intel_crtc *crtc;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
if (crtc->base.id == pipe_from_crtc_id->crtc_id) {
|
||||
pipe = intel_crtc->pipe;
|
||||
break;
|
||||
}
|
||||
}
|
||||
drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
|
||||
DRM_MODE_OBJECT_CRTC);
|
||||
|
||||
if (pipe == -1) {
|
||||
if (!drmmode_obj) {
|
||||
DRM_ERROR("no such CRTC id\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pipe_from_crtc_id->pipe = pipe;
|
||||
crtc = to_intel_crtc(obj_to_crtc(drmmode_obj));
|
||||
pipe_from_crtc_id->pipe = crtc->pipe;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
|
||||
|
@ -3362,8 +3779,56 @@ static const struct drm_mode_config_funcs intel_mode_funcs = {
|
|||
.fb_changed = intelfb_probe,
|
||||
};
|
||||
|
||||
void intel_init_clock_gating(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
/*
|
||||
* Disable clock gating reported to work incorrectly according to the
|
||||
* specs, but enable as much else as we can.
|
||||
*/
|
||||
if (IS_G4X(dev)) {
|
||||
uint32_t dspclk_gate;
|
||||
I915_WRITE(RENCLK_GATE_D1, 0);
|
||||
I915_WRITE(RENCLK_GATE_D2, VF_UNIT_CLOCK_GATE_DISABLE |
|
||||
GS_UNIT_CLOCK_GATE_DISABLE |
|
||||
CL_UNIT_CLOCK_GATE_DISABLE);
|
||||
I915_WRITE(RAMCLK_GATE_D, 0);
|
||||
dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
|
||||
OVRUNIT_CLOCK_GATE_DISABLE |
|
||||
OVCUNIT_CLOCK_GATE_DISABLE;
|
||||
if (IS_GM45(dev))
|
||||
dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
|
||||
I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
|
||||
} else if (IS_I965GM(dev)) {
|
||||
I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
|
||||
I915_WRITE(RENCLK_GATE_D2, 0);
|
||||
I915_WRITE(DSPCLK_GATE_D, 0);
|
||||
I915_WRITE(RAMCLK_GATE_D, 0);
|
||||
I915_WRITE16(DEUC, 0);
|
||||
} else if (IS_I965G(dev)) {
|
||||
I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
|
||||
I965_RCC_CLOCK_GATE_DISABLE |
|
||||
I965_RCPB_CLOCK_GATE_DISABLE |
|
||||
I965_ISC_CLOCK_GATE_DISABLE |
|
||||
I965_FBC_CLOCK_GATE_DISABLE);
|
||||
I915_WRITE(RENCLK_GATE_D2, 0);
|
||||
} else if (IS_I9XX(dev)) {
|
||||
u32 dstate = I915_READ(D_STATE);
|
||||
|
||||
dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
|
||||
DSTATE_DOT_CLOCK_GATING;
|
||||
I915_WRITE(D_STATE, dstate);
|
||||
} else if (IS_I855(dev) || IS_I865G(dev)) {
|
||||
I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
|
||||
} else if (IS_I830(dev)) {
|
||||
I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void intel_modeset_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int num_pipe;
|
||||
int i;
|
||||
|
||||
|
@ -3398,15 +3863,47 @@ void intel_modeset_init(struct drm_device *dev)
|
|||
DRM_DEBUG("%d display pipe%s available.\n",
|
||||
num_pipe, num_pipe > 1 ? "s" : "");
|
||||
|
||||
if (IS_I85X(dev))
|
||||
pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
|
||||
else if (IS_I9XX(dev) || IS_G4X(dev))
|
||||
pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
|
||||
|
||||
for (i = 0; i < num_pipe; i++) {
|
||||
intel_crtc_init(dev, i);
|
||||
}
|
||||
|
||||
intel_setup_outputs(dev);
|
||||
|
||||
intel_init_clock_gating(dev);
|
||||
|
||||
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
|
||||
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
|
||||
(unsigned long)dev);
|
||||
}
|
||||
|
||||
void intel_modeset_cleanup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
struct intel_crtc *intel_crtc;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
/* Skip inactive CRTCs */
|
||||
if (!crtc->fb)
|
||||
continue;
|
||||
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
intel_increase_pllclock(crtc, false);
|
||||
del_timer_sync(&intel_crtc->idle_timer);
|
||||
}
|
||||
|
||||
intel_increase_renderclock(dev, false);
|
||||
del_timer_sync(&dev_priv->idle_timer);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
drm_mode_config_cleanup(dev);
|
||||
}
|
||||
|
||||
|
@ -3420,3 +3917,20 @@ struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
|
|||
|
||||
return &intel_output->enc;
|
||||
}
|
||||
|
||||
/*
|
||||
* set vga decode state - true == enable VGA decode
|
||||
*/
|
||||
int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u16 gmch_ctrl;
|
||||
|
||||
pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &gmch_ctrl);
|
||||
if (state)
|
||||
gmch_ctrl &= ~INTEL_GMCH_VGA_DISABLE;
|
||||
else
|
||||
gmch_ctrl |= INTEL_GMCH_VGA_DISABLE;
|
||||
pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -117,9 +117,9 @@ struct intel_crtc {
|
|||
uint32_t cursor_addr;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
int dpms_mode;
|
||||
struct intel_framebuffer *fbdev_fb;
|
||||
/* a mode_set for fbdev users on this crtc */
|
||||
struct drm_mode_set mode_set;
|
||||
bool busy; /* is scanout buffer being updated frequently? */
|
||||
struct timer_list idle_timer;
|
||||
bool lowfreq_avail;
|
||||
};
|
||||
|
||||
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
|
||||
|
@ -138,6 +138,7 @@ extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
|
|||
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
|
||||
extern void intel_dvo_init(struct drm_device *dev);
|
||||
extern void intel_tv_init(struct drm_device *dev);
|
||||
extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj);
|
||||
extern void intel_lvds_init(struct drm_device *dev);
|
||||
extern void intel_dp_init(struct drm_device *dev, int dp_reg);
|
||||
void
|
||||
|
@ -178,4 +179,5 @@ extern int intel_framebuffer_create(struct drm_device *dev,
|
|||
struct drm_mode_fb_cmd *mode_cmd,
|
||||
struct drm_framebuffer **fb,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
#endif /* __INTEL_DRV_H__ */
|
||||
|
|
|
@ -39,339 +39,34 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_fb_helper.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
struct intelfb_par {
|
||||
struct drm_device *dev;
|
||||
struct drm_display_mode *our_mode;
|
||||
struct drm_fb_helper helper;
|
||||
struct intel_framebuffer *intel_fb;
|
||||
int crtc_count;
|
||||
/* crtc currently bound to this */
|
||||
uint32_t crtc_ids[2];
|
||||
struct drm_display_mode *our_mode;
|
||||
};
|
||||
|
||||
static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
unsigned blue, unsigned transp,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_crtc *crtc;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_mode_set *modeset = &intel_crtc->mode_set;
|
||||
struct drm_framebuffer *fb = modeset->fb;
|
||||
|
||||
for (i = 0; i < par->crtc_count; i++)
|
||||
if (crtc->base.id == par->crtc_ids[i])
|
||||
break;
|
||||
|
||||
if (i == par->crtc_count)
|
||||
continue;
|
||||
|
||||
|
||||
if (regno > 255)
|
||||
return 1;
|
||||
|
||||
if (fb->depth == 8) {
|
||||
intel_crtc_fb_gamma_set(crtc, red, green, blue, regno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (regno < 16) {
|
||||
switch (fb->depth) {
|
||||
case 15:
|
||||
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
|
||||
((green & 0xf800) >> 6) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 16:
|
||||
fb->pseudo_palette[regno] = (red & 0xf800) |
|
||||
((green & 0xfc00) >> 5) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
|
||||
(green & 0xff00) |
|
||||
((blue & 0xff00) >> 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intelfb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct intel_framebuffer *intel_fb = par->intel_fb;
|
||||
struct drm_framebuffer *fb = &intel_fb->base;
|
||||
int depth;
|
||||
|
||||
if (var->pixclock == -1 || !var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
/* Need to resize the fb object !!! */
|
||||
if (var->xres > fb->width || var->yres > fb->height) {
|
||||
DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
|
||||
DRM_ERROR("Need resizing code.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
var->red.offset = 0;
|
||||
var->green.offset = 0;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 5;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 1;
|
||||
var->transp.offset = 15;
|
||||
break;
|
||||
case 16:
|
||||
var->red.offset = 11;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 32:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 8;
|
||||
var->transp.offset = 24;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this will let fbcon do the mode init */
|
||||
/* FIXME: take mode config lock? */
|
||||
static int intelfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("%d %d\n", var->xres, var->pixclock);
|
||||
|
||||
if (var->pixclock != -1) {
|
||||
|
||||
DRM_ERROR("PIXEL CLOCK SET\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
struct drm_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
for (i = 0; i < par->crtc_count; i++)
|
||||
if (crtc->base.id == par->crtc_ids[i])
|
||||
break;
|
||||
|
||||
if (i == par->crtc_count)
|
||||
continue;
|
||||
|
||||
if (crtc->fb == intel_crtc->mode_set.fb) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = crtc->funcs->set_config(&intel_crtc->mode_set);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int intelfb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_crtc *crtc;
|
||||
struct intel_crtc *intel_crtc;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
for (i = 0; i < par->crtc_count; i++)
|
||||
if (crtc->base.id == par->crtc_ids[i])
|
||||
break;
|
||||
|
||||
if (i == par->crtc_count)
|
||||
continue;
|
||||
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
modeset = &intel_crtc->mode_set;
|
||||
|
||||
modeset->x = var->xoffset;
|
||||
modeset->y = var->yoffset;
|
||||
|
||||
if (modeset->num_connectors) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = crtc->funcs->set_config(modeset);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (!ret) {
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void intelfb_on(struct fb_info *info)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, find all associated encoders
|
||||
* and turn them off, then turn off the CRTC.
|
||||
*/
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
for (i = 0; i < par->crtc_count; i++)
|
||||
if (crtc->base.id == par->crtc_ids[i])
|
||||
break;
|
||||
|
||||
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
|
||||
/* Found a CRTC on this fb, now find encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
encoder_funcs = encoder->helper_private;
|
||||
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void intelfb_off(struct fb_info *info, int dpms_mode)
|
||||
{
|
||||
struct intelfb_par *par = info->par;
|
||||
struct drm_device *dev = par->dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, find all associated encoders
|
||||
* and turn them off, then turn off the CRTC.
|
||||
*/
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
for (i = 0; i < par->crtc_count; i++)
|
||||
if (crtc->base.id == par->crtc_ids[i])
|
||||
break;
|
||||
|
||||
/* Found a CRTC on this fb, now find encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
encoder_funcs = encoder->helper_private;
|
||||
encoder_funcs->dpms(encoder, dpms_mode);
|
||||
}
|
||||
}
|
||||
if (dpms_mode == DRM_MODE_DPMS_OFF)
|
||||
crtc_funcs->dpms(crtc, dpms_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static int intelfb_blank(int blank, struct fb_info *info)
|
||||
{
|
||||
switch (blank) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
intelfb_on(info);
|
||||
break;
|
||||
case FB_BLANK_NORMAL:
|
||||
intelfb_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
case FB_BLANK_HSYNC_SUSPEND:
|
||||
intelfb_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
case FB_BLANK_VSYNC_SUSPEND:
|
||||
intelfb_off(info, DRM_MODE_DPMS_SUSPEND);
|
||||
break;
|
||||
case FB_BLANK_POWERDOWN:
|
||||
intelfb_off(info, DRM_MODE_DPMS_OFF);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fb_ops intelfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = intelfb_check_var,
|
||||
.fb_set_par = intelfb_set_par,
|
||||
.fb_setcolreg = intelfb_setcolreg,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_setcolreg = drm_fb_helper_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_pan_display = intelfb_pan_display,
|
||||
.fb_blank = intelfb_blank,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
};
|
||||
|
||||
static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
|
||||
.gamma_set = intel_crtc_fb_gamma_set,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Curretly it is assumed that the old framebuffer is reused.
|
||||
*
|
||||
|
@ -412,25 +107,10 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
|
|||
}
|
||||
EXPORT_SYMBOL(intelfb_resize);
|
||||
|
||||
static struct drm_mode_set kernelfb_mode;
|
||||
|
||||
static int intelfb_panic(struct notifier_block *n, unsigned long ununsed,
|
||||
void *panic_str)
|
||||
{
|
||||
DRM_ERROR("panic occurred, switching back to text console\n");
|
||||
|
||||
intelfb_restore();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block paniced = {
|
||||
.notifier_call = intelfb_panic,
|
||||
};
|
||||
|
||||
static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
||||
uint32_t fb_height, uint32_t surface_width,
|
||||
uint32_t surface_height,
|
||||
struct intel_framebuffer **intel_fb_p)
|
||||
struct drm_framebuffer **fb_p)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct intelfb_par *par;
|
||||
|
@ -479,7 +159,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
|||
list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
|
||||
|
||||
intel_fb = to_intel_framebuffer(fb);
|
||||
*intel_fb_p = intel_fb;
|
||||
*fb_p = fb;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct intelfb_par), device);
|
||||
if (!info) {
|
||||
|
@ -489,21 +169,19 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
|||
|
||||
par = info->par;
|
||||
|
||||
par->helper.funcs = &intel_fb_helper_funcs;
|
||||
par->helper.dev = dev;
|
||||
ret = drm_fb_helper_init_crtc_count(&par->helper, 2,
|
||||
INTELFB_CONN_LIMIT);
|
||||
if (ret)
|
||||
goto out_unref;
|
||||
|
||||
strcpy(info->fix.id, "inteldrmfb");
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
info->fix.type_aux = 0;
|
||||
info->fix.xpanstep = 1; /* doing it in hw */
|
||||
info->fix.ypanstep = 1; /* doing it in hw */
|
||||
info->fix.ywrapstep = 0;
|
||||
info->fix.accel = FB_ACCEL_I830;
|
||||
info->fix.type_aux = 0;
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
|
||||
info->fbops = &intelfb_ops;
|
||||
|
||||
info->fix.line_length = fb->pitch;
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->aperture_base = dev->mode_config.fb_base;
|
||||
|
@ -527,18 +205,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
|||
|
||||
// memset(info->screen_base, 0, size);
|
||||
|
||||
info->pseudo_palette = fb->pseudo_palette;
|
||||
info->var.xres_virtual = fb->width;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->bits_per_pixel;
|
||||
info->var.xoffset = 0;
|
||||
info->var.yoffset = 0;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
info->var.height = -1;
|
||||
info->var.width = -1;
|
||||
|
||||
info->var.xres = fb_width;
|
||||
info->var.yres = fb_height;
|
||||
drm_fb_helper_fill_fix(info, fb->pitch);
|
||||
drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
|
||||
|
||||
/* FIXME: we really shouldn't expose mmio space at all */
|
||||
info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar);
|
||||
|
@ -550,64 +218,9 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
|||
info->pixmap.flags = FB_PIXMAP_SYSTEM;
|
||||
info->pixmap.scan_align = 1;
|
||||
|
||||
switch(fb->depth) {
|
||||
case 8:
|
||||
info->var.red.offset = 0;
|
||||
info->var.green.offset = 0;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8; /* 8bit DAC */
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 15:
|
||||
info->var.red.offset = 10;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 5;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 15;
|
||||
info->var.transp.length = 1;
|
||||
break;
|
||||
case 16:
|
||||
info->var.red.offset = 11;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 6;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 32:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fb->fbdev = info;
|
||||
|
||||
par->intel_fb = intel_fb;
|
||||
par->dev = dev;
|
||||
|
||||
/* To allow resizeing without swapping buffers */
|
||||
DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
|
||||
|
@ -625,307 +238,12 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
{
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_framebuffer *intel_fb;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_connector *connector;
|
||||
struct fb_info *info;
|
||||
struct intelfb_par *par;
|
||||
struct drm_mode_set *modeset;
|
||||
unsigned int width, height;
|
||||
int new_fb = 0;
|
||||
int ret, i, conn_count;
|
||||
|
||||
if (!drm_helper_crtc_in_use(crtc))
|
||||
return 0;
|
||||
|
||||
if (!crtc->desired_mode)
|
||||
return 0;
|
||||
|
||||
width = crtc->desired_mode->hdisplay;
|
||||
height = crtc->desired_mode->vdisplay;
|
||||
|
||||
/* is there an fb bound to this crtc already */
|
||||
if (!intel_crtc->mode_set.fb) {
|
||||
ret = intelfb_create(dev, width, height, width, height, &intel_fb);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
new_fb = 1;
|
||||
} else {
|
||||
fb = intel_crtc->mode_set.fb;
|
||||
intel_fb = to_intel_framebuffer(fb);
|
||||
if ((intel_fb->base.width < width) || (intel_fb->base.height < height))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info = intel_fb->base.fbdev;
|
||||
par = info->par;
|
||||
|
||||
modeset = &intel_crtc->mode_set;
|
||||
modeset->fb = &intel_fb->base;
|
||||
conn_count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder)
|
||||
if (connector->encoder->crtc == modeset->crtc) {
|
||||
modeset->connectors[conn_count] = connector;
|
||||
conn_count++;
|
||||
if (conn_count > INTELFB_CONN_LIMIT)
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
|
||||
modeset->connectors[i] = NULL;
|
||||
|
||||
par->crtc_ids[0] = crtc->base.id;
|
||||
|
||||
modeset->num_connectors = conn_count;
|
||||
if (modeset->crtc->desired_mode) {
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = drm_mode_duplicate(dev,
|
||||
modeset->crtc->desired_mode);
|
||||
}
|
||||
|
||||
par->crtc_count = 1;
|
||||
|
||||
if (new_fb) {
|
||||
info->var.pixclock = -1;
|
||||
if (register_framebuffer(info) < 0)
|
||||
return -EINVAL;
|
||||
} else
|
||||
intelfb_set_par(info);
|
||||
|
||||
DRM_INFO("fb%d: %s frame buffer device\n", info->node,
|
||||
info->fix.id);
|
||||
|
||||
/* Switch back to kernel console on panic */
|
||||
kernelfb_mode = *modeset;
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &paniced);
|
||||
DRM_DEBUG("registered panic notifier\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intelfb_multi_fb_probe(struct drm_device *dev)
|
||||
{
|
||||
|
||||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
ret = intelfb_multi_fb_probe_crtc(dev, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intelfb_single_fb_probe(struct drm_device *dev)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
|
||||
unsigned int surface_width = 0, surface_height = 0;
|
||||
int new_fb = 0;
|
||||
int crtc_count = 0;
|
||||
int ret, i, conn_count = 0;
|
||||
struct intel_framebuffer *intel_fb;
|
||||
struct fb_info *info;
|
||||
struct intelfb_par *par;
|
||||
struct drm_mode_set *modeset = NULL;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* Get a count of crtcs now in use and new min/maxes width/heights */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (!drm_helper_crtc_in_use(crtc))
|
||||
continue;
|
||||
|
||||
crtc_count++;
|
||||
if (!crtc->desired_mode)
|
||||
continue;
|
||||
|
||||
/* Smallest mode determines console size... */
|
||||
if (crtc->desired_mode->hdisplay < fb_width)
|
||||
fb_width = crtc->desired_mode->hdisplay;
|
||||
|
||||
if (crtc->desired_mode->vdisplay < fb_height)
|
||||
fb_height = crtc->desired_mode->vdisplay;
|
||||
|
||||
/* ... but largest for memory allocation dimensions */
|
||||
if (crtc->desired_mode->hdisplay > surface_width)
|
||||
surface_width = crtc->desired_mode->hdisplay;
|
||||
|
||||
if (crtc->desired_mode->vdisplay > surface_height)
|
||||
surface_height = crtc->desired_mode->vdisplay;
|
||||
}
|
||||
|
||||
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
|
||||
/* hmm everyone went away - assume VGA cable just fell out
|
||||
and will come back later. */
|
||||
DRM_DEBUG("no CRTCs available?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//fail
|
||||
/* Find the fb for our new config */
|
||||
if (list_empty(&dev->mode_config.fb_kernel_list)) {
|
||||
DRM_DEBUG("creating new fb (console size %dx%d, "
|
||||
"buffer size %dx%d)\n", fb_width, fb_height,
|
||||
surface_width, surface_height);
|
||||
ret = intelfb_create(dev, fb_width, fb_height, surface_width,
|
||||
surface_height, &intel_fb);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
new_fb = 1;
|
||||
} else {
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
fb = list_first_entry(&dev->mode_config.fb_kernel_list,
|
||||
struct drm_framebuffer, filp_head);
|
||||
intel_fb = to_intel_framebuffer(fb);
|
||||
|
||||
/* if someone hotplugs something bigger than we have already
|
||||
* allocated, we are pwned. As really we can't resize an
|
||||
* fbdev that is in the wild currently due to fbdev not really
|
||||
* being designed for the lower layers moving stuff around
|
||||
* under it.
|
||||
* - so in the grand style of things - punt.
|
||||
*/
|
||||
if ((fb->width < surface_width) ||
|
||||
(fb->height < surface_height)) {
|
||||
DRM_ERROR("fb not large enough for console\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
// fail
|
||||
|
||||
info = intel_fb->base.fbdev;
|
||||
par = info->par;
|
||||
|
||||
crtc_count = 0;
|
||||
/*
|
||||
* For each CRTC, set up the connector list for the CRTC's mode
|
||||
* set configuration.
|
||||
*/
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
|
||||
modeset = &intel_crtc->mode_set;
|
||||
modeset->fb = &intel_fb->base;
|
||||
conn_count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
||||
head) {
|
||||
if (!connector->encoder)
|
||||
continue;
|
||||
|
||||
if(connector->encoder->crtc == modeset->crtc) {
|
||||
modeset->connectors[conn_count++] = connector;
|
||||
if (conn_count > INTELFB_CONN_LIMIT)
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero out remaining connector pointers */
|
||||
for (i = conn_count; i < INTELFB_CONN_LIMIT; i++)
|
||||
modeset->connectors[i] = NULL;
|
||||
|
||||
par->crtc_ids[crtc_count++] = crtc->base.id;
|
||||
|
||||
modeset->num_connectors = conn_count;
|
||||
if (modeset->crtc->desired_mode) {
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = drm_mode_duplicate(dev,
|
||||
modeset->crtc->desired_mode);
|
||||
}
|
||||
}
|
||||
par->crtc_count = crtc_count;
|
||||
|
||||
if (new_fb) {
|
||||
info->var.pixclock = -1;
|
||||
if (register_framebuffer(info) < 0)
|
||||
return -EINVAL;
|
||||
} else
|
||||
intelfb_set_par(info);
|
||||
|
||||
DRM_INFO("fb%d: %s frame buffer device\n", info->node,
|
||||
info->fix.id);
|
||||
|
||||
/* Switch back to kernel console on panic */
|
||||
kernelfb_mode = *modeset;
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &paniced);
|
||||
DRM_DEBUG("registered panic notifier\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* intelfb_restore - restore the framebuffer console (kernel) config
|
||||
*
|
||||
* Restore's the kernel's fbcon mode, used for lastclose & panic paths.
|
||||
*/
|
||||
void intelfb_restore(void)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) {
|
||||
DRM_ERROR("Failed to restore crtc configuration: %d\n",
|
||||
ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void intelfb_restore_work_fn(struct work_struct *ignored)
|
||||
{
|
||||
intelfb_restore();
|
||||
}
|
||||
static DECLARE_WORK(intelfb_restore_work, intelfb_restore_work_fn);
|
||||
|
||||
static void intelfb_sysrq(int dummy1, struct tty_struct *dummy3)
|
||||
{
|
||||
schedule_work(&intelfb_restore_work);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_intelfb_restore_op = {
|
||||
.handler = intelfb_sysrq,
|
||||
.help_msg = "force-fb(V)",
|
||||
.action_msg = "Restore framebuffer console",
|
||||
};
|
||||
|
||||
int intelfb_probe(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* something has changed in the lower levels of hell - deal with it
|
||||
here */
|
||||
|
||||
/* two modes : a) 1 fb to rule all crtcs.
|
||||
b) one fb per crtc.
|
||||
two actions 1) new connected device
|
||||
2) device removed.
|
||||
case a/1 : if the fb surface isn't big enough - resize the surface fb.
|
||||
if the fb size isn't big enough - resize fb into surface.
|
||||
if everything big enough configure the new crtc/etc.
|
||||
case a/2 : undo the configuration
|
||||
possibly resize down the fb to fit the new configuration.
|
||||
case b/1 : see if it is on a new crtc - setup a new fb and add it.
|
||||
case b/2 : teardown the new fb.
|
||||
*/
|
||||
|
||||
/* mode a first */
|
||||
/* search for an fb */
|
||||
if (i915_fbpercrtc == 1) {
|
||||
ret = intelfb_multi_fb_probe(dev);
|
||||
} else {
|
||||
ret = intelfb_single_fb_probe(dev);
|
||||
}
|
||||
|
||||
register_sysrq_key('v', &sysrq_intelfb_restore_op);
|
||||
|
||||
ret = drm_fb_helper_single_fb_probe(dev, intelfb_create);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(intelfb_probe);
|
||||
|
@ -940,13 +258,14 @@ int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
info = fb->fbdev;
|
||||
|
||||
if (info) {
|
||||
struct intelfb_par *par = info->par;
|
||||
unregister_framebuffer(info);
|
||||
iounmap(info->screen_base);
|
||||
if (info->par)
|
||||
drm_fb_helper_free(&par->helper);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
|
||||
memset(&kernelfb_mode, 0, sizeof(struct drm_mode_set));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(intelfb_remove);
|
||||
|
|
|
@ -42,11 +42,11 @@ void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
|
|||
if (!IS_IGD(dev))
|
||||
return;
|
||||
if (enable)
|
||||
I915_WRITE(CG_2D_DIS,
|
||||
I915_READ(CG_2D_DIS) | DPCUNIT_CLOCK_GATE_DISABLE);
|
||||
I915_WRITE(DSPCLK_GATE_D,
|
||||
I915_READ(DSPCLK_GATE_D) | DPCUNIT_CLOCK_GATE_DISABLE);
|
||||
else
|
||||
I915_WRITE(CG_2D_DIS,
|
||||
I915_READ(CG_2D_DIS) & (~DPCUNIT_CLOCK_GATE_DISABLE));
|
||||
I915_WRITE(DSPCLK_GATE_D,
|
||||
I915_READ(DSPCLK_GATE_D) & (~DPCUNIT_CLOCK_GATE_DISABLE));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -38,16 +38,6 @@
|
|||
#include "i915_drv.h"
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#define I915_LVDS "i915_lvds"
|
||||
|
||||
/*
|
||||
* the following four scaling options are defined.
|
||||
* #define DRM_MODE_SCALE_NON_GPU 0
|
||||
* #define DRM_MODE_SCALE_FULLSCREEN 1
|
||||
* #define DRM_MODE_SCALE_NO_SCALE 2
|
||||
* #define DRM_MODE_SCALE_ASPECT 3
|
||||
*/
|
||||
|
||||
/* Private structure for the integrated LVDS support */
|
||||
struct intel_lvds_priv {
|
||||
int fitting_mode;
|
||||
|
@ -336,7 +326,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|||
I915_WRITE(BCLRPAT_B, 0);
|
||||
|
||||
switch (lvds_priv->fitting_mode) {
|
||||
case DRM_MODE_SCALE_NO_SCALE:
|
||||
case DRM_MODE_SCALE_CENTER:
|
||||
/*
|
||||
* For centered modes, we have to calculate border widths &
|
||||
* heights and modify the values programmed into the CRTC.
|
||||
|
@ -672,9 +662,8 @@ static int intel_lvds_set_property(struct drm_connector *connector,
|
|||
connector->encoder) {
|
||||
struct drm_crtc *crtc = connector->encoder->crtc;
|
||||
struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
|
||||
if (value == DRM_MODE_SCALE_NON_GPU) {
|
||||
DRM_DEBUG_KMS(I915_LVDS,
|
||||
"non_GPU property is unsupported\n");
|
||||
if (value == DRM_MODE_SCALE_NONE) {
|
||||
DRM_DEBUG_KMS("no scaling not supported\n");
|
||||
return 0;
|
||||
}
|
||||
if (lvds_priv->fitting_mode == value) {
|
||||
|
@ -731,8 +720,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
|
|||
|
||||
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
DRM_DEBUG_KMS(I915_LVDS,
|
||||
"Skipping LVDS initialization for %s\n", id->ident);
|
||||
DRM_DEBUG_KMS("Skipping LVDS initialization for %s\n", id->ident);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1027,7 +1015,7 @@ out:
|
|||
return;
|
||||
|
||||
failed:
|
||||
DRM_DEBUG_KMS(I915_LVDS, "No LVDS modes found, disabling.\n");
|
||||
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
|
||||
if (intel_output->ddc_bus)
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
drm_connector_cleanup(connector);
|
||||
|
|
|
@ -37,7 +37,19 @@
|
|||
#include "intel_sdvo_regs.h"
|
||||
|
||||
#undef SDVO_DEBUG
|
||||
#define I915_SDVO "i915_sdvo"
|
||||
|
||||
static char *tv_format_names[] = {
|
||||
"NTSC_M" , "NTSC_J" , "NTSC_443",
|
||||
"PAL_B" , "PAL_D" , "PAL_G" ,
|
||||
"PAL_H" , "PAL_I" , "PAL_M" ,
|
||||
"PAL_N" , "PAL_NC" , "PAL_60" ,
|
||||
"SECAM_B" , "SECAM_D" , "SECAM_G" ,
|
||||
"SECAM_K" , "SECAM_K1", "SECAM_L" ,
|
||||
"SECAM_60"
|
||||
};
|
||||
|
||||
#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))
|
||||
|
||||
struct intel_sdvo_priv {
|
||||
u8 slave_addr;
|
||||
|
||||
|
@ -71,6 +83,15 @@ struct intel_sdvo_priv {
|
|||
*/
|
||||
bool is_tv;
|
||||
|
||||
/* This is for current tv format name */
|
||||
char *tv_format_name;
|
||||
|
||||
/* This contains all current supported TV format */
|
||||
char *tv_format_supported[TV_FORMAT_NUM];
|
||||
int format_supported_num;
|
||||
struct drm_property *tv_format_property;
|
||||
struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
|
||||
|
||||
/**
|
||||
* This is set if we treat the device as HDMI, instead of DVI.
|
||||
*/
|
||||
|
@ -97,14 +118,6 @@ struct intel_sdvo_priv {
|
|||
*/
|
||||
struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
|
||||
|
||||
/**
|
||||
* Current selected TV format.
|
||||
*
|
||||
* This is stored in the same structure that's passed to the device, for
|
||||
* convenience.
|
||||
*/
|
||||
struct intel_sdvo_tv_format tv_format;
|
||||
|
||||
/*
|
||||
* supported encoding mode, used to determine whether HDMI is
|
||||
* supported
|
||||
|
@ -114,6 +127,9 @@ struct intel_sdvo_priv {
|
|||
/* DDC bus used by this SDVO output */
|
||||
uint8_t ddc_bus;
|
||||
|
||||
/* Mac mini hack -- use the same DDC as the analog connector */
|
||||
struct i2c_adapter *analog_ddc_bus;
|
||||
|
||||
int save_sdvo_mult;
|
||||
u16 save_active_outputs;
|
||||
struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
|
||||
|
@ -188,7 +204,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
|
|||
return true;
|
||||
}
|
||||
|
||||
DRM_DEBUG("i2c transfer returned %d\n", ret);
|
||||
DRM_DEBUG_KMS("i2c transfer returned %d\n", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -298,7 +314,7 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
|
|||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS(I915_SDVO, "%s: W: %02X ",
|
||||
DRM_DEBUG_KMS("%s: W: %02X ",
|
||||
SDVO_NAME(sdvo_priv), cmd);
|
||||
for (i = 0; i < args_len; i++)
|
||||
DRM_LOG_KMS("%02X ", ((u8 *)args)[i]);
|
||||
|
@ -351,7 +367,7 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output,
|
|||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS(I915_SDVO, "%s: R: ", SDVO_NAME(sdvo_priv));
|
||||
DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(sdvo_priv));
|
||||
for (i = 0; i < response_len; i++)
|
||||
DRM_LOG_KMS("%02X ", ((u8 *)response)[i]);
|
||||
for (; i < 8; i++)
|
||||
|
@ -668,10 +684,10 @@ static int intel_sdvo_get_clock_rate_mult(struct intel_output *intel_output)
|
|||
status = intel_sdvo_read_response(intel_output, &response, 1);
|
||||
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
||||
DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n");
|
||||
DRM_DEBUG_KMS("Couldn't get SDVO clock rate multiplier\n");
|
||||
return SDVO_CLOCK_RATE_MULT_1X;
|
||||
} else {
|
||||
DRM_DEBUG("Current clock rate multiplier: %d\n", response);
|
||||
DRM_DEBUG_KMS("Current clock rate multiplier: %d\n", response);
|
||||
}
|
||||
|
||||
return response;
|
||||
|
@ -945,23 +961,28 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
|
|||
|
||||
static void intel_sdvo_set_tv_format(struct intel_output *output)
|
||||
{
|
||||
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
||||
struct intel_sdvo_tv_format *format, unset;
|
||||
u8 status;
|
||||
|
||||
format = &sdvo_priv->tv_format;
|
||||
memset(&unset, 0, sizeof(unset));
|
||||
if (memcmp(format, &unset, sizeof(*format))) {
|
||||
DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
format->ntsc_m = 1;
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
|
||||
sizeof(*format));
|
||||
status = intel_sdvo_read_response(output, NULL, 0);
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
DRM_DEBUG("%s: Failed to set TV format\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
}
|
||||
struct intel_sdvo_tv_format format;
|
||||
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
||||
uint32_t format_map, i;
|
||||
uint8_t status;
|
||||
|
||||
for (i = 0; i < TV_FORMAT_NUM; i++)
|
||||
if (tv_format_names[i] == sdvo_priv->tv_format_name)
|
||||
break;
|
||||
|
||||
format_map = 1 << i;
|
||||
memset(&format, 0, sizeof(format));
|
||||
memcpy(&format, &format_map, sizeof(format_map) > sizeof(format) ?
|
||||
sizeof(format) : sizeof(format_map));
|
||||
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format_map,
|
||||
sizeof(format));
|
||||
|
||||
status = intel_sdvo_read_response(output, NULL, 0);
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
DRM_DEBUG("%s: Failed to set TV format\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
}
|
||||
|
||||
static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
||||
|
@ -1230,8 +1251,8 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
|
|||
* a given it the status is a success, we succeeded.
|
||||
*/
|
||||
if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
|
||||
DRM_DEBUG("First %s output reported failure to sync\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
DRM_DEBUG_KMS("First %s output reported failure to "
|
||||
"sync\n", SDVO_NAME(sdvo_priv));
|
||||
}
|
||||
|
||||
if (0)
|
||||
|
@ -1326,8 +1347,8 @@ static void intel_sdvo_restore(struct drm_connector *connector)
|
|||
intel_wait_for_vblank(dev);
|
||||
status = intel_sdvo_get_trained_inputs(intel_output, &input1, &input2);
|
||||
if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
|
||||
DRM_DEBUG("First %s output reported failure to sync\n",
|
||||
SDVO_NAME(sdvo_priv));
|
||||
DRM_DEBUG_KMS("First %s output reported failure to "
|
||||
"sync\n", SDVO_NAME(sdvo_priv));
|
||||
}
|
||||
|
||||
intel_sdvo_set_active_outputs(intel_output, sdvo_priv->save_active_outputs);
|
||||
|
@ -1405,7 +1426,7 @@ int intel_sdvo_supports_hotplug(struct drm_connector *connector)
|
|||
u8 response[2];
|
||||
u8 status;
|
||||
struct intel_output *intel_output;
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (!connector)
|
||||
return 0;
|
||||
|
@ -1478,6 +1499,36 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
|
|||
return (caps > 1);
|
||||
}
|
||||
|
||||
static struct drm_connector *
|
||||
intel_find_analog_connector(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct intel_output *intel_output;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
intel_output = to_intel_output(connector);
|
||||
if (intel_output->type == INTEL_OUTPUT_ANALOG)
|
||||
return connector;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_analog_is_connected(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *analog_connector;
|
||||
analog_connector = intel_find_analog_connector(dev);
|
||||
|
||||
if (!analog_connector)
|
||||
return false;
|
||||
|
||||
if (analog_connector->funcs->detect(analog_connector) ==
|
||||
connector_status_disconnected)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum drm_connector_status
|
||||
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
|
||||
{
|
||||
|
@ -1488,6 +1539,15 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
|
|||
|
||||
edid = drm_get_edid(&intel_output->base,
|
||||
intel_output->ddc_bus);
|
||||
|
||||
/* when there is no edid and no monitor is connected with VGA
|
||||
* port, try to use the CRT ddc to read the EDID for DVI-connector
|
||||
*/
|
||||
if (edid == NULL &&
|
||||
sdvo_priv->analog_ddc_bus &&
|
||||
!intel_analog_is_connected(intel_output->base.dev))
|
||||
edid = drm_get_edid(&intel_output->base,
|
||||
sdvo_priv->analog_ddc_bus);
|
||||
if (edid != NULL) {
|
||||
/* Don't report the output as connected if it's a DVI-I
|
||||
* connector with a non-digital EDID coming out.
|
||||
|
@ -1516,10 +1576,11 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
|
|||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
|
||||
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
|
||||
intel_sdvo_write_cmd(intel_output,
|
||||
SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
|
||||
status = intel_sdvo_read_response(intel_output, &response, 2);
|
||||
|
||||
DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8);
|
||||
DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8);
|
||||
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
return connector_status_unknown;
|
||||
|
@ -1540,50 +1601,32 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
|
|||
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
int num_modes;
|
||||
|
||||
/* set the bus switch and get the modes */
|
||||
intel_ddc_get_modes(intel_output);
|
||||
num_modes = intel_ddc_get_modes(intel_output);
|
||||
|
||||
#if 0
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
/* Mac mini hack. On this device, I get DDC through the analog, which
|
||||
* load-detects as disconnected. I fail to DDC through the SDVO DDC,
|
||||
* but it does load-detect as connected. So, just steal the DDC bits
|
||||
* from analog when we fail at finding it the right way.
|
||||
/*
|
||||
* Mac mini hack. On this device, the DVI-I connector shares one DDC
|
||||
* link between analog and digital outputs. So, if the regular SDVO
|
||||
* DDC fails, check to see if the analog output is disconnected, in
|
||||
* which case we'll look there for the digital DDC data.
|
||||
*/
|
||||
crt = xf86_config->output[0];
|
||||
intel_output = crt->driver_private;
|
||||
if (intel_output->type == I830_OUTPUT_ANALOG &&
|
||||
crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
|
||||
I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A");
|
||||
edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus);
|
||||
xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true);
|
||||
if (num_modes == 0 &&
|
||||
sdvo_priv->analog_ddc_bus &&
|
||||
!intel_analog_is_connected(intel_output->base.dev)) {
|
||||
struct i2c_adapter *digital_ddc_bus;
|
||||
|
||||
/* Switch to the analog ddc bus and try that
|
||||
*/
|
||||
digital_ddc_bus = intel_output->ddc_bus;
|
||||
intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
|
||||
|
||||
(void) intel_ddc_get_modes(intel_output);
|
||||
|
||||
intel_output->ddc_bus = digital_ddc_bus;
|
||||
}
|
||||
if (edid_mon) {
|
||||
xf86OutputSetEDID(output, edid_mon);
|
||||
modes = xf86OutputGetEDIDModes(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks the current TV format, and chooses a default if
|
||||
* it hasn't been set.
|
||||
*/
|
||||
static void
|
||||
intel_sdvo_check_tv_format(struct intel_output *output)
|
||||
{
|
||||
struct intel_sdvo_priv *dev_priv = output->dev_priv;
|
||||
struct intel_sdvo_tv_format format;
|
||||
uint8_t status;
|
||||
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
|
||||
status = intel_sdvo_read_response(output, &format, sizeof(format));
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
memcpy(&dev_priv->tv_format, &format, sizeof(format));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1656,17 +1699,26 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|||
struct intel_output *output = to_intel_output(connector);
|
||||
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
||||
struct intel_sdvo_sdtv_resolution_request tv_res;
|
||||
uint32_t reply = 0;
|
||||
uint32_t reply = 0, format_map = 0;
|
||||
int i;
|
||||
uint8_t status;
|
||||
int i = 0;
|
||||
|
||||
intel_sdvo_check_tv_format(output);
|
||||
|
||||
/* Read the list of supported input resolutions for the selected TV
|
||||
* format.
|
||||
*/
|
||||
memset(&tv_res, 0, sizeof(tv_res));
|
||||
memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
|
||||
for (i = 0; i < TV_FORMAT_NUM; i++)
|
||||
if (tv_format_names[i] == sdvo_priv->tv_format_name)
|
||||
break;
|
||||
|
||||
format_map = (1 << i);
|
||||
memcpy(&tv_res, &format_map,
|
||||
sizeof(struct intel_sdvo_sdtv_resolution_request) >
|
||||
sizeof(format_map) ? sizeof(format_map) :
|
||||
sizeof(struct intel_sdvo_sdtv_resolution_request));
|
||||
|
||||
intel_sdvo_set_target_output(output, sdvo_priv->controlled_output);
|
||||
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
|
||||
&tv_res, sizeof(tv_res));
|
||||
status = intel_sdvo_read_response(output, &reply, 3);
|
||||
|
@ -1681,6 +1733,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|||
if (nmode)
|
||||
drm_mode_probed_add(connector, nmode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
|
||||
|
@ -1748,17 +1801,62 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
|
|||
intel_i2c_destroy(intel_output->i2c_bus);
|
||||
if (intel_output->ddc_bus)
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
if (sdvo_priv->analog_ddc_bus)
|
||||
intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
|
||||
|
||||
if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
|
||||
drm_mode_destroy(connector->dev,
|
||||
sdvo_priv->sdvo_lvds_fixed_mode);
|
||||
|
||||
if (sdvo_priv->tv_format_property)
|
||||
drm_property_destroy(connector->dev,
|
||||
sdvo_priv->tv_format_property);
|
||||
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
|
||||
kfree(intel_output);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_sdvo_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val)
|
||||
{
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
struct drm_encoder *encoder = &intel_output->enc;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
int ret = 0;
|
||||
bool changed = false;
|
||||
|
||||
ret = drm_connector_property_set_value(connector, property, val);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (property == sdvo_priv->tv_format_property) {
|
||||
if (val >= TV_FORMAT_NUM) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (sdvo_priv->tv_format_name ==
|
||||
sdvo_priv->tv_format_supported[val])
|
||||
goto out;
|
||||
|
||||
sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
|
||||
changed = true;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (changed && crtc)
|
||||
drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
|
||||
crtc->y, crtc->fb);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
|
||||
.dpms = intel_sdvo_dpms,
|
||||
.mode_fixup = intel_sdvo_mode_fixup,
|
||||
|
@ -1773,6 +1871,7 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
|
|||
.restore = intel_sdvo_restore,
|
||||
.detect = intel_sdvo_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = intel_sdvo_set_property,
|
||||
.destroy = intel_sdvo_destroy,
|
||||
};
|
||||
|
||||
|
@ -2013,10 +2112,9 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
|
|||
|
||||
sdvo_priv->controlled_output = 0;
|
||||
memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
|
||||
DRM_DEBUG_KMS(I915_SDVO,
|
||||
"%s: Unknown SDVO output type (0x%02x%02x)\n",
|
||||
SDVO_NAME(sdvo_priv),
|
||||
bytes[0], bytes[1]);
|
||||
DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
|
||||
SDVO_NAME(sdvo_priv),
|
||||
bytes[0], bytes[1]);
|
||||
ret = false;
|
||||
}
|
||||
intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
||||
|
@ -2029,6 +2127,55 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
|
|||
|
||||
}
|
||||
|
||||
static void intel_sdvo_tv_create_property(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
||||
struct intel_sdvo_tv_format format;
|
||||
uint32_t format_map, i;
|
||||
uint8_t status;
|
||||
|
||||
intel_sdvo_set_target_output(intel_output,
|
||||
sdvo_priv->controlled_output);
|
||||
|
||||
intel_sdvo_write_cmd(intel_output,
|
||||
SDVO_CMD_GET_SUPPORTED_TV_FORMATS, NULL, 0);
|
||||
status = intel_sdvo_read_response(intel_output,
|
||||
&format, sizeof(format));
|
||||
if (status != SDVO_CMD_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
memcpy(&format_map, &format, sizeof(format) > sizeof(format_map) ?
|
||||
sizeof(format_map) : sizeof(format));
|
||||
|
||||
if (format_map == 0)
|
||||
return;
|
||||
|
||||
sdvo_priv->format_supported_num = 0;
|
||||
for (i = 0 ; i < TV_FORMAT_NUM; i++)
|
||||
if (format_map & (1 << i)) {
|
||||
sdvo_priv->tv_format_supported
|
||||
[sdvo_priv->format_supported_num++] =
|
||||
tv_format_names[i];
|
||||
}
|
||||
|
||||
|
||||
sdvo_priv->tv_format_property =
|
||||
drm_property_create(
|
||||
connector->dev, DRM_MODE_PROP_ENUM,
|
||||
"mode", sdvo_priv->format_supported_num);
|
||||
|
||||
for (i = 0; i < sdvo_priv->format_supported_num; i++)
|
||||
drm_property_add_enum(
|
||||
sdvo_priv->tv_format_property, i,
|
||||
i, sdvo_priv->tv_format_supported[i]);
|
||||
|
||||
sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[0];
|
||||
drm_connector_attach_property(
|
||||
connector, sdvo_priv->tv_format_property, 0);
|
||||
|
||||
}
|
||||
|
||||
bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
@ -2066,18 +2213,22 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|||
/* Read the regs to test if we can talk to the device */
|
||||
for (i = 0; i < 0x40; i++) {
|
||||
if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
|
||||
DRM_DEBUG_KMS(I915_SDVO,
|
||||
"No SDVO device found on SDVO%c\n",
|
||||
DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n",
|
||||
output_device == SDVOB ? 'B' : 'C');
|
||||
goto err_i2c;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the DDC bus. */
|
||||
if (output_device == SDVOB)
|
||||
if (output_device == SDVOB) {
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
|
||||
else
|
||||
sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
|
||||
"SDVOB/VGA DDC BUS");
|
||||
} else {
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
|
||||
sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
|
||||
"SDVOC/VGA DDC BUS");
|
||||
}
|
||||
|
||||
if (intel_output->ddc_bus == NULL)
|
||||
goto err_i2c;
|
||||
|
@ -2090,7 +2241,7 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|||
|
||||
if (intel_sdvo_output_setup(intel_output,
|
||||
sdvo_priv->caps.output_flags) != true) {
|
||||
DRM_DEBUG("SDVO output failed to setup on SDVO%c\n",
|
||||
DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
|
||||
output_device == SDVOB ? 'B' : 'C');
|
||||
goto err_i2c;
|
||||
}
|
||||
|
@ -2111,6 +2262,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|||
drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
|
||||
|
||||
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
|
||||
if (sdvo_priv->is_tv)
|
||||
intel_sdvo_tv_create_property(connector);
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
intel_sdvo_select_ddc_bus(sdvo_priv);
|
||||
|
@ -2123,7 +2276,7 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|||
&sdvo_priv->pixel_clock_max);
|
||||
|
||||
|
||||
DRM_DEBUG_KMS(I915_SDVO, "%s device VID/DID: %02X:%02X.%02X, "
|
||||
DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
|
||||
"clock range %dMHz - %dMHz, "
|
||||
"input 1: %c, input 2: %c, "
|
||||
"output 1: %c, output 2: %c\n",
|
||||
|
@ -2143,6 +2296,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|||
return true;
|
||||
|
||||
err_i2c:
|
||||
if (sdvo_priv->analog_ddc_bus != NULL)
|
||||
intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
|
||||
if (intel_output->ddc_bus != NULL)
|
||||
intel_i2c_destroy(intel_output->ddc_bus);
|
||||
if (intel_output->i2c_bus != NULL)
|
||||
|
|
|
@ -1437,6 +1437,35 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
|
|||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we set accurate tv format according to connector type
|
||||
* i.e Component TV should not be assigned by NTSC or PAL
|
||||
*/
|
||||
static void intel_tv_find_better_format(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
||||
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
||||
int i;
|
||||
|
||||
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
|
||||
tv_mode->component_only)
|
||||
return;
|
||||
|
||||
|
||||
for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
|
||||
tv_mode = tv_modes + i;
|
||||
|
||||
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
|
||||
tv_mode->component_only)
|
||||
break;
|
||||
}
|
||||
|
||||
tv_priv->tv_format = tv_mode->name;
|
||||
drm_connector_property_set_value(connector,
|
||||
connector->dev->mode_config.tv_mode_property, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the TV connection.
|
||||
*
|
||||
|
@ -1473,6 +1502,7 @@ intel_tv_detect(struct drm_connector *connector)
|
|||
if (type < 0)
|
||||
return connector_status_disconnected;
|
||||
|
||||
intel_tv_find_better_format(connector);
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
|
|
|
@ -444,7 +444,7 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
|
|||
{
|
||||
drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
unsigned int warp_size = mga_warp_microcode_size(dev_priv);
|
||||
unsigned int warp_size = MGA_WARP_UCODE_SIZE;
|
||||
int err;
|
||||
unsigned offset;
|
||||
const unsigned secondary_size = dma_bs->secondary_bin_count
|
||||
|
@ -619,7 +619,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
|
|||
{
|
||||
drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
unsigned int warp_size = mga_warp_microcode_size(dev_priv);
|
||||
unsigned int warp_size = MGA_WARP_UCODE_SIZE;
|
||||
unsigned int primary_size;
|
||||
unsigned int bin_count;
|
||||
int err;
|
||||
|
|
|
@ -177,7 +177,6 @@ extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
|
|||
extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
|
||||
|
||||
/* mga_warp.c */
|
||||
extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_init(drm_mga_private_t * dev_priv);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,132 +27,108 @@
|
|||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/ihex.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
#include "mga_ucode.h"
|
||||
|
||||
#define FIRMWARE_G200 "matrox/g200_warp.fw"
|
||||
#define FIRMWARE_G400 "matrox/g400_warp.fw"
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE_G200);
|
||||
MODULE_FIRMWARE(FIRMWARE_G400);
|
||||
|
||||
#define MGA_WARP_CODE_ALIGN 256 /* in bytes */
|
||||
|
||||
#define WARP_UCODE_SIZE( which ) \
|
||||
((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
|
||||
|
||||
#define WARP_UCODE_INSTALL( which, where ) \
|
||||
do { \
|
||||
DRM_DEBUG( " pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase );\
|
||||
dev_priv->warp_pipe_phys[where] = pcbase; \
|
||||
memcpy( vcbase, which, sizeof(which) ); \
|
||||
pcbase += WARP_UCODE_SIZE( which ); \
|
||||
vcbase += WARP_UCODE_SIZE( which ); \
|
||||
} while (0)
|
||||
|
||||
static const unsigned int mga_warp_g400_microcode_size =
|
||||
(WARP_UCODE_SIZE(warp_g400_tgz) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgza) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzf) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzs) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzsa) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzsaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_tgzsf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gz) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gza) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzaf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzf) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzs) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzsa) +
|
||||
WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
|
||||
|
||||
static const unsigned int mga_warp_g200_microcode_size =
|
||||
(WARP_UCODE_SIZE(warp_g200_tgz) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgza) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzaf) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzf) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzs) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzsa) +
|
||||
WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
|
||||
|
||||
unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
|
||||
{
|
||||
switch (dev_priv->chipset) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
case MGA_CARD_TYPE_G550:
|
||||
return PAGE_ALIGN(mga_warp_g400_microcode_size);
|
||||
case MGA_CARD_TYPE_G200:
|
||||
return PAGE_ALIGN(mga_warp_g200_microcode_size);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
|
||||
memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
|
||||
|
||||
WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
|
||||
WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
|
||||
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
|
||||
WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
|
||||
memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
|
||||
|
||||
WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
|
||||
WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define WARP_UCODE_SIZE(size) ALIGN(size, MGA_WARP_CODE_ALIGN)
|
||||
|
||||
int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
|
||||
{
|
||||
const unsigned int size = mga_warp_microcode_size(dev_priv);
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
const char *firmware_name;
|
||||
struct platform_device *pdev;
|
||||
const struct firmware *fw = NULL;
|
||||
const struct ihex_binrec *rec;
|
||||
unsigned int size;
|
||||
int n_pipes, where;
|
||||
int rc = 0;
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
case MGA_CARD_TYPE_G550:
|
||||
firmware_name = FIRMWARE_G400;
|
||||
n_pipes = MGA_MAX_G400_PIPES;
|
||||
break;
|
||||
case MGA_CARD_TYPE_G200:
|
||||
firmware_name = FIRMWARE_G200;
|
||||
n_pipes = MGA_MAX_G200_PIPES;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev = platform_device_register_simple("mga_warp", 0, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
DRM_ERROR("mga: Failed to register microcode\n");
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev);
|
||||
platform_device_unregister(pdev);
|
||||
if (rc) {
|
||||
DRM_ERROR("mga: Failed to load microcode \"%s\"\n",
|
||||
firmware_name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
size = 0;
|
||||
where = 0;
|
||||
for (rec = (const struct ihex_binrec *)fw->data;
|
||||
rec;
|
||||
rec = ihex_next_binrec(rec)) {
|
||||
size += WARP_UCODE_SIZE(be16_to_cpu(rec->len));
|
||||
where++;
|
||||
}
|
||||
|
||||
if (where != n_pipes) {
|
||||
DRM_ERROR("mga: Invalid microcode \"%s\"\n", firmware_name);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
size = PAGE_ALIGN(size);
|
||||
DRM_DEBUG("MGA ucode size = %d bytes\n", size);
|
||||
if (size > dev_priv->warp->size) {
|
||||
DRM_ERROR("microcode too large! (%u > %lu)\n",
|
||||
size, dev_priv->warp->size);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (dev_priv->chipset) {
|
||||
case MGA_CARD_TYPE_G400:
|
||||
case MGA_CARD_TYPE_G550:
|
||||
return mga_warp_install_g400_microcode(dev_priv);
|
||||
case MGA_CARD_TYPE_G200:
|
||||
return mga_warp_install_g200_microcode(dev_priv);
|
||||
default:
|
||||
return -EINVAL;
|
||||
memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
|
||||
|
||||
where = 0;
|
||||
for (rec = (const struct ihex_binrec *)fw->data;
|
||||
rec;
|
||||
rec = ihex_next_binrec(rec)) {
|
||||
unsigned int src_size, dst_size;
|
||||
|
||||
DRM_DEBUG(" pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase);
|
||||
dev_priv->warp_pipe_phys[where] = pcbase;
|
||||
src_size = be16_to_cpu(rec->len);
|
||||
dst_size = WARP_UCODE_SIZE(src_size);
|
||||
memcpy(vcbase, rec->data, src_size);
|
||||
pcbase += dst_size;
|
||||
vcbase += dst_size;
|
||||
where++;
|
||||
}
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
* Gareth Hughes <gareth@valinux.com>
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "r128_drm.h"
|
||||
|
@ -36,50 +39,9 @@
|
|||
|
||||
#define R128_FIFO_DEBUG 0
|
||||
|
||||
/* CCE microcode (from ATI) */
|
||||
static u32 r128_cce_microcode[] = {
|
||||
0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
|
||||
1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
|
||||
599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
|
||||
11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
|
||||
262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
|
||||
1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
|
||||
30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
|
||||
1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
|
||||
15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
|
||||
12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
|
||||
46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
|
||||
459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
|
||||
18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
|
||||
15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
|
||||
268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
|
||||
15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
|
||||
1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
|
||||
3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
|
||||
1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
|
||||
15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
|
||||
180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
|
||||
114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
|
||||
33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
|
||||
1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
|
||||
14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
|
||||
1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
|
||||
198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
|
||||
114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
|
||||
1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
|
||||
1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
|
||||
16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
|
||||
174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
|
||||
33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
|
||||
33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
|
||||
409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
#define FIRMWARE_NAME "r128/r128_cce.bin"
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE_NAME);
|
||||
|
||||
static int R128_READ_PLL(struct drm_device * dev, int addr)
|
||||
{
|
||||
|
@ -176,20 +138,50 @@ static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
|
|||
*/
|
||||
|
||||
/* Load the microcode for the CCE */
|
||||
static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
|
||||
static int r128_cce_load_microcode(drm_r128_private_t *dev_priv)
|
||||
{
|
||||
int i;
|
||||
struct platform_device *pdev;
|
||||
const struct firmware *fw;
|
||||
const __be32 *fw_data;
|
||||
int rc, i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
pdev = platform_device_register_simple("r128_cce", 0, NULL, 0);
|
||||
if (IS_ERR(pdev)) {
|
||||
printk(KERN_ERR "r128_cce: Failed to register firmware\n");
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
|
||||
platform_device_unregister(pdev);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n",
|
||||
FIRMWARE_NAME);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (fw->size != 256 * 8) {
|
||||
printk(KERN_ERR
|
||||
"r128_cce: Bogus length %zu in firmware \"%s\"\n",
|
||||
fw->size, FIRMWARE_NAME);
|
||||
rc = -EINVAL;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
r128_do_wait_for_idle(dev_priv);
|
||||
|
||||
fw_data = (const __be32 *)fw->data;
|
||||
R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
|
||||
for (i = 0; i < 256; i++) {
|
||||
R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
|
||||
R128_WRITE(R128_PM4_MICROCODE_DATAH,
|
||||
be32_to_cpup(&fw_data[i * 2]));
|
||||
R128_WRITE(R128_PM4_MICROCODE_DATAL,
|
||||
r128_cce_microcode[i * 2 + 1]);
|
||||
be32_to_cpup(&fw_data[i * 2 + 1]));
|
||||
}
|
||||
|
||||
out_release:
|
||||
release_firmware(fw);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Flush any pending commands to the CCE. This should only be used just
|
||||
|
@ -350,9 +342,15 @@ static void r128_cce_init_ring_buffer(struct drm_device * dev,
|
|||
static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
|
||||
{
|
||||
drm_r128_private_t *dev_priv;
|
||||
int rc;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dev->dev_private) {
|
||||
DRM_DEBUG("called when already initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL);
|
||||
if (dev_priv == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -575,13 +573,18 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
|
|||
#endif
|
||||
|
||||
r128_cce_init_ring_buffer(dev, dev_priv);
|
||||
r128_cce_load_microcode(dev_priv);
|
||||
rc = r128_cce_load_microcode(dev_priv);
|
||||
|
||||
dev->dev_private = (void *)dev_priv;
|
||||
|
||||
r128_do_engine_reset(dev);
|
||||
|
||||
return 0;
|
||||
if (rc) {
|
||||
DRM_ERROR("Failed to load firmware!\n");
|
||||
r128_do_cleanup_cce(dev);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int r128_do_cleanup_cce(struct drm_device * dev)
|
||||
|
@ -649,6 +652,8 @@ int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
|
||||
DRM_DEBUG("while CCE running\n");
|
||||
return 0;
|
||||
|
@ -671,6 +676,8 @@ int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
/* Flush any pending CCE commands. This ensures any outstanding
|
||||
* commands are exectuted by the engine before we turn it off.
|
||||
*/
|
||||
|
@ -708,10 +715,7 @@ int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_pri
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_DEBUG("called before init done\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
r128_do_cce_reset(dev_priv);
|
||||
|
||||
|
@ -728,6 +732,8 @@ int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
if (dev_priv->cce_running) {
|
||||
r128_do_cce_flush(dev_priv);
|
||||
}
|
||||
|
@ -741,6 +747,8 @@ int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev->dev_private);
|
||||
|
||||
return r128_do_engine_reset(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -422,6 +422,14 @@ static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
|
|||
* Misc helper macros
|
||||
*/
|
||||
|
||||
#define DEV_INIT_TEST_WITH_RETURN(_dev_priv) \
|
||||
do { \
|
||||
if (!_dev_priv) { \
|
||||
DRM_ERROR("called with no initialization\n"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \
|
||||
|
|
|
@ -1244,14 +1244,18 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
|
|||
static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_r128_sarea_t *sarea_priv;
|
||||
drm_r128_clear_t *clear = data;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
RING_SPACE_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
sarea_priv = dev_priv->sarea_priv;
|
||||
|
||||
if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
|
||||
|
||||
|
@ -1312,6 +1316,8 @@ static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
RING_SPACE_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
if (!dev_priv->page_flipping)
|
||||
|
@ -1331,6 +1337,8 @@ static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
RING_SPACE_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
|
||||
|
@ -1354,10 +1362,7 @@ static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
|
||||
DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
|
||||
|
@ -1410,10 +1415,7 @@ static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
|
||||
elts->idx, elts->start, elts->end, elts->discard);
|
||||
|
@ -1476,6 +1478,8 @@ static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
|
||||
|
||||
if (blit->idx < 0 || blit->idx >= dma->buf_count) {
|
||||
|
@ -1501,6 +1505,8 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
RING_SPACE_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
ret = -EINVAL;
|
||||
|
@ -1531,6 +1537,8 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -1555,10 +1563,7 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file
|
|||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
|
||||
indirect->idx, indirect->start, indirect->end,
|
||||
|
@ -1620,10 +1625,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
|
|||
drm_r128_getparam_t *param = data;
|
||||
int value;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DEV_INIT_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
config DRM_RADEON_KMS
|
||||
bool "Enable modesetting on radeon by default"
|
||||
depends on DRM_RADEON
|
||||
select DRM_TTM
|
||||
help
|
||||
Choose this option if you want kernel modesetting enabled by default,
|
||||
and you have a new enough userspace to support this. Running old
|
||||
|
|
|
@ -3,18 +3,53 @@
|
|||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
ccflags-y := -Iinclude/drm
|
||||
|
||||
hostprogs-y := mkregtable
|
||||
|
||||
quiet_cmd_mkregtable = MKREGTABLE $@
|
||||
cmd_mkregtable = $(obj)/mkregtable $< > $@
|
||||
|
||||
$(obj)/rn50_reg_safe.h: $(src)/reg_srcs/rn50 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/r100_reg_safe.h: $(src)/reg_srcs/r100 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/r200_reg_safe.h: $(src)/reg_srcs/r200 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/rv515_reg_safe.h: $(src)/reg_srcs/rv515 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/r300_reg_safe.h: $(src)/reg_srcs/r300 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable
|
||||
$(call if_changed,mkregtable)
|
||||
|
||||
$(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
|
||||
|
||||
$(obj)/r200.o: $(obj)/r200_reg_safe.h
|
||||
|
||||
$(obj)/rv515.o: $(obj)/rv515_reg_safe.h
|
||||
|
||||
$(obj)/r300.o: $(obj)/r300_reg_safe.h
|
||||
|
||||
$(obj)/rs600.o: $(obj)/rs600_reg_safe.h
|
||||
|
||||
radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
|
||||
radeon_irq.o r300_cmdbuf.o r600_cp.o
|
||||
|
||||
radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \
|
||||
# add KMS driver
|
||||
radeon-y += radeon_device.o radeon_kms.o \
|
||||
radeon_atombios.o radeon_agp.o atombios_crtc.o radeon_combios.o \
|
||||
atom.o radeon_fence.o radeon_ttm.o radeon_object.o radeon_gart.o \
|
||||
radeon_legacy_crtc.o radeon_legacy_encoders.o radeon_connectors.o \
|
||||
radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \
|
||||
radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \
|
||||
radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
|
||||
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \
|
||||
radeon_test.o
|
||||
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
|
||||
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
|
||||
r600_blit_kms.o
|
||||
|
||||
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
|
||||
|
||||
|
|
|
@ -2374,6 +2374,17 @@ typedef struct _ATOM_ANALOG_TV_INFO {
|
|||
ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING];
|
||||
} ATOM_ANALOG_TV_INFO;
|
||||
|
||||
#define MAX_SUPPORTED_TV_TIMING_V1_2 3
|
||||
|
||||
typedef struct _ATOM_ANALOG_TV_INFO_V1_2 {
|
||||
ATOM_COMMON_TABLE_HEADER sHeader;
|
||||
UCHAR ucTV_SupportedStandard;
|
||||
UCHAR ucTV_BootUpDefaultStandard;
|
||||
UCHAR ucExt_TV_ASIC_ID;
|
||||
UCHAR ucExt_TV_ASIC_SlaveAddr;
|
||||
ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING];
|
||||
} ATOM_ANALOG_TV_INFO_V1_2;
|
||||
|
||||
/**************************************************************************/
|
||||
/* VRAM usage and their defintions */
|
||||
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
#include "atom.h"
|
||||
#include "atom-bits.h"
|
||||
|
||||
/* evil but including atombios.h is much worse */
|
||||
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
|
||||
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
|
||||
int32_t *pixel_clock);
|
||||
static void atombios_overscan_setup(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
|
@ -89,17 +93,32 @@ static void atombios_scaler_setup(struct drm_crtc *crtc)
|
|||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
ENABLE_SCALER_PS_ALLOCATION args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
|
||||
|
||||
/* fixme - fill in enc_priv for atom dac */
|
||||
enum radeon_tv_std tv_std = TV_STD_NTSC;
|
||||
bool is_tv = false, is_cv = false;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
|
||||
return;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
/* find tv std */
|
||||
if (encoder->crtc == crtc) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
|
||||
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
tv_std = tv_dac->tv_std;
|
||||
is_tv = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
args.ucScaler = radeon_crtc->crtc_id;
|
||||
|
||||
if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
|
||||
if (is_tv) {
|
||||
switch (tv_std) {
|
||||
case TV_STD_NTSC:
|
||||
default:
|
||||
|
@ -128,7 +147,7 @@ static void atombios_scaler_setup(struct drm_crtc *crtc)
|
|||
break;
|
||||
}
|
||||
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
|
||||
} else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
|
||||
} else if (is_cv) {
|
||||
args.ucTVStandard = ATOM_TV_CV;
|
||||
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
|
||||
} else {
|
||||
|
@ -151,9 +170,9 @@ static void atombios_scaler_setup(struct drm_crtc *crtc)
|
|||
}
|
||||
}
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
|
||||
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
|
||||
atom_rv515_force_tv_scaler(rdev);
|
||||
if ((is_tv || is_cv)
|
||||
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {
|
||||
atom_rv515_force_tv_scaler(rdev, radeon_crtc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,6 +389,7 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
pll_flags |= RADEON_PLL_USE_REF_DIV;
|
||||
}
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,6 +488,11 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
}
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
fb_format =
|
||||
AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
|
||||
AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
|
||||
break;
|
||||
case 15:
|
||||
fb_format =
|
||||
AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
|
||||
|
@ -551,42 +576,68 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
|
|||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_encoder *encoder;
|
||||
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
|
||||
int need_tv_timings = 0;
|
||||
bool ret;
|
||||
|
||||
/* TODO color tiling */
|
||||
memset(&crtc_timing, 0, sizeof(crtc_timing));
|
||||
|
||||
/* TODO tv */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
/* find tv std */
|
||||
if (encoder->crtc == crtc) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
|
||||
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
if (tv_dac) {
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M)
|
||||
need_tv_timings = 1;
|
||||
else
|
||||
need_tv_timings = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crtc_timing.ucCRTC = radeon_crtc->crtc_id;
|
||||
crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
|
||||
crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
|
||||
crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
|
||||
crtc_timing.usH_SyncWidth =
|
||||
adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
|
||||
if (need_tv_timings) {
|
||||
ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1,
|
||||
&crtc_timing, &adjusted_mode->clock);
|
||||
if (ret == false)
|
||||
need_tv_timings = 0;
|
||||
}
|
||||
|
||||
crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
|
||||
crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
|
||||
crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
|
||||
crtc_timing.usV_SyncWidth =
|
||||
adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
|
||||
if (!need_tv_timings) {
|
||||
crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
|
||||
crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
|
||||
crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
|
||||
crtc_timing.usH_SyncWidth =
|
||||
adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
|
||||
crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
|
||||
crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
|
||||
crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
|
||||
crtc_timing.usV_SyncWidth =
|
||||
adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
|
||||
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
|
||||
}
|
||||
|
||||
atombios_crtc_set_pll(crtc, adjusted_mode);
|
||||
atombios_crtc_set_timing(crtc, &crtc_timing);
|
||||
|
|
69
drivers/gpu/drm/radeon/avivod.h
Normal file
69
drivers/gpu/drm/radeon/avivod.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2009 Advanced Micro Devices, Inc.
|
||||
* Copyright 2009 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#ifndef AVIVOD_H
|
||||
#define AVIVOD_H
|
||||
|
||||
|
||||
#define D1CRTC_CONTROL 0x6080
|
||||
#define CRTC_EN (1 << 0)
|
||||
#define D1CRTC_UPDATE_LOCK 0x60E8
|
||||
#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110
|
||||
#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118
|
||||
|
||||
#define D2CRTC_CONTROL 0x6880
|
||||
#define D2CRTC_UPDATE_LOCK 0x68E8
|
||||
#define D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910
|
||||
#define D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918
|
||||
|
||||
#define D1VGA_CONTROL 0x0330
|
||||
#define DVGA_CONTROL_MODE_ENABLE (1 << 0)
|
||||
#define DVGA_CONTROL_TIMING_SELECT (1 << 8)
|
||||
#define DVGA_CONTROL_SYNC_POLARITY_SELECT (1 << 9)
|
||||
#define DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1 << 10)
|
||||
#define DVGA_CONTROL_OVERSCAN_COLOR_EN (1 << 16)
|
||||
#define DVGA_CONTROL_ROTATE (1 << 24)
|
||||
#define D2VGA_CONTROL 0x0338
|
||||
|
||||
#define VGA_HDP_CONTROL 0x328
|
||||
#define VGA_MEM_PAGE_SELECT_EN (1 << 0)
|
||||
#define VGA_MEMORY_DISABLE (1 << 4)
|
||||
#define VGA_RBBM_LOCK_DISABLE (1 << 8)
|
||||
#define VGA_SOFT_RESET (1 << 16)
|
||||
#define VGA_MEMORY_BASE_ADDRESS 0x0310
|
||||
#define VGA_RENDER_CONTROL 0x0300
|
||||
#define VGA_VSTATUS_CNTL_MASK 0x00030000
|
||||
|
||||
/* AVIVO disable VGA rendering */
|
||||
static inline void radeon_avivo_vga_render_disable(struct radeon_device *rdev)
|
||||
{
|
||||
u32 vga_render;
|
||||
vga_render = RREG32(VGA_RENDER_CONTROL);
|
||||
vga_render &= ~VGA_VSTATUS_CNTL_MASK;
|
||||
WREG32(VGA_RENDER_CONTROL, vga_render);
|
||||
}
|
||||
|
||||
#endif
|
720
drivers/gpu/drm/radeon/mkregtable.c
Normal file
720
drivers/gpu/drm/radeon/mkregtable.c
Normal file
|
@ -0,0 +1,720 @@
|
|||
/* utility to create the register check tables
|
||||
* this includes inlined list.h safe for userspace.
|
||||
*
|
||||
* Copyright 2009 Jerome Glisse
|
||||
* Copyright 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Jerome Glisse
|
||||
* Dave Airlie
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
* @ptr: the pointer to the member.
|
||||
* @type: the type of the container struct this is embedded in.
|
||||
* @member: the name of the member within the struct.
|
||||
*
|
||||
*/
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof(((type *)0)->member)*__mptr = (ptr); \
|
||||
(type *)((char *)__mptr - offsetof(type, member)); })
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||
{
|
||||
list->next = list;
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
#ifndef CONFIG_DEBUG_LIST
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
#else
|
||||
extern void __list_add(struct list_head *new,
|
||||
struct list_head *prev, struct list_head *next);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty() on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
#ifndef CONFIG_DEBUG_LIST
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *)0xDEADBEEF;
|
||||
entry->prev = (void *)0xBEEFDEAD;
|
||||
}
|
||||
#else
|
||||
extern void list_del(struct list_head *entry);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* list_replace - replace old entry by new one
|
||||
* @old : the element to be replaced
|
||||
* @new : the new element to insert
|
||||
*
|
||||
* If @old was empty, it will be overwritten.
|
||||
*/
|
||||
static inline void list_replace(struct list_head *old, struct list_head *new)
|
||||
{
|
||||
new->next = old->next;
|
||||
new->next->prev = new;
|
||||
new->prev = old->prev;
|
||||
new->prev->next = new;
|
||||
}
|
||||
|
||||
static inline void list_replace_init(struct list_head *old,
|
||||
struct list_head *new)
|
||||
{
|
||||
list_replace(old, new);
|
||||
INIT_LIST_HEAD(old);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_is_last - tests whether @list is the last entry in list @head
|
||||
* @list: the entry to test
|
||||
* @head: the head of the list
|
||||
*/
|
||||
static inline int list_is_last(const struct list_head *list,
|
||||
const struct list_head *head)
|
||||
{
|
||||
return list->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty_careful - tests whether a list is empty and not being modified
|
||||
* @head: the list to test
|
||||
*
|
||||
* Description:
|
||||
* tests whether a list is empty _and_ checks that no other CPU might be
|
||||
* in the process of modifying either member (next or prev)
|
||||
*
|
||||
* NOTE: using list_empty_careful() without synchronization
|
||||
* can only be safe if the only activity that can happen
|
||||
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||
* if another CPU could re-list_add() it.
|
||||
*/
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
return (next == head) && (next == head->prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_is_singular - tests whether a list has just one entry.
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_is_singular(const struct list_head *head)
|
||||
{
|
||||
return !list_empty(head) && (head->next == head->prev);
|
||||
}
|
||||
|
||||
static inline void __list_cut_position(struct list_head *list,
|
||||
struct list_head *head,
|
||||
struct list_head *entry)
|
||||
{
|
||||
struct list_head *new_first = entry->next;
|
||||
list->next = head->next;
|
||||
list->next->prev = list;
|
||||
list->prev = entry;
|
||||
entry->next = list;
|
||||
head->next = new_first;
|
||||
new_first->prev = head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_cut_position - cut a list into two
|
||||
* @list: a new list to add all removed entries
|
||||
* @head: a list with entries
|
||||
* @entry: an entry within head, could be the head itself
|
||||
* and if so we won't cut the list
|
||||
*
|
||||
* This helper moves the initial part of @head, up to and
|
||||
* including @entry, from @head to @list. You should
|
||||
* pass on @entry an element you know is on @head. @list
|
||||
* should be an empty list or a list you do not care about
|
||||
* losing its data.
|
||||
*
|
||||
*/
|
||||
static inline void list_cut_position(struct list_head *list,
|
||||
struct list_head *head,
|
||||
struct list_head *entry)
|
||||
{
|
||||
if (list_empty(head))
|
||||
return;
|
||||
if (list_is_singular(head) && (head->next != entry && head != entry))
|
||||
return;
|
||||
if (entry == head)
|
||||
INIT_LIST_HEAD(list);
|
||||
else
|
||||
__list_cut_position(list, head, entry);
|
||||
}
|
||||
|
||||
static inline void __list_splice(const struct list_head *list,
|
||||
struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
|
||||
first->prev = prev;
|
||||
prev->next = first;
|
||||
|
||||
last->next = next;
|
||||
next->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists, this is designed for stacks
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(const struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_tail - join two lists, each list being a queue
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head->prev, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head, head->next);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_tail_init - join two lists and reinitialise the emptied list
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* Each of the lists is a queue.
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_tail_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head->prev, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_first_entry - get the first element from a list
|
||||
* @ptr: the list head to take the element from.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Note, that list is expected to be not empty.
|
||||
*/
|
||||
#define list_first_entry(ptr, type, member) \
|
||||
list_entry((ptr)->next, type, member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* __list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*
|
||||
* This variant differs from list_for_each() in that it's the
|
||||
* simplest possible list iteration code, no prefetching is done.
|
||||
* Use this for code that knows the list to be very short (empty
|
||||
* or 1 entry) most of the time.
|
||||
*/
|
||||
#define __list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
|
||||
pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop cursor.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev_safe(pos, n, head) \
|
||||
for (pos = (head)->prev, n = pos->prev; \
|
||||
prefetch(pos->prev), pos != (head); \
|
||||
pos = n, n = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member); \
|
||||
prefetch(pos->member.prev), &pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
|
||||
* @pos: the type * to use as a start point
|
||||
* @head: the head of the list
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member) \
|
||||
((pos) ? : list_entry(head, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - continue iteration over list of given type
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Continue to iterate over list of given type, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
prefetch(pos->member.next), &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue_reverse - iterate backwards from the given point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Start to iterate over list of given type backwards, continuing after
|
||||
* the current position.
|
||||
*/
|
||||
#define list_for_each_entry_continue_reverse(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
|
||||
prefetch(pos->member.prev), &pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_from - iterate over list of given type from the current point
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing from current position.
|
||||
*/
|
||||
#define list_for_each_entry_from(pos, head, member) \
|
||||
for (; prefetch(pos->member.next), &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_continue
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type, continuing after current point,
|
||||
* safe against removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_continue(pos, n, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_from
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate over list of given type from current point, safe against
|
||||
* removal of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_from(pos, n, head, member) \
|
||||
for (n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe_reverse
|
||||
* @pos: the type * to use as a loop cursor.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*
|
||||
* Iterate backwards over list of given type, safe against removal
|
||||
* of list entry.
|
||||
*/
|
||||
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
|
||||
|
||||
struct offset {
|
||||
struct list_head list;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
struct table {
|
||||
struct list_head offsets;
|
||||
unsigned offset_max;
|
||||
unsigned nentry;
|
||||
unsigned *table;
|
||||
char *gpu_prefix;
|
||||
};
|
||||
|
||||
struct offset *offset_new(unsigned o)
|
||||
{
|
||||
struct offset *offset;
|
||||
|
||||
offset = (struct offset *)malloc(sizeof(struct offset));
|
||||
if (offset) {
|
||||
INIT_LIST_HEAD(&offset->list);
|
||||
offset->offset = o;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void table_offset_add(struct table *t, struct offset *offset)
|
||||
{
|
||||
list_add_tail(&offset->list, &t->offsets);
|
||||
}
|
||||
|
||||
void table_init(struct table *t)
|
||||
{
|
||||
INIT_LIST_HEAD(&t->offsets);
|
||||
t->offset_max = 0;
|
||||
t->nentry = 0;
|
||||
t->table = NULL;
|
||||
}
|
||||
|
||||
void table_print(struct table *t)
|
||||
{
|
||||
unsigned nlloop, i, j, n, c, id;
|
||||
|
||||
nlloop = (t->nentry + 3) / 4;
|
||||
c = t->nentry;
|
||||
printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix,
|
||||
t->nentry);
|
||||
for (i = 0, id = 0; i < nlloop; i++) {
|
||||
n = 4;
|
||||
if (n > c)
|
||||
n = c;
|
||||
c -= n;
|
||||
for (j = 0; j < n; j++) {
|
||||
if (j == 0)
|
||||
printf("\t");
|
||||
else
|
||||
printf(" ");
|
||||
printf("0x%08X,", t->table[id++]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
int table_build(struct table *t)
|
||||
{
|
||||
struct offset *offset;
|
||||
unsigned i, m;
|
||||
|
||||
t->nentry = ((t->offset_max >> 2) + 31) / 32;
|
||||
t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry);
|
||||
if (t->table == NULL)
|
||||
return -1;
|
||||
memset(t->table, 0xff, sizeof(unsigned) * t->nentry);
|
||||
list_for_each_entry(offset, &t->offsets, list) {
|
||||
i = (offset->offset >> 2) / 32;
|
||||
m = (offset->offset >> 2) & 31;
|
||||
m = 1 << m;
|
||||
t->table[i] ^= m;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char gpu_name[10];
|
||||
int parser_auth(struct table *t, const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
regex_t mask_rex;
|
||||
regmatch_t match[4];
|
||||
char buf[1024];
|
||||
size_t end;
|
||||
int len;
|
||||
int done = 0;
|
||||
int r;
|
||||
unsigned o;
|
||||
struct offset *offset;
|
||||
char last_reg_s[10];
|
||||
int last_reg;
|
||||
|
||||
if (regcomp
|
||||
(&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) {
|
||||
fprintf(stderr, "Failed to compile regular expression\n");
|
||||
return -1;
|
||||
}
|
||||
file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Failed to open: %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
fseek(file, 0, SEEK_END);
|
||||
end = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
/* get header */
|
||||
if (fgets(buf, 1024, file) == NULL)
|
||||
return -1;
|
||||
|
||||
/* first line will contain the last register
|
||||
* and gpu name */
|
||||
sscanf(buf, "%s %s", gpu_name, last_reg_s);
|
||||
t->gpu_prefix = gpu_name;
|
||||
last_reg = strtol(last_reg_s, NULL, 16);
|
||||
|
||||
do {
|
||||
if (fgets(buf, 1024, file) == NULL)
|
||||
return -1;
|
||||
len = strlen(buf);
|
||||
if (ftell(file) == end)
|
||||
done = 1;
|
||||
if (len) {
|
||||
r = regexec(&mask_rex, buf, 4, match, 0);
|
||||
if (r == REG_NOMATCH) {
|
||||
} else if (r) {
|
||||
fprintf(stderr,
|
||||
"Error matching regular expression %d in %s\n",
|
||||
r, filename);
|
||||
return -1;
|
||||
} else {
|
||||
buf[match[0].rm_eo] = 0;
|
||||
buf[match[1].rm_eo] = 0;
|
||||
buf[match[2].rm_eo] = 0;
|
||||
o = strtol(&buf[match[1].rm_so], NULL, 16);
|
||||
offset = offset_new(o);
|
||||
table_offset_add(t, offset);
|
||||
if (o > t->offset_max)
|
||||
t->offset_max = o;
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
fclose(file);
|
||||
if (t->offset_max < last_reg)
|
||||
t->offset_max = last_reg;
|
||||
return table_build(t);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct table t;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <authfile>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
table_init(&t);
|
||||
if (parser_auth(&t, argv[1])) {
|
||||
fprintf(stderr, "Failed to parse file %s\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
table_print(&t);
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load diff
124
drivers/gpu/drm/radeon/r100_track.h
Normal file
124
drivers/gpu/drm/radeon/r100_track.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
|
||||
#define R100_TRACK_MAX_TEXTURE 3
|
||||
#define R200_TRACK_MAX_TEXTURE 6
|
||||
#define R300_TRACK_MAX_TEXTURE 16
|
||||
|
||||
#define R100_MAX_CB 1
|
||||
#define R300_MAX_CB 4
|
||||
|
||||
/*
|
||||
* CS functions
|
||||
*/
|
||||
struct r100_cs_track_cb {
|
||||
struct radeon_object *robj;
|
||||
unsigned pitch;
|
||||
unsigned cpp;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
struct r100_cs_track_array {
|
||||
struct radeon_object *robj;
|
||||
unsigned esize;
|
||||
};
|
||||
|
||||
struct r100_cs_cube_info {
|
||||
struct radeon_object *robj;
|
||||
unsigned offset;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
};
|
||||
|
||||
struct r100_cs_track_texture {
|
||||
struct radeon_object *robj;
|
||||
struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */
|
||||
unsigned pitch;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned num_levels;
|
||||
unsigned cpp;
|
||||
unsigned tex_coord_type;
|
||||
unsigned txdepth;
|
||||
unsigned width_11;
|
||||
unsigned height_11;
|
||||
bool use_pitch;
|
||||
bool enabled;
|
||||
bool roundup_w;
|
||||
bool roundup_h;
|
||||
};
|
||||
|
||||
struct r100_cs_track_limits {
|
||||
unsigned num_cb;
|
||||
unsigned num_texture;
|
||||
unsigned max_levels;
|
||||
};
|
||||
|
||||
struct r100_cs_track {
|
||||
struct radeon_device *rdev;
|
||||
unsigned num_cb;
|
||||
unsigned num_texture;
|
||||
unsigned maxy;
|
||||
unsigned vtx_size;
|
||||
unsigned vap_vf_cntl;
|
||||
unsigned immd_dwords;
|
||||
unsigned num_arrays;
|
||||
unsigned max_indx;
|
||||
struct r100_cs_track_array arrays[11];
|
||||
struct r100_cs_track_cb cb[R300_MAX_CB];
|
||||
struct r100_cs_track_cb zb;
|
||||
struct r100_cs_track_texture textures[R300_TRACK_MAX_TEXTURE];
|
||||
bool z_enabled;
|
||||
bool separate_cube;
|
||||
|
||||
};
|
||||
|
||||
int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track);
|
||||
void r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track);
|
||||
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc);
|
||||
void r100_cs_dump_packet(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt);
|
||||
|
||||
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
|
||||
|
||||
int r200_packet0_check(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx, unsigned reg);
|
||||
|
||||
static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx,
|
||||
unsigned reg)
|
||||
{
|
||||
int r;
|
||||
u32 tile_flags = 0;
|
||||
u32 tmp;
|
||||
struct radeon_cs_reloc *reloc;
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
tmp = ib_chunk->kdata[idx] & 0x003fffff;
|
||||
tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
|
||||
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
|
||||
tile_flags |= RADEON_DST_TILE_MACRO;
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
|
||||
if (reg == RADEON_SRC_PITCH_OFFSET) {
|
||||
DRM_ERROR("Cannot src blit from microtiled surface\n");
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return -EINVAL;
|
||||
}
|
||||
tile_flags |= RADEON_DST_TILE_MICRO;
|
||||
}
|
||||
|
||||
tmp |= tile_flags;
|
||||
p->ib->ptr[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
|
||||
return 0;
|
||||
}
|
607
drivers/gpu/drm/radeon/r100d.h
Normal file
607
drivers/gpu/drm/radeon/r100d.h
Normal file
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
* Copyright 2008 Advanced Micro Devices, Inc.
|
||||
* Copyright 2008 Red Hat Inc.
|
||||
* Copyright 2009 Jerome Glisse.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#ifndef __R100D_H__
|
||||
#define __R100D_H__
|
||||
|
||||
#define CP_PACKET0 0x00000000
|
||||
#define PACKET0_BASE_INDEX_SHIFT 0
|
||||
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0)
|
||||
#define PACKET0_COUNT_SHIFT 16
|
||||
#define PACKET0_COUNT_MASK (0x3fff << 16)
|
||||
#define CP_PACKET1 0x40000000
|
||||
#define CP_PACKET2 0x80000000
|
||||
#define PACKET2_PAD_SHIFT 0
|
||||
#define PACKET2_PAD_MASK (0x3fffffff << 0)
|
||||
#define CP_PACKET3 0xC0000000
|
||||
#define PACKET3_IT_OPCODE_SHIFT 8
|
||||
#define PACKET3_IT_OPCODE_MASK (0xff << 8)
|
||||
#define PACKET3_COUNT_SHIFT 16
|
||||
#define PACKET3_COUNT_MASK (0x3fff << 16)
|
||||
/* PACKET3 op code */
|
||||
#define PACKET3_NOP 0x10
|
||||
#define PACKET3_3D_DRAW_VBUF 0x28
|
||||
#define PACKET3_3D_DRAW_IMMD 0x29
|
||||
#define PACKET3_3D_DRAW_INDX 0x2A
|
||||
#define PACKET3_3D_LOAD_VBPNTR 0x2F
|
||||
#define PACKET3_INDX_BUFFER 0x33
|
||||
#define PACKET3_3D_DRAW_VBUF_2 0x34
|
||||
#define PACKET3_3D_DRAW_IMMD_2 0x35
|
||||
#define PACKET3_3D_DRAW_INDX_2 0x36
|
||||
#define PACKET3_BITBLT_MULTI 0x9B
|
||||
|
||||
#define PACKET0(reg, n) (CP_PACKET0 | \
|
||||
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \
|
||||
REG_SET(PACKET0_COUNT, (n)))
|
||||
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
|
||||
#define PACKET3(op, n) (CP_PACKET3 | \
|
||||
REG_SET(PACKET3_IT_OPCODE, (op)) | \
|
||||
REG_SET(PACKET3_COUNT, (n)))
|
||||
|
||||
#define PACKET_TYPE0 0
|
||||
#define PACKET_TYPE1 1
|
||||
#define PACKET_TYPE2 2
|
||||
#define PACKET_TYPE3 3
|
||||
|
||||
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
|
||||
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
|
||||
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
|
||||
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
|
||||
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
|
||||
|
||||
/* Registers */
|
||||
#define R_000040_GEN_INT_CNTL 0x000040
|
||||
#define S_000040_CRTC_VBLANK(x) (((x) & 0x1) << 0)
|
||||
#define G_000040_CRTC_VBLANK(x) (((x) >> 0) & 0x1)
|
||||
#define C_000040_CRTC_VBLANK 0xFFFFFFFE
|
||||
#define S_000040_CRTC_VLINE(x) (((x) & 0x1) << 1)
|
||||
#define G_000040_CRTC_VLINE(x) (((x) >> 1) & 0x1)
|
||||
#define C_000040_CRTC_VLINE 0xFFFFFFFD
|
||||
#define S_000040_CRTC_VSYNC(x) (((x) & 0x1) << 2)
|
||||
#define G_000040_CRTC_VSYNC(x) (((x) >> 2) & 0x1)
|
||||
#define C_000040_CRTC_VSYNC 0xFFFFFFFB
|
||||
#define S_000040_SNAPSHOT(x) (((x) & 0x1) << 3)
|
||||
#define G_000040_SNAPSHOT(x) (((x) >> 3) & 0x1)
|
||||
#define C_000040_SNAPSHOT 0xFFFFFFF7
|
||||
#define S_000040_FP_DETECT(x) (((x) & 0x1) << 4)
|
||||
#define G_000040_FP_DETECT(x) (((x) >> 4) & 0x1)
|
||||
#define C_000040_FP_DETECT 0xFFFFFFEF
|
||||
#define S_000040_CRTC2_VLINE(x) (((x) & 0x1) << 5)
|
||||
#define G_000040_CRTC2_VLINE(x) (((x) >> 5) & 0x1)
|
||||
#define C_000040_CRTC2_VLINE 0xFFFFFFDF
|
||||
#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12)
|
||||
#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1)
|
||||
#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF
|
||||
#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6)
|
||||
#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1)
|
||||
#define C_000040_CRTC2_VSYNC 0xFFFFFFBF
|
||||
#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7)
|
||||
#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1)
|
||||
#define C_000040_SNAPSHOT2 0xFFFFFF7F
|
||||
#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9)
|
||||
#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1)
|
||||
#define C_000040_CRTC2_VBLANK 0xFFFFFDFF
|
||||
#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10)
|
||||
#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1)
|
||||
#define C_000040_FP2_DETECT 0xFFFFFBFF
|
||||
#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11)
|
||||
#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1)
|
||||
#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF
|
||||
#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13)
|
||||
#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1)
|
||||
#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF
|
||||
#define S_000040_DMA_VIPH2_INT_EN(x) (((x) & 0x1) << 14)
|
||||
#define G_000040_DMA_VIPH2_INT_EN(x) (((x) >> 14) & 0x1)
|
||||
#define C_000040_DMA_VIPH2_INT_EN 0xFFFFBFFF
|
||||
#define S_000040_DMA_VIPH3_INT_EN(x) (((x) & 0x1) << 15)
|
||||
#define G_000040_DMA_VIPH3_INT_EN(x) (((x) >> 15) & 0x1)
|
||||
#define C_000040_DMA_VIPH3_INT_EN 0xFFFF7FFF
|
||||
#define S_000040_I2C_INT_EN(x) (((x) & 0x1) << 17)
|
||||
#define G_000040_I2C_INT_EN(x) (((x) >> 17) & 0x1)
|
||||
#define C_000040_I2C_INT_EN 0xFFFDFFFF
|
||||
#define S_000040_GUI_IDLE(x) (((x) & 0x1) << 19)
|
||||
#define G_000040_GUI_IDLE(x) (((x) >> 19) & 0x1)
|
||||
#define C_000040_GUI_IDLE 0xFFF7FFFF
|
||||
#define S_000040_VIPH_INT_EN(x) (((x) & 0x1) << 24)
|
||||
#define G_000040_VIPH_INT_EN(x) (((x) >> 24) & 0x1)
|
||||
#define C_000040_VIPH_INT_EN 0xFEFFFFFF
|
||||
#define S_000040_SW_INT_EN(x) (((x) & 0x1) << 25)
|
||||
#define G_000040_SW_INT_EN(x) (((x) >> 25) & 0x1)
|
||||
#define C_000040_SW_INT_EN 0xFDFFFFFF
|
||||
#define S_000040_GEYSERVILLE(x) (((x) & 0x1) << 27)
|
||||
#define G_000040_GEYSERVILLE(x) (((x) >> 27) & 0x1)
|
||||
#define C_000040_GEYSERVILLE 0xF7FFFFFF
|
||||
#define S_000040_HDCP_AUTHORIZED_INT(x) (((x) & 0x1) << 28)
|
||||
#define G_000040_HDCP_AUTHORIZED_INT(x) (((x) >> 28) & 0x1)
|
||||
#define C_000040_HDCP_AUTHORIZED_INT 0xEFFFFFFF
|
||||
#define S_000040_DVI_I2C_INT(x) (((x) & 0x1) << 29)
|
||||
#define G_000040_DVI_I2C_INT(x) (((x) >> 29) & 0x1)
|
||||
#define C_000040_DVI_I2C_INT 0xDFFFFFFF
|
||||
#define S_000040_GUIDMA(x) (((x) & 0x1) << 30)
|
||||
#define G_000040_GUIDMA(x) (((x) >> 30) & 0x1)
|
||||
#define C_000040_GUIDMA 0xBFFFFFFF
|
||||
#define S_000040_VIDDMA(x) (((x) & 0x1) << 31)
|
||||
#define G_000040_VIDDMA(x) (((x) >> 31) & 0x1)
|
||||
#define C_000040_VIDDMA 0x7FFFFFFF
|
||||
#define R_000044_GEN_INT_STATUS 0x000044
|
||||
#define S_000044_CRTC_VBLANK_STAT(x) (((x) & 0x1) << 0)
|
||||
#define G_000044_CRTC_VBLANK_STAT(x) (((x) >> 0) & 0x1)
|
||||
#define C_000044_CRTC_VBLANK_STAT 0xFFFFFFFE
|
||||
#define S_000044_CRTC_VBLANK_STAT_AK(x) (((x) & 0x1) << 0)
|
||||
#define G_000044_CRTC_VBLANK_STAT_AK(x) (((x) >> 0) & 0x1)
|
||||
#define C_000044_CRTC_VBLANK_STAT_AK 0xFFFFFFFE
|
||||
#define S_000044_CRTC_VLINE_STAT(x) (((x) & 0x1) << 1)
|
||||
#define G_000044_CRTC_VLINE_STAT(x) (((x) >> 1) & 0x1)
|
||||
#define C_000044_CRTC_VLINE_STAT 0xFFFFFFFD
|
||||
#define S_000044_CRTC_VLINE_STAT_AK(x) (((x) & 0x1) << 1)
|
||||
#define G_000044_CRTC_VLINE_STAT_AK(x) (((x) >> 1) & 0x1)
|
||||
#define C_000044_CRTC_VLINE_STAT_AK 0xFFFFFFFD
|
||||
#define S_000044_CRTC_VSYNC_STAT(x) (((x) & 0x1) << 2)
|
||||
#define G_000044_CRTC_VSYNC_STAT(x) (((x) >> 2) & 0x1)
|
||||
#define C_000044_CRTC_VSYNC_STAT 0xFFFFFFFB
|
||||
#define S_000044_CRTC_VSYNC_STAT_AK(x) (((x) & 0x1) << 2)
|
||||
#define G_000044_CRTC_VSYNC_STAT_AK(x) (((x) >> 2) & 0x1)
|
||||
#define C_000044_CRTC_VSYNC_STAT_AK 0xFFFFFFFB
|
||||
#define S_000044_SNAPSHOT_STAT(x) (((x) & 0x1) << 3)
|
||||
#define G_000044_SNAPSHOT_STAT(x) (((x) >> 3) & 0x1)
|
||||
#define C_000044_SNAPSHOT_STAT 0xFFFFFFF7
|
||||
#define S_000044_SNAPSHOT_STAT_AK(x) (((x) & 0x1) << 3)
|
||||
#define G_000044_SNAPSHOT_STAT_AK(x) (((x) >> 3) & 0x1)
|
||||
#define C_000044_SNAPSHOT_STAT_AK 0xFFFFFFF7
|
||||
#define S_000044_FP_DETECT_STAT(x) (((x) & 0x1) << 4)
|
||||
#define G_000044_FP_DETECT_STAT(x) (((x) >> 4) & 0x1)
|
||||
#define C_000044_FP_DETECT_STAT 0xFFFFFFEF
|
||||
#define S_000044_FP_DETECT_STAT_AK(x) (((x) & 0x1) << 4)
|
||||
#define G_000044_FP_DETECT_STAT_AK(x) (((x) >> 4) & 0x1)
|
||||
#define C_000044_FP_DETECT_STAT_AK 0xFFFFFFEF
|
||||
#define S_000044_CRTC2_VLINE_STAT(x) (((x) & 0x1) << 5)
|
||||
#define G_000044_CRTC2_VLINE_STAT(x) (((x) >> 5) & 0x1)
|
||||
#define C_000044_CRTC2_VLINE_STAT 0xFFFFFFDF
|
||||
#define S_000044_CRTC2_VLINE_STAT_AK(x) (((x) & 0x1) << 5)
|
||||
#define G_000044_CRTC2_VLINE_STAT_AK(x) (((x) >> 5) & 0x1)
|
||||
#define C_000044_CRTC2_VLINE_STAT_AK 0xFFFFFFDF
|
||||
#define S_000044_CRTC2_VSYNC_STAT(x) (((x) & 0x1) << 6)
|
||||
#define G_000044_CRTC2_VSYNC_STAT(x) (((x) >> 6) & 0x1)
|
||||
#define C_000044_CRTC2_VSYNC_STAT 0xFFFFFFBF
|
||||
#define S_000044_CRTC2_VSYNC_STAT_AK(x) (((x) & 0x1) << 6)
|
||||
#define G_000044_CRTC2_VSYNC_STAT_AK(x) (((x) >> 6) & 0x1)
|
||||
#define C_000044_CRTC2_VSYNC_STAT_AK 0xFFFFFFBF
|
||||
#define S_000044_SNAPSHOT2_STAT(x) (((x) & 0x1) << 7)
|
||||
#define G_000044_SNAPSHOT2_STAT(x) (((x) >> 7) & 0x1)
|
||||
#define C_000044_SNAPSHOT2_STAT 0xFFFFFF7F
|
||||
#define S_000044_SNAPSHOT2_STAT_AK(x) (((x) & 0x1) << 7)
|
||||
#define G_000044_SNAPSHOT2_STAT_AK(x) (((x) >> 7) & 0x1)
|
||||
#define C_000044_SNAPSHOT2_STAT_AK 0xFFFFFF7F
|
||||
#define S_000044_CAP0_INT_ACTIVE(x) (((x) & 0x1) << 8)
|
||||
#define G_000044_CAP0_INT_ACTIVE(x) (((x) >> 8) & 0x1)
|
||||
#define C_000044_CAP0_INT_ACTIVE 0xFFFFFEFF
|
||||
#define S_000044_CRTC2_VBLANK_STAT(x) (((x) & 0x1) << 9)
|
||||
#define G_000044_CRTC2_VBLANK_STAT(x) (((x) >> 9) & 0x1)
|
||||
#define C_000044_CRTC2_VBLANK_STAT 0xFFFFFDFF
|
||||
#define S_000044_CRTC2_VBLANK_STAT_AK(x) (((x) & 0x1) << 9)
|
||||
#define G_000044_CRTC2_VBLANK_STAT_AK(x) (((x) >> 9) & 0x1)
|
||||
#define C_000044_CRTC2_VBLANK_STAT_AK 0xFFFFFDFF
|
||||
#define S_000044_FP2_DETECT_STAT(x) (((x) & 0x1) << 10)
|
||||
#define G_000044_FP2_DETECT_STAT(x) (((x) >> 10) & 0x1)
|
||||
#define C_000044_FP2_DETECT_STAT 0xFFFFFBFF
|
||||
#define S_000044_FP2_DETECT_STAT_AK(x) (((x) & 0x1) << 10)
|
||||
#define G_000044_FP2_DETECT_STAT_AK(x) (((x) >> 10) & 0x1)
|
||||
#define C_000044_FP2_DETECT_STAT_AK 0xFFFFFBFF
|
||||
#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) & 0x1) << 11)
|
||||
#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) >> 11) & 0x1)
|
||||
#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT 0xFFFFF7FF
|
||||
#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) & 0x1) << 11)
|
||||
#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) >> 11) & 0x1)
|
||||
#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK 0xFFFFF7FF
|
||||
#define S_000044_DMA_VIPH0_INT(x) (((x) & 0x1) << 12)
|
||||
#define G_000044_DMA_VIPH0_INT(x) (((x) >> 12) & 0x1)
|
||||
#define C_000044_DMA_VIPH0_INT 0xFFFFEFFF
|
||||
#define S_000044_DMA_VIPH0_INT_AK(x) (((x) & 0x1) << 12)
|
||||
#define G_000044_DMA_VIPH0_INT_AK(x) (((x) >> 12) & 0x1)
|
||||
#define C_000044_DMA_VIPH0_INT_AK 0xFFFFEFFF
|
||||
#define S_000044_DMA_VIPH1_INT(x) (((x) & 0x1) << 13)
|
||||
#define G_000044_DMA_VIPH1_INT(x) (((x) >> 13) & 0x1)
|
||||
#define C_000044_DMA_VIPH1_INT 0xFFFFDFFF
|
||||
#define S_000044_DMA_VIPH1_INT_AK(x) (((x) & 0x1) << 13)
|
||||
#define G_000044_DMA_VIPH1_INT_AK(x) (((x) >> 13) & 0x1)
|
||||
#define C_000044_DMA_VIPH1_INT_AK 0xFFFFDFFF
|
||||
#define S_000044_DMA_VIPH2_INT(x) (((x) & 0x1) << 14)
|
||||
#define G_000044_DMA_VIPH2_INT(x) (((x) >> 14) & 0x1)
|
||||
#define C_000044_DMA_VIPH2_INT 0xFFFFBFFF
|
||||
#define S_000044_DMA_VIPH2_INT_AK(x) (((x) & 0x1) << 14)
|
||||
#define G_000044_DMA_VIPH2_INT_AK(x) (((x) >> 14) & 0x1)
|
||||
#define C_000044_DMA_VIPH2_INT_AK 0xFFFFBFFF
|
||||
#define S_000044_DMA_VIPH3_INT(x) (((x) & 0x1) << 15)
|
||||
#define G_000044_DMA_VIPH3_INT(x) (((x) >> 15) & 0x1)
|
||||
#define C_000044_DMA_VIPH3_INT 0xFFFF7FFF
|
||||
#define S_000044_DMA_VIPH3_INT_AK(x) (((x) & 0x1) << 15)
|
||||
#define G_000044_DMA_VIPH3_INT_AK(x) (((x) >> 15) & 0x1)
|
||||
#define C_000044_DMA_VIPH3_INT_AK 0xFFFF7FFF
|
||||
#define S_000044_I2C_INT(x) (((x) & 0x1) << 17)
|
||||
#define G_000044_I2C_INT(x) (((x) >> 17) & 0x1)
|
||||
#define C_000044_I2C_INT 0xFFFDFFFF
|
||||
#define S_000044_I2C_INT_AK(x) (((x) & 0x1) << 17)
|
||||
#define G_000044_I2C_INT_AK(x) (((x) >> 17) & 0x1)
|
||||
#define C_000044_I2C_INT_AK 0xFFFDFFFF
|
||||
#define S_000044_GUI_IDLE_STAT(x) (((x) & 0x1) << 19)
|
||||
#define G_000044_GUI_IDLE_STAT(x) (((x) >> 19) & 0x1)
|
||||
#define C_000044_GUI_IDLE_STAT 0xFFF7FFFF
|
||||
#define S_000044_GUI_IDLE_STAT_AK(x) (((x) & 0x1) << 19)
|
||||
#define G_000044_GUI_IDLE_STAT_AK(x) (((x) >> 19) & 0x1)
|
||||
#define C_000044_GUI_IDLE_STAT_AK 0xFFF7FFFF
|
||||
#define S_000044_VIPH_INT(x) (((x) & 0x1) << 24)
|
||||
#define G_000044_VIPH_INT(x) (((x) >> 24) & 0x1)
|
||||
#define C_000044_VIPH_INT 0xFEFFFFFF
|
||||
#define S_000044_SW_INT(x) (((x) & 0x1) << 25)
|
||||
#define G_000044_SW_INT(x) (((x) >> 25) & 0x1)
|
||||
#define C_000044_SW_INT 0xFDFFFFFF
|
||||
#define S_000044_SW_INT_AK(x) (((x) & 0x1) << 25)
|
||||
#define G_000044_SW_INT_AK(x) (((x) >> 25) & 0x1)
|
||||
#define C_000044_SW_INT_AK 0xFDFFFFFF
|
||||
#define S_000044_SW_INT_SET(x) (((x) & 0x1) << 26)
|
||||
#define G_000044_SW_INT_SET(x) (((x) >> 26) & 0x1)
|
||||
#define C_000044_SW_INT_SET 0xFBFFFFFF
|
||||
#define S_000044_GEYSERVILLE_STAT(x) (((x) & 0x1) << 27)
|
||||
#define G_000044_GEYSERVILLE_STAT(x) (((x) >> 27) & 0x1)
|
||||
#define C_000044_GEYSERVILLE_STAT 0xF7FFFFFF
|
||||
#define S_000044_GEYSERVILLE_STAT_AK(x) (((x) & 0x1) << 27)
|
||||
#define G_000044_GEYSERVILLE_STAT_AK(x) (((x) >> 27) & 0x1)
|
||||
#define C_000044_GEYSERVILLE_STAT_AK 0xF7FFFFFF
|
||||
#define S_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) & 0x1) << 28)
|
||||
#define G_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) >> 28) & 0x1)
|
||||
#define C_000044_HDCP_AUTHORIZED_INT_STAT 0xEFFFFFFF
|
||||
#define S_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) & 0x1) << 28)
|
||||
#define G_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) >> 28) & 0x1)
|
||||
#define C_000044_HDCP_AUTHORIZED_INT_AK 0xEFFFFFFF
|
||||
#define S_000044_DVI_I2C_INT_STAT(x) (((x) & 0x1) << 29)
|
||||
#define G_000044_DVI_I2C_INT_STAT(x) (((x) >> 29) & 0x1)
|
||||
#define C_000044_DVI_I2C_INT_STAT 0xDFFFFFFF
|
||||
#define S_000044_DVI_I2C_INT_AK(x) (((x) & 0x1) << 29)
|
||||
#define G_000044_DVI_I2C_INT_AK(x) (((x) >> 29) & 0x1)
|
||||
#define C_000044_DVI_I2C_INT_AK 0xDFFFFFFF
|
||||
#define S_000044_GUIDMA_STAT(x) (((x) & 0x1) << 30)
|
||||
#define G_000044_GUIDMA_STAT(x) (((x) >> 30) & 0x1)
|
||||
#define C_000044_GUIDMA_STAT 0xBFFFFFFF
|
||||
#define S_000044_GUIDMA_AK(x) (((x) & 0x1) << 30)
|
||||
#define G_000044_GUIDMA_AK(x) (((x) >> 30) & 0x1)
|
||||
#define C_000044_GUIDMA_AK 0xBFFFFFFF
|
||||
#define S_000044_VIDDMA_STAT(x) (((x) & 0x1) << 31)
|
||||
#define G_000044_VIDDMA_STAT(x) (((x) >> 31) & 0x1)
|
||||
#define C_000044_VIDDMA_STAT 0x7FFFFFFF
|
||||
#define S_000044_VIDDMA_AK(x) (((x) & 0x1) << 31)
|
||||
#define G_000044_VIDDMA_AK(x) (((x) >> 31) & 0x1)
|
||||
#define C_000044_VIDDMA_AK 0x7FFFFFFF
|
||||
#define R_000050_CRTC_GEN_CNTL 0x000050
|
||||
#define S_000050_CRTC_DBL_SCAN_EN(x) (((x) & 0x1) << 0)
|
||||
#define G_000050_CRTC_DBL_SCAN_EN(x) (((x) >> 0) & 0x1)
|
||||
#define C_000050_CRTC_DBL_SCAN_EN 0xFFFFFFFE
|
||||
#define S_000050_CRTC_INTERLACE_EN(x) (((x) & 0x1) << 1)
|
||||
#define G_000050_CRTC_INTERLACE_EN(x) (((x) >> 1) & 0x1)
|
||||
#define C_000050_CRTC_INTERLACE_EN 0xFFFFFFFD
|
||||
#define S_000050_CRTC_C_SYNC_EN(x) (((x) & 0x1) << 4)
|
||||
#define G_000050_CRTC_C_SYNC_EN(x) (((x) >> 4) & 0x1)
|
||||
#define C_000050_CRTC_C_SYNC_EN 0xFFFFFFEF
|
||||
#define S_000050_CRTC_PIX_WIDTH(x) (((x) & 0xF) << 8)
|
||||
#define G_000050_CRTC_PIX_WIDTH(x) (((x) >> 8) & 0xF)
|
||||
#define C_000050_CRTC_PIX_WIDTH 0xFFFFF0FF
|
||||
#define S_000050_CRTC_ICON_EN(x) (((x) & 0x1) << 15)
|
||||
#define G_000050_CRTC_ICON_EN(x) (((x) >> 15) & 0x1)
|
||||
#define C_000050_CRTC_ICON_EN 0xFFFF7FFF
|
||||
#define S_000050_CRTC_CUR_EN(x) (((x) & 0x1) << 16)
|
||||
#define G_000050_CRTC_CUR_EN(x) (((x) >> 16) & 0x1)
|
||||
#define C_000050_CRTC_CUR_EN 0xFFFEFFFF
|
||||
#define S_000050_CRTC_VSTAT_MODE(x) (((x) & 0x3) << 17)
|
||||
#define G_000050_CRTC_VSTAT_MODE(x) (((x) >> 17) & 0x3)
|
||||
#define C_000050_CRTC_VSTAT_MODE 0xFFF9FFFF
|
||||
#define S_000050_CRTC_CUR_MODE(x) (((x) & 0x7) << 20)
|
||||
#define G_000050_CRTC_CUR_MODE(x) (((x) >> 20) & 0x7)
|
||||
#define C_000050_CRTC_CUR_MODE 0xFF8FFFFF
|
||||
#define S_000050_CRTC_EXT_DISP_EN(x) (((x) & 0x1) << 24)
|
||||
#define G_000050_CRTC_EXT_DISP_EN(x) (((x) >> 24) & 0x1)
|
||||
#define C_000050_CRTC_EXT_DISP_EN 0xFEFFFFFF
|
||||
#define S_000050_CRTC_EN(x) (((x) & 0x1) << 25)
|
||||
#define G_000050_CRTC_EN(x) (((x) >> 25) & 0x1)
|
||||
#define C_000050_CRTC_EN 0xFDFFFFFF
|
||||
#define S_000050_CRTC_DISP_REQ_EN_B(x) (((x) & 0x1) << 26)
|
||||
#define G_000050_CRTC_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1)
|
||||
#define C_000050_CRTC_DISP_REQ_EN_B 0xFBFFFFFF
|
||||
#define R_000054_CRTC_EXT_CNTL 0x000054
|
||||
#define S_000054_CRTC_VGA_XOVERSCAN(x) (((x) & 0x1) << 0)
|
||||
#define G_000054_CRTC_VGA_XOVERSCAN(x) (((x) >> 0) & 0x1)
|
||||
#define C_000054_CRTC_VGA_XOVERSCAN 0xFFFFFFFE
|
||||
#define S_000054_VGA_BLINK_RATE(x) (((x) & 0x3) << 1)
|
||||
#define G_000054_VGA_BLINK_RATE(x) (((x) >> 1) & 0x3)
|
||||
#define C_000054_VGA_BLINK_RATE 0xFFFFFFF9
|
||||
#define S_000054_VGA_ATI_LINEAR(x) (((x) & 0x1) << 3)
|
||||
#define G_000054_VGA_ATI_LINEAR(x) (((x) >> 3) & 0x1)
|
||||
#define C_000054_VGA_ATI_LINEAR 0xFFFFFFF7
|
||||
#define S_000054_VGA_128KAP_PAGING(x) (((x) & 0x1) << 4)
|
||||
#define G_000054_VGA_128KAP_PAGING(x) (((x) >> 4) & 0x1)
|
||||
#define C_000054_VGA_128KAP_PAGING 0xFFFFFFEF
|
||||
#define S_000054_VGA_TEXT_132(x) (((x) & 0x1) << 5)
|
||||
#define G_000054_VGA_TEXT_132(x) (((x) >> 5) & 0x1)
|
||||
#define C_000054_VGA_TEXT_132 0xFFFFFFDF
|
||||
#define S_000054_VGA_XCRT_CNT_EN(x) (((x) & 0x1) << 6)
|
||||
#define G_000054_VGA_XCRT_CNT_EN(x) (((x) >> 6) & 0x1)
|
||||
#define C_000054_VGA_XCRT_CNT_EN 0xFFFFFFBF
|
||||
#define S_000054_CRTC_HSYNC_DIS(x) (((x) & 0x1) << 8)
|
||||
#define G_000054_CRTC_HSYNC_DIS(x) (((x) >> 8) & 0x1)
|
||||
#define C_000054_CRTC_HSYNC_DIS 0xFFFFFEFF
|
||||
#define S_000054_CRTC_VSYNC_DIS(x) (((x) & 0x1) << 9)
|
||||
#define G_000054_CRTC_VSYNC_DIS(x) (((x) >> 9) & 0x1)
|
||||
#define C_000054_CRTC_VSYNC_DIS 0xFFFFFDFF
|
||||
#define S_000054_CRTC_DISPLAY_DIS(x) (((x) & 0x1) << 10)
|
||||
#define G_000054_CRTC_DISPLAY_DIS(x) (((x) >> 10) & 0x1)
|
||||
#define C_000054_CRTC_DISPLAY_DIS 0xFFFFFBFF
|
||||
#define S_000054_CRTC_SYNC_TRISTATE(x) (((x) & 0x1) << 11)
|
||||
#define G_000054_CRTC_SYNC_TRISTATE(x) (((x) >> 11) & 0x1)
|
||||
#define C_000054_CRTC_SYNC_TRISTATE 0xFFFFF7FF
|
||||
#define S_000054_CRTC_HSYNC_TRISTATE(x) (((x) & 0x1) << 12)
|
||||
#define G_000054_CRTC_HSYNC_TRISTATE(x) (((x) >> 12) & 0x1)
|
||||
#define C_000054_CRTC_HSYNC_TRISTATE 0xFFFFEFFF
|
||||
#define S_000054_CRTC_VSYNC_TRISTATE(x) (((x) & 0x1) << 13)
|
||||
#define G_000054_CRTC_VSYNC_TRISTATE(x) (((x) >> 13) & 0x1)
|
||||
#define C_000054_CRTC_VSYNC_TRISTATE 0xFFFFDFFF
|
||||
#define S_000054_CRT_ON(x) (((x) & 0x1) << 15)
|
||||
#define G_000054_CRT_ON(x) (((x) >> 15) & 0x1)
|
||||
#define C_000054_CRT_ON 0xFFFF7FFF
|
||||
#define S_000054_VGA_CUR_B_TEST(x) (((x) & 0x1) << 17)
|
||||
#define G_000054_VGA_CUR_B_TEST(x) (((x) >> 17) & 0x1)
|
||||
#define C_000054_VGA_CUR_B_TEST 0xFFFDFFFF
|
||||
#define S_000054_VGA_PACK_DIS(x) (((x) & 0x1) << 18)
|
||||
#define G_000054_VGA_PACK_DIS(x) (((x) >> 18) & 0x1)
|
||||
#define C_000054_VGA_PACK_DIS 0xFFFBFFFF
|
||||
#define S_000054_VGA_MEM_PS_EN(x) (((x) & 0x1) << 19)
|
||||
#define G_000054_VGA_MEM_PS_EN(x) (((x) >> 19) & 0x1)
|
||||
#define C_000054_VGA_MEM_PS_EN 0xFFF7FFFF
|
||||
#define S_000054_VCRTC_IDX_MASTER(x) (((x) & 0x7F) << 24)
|
||||
#define G_000054_VCRTC_IDX_MASTER(x) (((x) >> 24) & 0x7F)
|
||||
#define C_000054_VCRTC_IDX_MASTER 0x80FFFFFF
|
||||
#define R_00023C_DISPLAY_BASE_ADDR 0x00023C
|
||||
#define S_00023C_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_00023C_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_00023C_DISPLAY_BASE_ADDR 0x00000000
|
||||
#define R_000260_CUR_OFFSET 0x000260
|
||||
#define S_000260_CUR_OFFSET(x) (((x) & 0x7FFFFFF) << 0)
|
||||
#define G_000260_CUR_OFFSET(x) (((x) >> 0) & 0x7FFFFFF)
|
||||
#define C_000260_CUR_OFFSET 0xF8000000
|
||||
#define S_000260_CUR_LOCK(x) (((x) & 0x1) << 31)
|
||||
#define G_000260_CUR_LOCK(x) (((x) >> 31) & 0x1)
|
||||
#define C_000260_CUR_LOCK 0x7FFFFFFF
|
||||
#define R_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00033C
|
||||
#define S_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00000000
|
||||
#define R_000360_CUR2_OFFSET 0x000360
|
||||
#define S_000360_CUR2_OFFSET(x) (((x) & 0x7FFFFFF) << 0)
|
||||
#define G_000360_CUR2_OFFSET(x) (((x) >> 0) & 0x7FFFFFF)
|
||||
#define C_000360_CUR2_OFFSET 0xF8000000
|
||||
#define S_000360_CUR2_LOCK(x) (((x) & 0x1) << 31)
|
||||
#define G_000360_CUR2_LOCK(x) (((x) >> 31) & 0x1)
|
||||
#define C_000360_CUR2_LOCK 0x7FFFFFFF
|
||||
#define R_0003C0_GENMO_WT 0x0003C0
|
||||
#define S_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) & 0x1) << 0)
|
||||
#define G_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) >> 0) & 0x1)
|
||||
#define C_0003C0_GENMO_MONO_ADDRESS_B 0xFFFFFFFE
|
||||
#define S_0003C0_VGA_RAM_EN(x) (((x) & 0x1) << 1)
|
||||
#define G_0003C0_VGA_RAM_EN(x) (((x) >> 1) & 0x1)
|
||||
#define C_0003C0_VGA_RAM_EN 0xFFFFFFFD
|
||||
#define S_0003C0_VGA_CKSEL(x) (((x) & 0x3) << 2)
|
||||
#define G_0003C0_VGA_CKSEL(x) (((x) >> 2) & 0x3)
|
||||
#define C_0003C0_VGA_CKSEL 0xFFFFFFF3
|
||||
#define S_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) & 0x1) << 5)
|
||||
#define G_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) >> 5) & 0x1)
|
||||
#define C_0003C0_ODD_EVEN_MD_PGSEL 0xFFFFFFDF
|
||||
#define S_0003C0_VGA_HSYNC_POL(x) (((x) & 0x1) << 6)
|
||||
#define G_0003C0_VGA_HSYNC_POL(x) (((x) >> 6) & 0x1)
|
||||
#define C_0003C0_VGA_HSYNC_POL 0xFFFFFFBF
|
||||
#define S_0003C0_VGA_VSYNC_POL(x) (((x) & 0x1) << 7)
|
||||
#define G_0003C0_VGA_VSYNC_POL(x) (((x) >> 7) & 0x1)
|
||||
#define C_0003C0_VGA_VSYNC_POL 0xFFFFFF7F
|
||||
#define R_0003F8_CRTC2_GEN_CNTL 0x0003F8
|
||||
#define S_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) & 0x1) << 0)
|
||||
#define G_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) >> 0) & 0x1)
|
||||
#define C_0003F8_CRTC2_DBL_SCAN_EN 0xFFFFFFFE
|
||||
#define S_0003F8_CRTC2_INTERLACE_EN(x) (((x) & 0x1) << 1)
|
||||
#define G_0003F8_CRTC2_INTERLACE_EN(x) (((x) >> 1) & 0x1)
|
||||
#define C_0003F8_CRTC2_INTERLACE_EN 0xFFFFFFFD
|
||||
#define S_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) & 0x1) << 4)
|
||||
#define G_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) >> 4) & 0x1)
|
||||
#define C_0003F8_CRTC2_SYNC_TRISTATE 0xFFFFFFEF
|
||||
#define S_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) & 0x1) << 5)
|
||||
#define G_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) >> 5) & 0x1)
|
||||
#define C_0003F8_CRTC2_HSYNC_TRISTATE 0xFFFFFFDF
|
||||
#define S_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) & 0x1) << 6)
|
||||
#define G_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) >> 6) & 0x1)
|
||||
#define C_0003F8_CRTC2_VSYNC_TRISTATE 0xFFFFFFBF
|
||||
#define S_0003F8_CRT2_ON(x) (((x) & 0x1) << 7)
|
||||
#define G_0003F8_CRT2_ON(x) (((x) >> 7) & 0x1)
|
||||
#define C_0003F8_CRT2_ON 0xFFFFFF7F
|
||||
#define S_0003F8_CRTC2_PIX_WIDTH(x) (((x) & 0xF) << 8)
|
||||
#define G_0003F8_CRTC2_PIX_WIDTH(x) (((x) >> 8) & 0xF)
|
||||
#define C_0003F8_CRTC2_PIX_WIDTH 0xFFFFF0FF
|
||||
#define S_0003F8_CRTC2_ICON_EN(x) (((x) & 0x1) << 15)
|
||||
#define G_0003F8_CRTC2_ICON_EN(x) (((x) >> 15) & 0x1)
|
||||
#define C_0003F8_CRTC2_ICON_EN 0xFFFF7FFF
|
||||
#define S_0003F8_CRTC2_CUR_EN(x) (((x) & 0x1) << 16)
|
||||
#define G_0003F8_CRTC2_CUR_EN(x) (((x) >> 16) & 0x1)
|
||||
#define C_0003F8_CRTC2_CUR_EN 0xFFFEFFFF
|
||||
#define S_0003F8_CRTC2_CUR_MODE(x) (((x) & 0x7) << 20)
|
||||
#define G_0003F8_CRTC2_CUR_MODE(x) (((x) >> 20) & 0x7)
|
||||
#define C_0003F8_CRTC2_CUR_MODE 0xFF8FFFFF
|
||||
#define S_0003F8_CRTC2_DISPLAY_DIS(x) (((x) & 0x1) << 23)
|
||||
#define G_0003F8_CRTC2_DISPLAY_DIS(x) (((x) >> 23) & 0x1)
|
||||
#define C_0003F8_CRTC2_DISPLAY_DIS 0xFF7FFFFF
|
||||
#define S_0003F8_CRTC2_EN(x) (((x) & 0x1) << 25)
|
||||
#define G_0003F8_CRTC2_EN(x) (((x) >> 25) & 0x1)
|
||||
#define C_0003F8_CRTC2_EN 0xFDFFFFFF
|
||||
#define S_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) & 0x1) << 26)
|
||||
#define G_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1)
|
||||
#define C_0003F8_CRTC2_DISP_REQ_EN_B 0xFBFFFFFF
|
||||
#define S_0003F8_CRTC2_C_SYNC_EN(x) (((x) & 0x1) << 27)
|
||||
#define G_0003F8_CRTC2_C_SYNC_EN(x) (((x) >> 27) & 0x1)
|
||||
#define C_0003F8_CRTC2_C_SYNC_EN 0xF7FFFFFF
|
||||
#define S_0003F8_CRTC2_HSYNC_DIS(x) (((x) & 0x1) << 28)
|
||||
#define G_0003F8_CRTC2_HSYNC_DIS(x) (((x) >> 28) & 0x1)
|
||||
#define C_0003F8_CRTC2_HSYNC_DIS 0xEFFFFFFF
|
||||
#define S_0003F8_CRTC2_VSYNC_DIS(x) (((x) & 0x1) << 29)
|
||||
#define G_0003F8_CRTC2_VSYNC_DIS(x) (((x) >> 29) & 0x1)
|
||||
#define C_0003F8_CRTC2_VSYNC_DIS 0xDFFFFFFF
|
||||
#define R_000420_OV0_SCALE_CNTL 0x000420
|
||||
#define S_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) & 0x1) << 1)
|
||||
#define G_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) >> 1) & 0x1)
|
||||
#define C_000420_OV0_NO_READ_BEHIND_SCAN 0xFFFFFFFD
|
||||
#define S_000420_OV0_HORZ_PICK_NEAREST(x) (((x) & 0x1) << 2)
|
||||
#define G_000420_OV0_HORZ_PICK_NEAREST(x) (((x) >> 2) & 0x1)
|
||||
#define C_000420_OV0_HORZ_PICK_NEAREST 0xFFFFFFFB
|
||||
#define S_000420_OV0_VERT_PICK_NEAREST(x) (((x) & 0x1) << 3)
|
||||
#define G_000420_OV0_VERT_PICK_NEAREST(x) (((x) >> 3) & 0x1)
|
||||
#define C_000420_OV0_VERT_PICK_NEAREST 0xFFFFFFF7
|
||||
#define S_000420_OV0_SIGNED_UV(x) (((x) & 0x1) << 4)
|
||||
#define G_000420_OV0_SIGNED_UV(x) (((x) >> 4) & 0x1)
|
||||
#define C_000420_OV0_SIGNED_UV 0xFFFFFFEF
|
||||
#define S_000420_OV0_GAMMA_SEL(x) (((x) & 0x7) << 5)
|
||||
#define G_000420_OV0_GAMMA_SEL(x) (((x) >> 5) & 0x7)
|
||||
#define C_000420_OV0_GAMMA_SEL 0xFFFFFF1F
|
||||
#define S_000420_OV0_SURFACE_FORMAT(x) (((x) & 0xF) << 8)
|
||||
#define G_000420_OV0_SURFACE_FORMAT(x) (((x) >> 8) & 0xF)
|
||||
#define C_000420_OV0_SURFACE_FORMAT 0xFFFFF0FF
|
||||
#define S_000420_OV0_ADAPTIVE_DEINT(x) (((x) & 0x1) << 12)
|
||||
#define G_000420_OV0_ADAPTIVE_DEINT(x) (((x) >> 12) & 0x1)
|
||||
#define C_000420_OV0_ADAPTIVE_DEINT 0xFFFFEFFF
|
||||
#define S_000420_OV0_CRTC_SEL(x) (((x) & 0x1) << 14)
|
||||
#define G_000420_OV0_CRTC_SEL(x) (((x) >> 14) & 0x1)
|
||||
#define C_000420_OV0_CRTC_SEL 0xFFFFBFFF
|
||||
#define S_000420_OV0_BURST_PER_PLANE(x) (((x) & 0x7F) << 16)
|
||||
#define G_000420_OV0_BURST_PER_PLANE(x) (((x) >> 16) & 0x7F)
|
||||
#define C_000420_OV0_BURST_PER_PLANE 0xFF80FFFF
|
||||
#define S_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) & 0x1) << 24)
|
||||
#define G_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) >> 24) & 0x1)
|
||||
#define C_000420_OV0_DOUBLE_BUFFER_REGS 0xFEFFFFFF
|
||||
#define S_000420_OV0_BANDWIDTH(x) (((x) & 0x1) << 26)
|
||||
#define G_000420_OV0_BANDWIDTH(x) (((x) >> 26) & 0x1)
|
||||
#define C_000420_OV0_BANDWIDTH 0xFBFFFFFF
|
||||
#define S_000420_OV0_LIN_TRANS_BYPASS(x) (((x) & 0x1) << 28)
|
||||
#define G_000420_OV0_LIN_TRANS_BYPASS(x) (((x) >> 28) & 0x1)
|
||||
#define C_000420_OV0_LIN_TRANS_BYPASS 0xEFFFFFFF
|
||||
#define S_000420_OV0_INT_EMU(x) (((x) & 0x1) << 29)
|
||||
#define G_000420_OV0_INT_EMU(x) (((x) >> 29) & 0x1)
|
||||
#define C_000420_OV0_INT_EMU 0xDFFFFFFF
|
||||
#define S_000420_OV0_OVERLAY_EN(x) (((x) & 0x1) << 30)
|
||||
#define G_000420_OV0_OVERLAY_EN(x) (((x) >> 30) & 0x1)
|
||||
#define C_000420_OV0_OVERLAY_EN 0xBFFFFFFF
|
||||
#define S_000420_OV0_SOFT_RESET(x) (((x) & 0x1) << 31)
|
||||
#define G_000420_OV0_SOFT_RESET(x) (((x) >> 31) & 0x1)
|
||||
#define C_000420_OV0_SOFT_RESET 0x7FFFFFFF
|
||||
#define R_00070C_CP_RB_RPTR_ADDR 0x00070C
|
||||
#define S_00070C_RB_RPTR_SWAP(x) (((x) & 0x3) << 0)
|
||||
#define G_00070C_RB_RPTR_SWAP(x) (((x) >> 0) & 0x3)
|
||||
#define C_00070C_RB_RPTR_SWAP 0xFFFFFFFC
|
||||
#define S_00070C_RB_RPTR_ADDR(x) (((x) & 0x3FFFFFFF) << 2)
|
||||
#define G_00070C_RB_RPTR_ADDR(x) (((x) >> 2) & 0x3FFFFFFF)
|
||||
#define C_00070C_RB_RPTR_ADDR 0x00000003
|
||||
#define R_000740_CP_CSQ_CNTL 0x000740
|
||||
#define S_000740_CSQ_CNT_PRIMARY(x) (((x) & 0xFF) << 0)
|
||||
#define G_000740_CSQ_CNT_PRIMARY(x) (((x) >> 0) & 0xFF)
|
||||
#define C_000740_CSQ_CNT_PRIMARY 0xFFFFFF00
|
||||
#define S_000740_CSQ_CNT_INDIRECT(x) (((x) & 0xFF) << 8)
|
||||
#define G_000740_CSQ_CNT_INDIRECT(x) (((x) >> 8) & 0xFF)
|
||||
#define C_000740_CSQ_CNT_INDIRECT 0xFFFF00FF
|
||||
#define S_000740_CSQ_MODE(x) (((x) & 0xF) << 28)
|
||||
#define G_000740_CSQ_MODE(x) (((x) >> 28) & 0xF)
|
||||
#define C_000740_CSQ_MODE 0x0FFFFFFF
|
||||
#define R_000770_SCRATCH_UMSK 0x000770
|
||||
#define S_000770_SCRATCH_UMSK(x) (((x) & 0x3F) << 0)
|
||||
#define G_000770_SCRATCH_UMSK(x) (((x) >> 0) & 0x3F)
|
||||
#define C_000770_SCRATCH_UMSK 0xFFFFFFC0
|
||||
#define S_000770_SCRATCH_SWAP(x) (((x) & 0x3) << 16)
|
||||
#define G_000770_SCRATCH_SWAP(x) (((x) >> 16) & 0x3)
|
||||
#define C_000770_SCRATCH_SWAP 0xFFFCFFFF
|
||||
#define R_000774_SCRATCH_ADDR 0x000774
|
||||
#define S_000774_SCRATCH_ADDR(x) (((x) & 0x7FFFFFF) << 5)
|
||||
#define G_000774_SCRATCH_ADDR(x) (((x) >> 5) & 0x7FFFFFF)
|
||||
#define C_000774_SCRATCH_ADDR 0x0000001F
|
||||
#define R_000E40_RBBM_STATUS 0x000E40
|
||||
#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
|
||||
#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
|
||||
#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
|
||||
#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
|
||||
#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
|
||||
#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
|
||||
#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
|
||||
#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
|
||||
#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
|
||||
#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
|
||||
#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
|
||||
#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
|
||||
#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
|
||||
#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
|
||||
#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
|
||||
#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
|
||||
#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
|
||||
#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
|
||||
#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
|
||||
#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
|
||||
#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
|
||||
#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
|
||||
#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
|
||||
#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
|
||||
#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
|
||||
#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
|
||||
#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
|
||||
#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
|
||||
#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
|
||||
#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
|
||||
#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
|
||||
#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
|
||||
#define C_000E40_E2_BUSY 0xFFFDFFFF
|
||||
#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
|
||||
#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
|
||||
#define C_000E40_RB2D_BUSY 0xFFFBFFFF
|
||||
#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
|
||||
#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
|
||||
#define C_000E40_RB3D_BUSY 0xFFF7FFFF
|
||||
#define S_000E40_SE_BUSY(x) (((x) & 0x1) << 20)
|
||||
#define G_000E40_SE_BUSY(x) (((x) >> 20) & 0x1)
|
||||
#define C_000E40_SE_BUSY 0xFFEFFFFF
|
||||
#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
|
||||
#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
|
||||
#define C_000E40_RE_BUSY 0xFFDFFFFF
|
||||
#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
|
||||
#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
|
||||
#define C_000E40_TAM_BUSY 0xFFBFFFFF
|
||||
#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
|
||||
#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
|
||||
#define C_000E40_TDM_BUSY 0xFF7FFFFF
|
||||
#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
|
||||
#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
|
||||
#define C_000E40_PB_BUSY 0xFEFFFFFF
|
||||
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
|
||||
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
|
||||
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
|
||||
|
||||
#endif
|
456
drivers/gpu/drm/radeon/r200.c
Normal file
456
drivers/gpu/drm/radeon/r200.c
Normal file
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
* Copyright 2008 Advanced Micro Devices, Inc.
|
||||
* Copyright 2008 Red Hat Inc.
|
||||
* Copyright 2009 Jerome Glisse.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
|
||||
#include "r200_reg_safe.h"
|
||||
|
||||
#include "r100_track.h"
|
||||
|
||||
static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
|
||||
{
|
||||
int vtx_size, i;
|
||||
vtx_size = 2;
|
||||
|
||||
if (vtx_fmt_0 & R200_VTX_Z0)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_W0)
|
||||
vtx_size++;
|
||||
/* blend weight */
|
||||
if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
|
||||
vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
|
||||
if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_N0)
|
||||
vtx_size += 3;
|
||||
if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_SHININESS_0)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_SHININESS_1)
|
||||
vtx_size++;
|
||||
for (i = 0; i < 8; i++) {
|
||||
int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
|
||||
switch (color_size) {
|
||||
case 0: break;
|
||||
case 1: vtx_size++; break;
|
||||
case 2: vtx_size += 3; break;
|
||||
case 3: vtx_size += 4; break;
|
||||
}
|
||||
}
|
||||
if (vtx_fmt_0 & R200_VTX_XY1)
|
||||
vtx_size += 2;
|
||||
if (vtx_fmt_0 & R200_VTX_Z1)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_W1)
|
||||
vtx_size++;
|
||||
if (vtx_fmt_0 & R200_VTX_N1)
|
||||
vtx_size += 3;
|
||||
return vtx_size;
|
||||
}
|
||||
|
||||
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
|
||||
{
|
||||
int vtx_size, i, tex_size;
|
||||
vtx_size = 0;
|
||||
for (i = 0; i < 6; i++) {
|
||||
tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
|
||||
if (tex_size > 4)
|
||||
continue;
|
||||
vtx_size += tex_size;
|
||||
}
|
||||
return vtx_size;
|
||||
}
|
||||
|
||||
int r200_packet0_check(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx, unsigned reg)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_cs_reloc *reloc;
|
||||
struct r100_cs_track *track;
|
||||
volatile uint32_t *ib;
|
||||
uint32_t tmp;
|
||||
int r;
|
||||
int i;
|
||||
int face;
|
||||
u32 tile_flags = 0;
|
||||
|
||||
ib = p->ib->ptr;
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
track = (struct r100_cs_track *)p->track;
|
||||
|
||||
switch (reg) {
|
||||
case RADEON_CRTC_GUI_TRIG_VLINE:
|
||||
r = r100_cs_packet_parse_vline(p);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
/* FIXME: only allow PACKET3 blit? easier to check for out of
|
||||
* range access */
|
||||
case RADEON_DST_PITCH_OFFSET:
|
||||
case RADEON_SRC_PITCH_OFFSET:
|
||||
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
|
||||
if (r)
|
||||
return r;
|
||||
break;
|
||||
case RADEON_RB3D_DEPTHOFFSET:
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
track->zb.robj = reloc->robj;
|
||||
track->zb.offset = ib_chunk->kdata[idx];
|
||||
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
|
||||
break;
|
||||
case RADEON_RB3D_COLOROFFSET:
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
track->cb[0].robj = reloc->robj;
|
||||
track->cb[0].offset = ib_chunk->kdata[idx];
|
||||
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
|
||||
break;
|
||||
case R200_PP_TXOFFSET_0:
|
||||
case R200_PP_TXOFFSET_1:
|
||||
case R200_PP_TXOFFSET_2:
|
||||
case R200_PP_TXOFFSET_3:
|
||||
case R200_PP_TXOFFSET_4:
|
||||
case R200_PP_TXOFFSET_5:
|
||||
i = (reg - R200_PP_TXOFFSET_0) / 24;
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
|
||||
track->textures[i].robj = reloc->robj;
|
||||
break;
|
||||
case R200_PP_CUBIC_OFFSET_F1_0:
|
||||
case R200_PP_CUBIC_OFFSET_F2_0:
|
||||
case R200_PP_CUBIC_OFFSET_F3_0:
|
||||
case R200_PP_CUBIC_OFFSET_F4_0:
|
||||
case R200_PP_CUBIC_OFFSET_F5_0:
|
||||
case R200_PP_CUBIC_OFFSET_F1_1:
|
||||
case R200_PP_CUBIC_OFFSET_F2_1:
|
||||
case R200_PP_CUBIC_OFFSET_F3_1:
|
||||
case R200_PP_CUBIC_OFFSET_F4_1:
|
||||
case R200_PP_CUBIC_OFFSET_F5_1:
|
||||
case R200_PP_CUBIC_OFFSET_F1_2:
|
||||
case R200_PP_CUBIC_OFFSET_F2_2:
|
||||
case R200_PP_CUBIC_OFFSET_F3_2:
|
||||
case R200_PP_CUBIC_OFFSET_F4_2:
|
||||
case R200_PP_CUBIC_OFFSET_F5_2:
|
||||
case R200_PP_CUBIC_OFFSET_F1_3:
|
||||
case R200_PP_CUBIC_OFFSET_F2_3:
|
||||
case R200_PP_CUBIC_OFFSET_F3_3:
|
||||
case R200_PP_CUBIC_OFFSET_F4_3:
|
||||
case R200_PP_CUBIC_OFFSET_F5_3:
|
||||
case R200_PP_CUBIC_OFFSET_F1_4:
|
||||
case R200_PP_CUBIC_OFFSET_F2_4:
|
||||
case R200_PP_CUBIC_OFFSET_F3_4:
|
||||
case R200_PP_CUBIC_OFFSET_F4_4:
|
||||
case R200_PP_CUBIC_OFFSET_F5_4:
|
||||
case R200_PP_CUBIC_OFFSET_F1_5:
|
||||
case R200_PP_CUBIC_OFFSET_F2_5:
|
||||
case R200_PP_CUBIC_OFFSET_F3_5:
|
||||
case R200_PP_CUBIC_OFFSET_F4_5:
|
||||
case R200_PP_CUBIC_OFFSET_F5_5:
|
||||
i = (reg - R200_PP_TXOFFSET_0) / 24;
|
||||
face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
track->textures[i].cube_info[face - 1].offset = ib_chunk->kdata[idx];
|
||||
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
|
||||
track->textures[i].cube_info[face - 1].robj = reloc->robj;
|
||||
break;
|
||||
case RADEON_RE_WIDTH_HEIGHT:
|
||||
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF);
|
||||
break;
|
||||
case RADEON_RB3D_COLORPITCH:
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
|
||||
tile_flags |= RADEON_COLOR_TILE_ENABLE;
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
|
||||
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
|
||||
|
||||
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
|
||||
tmp |= tile_flags;
|
||||
ib[idx] = tmp;
|
||||
|
||||
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK;
|
||||
break;
|
||||
case RADEON_RB3D_DEPTHPITCH:
|
||||
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK;
|
||||
break;
|
||||
case RADEON_RB3D_CNTL:
|
||||
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 11:
|
||||
case 12:
|
||||
track->cb[0].cpp = 1;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 15:
|
||||
track->cb[0].cpp = 2;
|
||||
break;
|
||||
case 6:
|
||||
track->cb[0].cpp = 4;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Invalid color buffer format (%d) !\n",
|
||||
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ib_chunk->kdata[idx] & RADEON_DEPTHXY_OFFSET_ENABLE) {
|
||||
DRM_ERROR("No support for depth xy offset in kms\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE);
|
||||
break;
|
||||
case RADEON_RB3D_ZSTENCILCNTL:
|
||||
switch (ib_chunk->kdata[idx] & 0xf) {
|
||||
case 0:
|
||||
track->zb.cpp = 2;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 9:
|
||||
case 11:
|
||||
track->zb.cpp = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RADEON_RB3D_ZPASS_ADDR:
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return r;
|
||||
}
|
||||
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
|
||||
break;
|
||||
case RADEON_PP_CNTL:
|
||||
{
|
||||
uint32_t temp = ib_chunk->kdata[idx] >> 4;
|
||||
for (i = 0; i < track->num_texture; i++)
|
||||
track->textures[i].enabled = !!(temp & (1 << i));
|
||||
}
|
||||
break;
|
||||
case RADEON_SE_VF_CNTL:
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx];
|
||||
break;
|
||||
case 0x210c:
|
||||
/* VAP_VF_MAX_VTX_INDX */
|
||||
track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
|
||||
break;
|
||||
case R200_SE_VTX_FMT_0:
|
||||
track->vtx_size = r200_get_vtx_size_0(ib_chunk->kdata[idx]);
|
||||
break;
|
||||
case R200_SE_VTX_FMT_1:
|
||||
track->vtx_size += r200_get_vtx_size_1(ib_chunk->kdata[idx]);
|
||||
break;
|
||||
case R200_PP_TXSIZE_0:
|
||||
case R200_PP_TXSIZE_1:
|
||||
case R200_PP_TXSIZE_2:
|
||||
case R200_PP_TXSIZE_3:
|
||||
case R200_PP_TXSIZE_4:
|
||||
case R200_PP_TXSIZE_5:
|
||||
i = (reg - R200_PP_TXSIZE_0) / 32;
|
||||
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1;
|
||||
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
|
||||
break;
|
||||
case R200_PP_TXPITCH_0:
|
||||
case R200_PP_TXPITCH_1:
|
||||
case R200_PP_TXPITCH_2:
|
||||
case R200_PP_TXPITCH_3:
|
||||
case R200_PP_TXPITCH_4:
|
||||
case R200_PP_TXPITCH_5:
|
||||
i = (reg - R200_PP_TXPITCH_0) / 32;
|
||||
track->textures[i].pitch = ib_chunk->kdata[idx] + 32;
|
||||
break;
|
||||
case R200_PP_TXFILTER_0:
|
||||
case R200_PP_TXFILTER_1:
|
||||
case R200_PP_TXFILTER_2:
|
||||
case R200_PP_TXFILTER_3:
|
||||
case R200_PP_TXFILTER_4:
|
||||
case R200_PP_TXFILTER_5:
|
||||
i = (reg - R200_PP_TXFILTER_0) / 32;
|
||||
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & R200_MAX_MIP_LEVEL_MASK)
|
||||
>> R200_MAX_MIP_LEVEL_SHIFT);
|
||||
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7;
|
||||
if (tmp == 2 || tmp == 6)
|
||||
track->textures[i].roundup_w = false;
|
||||
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7;
|
||||
if (tmp == 2 || tmp == 6)
|
||||
track->textures[i].roundup_h = false;
|
||||
break;
|
||||
case R200_PP_TXMULTI_CTL_0:
|
||||
case R200_PP_TXMULTI_CTL_1:
|
||||
case R200_PP_TXMULTI_CTL_2:
|
||||
case R200_PP_TXMULTI_CTL_3:
|
||||
case R200_PP_TXMULTI_CTL_4:
|
||||
case R200_PP_TXMULTI_CTL_5:
|
||||
i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
|
||||
break;
|
||||
case R200_PP_TXFORMAT_X_0:
|
||||
case R200_PP_TXFORMAT_X_1:
|
||||
case R200_PP_TXFORMAT_X_2:
|
||||
case R200_PP_TXFORMAT_X_3:
|
||||
case R200_PP_TXFORMAT_X_4:
|
||||
case R200_PP_TXFORMAT_X_5:
|
||||
i = (reg - R200_PP_TXFORMAT_X_0) / 32;
|
||||
track->textures[i].txdepth = ib_chunk->kdata[idx] & 0x7;
|
||||
tmp = (ib_chunk->kdata[idx] >> 16) & 0x3;
|
||||
/* 2D, 3D, CUBE */
|
||||
switch (tmp) {
|
||||
case 0:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
track->textures[i].tex_coord_type = 0;
|
||||
break;
|
||||
case 1:
|
||||
track->textures[i].tex_coord_type = 1;
|
||||
break;
|
||||
case 2:
|
||||
track->textures[i].tex_coord_type = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case R200_PP_TXFORMAT_0:
|
||||
case R200_PP_TXFORMAT_1:
|
||||
case R200_PP_TXFORMAT_2:
|
||||
case R200_PP_TXFORMAT_3:
|
||||
case R200_PP_TXFORMAT_4:
|
||||
case R200_PP_TXFORMAT_5:
|
||||
i = (reg - R200_PP_TXFORMAT_0) / 32;
|
||||
if (ib_chunk->kdata[idx] & R200_TXFORMAT_NON_POWER2) {
|
||||
track->textures[i].use_pitch = 1;
|
||||
} else {
|
||||
track->textures[i].use_pitch = 0;
|
||||
track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
|
||||
track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
|
||||
}
|
||||
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) {
|
||||
case R200_TXFORMAT_I8:
|
||||
case R200_TXFORMAT_RGB332:
|
||||
case R200_TXFORMAT_Y8:
|
||||
track->textures[i].cpp = 1;
|
||||
break;
|
||||
case R200_TXFORMAT_DXT1:
|
||||
case R200_TXFORMAT_AI88:
|
||||
case R200_TXFORMAT_ARGB1555:
|
||||
case R200_TXFORMAT_RGB565:
|
||||
case R200_TXFORMAT_ARGB4444:
|
||||
case R200_TXFORMAT_VYUY422:
|
||||
case R200_TXFORMAT_YVYU422:
|
||||
case R200_TXFORMAT_LDVDU655:
|
||||
case R200_TXFORMAT_DVDU88:
|
||||
case R200_TXFORMAT_AVYU4444:
|
||||
track->textures[i].cpp = 2;
|
||||
break;
|
||||
case R200_TXFORMAT_ARGB8888:
|
||||
case R200_TXFORMAT_RGBA8888:
|
||||
case R200_TXFORMAT_ABGR8888:
|
||||
case R200_TXFORMAT_BGR111110:
|
||||
case R200_TXFORMAT_LDVDU8888:
|
||||
case R200_TXFORMAT_DXT23:
|
||||
case R200_TXFORMAT_DXT45:
|
||||
track->textures[i].cpp = 4;
|
||||
break;
|
||||
}
|
||||
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf);
|
||||
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf);
|
||||
break;
|
||||
case R200_PP_CUBIC_FACES_0:
|
||||
case R200_PP_CUBIC_FACES_1:
|
||||
case R200_PP_CUBIC_FACES_2:
|
||||
case R200_PP_CUBIC_FACES_3:
|
||||
case R200_PP_CUBIC_FACES_4:
|
||||
case R200_PP_CUBIC_FACES_5:
|
||||
tmp = ib_chunk->kdata[idx];
|
||||
i = (reg - R200_PP_CUBIC_FACES_0) / 32;
|
||||
for (face = 0; face < 4; face++) {
|
||||
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
|
||||
track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
|
||||
reg, idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r200_init(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
|
||||
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
|
||||
return 0;
|
||||
}
|
|
@ -31,7 +31,10 @@
|
|||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_share.h"
|
||||
#include "r100_track.h"
|
||||
#include "r300d.h"
|
||||
|
||||
#include "r300_reg_safe.h"
|
||||
|
||||
/* r300,r350,rv350,rv370,rv380 depends on : */
|
||||
void r100_hdp_reset(struct radeon_device *rdev);
|
||||
|
@ -39,7 +42,6 @@ int r100_cp_reset(struct radeon_device *rdev);
|
|||
int r100_rb2d_reset(struct radeon_device *rdev);
|
||||
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
|
||||
int r100_pci_gart_enable(struct radeon_device *rdev);
|
||||
void r100_pci_gart_disable(struct radeon_device *rdev);
|
||||
void r100_mc_setup(struct radeon_device *rdev);
|
||||
void r100_mc_disable_clients(struct radeon_device *rdev);
|
||||
int r100_gui_wait_for_idle(struct radeon_device *rdev);
|
||||
|
@ -47,14 +49,10 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p,
|
|||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx);
|
||||
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
|
||||
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc);
|
||||
int r100_cs_parse_packet0(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
const unsigned *auth, unsigned n,
|
||||
radeon_packet0_check_t check);
|
||||
void r100_cs_dump_packet(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt);
|
||||
int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
struct radeon_object *robj);
|
||||
|
@ -87,26 +85,57 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
|
|||
mb();
|
||||
}
|
||||
|
||||
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
|
||||
{
|
||||
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
|
||||
|
||||
if (i < 0 || i > rdev->gart.num_gpu_pages) {
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = (lower_32_bits(addr) >> 8) |
|
||||
((upper_32_bits(addr) & 0xff) << 24) |
|
||||
0xc;
|
||||
/* on x86 we want this to be CPU endian, on powerpc
|
||||
* on powerpc without HW swappers, it'll get swapped on way
|
||||
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
|
||||
writel(addr, ((void __iomem *)ptr) + (i * 4));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rv370_pcie_gart_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (rdev->gart.table.vram.robj) {
|
||||
WARN(1, "RV370 PCIE GART already initialized.\n");
|
||||
return 0;
|
||||
}
|
||||
/* Initialize common gart structure */
|
||||
r = radeon_gart_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
r = rv370_debugfs_pcie_gart_info_init(rdev);
|
||||
if (r)
|
||||
DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
|
||||
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
|
||||
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
|
||||
return radeon_gart_table_vram_alloc(rdev);
|
||||
}
|
||||
|
||||
int rv370_pcie_gart_enable(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t table_addr;
|
||||
uint32_t tmp;
|
||||
int r;
|
||||
|
||||
/* Initialize common gart structure */
|
||||
r = radeon_gart_init(rdev);
|
||||
if (r) {
|
||||
if (rdev->gart.table.vram.robj == NULL) {
|
||||
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = radeon_gart_table_vram_pin(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
r = rv370_debugfs_pcie_gart_info_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
|
||||
}
|
||||
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
|
||||
r = radeon_gart_table_vram_alloc(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* discard memory request outside of configured range */
|
||||
tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
|
||||
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
|
||||
|
@ -128,7 +157,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
|
|||
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
|
||||
rv370_pcie_gart_tlb_flush(rdev);
|
||||
DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
|
||||
rdev->mc.gtt_size >> 20, table_addr);
|
||||
(unsigned)(rdev->mc.gtt_size >> 20), table_addr);
|
||||
rdev->gart.ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
@ -146,45 +175,13 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
|
|||
}
|
||||
}
|
||||
|
||||
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
|
||||
void rv370_pcie_gart_fini(struct radeon_device *rdev)
|
||||
{
|
||||
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
|
||||
|
||||
if (i < 0 || i > rdev->gart.num_gpu_pages) {
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = (lower_32_bits(addr) >> 8) |
|
||||
((upper_32_bits(addr) & 0xff) << 24) |
|
||||
0xc;
|
||||
/* on x86 we want this to be CPU endian, on powerpc
|
||||
* on powerpc without HW swappers, it'll get swapped on way
|
||||
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
|
||||
writel(addr, ((void __iomem *)ptr) + (i * 4));
|
||||
return 0;
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
radeon_gart_table_vram_free(rdev);
|
||||
radeon_gart_fini(rdev);
|
||||
}
|
||||
|
||||
int r300_gart_enable(struct radeon_device *rdev)
|
||||
{
|
||||
#if __OS_HAS_AGP
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
if (rdev->family > CHIP_RV350) {
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
} else {
|
||||
r100_pci_gart_disable(rdev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
|
||||
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
|
||||
return rv370_pcie_gart_enable(rdev);
|
||||
}
|
||||
return r100_pci_gart_enable(rdev);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MC
|
||||
*/
|
||||
|
@ -232,14 +229,6 @@ int r300_mc_init(struct radeon_device *rdev)
|
|||
|
||||
void r300_mc_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
radeon_gart_table_vram_free(rdev);
|
||||
} else {
|
||||
r100_pci_gart_disable(rdev);
|
||||
radeon_gart_table_ram_free(rdev);
|
||||
}
|
||||
radeon_gart_fini(rdev);
|
||||
}
|
||||
|
||||
|
||||
|
@ -704,307 +693,13 @@ int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
|
|||
/*
|
||||
* CS functions
|
||||
*/
|
||||
struct r300_cs_track_cb {
|
||||
struct radeon_object *robj;
|
||||
unsigned pitch;
|
||||
unsigned cpp;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
struct r300_cs_track_array {
|
||||
struct radeon_object *robj;
|
||||
unsigned esize;
|
||||
};
|
||||
|
||||
struct r300_cs_track_texture {
|
||||
struct radeon_object *robj;
|
||||
unsigned pitch;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned num_levels;
|
||||
unsigned cpp;
|
||||
unsigned tex_coord_type;
|
||||
unsigned txdepth;
|
||||
unsigned width_11;
|
||||
unsigned height_11;
|
||||
bool use_pitch;
|
||||
bool enabled;
|
||||
bool roundup_w;
|
||||
bool roundup_h;
|
||||
};
|
||||
|
||||
struct r300_cs_track {
|
||||
unsigned num_cb;
|
||||
unsigned maxy;
|
||||
unsigned vtx_size;
|
||||
unsigned vap_vf_cntl;
|
||||
unsigned immd_dwords;
|
||||
unsigned num_arrays;
|
||||
unsigned max_indx;
|
||||
struct r300_cs_track_array arrays[11];
|
||||
struct r300_cs_track_cb cb[4];
|
||||
struct r300_cs_track_cb zb;
|
||||
struct r300_cs_track_texture textures[16];
|
||||
bool z_enabled;
|
||||
};
|
||||
|
||||
static inline void r300_cs_track_texture_print(struct r300_cs_track_texture *t)
|
||||
{
|
||||
DRM_ERROR("pitch %d\n", t->pitch);
|
||||
DRM_ERROR("width %d\n", t->width);
|
||||
DRM_ERROR("height %d\n", t->height);
|
||||
DRM_ERROR("num levels %d\n", t->num_levels);
|
||||
DRM_ERROR("depth %d\n", t->txdepth);
|
||||
DRM_ERROR("bpp %d\n", t->cpp);
|
||||
DRM_ERROR("coordinate type %d\n", t->tex_coord_type);
|
||||
DRM_ERROR("width round to power of 2 %d\n", t->roundup_w);
|
||||
DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
|
||||
}
|
||||
|
||||
static inline int r300_cs_track_texture_check(struct radeon_device *rdev,
|
||||
struct r300_cs_track *track)
|
||||
{
|
||||
struct radeon_object *robj;
|
||||
unsigned long size;
|
||||
unsigned u, i, w, h;
|
||||
|
||||
for (u = 0; u < 16; u++) {
|
||||
if (!track->textures[u].enabled)
|
||||
continue;
|
||||
robj = track->textures[u].robj;
|
||||
if (robj == NULL) {
|
||||
DRM_ERROR("No texture bound to unit %u\n", u);
|
||||
return -EINVAL;
|
||||
}
|
||||
size = 0;
|
||||
for (i = 0; i <= track->textures[u].num_levels; i++) {
|
||||
if (track->textures[u].use_pitch) {
|
||||
w = track->textures[u].pitch / (1 << i);
|
||||
} else {
|
||||
w = track->textures[u].width / (1 << i);
|
||||
if (rdev->family >= CHIP_RV515)
|
||||
w |= track->textures[u].width_11;
|
||||
if (track->textures[u].roundup_w)
|
||||
w = roundup_pow_of_two(w);
|
||||
}
|
||||
h = track->textures[u].height / (1 << i);
|
||||
if (rdev->family >= CHIP_RV515)
|
||||
h |= track->textures[u].height_11;
|
||||
if (track->textures[u].roundup_h)
|
||||
h = roundup_pow_of_two(h);
|
||||
size += w * h;
|
||||
}
|
||||
size *= track->textures[u].cpp;
|
||||
switch (track->textures[u].tex_coord_type) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
size *= (1 << track->textures[u].txdepth);
|
||||
break;
|
||||
case 2:
|
||||
size *= 6;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Invalid texture coordinate type %u for unit "
|
||||
"%u\n", track->textures[u].tex_coord_type, u);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (size > radeon_object_size(robj)) {
|
||||
DRM_ERROR("Texture of unit %u needs %lu bytes but is "
|
||||
"%lu\n", u, size, radeon_object_size(robj));
|
||||
r300_cs_track_texture_print(&track->textures[u]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned long size;
|
||||
unsigned prim_walk;
|
||||
unsigned nverts;
|
||||
|
||||
for (i = 0; i < track->num_cb; i++) {
|
||||
if (track->cb[i].robj == NULL) {
|
||||
DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
size = track->cb[i].pitch * track->cb[i].cpp * track->maxy;
|
||||
size += track->cb[i].offset;
|
||||
if (size > radeon_object_size(track->cb[i].robj)) {
|
||||
DRM_ERROR("[drm] Buffer too small for color buffer %d "
|
||||
"(need %lu have %lu) !\n", i, size,
|
||||
radeon_object_size(track->cb[i].robj));
|
||||
DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n",
|
||||
i, track->cb[i].pitch, track->cb[i].cpp,
|
||||
track->cb[i].offset, track->maxy);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (track->z_enabled) {
|
||||
if (track->zb.robj == NULL) {
|
||||
DRM_ERROR("[drm] No buffer for z buffer !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
size = track->zb.pitch * track->zb.cpp * track->maxy;
|
||||
size += track->zb.offset;
|
||||
if (size > radeon_object_size(track->zb.robj)) {
|
||||
DRM_ERROR("[drm] Buffer too small for z buffer "
|
||||
"(need %lu have %lu) !\n", size,
|
||||
radeon_object_size(track->zb.robj));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
|
||||
nverts = (track->vap_vf_cntl >> 16) & 0xFFFF;
|
||||
switch (prim_walk) {
|
||||
case 1:
|
||||
for (i = 0; i < track->num_arrays; i++) {
|
||||
size = track->arrays[i].esize * track->max_indx * 4;
|
||||
if (track->arrays[i].robj == NULL) {
|
||||
DRM_ERROR("(PW %u) Vertex array %u no buffer "
|
||||
"bound\n", prim_walk, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (size > radeon_object_size(track->arrays[i].robj)) {
|
||||
DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
|
||||
"have %lu dwords\n", prim_walk, i,
|
||||
size >> 2,
|
||||
radeon_object_size(track->arrays[i].robj) >> 2);
|
||||
DRM_ERROR("Max indices %u\n", track->max_indx);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (i = 0; i < track->num_arrays; i++) {
|
||||
size = track->arrays[i].esize * (nverts - 1) * 4;
|
||||
if (track->arrays[i].robj == NULL) {
|
||||
DRM_ERROR("(PW %u) Vertex array %u no buffer "
|
||||
"bound\n", prim_walk, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (size > radeon_object_size(track->arrays[i].robj)) {
|
||||
DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
|
||||
"have %lu dwords\n", prim_walk, i, size >> 2,
|
||||
radeon_object_size(track->arrays[i].robj) >> 2);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
size = track->vtx_size * nverts;
|
||||
if (size != track->immd_dwords) {
|
||||
DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n",
|
||||
track->immd_dwords, size);
|
||||
DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n",
|
||||
nverts, track->vtx_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n",
|
||||
prim_walk);
|
||||
return -EINVAL;
|
||||
}
|
||||
return r300_cs_track_texture_check(rdev, track);
|
||||
}
|
||||
|
||||
static inline void r300_cs_track_clear(struct r300_cs_track *track)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
track->num_cb = 4;
|
||||
track->maxy = 4096;
|
||||
for (i = 0; i < track->num_cb; i++) {
|
||||
track->cb[i].robj = NULL;
|
||||
track->cb[i].pitch = 8192;
|
||||
track->cb[i].cpp = 16;
|
||||
track->cb[i].offset = 0;
|
||||
}
|
||||
track->z_enabled = true;
|
||||
track->zb.robj = NULL;
|
||||
track->zb.pitch = 8192;
|
||||
track->zb.cpp = 4;
|
||||
track->zb.offset = 0;
|
||||
track->vtx_size = 0x7F;
|
||||
track->immd_dwords = 0xFFFFFFFFUL;
|
||||
track->num_arrays = 11;
|
||||
track->max_indx = 0x00FFFFFFUL;
|
||||
for (i = 0; i < track->num_arrays; i++) {
|
||||
track->arrays[i].robj = NULL;
|
||||
track->arrays[i].esize = 0x7F;
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
track->textures[i].pitch = 16536;
|
||||
track->textures[i].width = 16536;
|
||||
track->textures[i].height = 16536;
|
||||
track->textures[i].width_11 = 1 << 11;
|
||||
track->textures[i].height_11 = 1 << 11;
|
||||
track->textures[i].num_levels = 12;
|
||||
track->textures[i].txdepth = 16;
|
||||
track->textures[i].cpp = 64;
|
||||
track->textures[i].tex_coord_type = 1;
|
||||
track->textures[i].robj = NULL;
|
||||
/* CS IB emission code makes sure texture unit are disabled */
|
||||
track->textures[i].enabled = false;
|
||||
track->textures[i].roundup_w = true;
|
||||
track->textures[i].roundup_h = true;
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned r300_reg_safe_bm[159] = {
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
|
||||
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
|
||||
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
|
||||
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
|
||||
0x00000000, 0x0000C100, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x0003FC01, 0xFFFFFCF8, 0xFF800B19,
|
||||
};
|
||||
|
||||
static int r300_packet0_check(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx, unsigned reg)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_cs_reloc *reloc;
|
||||
struct r300_cs_track *track;
|
||||
struct r100_cs_track *track;
|
||||
volatile uint32_t *ib;
|
||||
uint32_t tmp, tile_flags = 0;
|
||||
unsigned i;
|
||||
|
@ -1012,7 +707,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
|
||||
ib = p->ib->ptr;
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
track = (struct r300_cs_track*)p->track;
|
||||
track = (struct r100_cs_track *)p->track;
|
||||
switch(reg) {
|
||||
case AVIVO_D1MODE_VLINE_START_END:
|
||||
case RADEON_CRTC_GUI_TRIG_VLINE:
|
||||
|
@ -1026,28 +721,9 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
break;
|
||||
case RADEON_DST_PITCH_OFFSET:
|
||||
case RADEON_SRC_PITCH_OFFSET:
|
||||
r = r100_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
|
||||
idx, reg);
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
tmp = ib_chunk->kdata[idx] & 0x003fffff;
|
||||
tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
|
||||
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
|
||||
tile_flags |= RADEON_DST_TILE_MACRO;
|
||||
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
|
||||
if (reg == RADEON_SRC_PITCH_OFFSET) {
|
||||
DRM_ERROR("Cannot src blit from microtiled surface\n");
|
||||
r100_cs_dump_packet(p, pkt);
|
||||
return -EINVAL;
|
||||
}
|
||||
tile_flags |= RADEON_DST_TILE_MICRO;
|
||||
}
|
||||
tmp |= tile_flags;
|
||||
ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
|
||||
break;
|
||||
case R300_RB3D_COLOROFFSET0:
|
||||
case R300_RB3D_COLOROFFSET1:
|
||||
|
@ -1256,42 +932,41 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
tmp = (ib_chunk->kdata[idx] >> 25) & 0x3;
|
||||
track->textures[i].tex_coord_type = tmp;
|
||||
switch ((ib_chunk->kdata[idx] & 0x1F)) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 5:
|
||||
case 18:
|
||||
case 20:
|
||||
case 21:
|
||||
case R300_TX_FORMAT_X8:
|
||||
case R300_TX_FORMAT_Y4X4:
|
||||
case R300_TX_FORMAT_Z3Y3X2:
|
||||
track->textures[i].cpp = 1;
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
case 6:
|
||||
case 7:
|
||||
case 10:
|
||||
case 11:
|
||||
case 19:
|
||||
case 22:
|
||||
case 24:
|
||||
case R300_TX_FORMAT_X16:
|
||||
case R300_TX_FORMAT_Y8X8:
|
||||
case R300_TX_FORMAT_Z5Y6X5:
|
||||
case R300_TX_FORMAT_Z6Y5X5:
|
||||
case R300_TX_FORMAT_W4Z4Y4X4:
|
||||
case R300_TX_FORMAT_W1Z5Y5X5:
|
||||
case R300_TX_FORMAT_DXT1:
|
||||
case R300_TX_FORMAT_D3DMFT_CxV8U8:
|
||||
case R300_TX_FORMAT_B8G8_B8G8:
|
||||
case R300_TX_FORMAT_G8R8_G8B8:
|
||||
track->textures[i].cpp = 2;
|
||||
break;
|
||||
case 4:
|
||||
case 8:
|
||||
case 9:
|
||||
case 12:
|
||||
case 13:
|
||||
case 23:
|
||||
case 25:
|
||||
case 27:
|
||||
case 30:
|
||||
case R300_TX_FORMAT_Y16X16:
|
||||
case R300_TX_FORMAT_Z11Y11X10:
|
||||
case R300_TX_FORMAT_Z10Y11X11:
|
||||
case R300_TX_FORMAT_W8Z8Y8X8:
|
||||
case R300_TX_FORMAT_W2Z10Y10X10:
|
||||
case 0x17:
|
||||
case R300_TX_FORMAT_FL_I32:
|
||||
case 0x1e:
|
||||
case R300_TX_FORMAT_DXT3:
|
||||
case R300_TX_FORMAT_DXT5:
|
||||
track->textures[i].cpp = 4;
|
||||
break;
|
||||
case 14:
|
||||
case 26:
|
||||
case 28:
|
||||
case R300_TX_FORMAT_W16Z16Y16X16:
|
||||
case R300_TX_FORMAT_FL_R16G16B16A16:
|
||||
case R300_TX_FORMAT_FL_I32A32:
|
||||
track->textures[i].cpp = 8;
|
||||
break;
|
||||
case 29:
|
||||
case R300_TX_FORMAT_FL_R32G32B32A32:
|
||||
track->textures[i].cpp = 16;
|
||||
break;
|
||||
default:
|
||||
|
@ -1319,11 +994,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
|
|||
case 0x443C:
|
||||
/* TX_FILTER0_[0-15] */
|
||||
i = (reg - 0x4400) >> 2;
|
||||
tmp = ib_chunk->kdata[idx] & 0x7;;
|
||||
tmp = ib_chunk->kdata[idx] & 0x7;
|
||||
if (tmp == 2 || tmp == 4 || tmp == 6) {
|
||||
track->textures[i].roundup_w = false;
|
||||
}
|
||||
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;;
|
||||
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;
|
||||
if (tmp == 2 || tmp == 4 || tmp == 6) {
|
||||
track->textures[i].roundup_h = false;
|
||||
}
|
||||
|
@ -1411,8 +1086,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
|
|||
struct radeon_cs_packet *pkt)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
|
||||
struct radeon_cs_reloc *reloc;
|
||||
struct r300_cs_track *track;
|
||||
struct r100_cs_track *track;
|
||||
volatile uint32_t *ib;
|
||||
unsigned idx;
|
||||
unsigned i, c;
|
||||
|
@ -1421,7 +1097,7 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
|
|||
ib = p->ib->ptr;
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
idx = pkt->idx + 1;
|
||||
track = (struct r300_cs_track*)p->track;
|
||||
track = (struct r100_cs_track *)p->track;
|
||||
switch(pkt->opcode) {
|
||||
case PACKET3_3D_LOAD_VBPNTR:
|
||||
c = ib_chunk->kdata[idx++] & 0x1F;
|
||||
|
@ -1488,7 +1164,7 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
|
|||
}
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx+1];
|
||||
track->immd_dwords = pkt->count - 1;
|
||||
r = r300_cs_track_check(p->rdev, track);
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
@ -1503,35 +1179,35 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
|
|||
}
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx];
|
||||
track->immd_dwords = pkt->count;
|
||||
r = r300_cs_track_check(p->rdev, track);
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_3D_DRAW_VBUF:
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
|
||||
r = r300_cs_track_check(p->rdev, track);
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_3D_DRAW_VBUF_2:
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx];
|
||||
r = r300_cs_track_check(p->rdev, track);
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_3D_DRAW_INDX:
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
|
||||
r = r300_cs_track_check(p->rdev, track);
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case PACKET3_3D_DRAW_INDX_2:
|
||||
track->vap_vf_cntl = ib_chunk->kdata[idx];
|
||||
r = r300_cs_track_check(p->rdev, track);
|
||||
r = r100_cs_track_check(p->rdev, track);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
@ -1548,11 +1224,12 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
|
|||
int r300_cs_parse(struct radeon_cs_parser *p)
|
||||
{
|
||||
struct radeon_cs_packet pkt;
|
||||
struct r300_cs_track track;
|
||||
struct r100_cs_track *track;
|
||||
int r;
|
||||
|
||||
r300_cs_track_clear(&track);
|
||||
p->track = &track;
|
||||
track = kzalloc(sizeof(*track), GFP_KERNEL);
|
||||
r100_cs_track_clear(p->rdev, track);
|
||||
p->track = track;
|
||||
do {
|
||||
r = r100_cs_packet_parse(p, &pkt, p->idx);
|
||||
if (r) {
|
||||
|
@ -1582,9 +1259,48 @@ int r300_cs_parse(struct radeon_cs_parser *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int r300_init(struct radeon_device *rdev)
|
||||
void r300_set_reg_safe(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
|
||||
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
|
||||
}
|
||||
|
||||
int r300_init(struct radeon_device *rdev)
|
||||
{
|
||||
r300_set_reg_safe(rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r300_mc_program(struct radeon_device *rdev)
|
||||
{
|
||||
struct r100_mc_save save;
|
||||
int r;
|
||||
|
||||
r = r100_debugfs_mc_info_init(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n");
|
||||
}
|
||||
|
||||
/* Stops all mc clients */
|
||||
r100_mc_stop(rdev, &save);
|
||||
if (rdev->flags & RADEON_IS_AGP) {
|
||||
WREG32(R_00014C_MC_AGP_LOCATION,
|
||||
S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) |
|
||||
S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
|
||||
WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
|
||||
WREG32(R_00015C_AGP_BASE_2,
|
||||
upper_32_bits(rdev->mc.agp_base) & 0xff);
|
||||
} else {
|
||||
WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF);
|
||||
WREG32(R_000170_AGP_BASE, 0);
|
||||
WREG32(R_00015C_AGP_BASE_2, 0);
|
||||
}
|
||||
/* Wait for mc idle */
|
||||
if (r300_mc_wait_for_idle(rdev))
|
||||
DRM_INFO("Failed to wait MC idle before programming MC.\n");
|
||||
/* Program MC, should be a 32bits limited address space */
|
||||
WREG32(R_000148_MC_FB_LOCATION,
|
||||
S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
|
||||
S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
|
||||
r100_mc_resume(rdev, &save);
|
||||
}
|
||||
|
|
|
@ -1,36 +0,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 R300_H
|
||||
#define R300_H
|
||||
|
||||
struct r300_asic {
|
||||
const unsigned *reg_safe_bm;
|
||||
unsigned reg_safe_bm_size;
|
||||
};
|
||||
|
||||
#endif
|
101
drivers/gpu/drm/radeon/r300d.h
Normal file
101
drivers/gpu/drm/radeon/r300d.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2008 Advanced Micro Devices, Inc.
|
||||
* Copyright 2008 Red Hat Inc.
|
||||
* Copyright 2009 Jerome Glisse.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#ifndef __R300D_H__
|
||||
#define __R300D_H__
|
||||
|
||||
#define CP_PACKET0 0x00000000
|
||||
#define PACKET0_BASE_INDEX_SHIFT 0
|
||||
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0)
|
||||
#define PACKET0_COUNT_SHIFT 16
|
||||
#define PACKET0_COUNT_MASK (0x3fff << 16)
|
||||
#define CP_PACKET1 0x40000000
|
||||
#define CP_PACKET2 0x80000000
|
||||
#define PACKET2_PAD_SHIFT 0
|
||||
#define PACKET2_PAD_MASK (0x3fffffff << 0)
|
||||
#define CP_PACKET3 0xC0000000
|
||||
#define PACKET3_IT_OPCODE_SHIFT 8
|
||||
#define PACKET3_IT_OPCODE_MASK (0xff << 8)
|
||||
#define PACKET3_COUNT_SHIFT 16
|
||||
#define PACKET3_COUNT_MASK (0x3fff << 16)
|
||||
/* PACKET3 op code */
|
||||
#define PACKET3_NOP 0x10
|
||||
#define PACKET3_3D_DRAW_VBUF 0x28
|
||||
#define PACKET3_3D_DRAW_IMMD 0x29
|
||||
#define PACKET3_3D_DRAW_INDX 0x2A
|
||||
#define PACKET3_3D_LOAD_VBPNTR 0x2F
|
||||
#define PACKET3_INDX_BUFFER 0x33
|
||||
#define PACKET3_3D_DRAW_VBUF_2 0x34
|
||||
#define PACKET3_3D_DRAW_IMMD_2 0x35
|
||||
#define PACKET3_3D_DRAW_INDX_2 0x36
|
||||
#define PACKET3_BITBLT_MULTI 0x9B
|
||||
|
||||
#define PACKET0(reg, n) (CP_PACKET0 | \
|
||||
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \
|
||||
REG_SET(PACKET0_COUNT, (n)))
|
||||
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
|
||||
#define PACKET3(op, n) (CP_PACKET3 | \
|
||||
REG_SET(PACKET3_IT_OPCODE, (op)) | \
|
||||
REG_SET(PACKET3_COUNT, (n)))
|
||||
|
||||
#define PACKET_TYPE0 0
|
||||
#define PACKET_TYPE1 1
|
||||
#define PACKET_TYPE2 2
|
||||
#define PACKET_TYPE3 3
|
||||
|
||||
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
|
||||
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
|
||||
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
|
||||
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
|
||||
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
|
||||
|
||||
/* Registers */
|
||||
#define R_000148_MC_FB_LOCATION 0x000148
|
||||
#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0)
|
||||
#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF)
|
||||
#define C_000148_MC_FB_START 0xFFFF0000
|
||||
#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16)
|
||||
#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF)
|
||||
#define C_000148_MC_FB_TOP 0x0000FFFF
|
||||
#define R_00014C_MC_AGP_LOCATION 0x00014C
|
||||
#define S_00014C_MC_AGP_START(x) (((x) & 0xFFFF) << 0)
|
||||
#define G_00014C_MC_AGP_START(x) (((x) >> 0) & 0xFFFF)
|
||||
#define C_00014C_MC_AGP_START 0xFFFF0000
|
||||
#define S_00014C_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16)
|
||||
#define G_00014C_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF)
|
||||
#define C_00014C_MC_AGP_TOP 0x0000FFFF
|
||||
#define R_00015C_AGP_BASE_2 0x00015C
|
||||
#define S_00015C_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0)
|
||||
#define G_00015C_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF)
|
||||
#define C_00015C_AGP_BASE_ADDR_2 0xFFFFFFF0
|
||||
#define R_000170_AGP_BASE 0x000170
|
||||
#define S_000170_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_000170_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_000170_AGP_BASE_ADDR 0x00000000
|
||||
|
||||
|
||||
#endif
|
|
@ -29,47 +29,13 @@
|
|||
#include "drmP.h"
|
||||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
#include "r420d.h"
|
||||
|
||||
/* r420,r423,rv410 depends on : */
|
||||
void r100_pci_gart_disable(struct radeon_device *rdev);
|
||||
void r100_hdp_reset(struct radeon_device *rdev);
|
||||
void r100_mc_setup(struct radeon_device *rdev);
|
||||
int r100_gui_wait_for_idle(struct radeon_device *rdev);
|
||||
void r100_mc_disable_clients(struct radeon_device *rdev);
|
||||
void r300_vram_info(struct radeon_device *rdev);
|
||||
int r300_mc_wait_for_idle(struct radeon_device *rdev);
|
||||
int rv370_pcie_gart_enable(struct radeon_device *rdev);
|
||||
void rv370_pcie_gart_disable(struct radeon_device *rdev);
|
||||
|
||||
/* This files gather functions specifics to :
|
||||
* r420,r423,rv410
|
||||
*
|
||||
* Some of these functions might be used by newer ASICs.
|
||||
*/
|
||||
void r420_gpu_init(struct radeon_device *rdev);
|
||||
int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
|
||||
|
||||
|
||||
/*
|
||||
* MC
|
||||
*/
|
||||
int r420_mc_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (r100_debugfs_rbbm_init(rdev)) {
|
||||
DRM_ERROR("Failed to register debugfs file for RBBM !\n");
|
||||
}
|
||||
if (r420_debugfs_pipes_info_init(rdev)) {
|
||||
DRM_ERROR("Failed to register debugfs file for pipes !\n");
|
||||
}
|
||||
|
||||
r420_gpu_init(rdev);
|
||||
r100_pci_gart_disable(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
}
|
||||
|
||||
/* Setup GPU memory space */
|
||||
rdev->mc.vram_location = 0xFFFFFFFFUL;
|
||||
rdev->mc.gtt_location = 0xFFFFFFFFUL;
|
||||
|
@ -87,33 +53,9 @@ int r420_mc_init(struct radeon_device *rdev)
|
|||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Program GPU memory space */
|
||||
r100_mc_disable_clients(rdev);
|
||||
if (r300_mc_wait_for_idle(rdev)) {
|
||||
printk(KERN_WARNING "Failed to wait MC idle while "
|
||||
"programming pipes. Bad things might happen.\n");
|
||||
}
|
||||
r100_mc_setup(rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r420_mc_fini(struct radeon_device *rdev)
|
||||
{
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
radeon_gart_table_vram_free(rdev);
|
||||
radeon_gart_fini(rdev);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Global GPU functions
|
||||
*/
|
||||
void r420_errata(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->pll_errata = 0;
|
||||
}
|
||||
|
||||
void r420_pipes_init(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned tmp;
|
||||
|
@ -122,6 +64,11 @@ void r420_pipes_init(struct radeon_device *rdev)
|
|||
|
||||
/* GA_ENHANCE workaround TCL deadlock issue */
|
||||
WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
|
||||
/* add idle wait as per freedesktop.org bug 24041 */
|
||||
if (r100_gui_wait_for_idle(rdev)) {
|
||||
printk(KERN_WARNING "Failed to wait GUI idle while "
|
||||
"programming pipes. Bad things might happen.\n");
|
||||
}
|
||||
/* get max number of pipes */
|
||||
gb_pipe_select = RREG32(0x402C);
|
||||
num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
|
||||
|
@ -179,25 +126,239 @@ void r420_pipes_init(struct radeon_device *rdev)
|
|||
rdev->num_gb_pipes, rdev->num_z_pipes);
|
||||
}
|
||||
|
||||
void r420_gpu_init(struct radeon_device *rdev)
|
||||
u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg)
|
||||
{
|
||||
r100_hdp_reset(rdev);
|
||||
r420_pipes_init(rdev);
|
||||
if (r300_mc_wait_for_idle(rdev)) {
|
||||
printk(KERN_WARNING "Failed to wait MC idle while "
|
||||
"programming pipes. Bad things might happen.\n");
|
||||
u32 r;
|
||||
|
||||
WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg));
|
||||
r = RREG32(R_0001FC_MC_IND_DATA);
|
||||
return r;
|
||||
}
|
||||
|
||||
void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||
{
|
||||
WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) |
|
||||
S_0001F8_MC_IND_WR_EN(1));
|
||||
WREG32(R_0001FC_MC_IND_DATA, v);
|
||||
}
|
||||
|
||||
static void r420_debugfs(struct radeon_device *rdev)
|
||||
{
|
||||
if (r100_debugfs_rbbm_init(rdev)) {
|
||||
DRM_ERROR("Failed to register debugfs file for RBBM !\n");
|
||||
}
|
||||
if (r420_debugfs_pipes_info_init(rdev)) {
|
||||
DRM_ERROR("Failed to register debugfs file for pipes !\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* r420,r423,rv410 VRAM info
|
||||
*/
|
||||
void r420_vram_info(struct radeon_device *rdev)
|
||||
static void r420_clock_resume(struct radeon_device *rdev)
|
||||
{
|
||||
r300_vram_info(rdev);
|
||||
u32 sclk_cntl;
|
||||
sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL);
|
||||
sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
|
||||
if (rdev->family == CHIP_R420)
|
||||
sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1);
|
||||
WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl);
|
||||
}
|
||||
|
||||
static int r420_startup(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r300_mc_program(rdev);
|
||||
/* Initialize GART (initialize after TTM so we can allocate
|
||||
* memory through TTM but finalize after TTM) */
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
r = rv370_pcie_gart_enable(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
if (rdev->flags & RADEON_IS_PCI) {
|
||||
r = r100_pci_gart_enable(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
r420_pipes_init(rdev);
|
||||
/* Enable IRQ */
|
||||
rdev->irq.sw_int = true;
|
||||
r100_irq_set(rdev);
|
||||
/* 1M ring buffer */
|
||||
r = r100_cp_init(rdev, 1024 * 1024);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
r = r100_wb_init(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
|
||||
}
|
||||
r = r100_ib_init(rdev);
|
||||
if (r) {
|
||||
dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r420_resume(struct radeon_device *rdev)
|
||||
{
|
||||
/* Make sur GART are not working */
|
||||
if (rdev->flags & RADEON_IS_PCIE)
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCI)
|
||||
r100_pci_gart_disable(rdev);
|
||||
/* Resume clock before doing reset */
|
||||
r420_clock_resume(rdev);
|
||||
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
|
||||
if (radeon_gpu_reset(rdev)) {
|
||||
dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
|
||||
RREG32(R_000E40_RBBM_STATUS),
|
||||
RREG32(R_0007C0_CP_STAT));
|
||||
}
|
||||
/* check if cards are posted or not */
|
||||
if (rdev->is_atom_bios) {
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
} else {
|
||||
radeon_combios_asic_init(rdev->ddev);
|
||||
}
|
||||
/* Resume clock after posting */
|
||||
r420_clock_resume(rdev);
|
||||
|
||||
return r420_startup(rdev);
|
||||
}
|
||||
|
||||
int r420_suspend(struct radeon_device *rdev)
|
||||
{
|
||||
r100_cp_disable(rdev);
|
||||
r100_wb_disable(rdev);
|
||||
r100_irq_disable(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCIE)
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCI)
|
||||
r100_pci_gart_disable(rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r420_fini(struct radeon_device *rdev)
|
||||
{
|
||||
r100_cp_fini(rdev);
|
||||
r100_wb_fini(rdev);
|
||||
r100_ib_fini(rdev);
|
||||
radeon_gem_fini(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCIE)
|
||||
rv370_pcie_gart_fini(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCI)
|
||||
r100_pci_gart_fini(rdev);
|
||||
radeon_agp_fini(rdev);
|
||||
radeon_irq_kms_fini(rdev);
|
||||
radeon_fence_driver_fini(rdev);
|
||||
radeon_object_fini(rdev);
|
||||
if (rdev->is_atom_bios) {
|
||||
radeon_atombios_fini(rdev);
|
||||
} else {
|
||||
radeon_combios_fini(rdev);
|
||||
}
|
||||
kfree(rdev->bios);
|
||||
rdev->bios = NULL;
|
||||
}
|
||||
|
||||
int r420_init(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
rdev->new_init_path = true;
|
||||
/* Initialize scratch registers */
|
||||
radeon_scratch_init(rdev);
|
||||
/* Initialize surface registers */
|
||||
radeon_surface_init(rdev);
|
||||
/* TODO: disable VGA need to use VGA request */
|
||||
/* BIOS*/
|
||||
if (!radeon_get_bios(rdev)) {
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rdev->is_atom_bios) {
|
||||
r = radeon_atombios_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
r = radeon_combios_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
|
||||
if (radeon_gpu_reset(rdev)) {
|
||||
dev_warn(rdev->dev,
|
||||
"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
|
||||
RREG32(R_000E40_RBBM_STATUS),
|
||||
RREG32(R_0007C0_CP_STAT));
|
||||
}
|
||||
/* check if cards are posted or not */
|
||||
if (!radeon_card_posted(rdev) && rdev->bios) {
|
||||
DRM_INFO("GPU not posted. posting now...\n");
|
||||
if (rdev->is_atom_bios) {
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
} else {
|
||||
radeon_combios_asic_init(rdev->ddev);
|
||||
}
|
||||
}
|
||||
/* Initialize clocks */
|
||||
radeon_get_clock_info(rdev->ddev);
|
||||
/* Get vram informations */
|
||||
r300_vram_info(rdev);
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = r420_mc_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r420_debugfs(rdev);
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = radeon_irq_kms_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Memory manager */
|
||||
r = radeon_object_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
r = rv370_pcie_gart_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
if (rdev->flags & RADEON_IS_PCI) {
|
||||
r = r100_pci_gart_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
r300_set_reg_safe(rdev);
|
||||
rdev->accel_working = true;
|
||||
r = r420_startup(rdev);
|
||||
if (r) {
|
||||
/* Somethings want wront with the accel init stop accel */
|
||||
dev_err(rdev->dev, "Disabling GPU acceleration\n");
|
||||
r420_suspend(rdev);
|
||||
r100_cp_fini(rdev);
|
||||
r100_wb_fini(rdev);
|
||||
r100_ib_fini(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCIE)
|
||||
rv370_pcie_gart_fini(rdev);
|
||||
if (rdev->flags & RADEON_IS_PCI)
|
||||
r100_pci_gart_fini(rdev);
|
||||
radeon_agp_fini(rdev);
|
||||
radeon_irq_kms_fini(rdev);
|
||||
rdev->accel_working = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugfs info
|
||||
|
|
249
drivers/gpu/drm/radeon/r420d.h
Normal file
249
drivers/gpu/drm/radeon/r420d.h
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* Copyright 2008 Advanced Micro Devices, Inc.
|
||||
* Copyright 2008 Red Hat Inc.
|
||||
* Copyright 2009 Jerome Glisse.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#ifndef R420D_H
|
||||
#define R420D_H
|
||||
|
||||
#define R_0001F8_MC_IND_INDEX 0x0001F8
|
||||
#define S_0001F8_MC_IND_ADDR(x) (((x) & 0x7F) << 0)
|
||||
#define G_0001F8_MC_IND_ADDR(x) (((x) >> 0) & 0x7F)
|
||||
#define C_0001F8_MC_IND_ADDR 0xFFFFFF80
|
||||
#define S_0001F8_MC_IND_WR_EN(x) (((x) & 0x1) << 8)
|
||||
#define G_0001F8_MC_IND_WR_EN(x) (((x) >> 8) & 0x1)
|
||||
#define C_0001F8_MC_IND_WR_EN 0xFFFFFEFF
|
||||
#define R_0001FC_MC_IND_DATA 0x0001FC
|
||||
#define S_0001FC_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0)
|
||||
#define G_0001FC_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF)
|
||||
#define C_0001FC_MC_IND_DATA 0x00000000
|
||||
#define R_0007C0_CP_STAT 0x0007C0
|
||||
#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0)
|
||||
#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1)
|
||||
#define C_0007C0_MRU_BUSY 0xFFFFFFFE
|
||||
#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1)
|
||||
#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1)
|
||||
#define C_0007C0_MWU_BUSY 0xFFFFFFFD
|
||||
#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2)
|
||||
#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1)
|
||||
#define C_0007C0_RSIU_BUSY 0xFFFFFFFB
|
||||
#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3)
|
||||
#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1)
|
||||
#define C_0007C0_RCIU_BUSY 0xFFFFFFF7
|
||||
#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9)
|
||||
#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1)
|
||||
#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF
|
||||
#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10)
|
||||
#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1)
|
||||
#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF
|
||||
#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11)
|
||||
#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1)
|
||||
#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF
|
||||
#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12)
|
||||
#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1)
|
||||
#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF
|
||||
#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13)
|
||||
#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1)
|
||||
#define C_0007C0_CSI_BUSY 0xFFFFDFFF
|
||||
#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14)
|
||||
#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1)
|
||||
#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF
|
||||
#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15)
|
||||
#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1)
|
||||
#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF
|
||||
#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28)
|
||||
#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1)
|
||||
#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF
|
||||
#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29)
|
||||
#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1)
|
||||
#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF
|
||||
#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30)
|
||||
#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1)
|
||||
#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF
|
||||
#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31)
|
||||
#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1)
|
||||
#define C_0007C0_CP_BUSY 0x7FFFFFFF
|
||||
#define R_000E40_RBBM_STATUS 0x000E40
|
||||
#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
|
||||
#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
|
||||
#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
|
||||
#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
|
||||
#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
|
||||
#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
|
||||
#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
|
||||
#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
|
||||
#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
|
||||
#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
|
||||
#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
|
||||
#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
|
||||
#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
|
||||
#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
|
||||
#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
|
||||
#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
|
||||
#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
|
||||
#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
|
||||
#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
|
||||
#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
|
||||
#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
|
||||
#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
|
||||
#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
|
||||
#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
|
||||
#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
|
||||
#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
|
||||
#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
|
||||
#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
|
||||
#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
|
||||
#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
|
||||
#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
|
||||
#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
|
||||
#define C_000E40_E2_BUSY 0xFFFDFFFF
|
||||
#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
|
||||
#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
|
||||
#define C_000E40_RB2D_BUSY 0xFFFBFFFF
|
||||
#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
|
||||
#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
|
||||
#define C_000E40_RB3D_BUSY 0xFFF7FFFF
|
||||
#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20)
|
||||
#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1)
|
||||
#define C_000E40_VAP_BUSY 0xFFEFFFFF
|
||||
#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
|
||||
#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
|
||||
#define C_000E40_RE_BUSY 0xFFDFFFFF
|
||||
#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
|
||||
#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
|
||||
#define C_000E40_TAM_BUSY 0xFFBFFFFF
|
||||
#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
|
||||
#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
|
||||
#define C_000E40_TDM_BUSY 0xFF7FFFFF
|
||||
#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
|
||||
#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
|
||||
#define C_000E40_PB_BUSY 0xFEFFFFFF
|
||||
#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25)
|
||||
#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1)
|
||||
#define C_000E40_TIM_BUSY 0xFDFFFFFF
|
||||
#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26)
|
||||
#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1)
|
||||
#define C_000E40_GA_BUSY 0xFBFFFFFF
|
||||
#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27)
|
||||
#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1)
|
||||
#define C_000E40_CBA2D_BUSY 0xF7FFFFFF
|
||||
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
|
||||
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
|
||||
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
|
||||
|
||||
/* CLK registers */
|
||||
#define R_00000D_SCLK_CNTL 0x00000D
|
||||
#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0)
|
||||
#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7)
|
||||
#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8
|
||||
#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3)
|
||||
#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1)
|
||||
#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7
|
||||
#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4)
|
||||
#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1)
|
||||
#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF
|
||||
#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5)
|
||||
#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1)
|
||||
#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF
|
||||
#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6)
|
||||
#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1)
|
||||
#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF
|
||||
#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7)
|
||||
#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1)
|
||||
#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F
|
||||
#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8)
|
||||
#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1)
|
||||
#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF
|
||||
#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9)
|
||||
#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1)
|
||||
#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF
|
||||
#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10)
|
||||
#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1)
|
||||
#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF
|
||||
#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11)
|
||||
#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1)
|
||||
#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF
|
||||
#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12)
|
||||
#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1)
|
||||
#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF
|
||||
#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13)
|
||||
#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1)
|
||||
#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF
|
||||
#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14)
|
||||
#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1)
|
||||
#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF
|
||||
#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15)
|
||||
#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1)
|
||||
#define C_00000D_FORCE_DISP2 0xFFFF7FFF
|
||||
#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16)
|
||||
#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1)
|
||||
#define C_00000D_FORCE_CP 0xFFFEFFFF
|
||||
#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17)
|
||||
#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1)
|
||||
#define C_00000D_FORCE_HDP 0xFFFDFFFF
|
||||
#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18)
|
||||
#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1)
|
||||
#define C_00000D_FORCE_DISP1 0xFFFBFFFF
|
||||
#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19)
|
||||
#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1)
|
||||
#define C_00000D_FORCE_TOP 0xFFF7FFFF
|
||||
#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20)
|
||||
#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1)
|
||||
#define C_00000D_FORCE_E2 0xFFEFFFFF
|
||||
#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21)
|
||||
#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1)
|
||||
#define C_00000D_FORCE_SE 0xFFDFFFFF
|
||||
#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22)
|
||||
#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1)
|
||||
#define C_00000D_FORCE_IDCT 0xFFBFFFFF
|
||||
#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23)
|
||||
#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1)
|
||||
#define C_00000D_FORCE_VIP 0xFF7FFFFF
|
||||
#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24)
|
||||
#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1)
|
||||
#define C_00000D_FORCE_RE 0xFEFFFFFF
|
||||
#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25)
|
||||
#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1)
|
||||
#define C_00000D_FORCE_PB 0xFDFFFFFF
|
||||
#define S_00000D_FORCE_PX(x) (((x) & 0x1) << 26)
|
||||
#define G_00000D_FORCE_PX(x) (((x) >> 26) & 0x1)
|
||||
#define C_00000D_FORCE_PX 0xFBFFFFFF
|
||||
#define S_00000D_FORCE_TX(x) (((x) & 0x1) << 27)
|
||||
#define G_00000D_FORCE_TX(x) (((x) >> 27) & 0x1)
|
||||
#define C_00000D_FORCE_TX 0xF7FFFFFF
|
||||
#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28)
|
||||
#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1)
|
||||
#define C_00000D_FORCE_RB 0xEFFFFFFF
|
||||
#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29)
|
||||
#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1)
|
||||
#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF
|
||||
#define S_00000D_FORCE_SUBPIC(x) (((x) & 0x1) << 30)
|
||||
#define G_00000D_FORCE_SUBPIC(x) (((x) >> 30) & 0x1)
|
||||
#define C_00000D_FORCE_SUBPIC 0xBFFFFFFF
|
||||
#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31)
|
||||
#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1)
|
||||
#define C_00000D_FORCE_OV0 0x7FFFFFFF
|
||||
|
||||
#endif
|
|
@ -28,12 +28,9 @@
|
|||
#include "drmP.h"
|
||||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
#include "radeon_share.h"
|
||||
|
||||
/* r520,rv530,rv560,rv570,r580 depends on : */
|
||||
void r100_hdp_reset(struct radeon_device *rdev);
|
||||
int rv370_pcie_gart_enable(struct radeon_device *rdev);
|
||||
void rv370_pcie_gart_disable(struct radeon_device *rdev);
|
||||
void r420_pipes_init(struct radeon_device *rdev);
|
||||
void rs600_mc_disable_clients(struct radeon_device *rdev);
|
||||
void rs600_disable_vga(struct radeon_device *rdev);
|
||||
|
@ -119,9 +116,6 @@ int r520_mc_init(struct radeon_device *rdev)
|
|||
|
||||
void r520_mc_fini(struct radeon_device *rdev)
|
||||
{
|
||||
rv370_pcie_gart_disable(rdev);
|
||||
radeon_gart_table_vram_free(rdev);
|
||||
radeon_gart_fini(rdev);
|
||||
}
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
850
drivers/gpu/drm/radeon/r600_blit.c
Normal file
850
drivers/gpu/drm/radeon/r600_blit.c
Normal file
|
@ -0,0 +1,850 @@
|
|||
/*
|
||||
* Copyright 2009 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) 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) AND/OR ITS SUPPLIERS 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:
|
||||
* Alex Deucher <alexander.deucher@amd.com>
|
||||
*/
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
||||
#include "r600_blit_shaders.h"
|
||||
|
||||
#define DI_PT_RECTLIST 0x11
|
||||
#define DI_INDEX_SIZE_16_BIT 0x0
|
||||
#define DI_SRC_SEL_AUTO_INDEX 0x2
|
||||
|
||||
#define FMT_8 0x1
|
||||
#define FMT_5_6_5 0x8
|
||||
#define FMT_8_8_8_8 0x1a
|
||||
#define COLOR_8 0x1
|
||||
#define COLOR_5_6_5 0x8
|
||||
#define COLOR_8_8_8_8 0x1a
|
||||
|
||||
static inline void
|
||||
set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr)
|
||||
{
|
||||
u32 cb_color_info;
|
||||
int pitch, slice;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
h = (h + 7) & ~7;
|
||||
if (h < 8)
|
||||
h = 8;
|
||||
|
||||
cb_color_info = ((format << 2) | (1 << 27));
|
||||
pitch = (w / 8) - 1;
|
||||
slice = ((w * h) / 64) - 1;
|
||||
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600) &&
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) {
|
||||
BEGIN_RING(21 + 2);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(gpu_addr >> 8);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0));
|
||||
OUT_RING(2 << 0);
|
||||
} else {
|
||||
BEGIN_RING(21);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(gpu_addr >> 8);
|
||||
}
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_SIZE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING((pitch << 0) | (slice << 10));
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_VIEW - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(0);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_INFO - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(cb_color_info);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_TILE - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(0);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_FRAG - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(0);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_CB_COLOR0_MASK - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(0);
|
||||
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static inline void
|
||||
cp_set_surface_sync(drm_radeon_private_t *dev_priv,
|
||||
u32 sync_type, u32 size, u64 mc_addr)
|
||||
{
|
||||
u32 cp_coher_size;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (size == 0xffffffff)
|
||||
cp_coher_size = 0xffffffff;
|
||||
else
|
||||
cp_coher_size = ((size + 255) >> 8);
|
||||
|
||||
BEGIN_RING(5);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SURFACE_SYNC, 3));
|
||||
OUT_RING(sync_type);
|
||||
OUT_RING(cp_coher_size);
|
||||
OUT_RING((mc_addr >> 8));
|
||||
OUT_RING(10); /* poll interval */
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_shaders(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
u64 gpu_addr;
|
||||
int i;
|
||||
u32 *vs, *ps;
|
||||
uint32_t sq_pgm_resources;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* load shaders */
|
||||
vs = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset);
|
||||
ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256);
|
||||
|
||||
for (i = 0; i < r6xx_vs_size; i++)
|
||||
vs[i] = r6xx_vs[i];
|
||||
for (i = 0; i < r6xx_ps_size; i++)
|
||||
ps[i] = r6xx_ps[i];
|
||||
|
||||
dev_priv->blit_vb->used = 512;
|
||||
|
||||
gpu_addr = dev_priv->gart_buffers_offset + dev_priv->blit_vb->offset;
|
||||
|
||||
/* setup shader regs */
|
||||
sq_pgm_resources = (1 << 0);
|
||||
|
||||
BEGIN_RING(9 + 12);
|
||||
/* VS */
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_START_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(gpu_addr >> 8);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_RESOURCES_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(sq_pgm_resources);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_CF_OFFSET_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(0);
|
||||
|
||||
/* PS */
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_START_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING((gpu_addr + 256) >> 8);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_RESOURCES_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(sq_pgm_resources | (1 << 28));
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_EXPORTS_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(2);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1));
|
||||
OUT_RING((R600_SQ_PGM_CF_OFFSET_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING(0);
|
||||
ADVANCE_RING();
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_SH_ACTION_ENA, 512, gpu_addr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr)
|
||||
{
|
||||
uint32_t sq_vtx_constant_word2;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
sq_vtx_constant_word2 = (((gpu_addr >> 32) & 0xff) | (16 << 8));
|
||||
|
||||
BEGIN_RING(9);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
|
||||
OUT_RING(0x460);
|
||||
OUT_RING(gpu_addr & 0xffffffff);
|
||||
OUT_RING(48 - 1);
|
||||
OUT_RING(sq_vtx_constant_word2);
|
||||
OUT_RING(1 << 0);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
OUT_RING(R600_SQ_TEX_VTX_VALID_BUFFER << 30);
|
||||
ADVANCE_RING();
|
||||
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710))
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_TC_ACTION_ENA, 48, gpu_addr);
|
||||
else
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_VC_ACTION_ENA, 48, gpu_addr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_tex_resource(drm_radeon_private_t *dev_priv,
|
||||
int format, int w, int h, int pitch, u64 gpu_addr)
|
||||
{
|
||||
uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (h < 1)
|
||||
h = 1;
|
||||
|
||||
sq_tex_resource_word0 = (1 << 0);
|
||||
sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
|
||||
((w - 1) << 19));
|
||||
|
||||
sq_tex_resource_word1 = (format << 26);
|
||||
sq_tex_resource_word1 |= ((h - 1) << 0);
|
||||
|
||||
sq_tex_resource_word4 = ((1 << 14) |
|
||||
(0 << 16) |
|
||||
(1 << 19) |
|
||||
(2 << 22) |
|
||||
(3 << 25));
|
||||
|
||||
BEGIN_RING(9);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7));
|
||||
OUT_RING(0);
|
||||
OUT_RING(sq_tex_resource_word0);
|
||||
OUT_RING(sq_tex_resource_word1);
|
||||
OUT_RING(gpu_addr >> 8);
|
||||
OUT_RING(gpu_addr >> 8);
|
||||
OUT_RING(sq_tex_resource_word4);
|
||||
OUT_RING(0);
|
||||
OUT_RING(R600_SQ_TEX_VTX_VALID_TEXTURE << 30);
|
||||
ADVANCE_RING();
|
||||
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(12);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
|
||||
OUT_RING((R600_PA_SC_SCREEN_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING((x1 << 0) | (y1 << 16));
|
||||
OUT_RING((x2 << 0) | (y2 << 16));
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
|
||||
OUT_RING((R600_PA_SC_GENERIC_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31));
|
||||
OUT_RING((x2 << 0) | (y2 << 16));
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2));
|
||||
OUT_RING((R600_PA_SC_WINDOW_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31));
|
||||
OUT_RING((x2 << 0) | (y2 << 16));
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static inline void
|
||||
draw_auto(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(10);
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
|
||||
OUT_RING((R600_VGT_PRIMITIVE_TYPE - R600_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
OUT_RING(DI_PT_RECTLIST);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_INDEX_TYPE, 0));
|
||||
OUT_RING(DI_INDEX_SIZE_16_BIT);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_NUM_INSTANCES, 0));
|
||||
OUT_RING(1);
|
||||
|
||||
OUT_RING(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1));
|
||||
OUT_RING(3);
|
||||
OUT_RING(DI_SRC_SEL_AUTO_INDEX);
|
||||
|
||||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_default_state(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
int i;
|
||||
u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2;
|
||||
u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2;
|
||||
int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs;
|
||||
int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads;
|
||||
int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
|
||||
RING_LOCALS;
|
||||
|
||||
switch ((dev_priv->flags & RADEON_FAMILY_MASK)) {
|
||||
case CHIP_R600:
|
||||
num_ps_gprs = 192;
|
||||
num_vs_gprs = 56;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 136;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 128;
|
||||
num_vs_stack_entries = 128;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
case CHIP_RV630:
|
||||
case CHIP_RV635:
|
||||
num_ps_gprs = 84;
|
||||
num_vs_gprs = 36;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 144;
|
||||
num_vs_threads = 40;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 40;
|
||||
num_vs_stack_entries = 40;
|
||||
num_gs_stack_entries = 32;
|
||||
num_es_stack_entries = 16;
|
||||
break;
|
||||
case CHIP_RV610:
|
||||
case CHIP_RV620:
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880:
|
||||
default:
|
||||
num_ps_gprs = 84;
|
||||
num_vs_gprs = 36;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 136;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 40;
|
||||
num_vs_stack_entries = 40;
|
||||
num_gs_stack_entries = 32;
|
||||
num_es_stack_entries = 16;
|
||||
break;
|
||||
case CHIP_RV670:
|
||||
num_ps_gprs = 144;
|
||||
num_vs_gprs = 40;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 136;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 40;
|
||||
num_vs_stack_entries = 40;
|
||||
num_gs_stack_entries = 32;
|
||||
num_es_stack_entries = 16;
|
||||
break;
|
||||
case CHIP_RV770:
|
||||
num_ps_gprs = 192;
|
||||
num_vs_gprs = 56;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 188;
|
||||
num_vs_threads = 60;
|
||||
num_gs_threads = 0;
|
||||
num_es_threads = 0;
|
||||
num_ps_stack_entries = 256;
|
||||
num_vs_stack_entries = 256;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV740:
|
||||
num_ps_gprs = 84;
|
||||
num_vs_gprs = 36;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 188;
|
||||
num_vs_threads = 60;
|
||||
num_gs_threads = 0;
|
||||
num_es_threads = 0;
|
||||
num_ps_stack_entries = 128;
|
||||
num_vs_stack_entries = 128;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
num_ps_gprs = 192;
|
||||
num_vs_gprs = 56;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 144;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 0;
|
||||
num_es_threads = 0;
|
||||
num_ps_stack_entries = 128;
|
||||
num_vs_stack_entries = 128;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710))
|
||||
sq_config = 0;
|
||||
else
|
||||
sq_config = R600_VC_ENABLE;
|
||||
|
||||
sq_config |= (R600_DX9_CONSTS |
|
||||
R600_ALU_INST_PREFER_VECTOR |
|
||||
R600_PS_PRIO(0) |
|
||||
R600_VS_PRIO(1) |
|
||||
R600_GS_PRIO(2) |
|
||||
R600_ES_PRIO(3));
|
||||
|
||||
sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(num_ps_gprs) |
|
||||
R600_NUM_VS_GPRS(num_vs_gprs) |
|
||||
R600_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs));
|
||||
sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(num_gs_gprs) |
|
||||
R600_NUM_ES_GPRS(num_es_gprs));
|
||||
sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(num_ps_threads) |
|
||||
R600_NUM_VS_THREADS(num_vs_threads) |
|
||||
R600_NUM_GS_THREADS(num_gs_threads) |
|
||||
R600_NUM_ES_THREADS(num_es_threads));
|
||||
sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(num_ps_stack_entries) |
|
||||
R600_NUM_VS_STACK_ENTRIES(num_vs_stack_entries));
|
||||
sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(num_gs_stack_entries) |
|
||||
R600_NUM_ES_STACK_ENTRIES(num_es_stack_entries));
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
|
||||
BEGIN_RING(r7xx_default_size + 10);
|
||||
for (i = 0; i < r7xx_default_size; i++)
|
||||
OUT_RING(r7xx_default_state[i]);
|
||||
} else {
|
||||
BEGIN_RING(r6xx_default_size + 10);
|
||||
for (i = 0; i < r6xx_default_size; i++)
|
||||
OUT_RING(r6xx_default_state[i]);
|
||||
}
|
||||
OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
|
||||
OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* SQ config */
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 6));
|
||||
OUT_RING((R600_SQ_CONFIG - R600_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
OUT_RING(sq_config);
|
||||
OUT_RING(sq_gpr_resource_mgmt_1);
|
||||
OUT_RING(sq_gpr_resource_mgmt_2);
|
||||
OUT_RING(sq_thread_resource_mgmt);
|
||||
OUT_RING(sq_stack_resource_mgmt_1);
|
||||
OUT_RING(sq_stack_resource_mgmt_2);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
static inline uint32_t i2f(uint32_t input)
|
||||
{
|
||||
u32 result, i, exponent, fraction;
|
||||
|
||||
if ((input & 0x3fff) == 0)
|
||||
result = 0; /* 0 is a special case */
|
||||
else {
|
||||
exponent = 140; /* exponent biased by 127; */
|
||||
fraction = (input & 0x3fff) << 10; /* cheat and only
|
||||
handle numbers below 2^^15 */
|
||||
for (i = 0; i < 14; i++) {
|
||||
if (fraction & 0x800000)
|
||||
break;
|
||||
else {
|
||||
fraction = fraction << 1; /* keep
|
||||
shifting left until top bit = 1 */
|
||||
exponent = exponent - 1;
|
||||
}
|
||||
}
|
||||
result = exponent << 23 | (fraction & 0x7fffff); /* mask
|
||||
off top bit; assumed 1 */
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline int r600_nomm_get_vb(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
dev_priv->blit_vb = radeon_freelist_get(dev);
|
||||
if (!dev_priv->blit_vb) {
|
||||
DRM_ERROR("Unable to allocate vertex buffer for blit\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void r600_nomm_put_vb(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->blit_vb->used = 0;
|
||||
radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb);
|
||||
}
|
||||
|
||||
static inline void *r600_nomm_get_vb_ptr(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
return (((char *)dev->agp_buffer_map->handle +
|
||||
dev_priv->blit_vb->offset + dev_priv->blit_vb->used));
|
||||
}
|
||||
|
||||
int
|
||||
r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
r600_nomm_get_vb(dev);
|
||||
|
||||
dev_priv->blit_vb->file_priv = file_priv;
|
||||
|
||||
set_default_state(dev_priv);
|
||||
set_shaders(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
r600_done_blit_copy(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
BEGIN_RING(5);
|
||||
OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
|
||||
OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* wait for 3D idle clean */
|
||||
OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
|
||||
OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN);
|
||||
|
||||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
|
||||
r600_nomm_put_vb(dev);
|
||||
}
|
||||
|
||||
void
|
||||
r600_blit_copy(struct drm_device *dev,
|
||||
uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
|
||||
int size_bytes)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
int max_bytes;
|
||||
u64 vb_addr;
|
||||
u32 *vb;
|
||||
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
|
||||
if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
|
||||
max_bytes = 8192;
|
||||
|
||||
while (size_bytes) {
|
||||
int cur_size = size_bytes;
|
||||
int src_x = src_gpu_addr & 255;
|
||||
int dst_x = dst_gpu_addr & 255;
|
||||
int h = 1;
|
||||
src_gpu_addr = src_gpu_addr & ~255;
|
||||
dst_gpu_addr = dst_gpu_addr & ~255;
|
||||
|
||||
if (!src_x && !dst_x) {
|
||||
h = (cur_size / max_bytes);
|
||||
if (h > 8192)
|
||||
h = 8192;
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
else
|
||||
cur_size = max_bytes;
|
||||
} else {
|
||||
if (cur_size > max_bytes)
|
||||
cur_size = max_bytes;
|
||||
if (cur_size > (max_bytes - dst_x))
|
||||
cur_size = (max_bytes - dst_x);
|
||||
if (cur_size > (max_bytes - src_x))
|
||||
cur_size = (max_bytes - src_x);
|
||||
}
|
||||
|
||||
if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
|
||||
|
||||
r600_nomm_put_vb(dev);
|
||||
r600_nomm_get_vb(dev);
|
||||
if (!dev_priv->blit_vb)
|
||||
return;
|
||||
set_shaders(dev);
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
}
|
||||
|
||||
vb[0] = i2f(dst_x);
|
||||
vb[1] = 0;
|
||||
vb[2] = i2f(src_x);
|
||||
vb[3] = 0;
|
||||
|
||||
vb[4] = i2f(dst_x);
|
||||
vb[5] = i2f(h);
|
||||
vb[6] = i2f(src_x);
|
||||
vb[7] = i2f(h);
|
||||
|
||||
vb[8] = i2f(dst_x + cur_size);
|
||||
vb[9] = i2f(h);
|
||||
vb[10] = i2f(src_x + cur_size);
|
||||
vb[11] = i2f(h);
|
||||
|
||||
/* src */
|
||||
set_tex_resource(dev_priv, FMT_8,
|
||||
src_x + cur_size, h, src_x + cur_size,
|
||||
src_gpu_addr);
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
|
||||
|
||||
/* dst */
|
||||
set_render_target(dev_priv, COLOR_8,
|
||||
dst_x + cur_size, h,
|
||||
dst_gpu_addr);
|
||||
|
||||
/* scissors */
|
||||
set_scissors(dev_priv, dst_x, 0, dst_x + cur_size, h);
|
||||
|
||||
/* Vertex buffer setup */
|
||||
vb_addr = dev_priv->gart_buffers_offset +
|
||||
dev_priv->blit_vb->offset +
|
||||
dev_priv->blit_vb->used;
|
||||
set_vtx_resource(dev_priv, vb_addr);
|
||||
|
||||
/* draw */
|
||||
draw_auto(dev_priv);
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
|
||||
cur_size * h, dst_gpu_addr);
|
||||
|
||||
vb += 12;
|
||||
dev_priv->blit_vb->used += 12 * 4;
|
||||
|
||||
src_gpu_addr += cur_size * h;
|
||||
dst_gpu_addr += cur_size * h;
|
||||
size_bytes -= cur_size * h;
|
||||
}
|
||||
} else {
|
||||
max_bytes = 8192 * 4;
|
||||
|
||||
while (size_bytes) {
|
||||
int cur_size = size_bytes;
|
||||
int src_x = (src_gpu_addr & 255);
|
||||
int dst_x = (dst_gpu_addr & 255);
|
||||
int h = 1;
|
||||
src_gpu_addr = src_gpu_addr & ~255;
|
||||
dst_gpu_addr = dst_gpu_addr & ~255;
|
||||
|
||||
if (!src_x && !dst_x) {
|
||||
h = (cur_size / max_bytes);
|
||||
if (h > 8192)
|
||||
h = 8192;
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
else
|
||||
cur_size = max_bytes;
|
||||
} else {
|
||||
if (cur_size > max_bytes)
|
||||
cur_size = max_bytes;
|
||||
if (cur_size > (max_bytes - dst_x))
|
||||
cur_size = (max_bytes - dst_x);
|
||||
if (cur_size > (max_bytes - src_x))
|
||||
cur_size = (max_bytes - src_x);
|
||||
}
|
||||
|
||||
if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
|
||||
r600_nomm_put_vb(dev);
|
||||
r600_nomm_get_vb(dev);
|
||||
if (!dev_priv->blit_vb)
|
||||
return;
|
||||
|
||||
set_shaders(dev);
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
}
|
||||
|
||||
vb[0] = i2f(dst_x / 4);
|
||||
vb[1] = 0;
|
||||
vb[2] = i2f(src_x / 4);
|
||||
vb[3] = 0;
|
||||
|
||||
vb[4] = i2f(dst_x / 4);
|
||||
vb[5] = i2f(h);
|
||||
vb[6] = i2f(src_x / 4);
|
||||
vb[7] = i2f(h);
|
||||
|
||||
vb[8] = i2f((dst_x + cur_size) / 4);
|
||||
vb[9] = i2f(h);
|
||||
vb[10] = i2f((src_x + cur_size) / 4);
|
||||
vb[11] = i2f(h);
|
||||
|
||||
/* src */
|
||||
set_tex_resource(dev_priv, FMT_8_8_8_8,
|
||||
(src_x + cur_size) / 4,
|
||||
h, (src_x + cur_size) / 4,
|
||||
src_gpu_addr);
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
|
||||
|
||||
/* dst */
|
||||
set_render_target(dev_priv, COLOR_8_8_8_8,
|
||||
dst_x + cur_size, h,
|
||||
dst_gpu_addr);
|
||||
|
||||
/* scissors */
|
||||
set_scissors(dev_priv, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
|
||||
|
||||
/* Vertex buffer setup */
|
||||
vb_addr = dev_priv->gart_buffers_offset +
|
||||
dev_priv->blit_vb->offset +
|
||||
dev_priv->blit_vb->used;
|
||||
set_vtx_resource(dev_priv, vb_addr);
|
||||
|
||||
/* draw */
|
||||
draw_auto(dev_priv);
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
|
||||
cur_size * h, dst_gpu_addr);
|
||||
|
||||
vb += 12;
|
||||
dev_priv->blit_vb->used += 12 * 4;
|
||||
|
||||
src_gpu_addr += cur_size * h;
|
||||
dst_gpu_addr += cur_size * h;
|
||||
size_bytes -= cur_size * h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
r600_blit_swap(struct drm_device *dev,
|
||||
uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h, int src_pitch, int dst_pitch, int cpp)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
int cb_format, tex_format;
|
||||
u64 vb_addr;
|
||||
u32 *vb;
|
||||
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
|
||||
if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) {
|
||||
|
||||
r600_nomm_put_vb(dev);
|
||||
r600_nomm_get_vb(dev);
|
||||
if (!dev_priv->blit_vb)
|
||||
return;
|
||||
|
||||
set_shaders(dev);
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
}
|
||||
|
||||
if (cpp == 4) {
|
||||
cb_format = COLOR_8_8_8_8;
|
||||
tex_format = FMT_8_8_8_8;
|
||||
} else if (cpp == 2) {
|
||||
cb_format = COLOR_5_6_5;
|
||||
tex_format = FMT_5_6_5;
|
||||
} else {
|
||||
cb_format = COLOR_8;
|
||||
tex_format = FMT_8;
|
||||
}
|
||||
|
||||
vb[0] = i2f(dx);
|
||||
vb[1] = i2f(dy);
|
||||
vb[2] = i2f(sx);
|
||||
vb[3] = i2f(sy);
|
||||
|
||||
vb[4] = i2f(dx);
|
||||
vb[5] = i2f(dy + h);
|
||||
vb[6] = i2f(sx);
|
||||
vb[7] = i2f(sy + h);
|
||||
|
||||
vb[8] = i2f(dx + w);
|
||||
vb[9] = i2f(dy + h);
|
||||
vb[10] = i2f(sx + w);
|
||||
vb[11] = i2f(sy + h);
|
||||
|
||||
/* src */
|
||||
set_tex_resource(dev_priv, tex_format,
|
||||
src_pitch / cpp,
|
||||
sy + h, src_pitch / cpp,
|
||||
src_gpu_addr);
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_TC_ACTION_ENA, (src_pitch * (sy + h)), src_gpu_addr);
|
||||
|
||||
/* dst */
|
||||
set_render_target(dev_priv, cb_format,
|
||||
dst_pitch / cpp, dy + h,
|
||||
dst_gpu_addr);
|
||||
|
||||
/* scissors */
|
||||
set_scissors(dev_priv, dx, dy, dx + w, dy + h);
|
||||
|
||||
/* Vertex buffer setup */
|
||||
vb_addr = dev_priv->gart_buffers_offset +
|
||||
dev_priv->blit_vb->offset +
|
||||
dev_priv->blit_vb->used;
|
||||
set_vtx_resource(dev_priv, vb_addr);
|
||||
|
||||
/* draw */
|
||||
draw_auto(dev_priv);
|
||||
|
||||
cp_set_surface_sync(dev_priv,
|
||||
R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA,
|
||||
dst_pitch * (dy + h), dst_gpu_addr);
|
||||
|
||||
dev_priv->blit_vb->used += 12 * 4;
|
||||
}
|
805
drivers/gpu/drm/radeon/r600_blit_kms.c
Normal file
805
drivers/gpu/drm/radeon/r600_blit_kms.c
Normal file
|
@ -0,0 +1,805 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon.h"
|
||||
|
||||
#include "r600d.h"
|
||||
#include "r600_blit_shaders.h"
|
||||
|
||||
#define DI_PT_RECTLIST 0x11
|
||||
#define DI_INDEX_SIZE_16_BIT 0x0
|
||||
#define DI_SRC_SEL_AUTO_INDEX 0x2
|
||||
|
||||
#define FMT_8 0x1
|
||||
#define FMT_5_6_5 0x8
|
||||
#define FMT_8_8_8_8 0x1a
|
||||
#define COLOR_8 0x1
|
||||
#define COLOR_5_6_5 0x8
|
||||
#define COLOR_8_8_8_8 0x1a
|
||||
|
||||
/* emits 21 on rv770+, 23 on r600 */
|
||||
static void
|
||||
set_render_target(struct radeon_device *rdev, int format,
|
||||
int w, int h, u64 gpu_addr)
|
||||
{
|
||||
u32 cb_color_info;
|
||||
int pitch, slice;
|
||||
|
||||
h = (h + 7) & ~7;
|
||||
if (h < 8)
|
||||
h = 8;
|
||||
|
||||
cb_color_info = ((format << 2) | (1 << 27));
|
||||
pitch = (w / 8) - 1;
|
||||
slice = ((w * h) / 64) - 1;
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_BASE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, gpu_addr >> 8);
|
||||
|
||||
if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770) {
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_BASE_UPDATE, 0));
|
||||
radeon_ring_write(rdev, 2 << 0);
|
||||
}
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_SIZE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, (pitch << 0) | (slice << 10));
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_VIEW - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 0);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_INFO - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, cb_color_info);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_TILE - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 0);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_FRAG - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 0);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (CB_COLOR0_MASK - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 0);
|
||||
}
|
||||
|
||||
/* emits 5dw */
|
||||
static void
|
||||
cp_set_surface_sync(struct radeon_device *rdev,
|
||||
u32 sync_type, u32 size,
|
||||
u64 mc_addr)
|
||||
{
|
||||
u32 cp_coher_size;
|
||||
|
||||
if (size == 0xffffffff)
|
||||
cp_coher_size = 0xffffffff;
|
||||
else
|
||||
cp_coher_size = ((size + 255) >> 8);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
|
||||
radeon_ring_write(rdev, sync_type);
|
||||
radeon_ring_write(rdev, cp_coher_size);
|
||||
radeon_ring_write(rdev, mc_addr >> 8);
|
||||
radeon_ring_write(rdev, 10); /* poll interval */
|
||||
}
|
||||
|
||||
/* emits 21dw + 1 surface sync = 26dw */
|
||||
static void
|
||||
set_shaders(struct radeon_device *rdev)
|
||||
{
|
||||
u64 gpu_addr;
|
||||
u32 sq_pgm_resources;
|
||||
|
||||
/* setup shader regs */
|
||||
sq_pgm_resources = (1 << 0);
|
||||
|
||||
/* VS */
|
||||
gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset;
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_START_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, gpu_addr >> 8);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_RESOURCES_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, sq_pgm_resources);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_CF_OFFSET_VS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 0);
|
||||
|
||||
/* PS */
|
||||
gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.ps_offset;
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_START_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, gpu_addr >> 8);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_RESOURCES_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, sq_pgm_resources | (1 << 28));
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_EXPORTS_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 2);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 1));
|
||||
radeon_ring_write(rdev, (SQ_PGM_CF_OFFSET_PS - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, 0);
|
||||
|
||||
gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.vs_offset;
|
||||
cp_set_surface_sync(rdev, PACKET3_SH_ACTION_ENA, 512, gpu_addr);
|
||||
}
|
||||
|
||||
/* emits 9 + 1 sync (5) = 14*/
|
||||
static void
|
||||
set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
|
||||
{
|
||||
u32 sq_vtx_constant_word2;
|
||||
|
||||
sq_vtx_constant_word2 = ((upper_32_bits(gpu_addr) & 0xff) | (16 << 8));
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
|
||||
radeon_ring_write(rdev, 0x460);
|
||||
radeon_ring_write(rdev, gpu_addr & 0xffffffff);
|
||||
radeon_ring_write(rdev, 48 - 1);
|
||||
radeon_ring_write(rdev, sq_vtx_constant_word2);
|
||||
radeon_ring_write(rdev, 1 << 0);
|
||||
radeon_ring_write(rdev, 0);
|
||||
radeon_ring_write(rdev, 0);
|
||||
radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30);
|
||||
|
||||
if ((rdev->family == CHIP_RV610) ||
|
||||
(rdev->family == CHIP_RV620) ||
|
||||
(rdev->family == CHIP_RS780) ||
|
||||
(rdev->family == CHIP_RS880) ||
|
||||
(rdev->family == CHIP_RV710))
|
||||
cp_set_surface_sync(rdev,
|
||||
PACKET3_TC_ACTION_ENA, 48, gpu_addr);
|
||||
else
|
||||
cp_set_surface_sync(rdev,
|
||||
PACKET3_VC_ACTION_ENA, 48, gpu_addr);
|
||||
}
|
||||
|
||||
/* emits 9 */
|
||||
static void
|
||||
set_tex_resource(struct radeon_device *rdev,
|
||||
int format, int w, int h, int pitch,
|
||||
u64 gpu_addr)
|
||||
{
|
||||
uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
|
||||
|
||||
if (h < 1)
|
||||
h = 1;
|
||||
|
||||
sq_tex_resource_word0 = (1 << 0);
|
||||
sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) |
|
||||
((w - 1) << 19));
|
||||
|
||||
sq_tex_resource_word1 = (format << 26);
|
||||
sq_tex_resource_word1 |= ((h - 1) << 0);
|
||||
|
||||
sq_tex_resource_word4 = ((1 << 14) |
|
||||
(0 << 16) |
|
||||
(1 << 19) |
|
||||
(2 << 22) |
|
||||
(3 << 25));
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
|
||||
radeon_ring_write(rdev, 0);
|
||||
radeon_ring_write(rdev, sq_tex_resource_word0);
|
||||
radeon_ring_write(rdev, sq_tex_resource_word1);
|
||||
radeon_ring_write(rdev, gpu_addr >> 8);
|
||||
radeon_ring_write(rdev, gpu_addr >> 8);
|
||||
radeon_ring_write(rdev, sq_tex_resource_word4);
|
||||
radeon_ring_write(rdev, 0);
|
||||
radeon_ring_write(rdev, SQ_TEX_VTX_VALID_TEXTURE << 30);
|
||||
}
|
||||
|
||||
/* emits 12 */
|
||||
static void
|
||||
set_scissors(struct radeon_device *rdev, int x1, int y1,
|
||||
int x2, int y2)
|
||||
{
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2));
|
||||
radeon_ring_write(rdev, (PA_SC_SCREEN_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, (x1 << 0) | (y1 << 16));
|
||||
radeon_ring_write(rdev, (x2 << 0) | (y2 << 16));
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2));
|
||||
radeon_ring_write(rdev, (PA_SC_GENERIC_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31));
|
||||
radeon_ring_write(rdev, (x2 << 0) | (y2 << 16));
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2));
|
||||
radeon_ring_write(rdev, (PA_SC_WINDOW_SCISSOR_TL - PACKET3_SET_CONTEXT_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, (x1 << 0) | (y1 << 16) | (1 << 31));
|
||||
radeon_ring_write(rdev, (x2 << 0) | (y2 << 16));
|
||||
}
|
||||
|
||||
/* emits 10 */
|
||||
static void
|
||||
draw_auto(struct radeon_device *rdev)
|
||||
{
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
|
||||
radeon_ring_write(rdev, (VGT_PRIMITIVE_TYPE - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, DI_PT_RECTLIST);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_INDEX_TYPE, 0));
|
||||
radeon_ring_write(rdev, DI_INDEX_SIZE_16_BIT);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_NUM_INSTANCES, 0));
|
||||
radeon_ring_write(rdev, 1);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_DRAW_INDEX_AUTO, 1));
|
||||
radeon_ring_write(rdev, 3);
|
||||
radeon_ring_write(rdev, DI_SRC_SEL_AUTO_INDEX);
|
||||
|
||||
}
|
||||
|
||||
/* emits 14 */
|
||||
static void
|
||||
set_default_state(struct radeon_device *rdev)
|
||||
{
|
||||
u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2;
|
||||
u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2;
|
||||
int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs;
|
||||
int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads;
|
||||
int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
|
||||
u64 gpu_addr;
|
||||
int dwords;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_R600:
|
||||
num_ps_gprs = 192;
|
||||
num_vs_gprs = 56;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 136;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 128;
|
||||
num_vs_stack_entries = 128;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
case CHIP_RV630:
|
||||
case CHIP_RV635:
|
||||
num_ps_gprs = 84;
|
||||
num_vs_gprs = 36;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 144;
|
||||
num_vs_threads = 40;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 40;
|
||||
num_vs_stack_entries = 40;
|
||||
num_gs_stack_entries = 32;
|
||||
num_es_stack_entries = 16;
|
||||
break;
|
||||
case CHIP_RV610:
|
||||
case CHIP_RV620:
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880:
|
||||
default:
|
||||
num_ps_gprs = 84;
|
||||
num_vs_gprs = 36;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 136;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 40;
|
||||
num_vs_stack_entries = 40;
|
||||
num_gs_stack_entries = 32;
|
||||
num_es_stack_entries = 16;
|
||||
break;
|
||||
case CHIP_RV670:
|
||||
num_ps_gprs = 144;
|
||||
num_vs_gprs = 40;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 136;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 4;
|
||||
num_es_threads = 4;
|
||||
num_ps_stack_entries = 40;
|
||||
num_vs_stack_entries = 40;
|
||||
num_gs_stack_entries = 32;
|
||||
num_es_stack_entries = 16;
|
||||
break;
|
||||
case CHIP_RV770:
|
||||
num_ps_gprs = 192;
|
||||
num_vs_gprs = 56;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 188;
|
||||
num_vs_threads = 60;
|
||||
num_gs_threads = 0;
|
||||
num_es_threads = 0;
|
||||
num_ps_stack_entries = 256;
|
||||
num_vs_stack_entries = 256;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV740:
|
||||
num_ps_gprs = 84;
|
||||
num_vs_gprs = 36;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 188;
|
||||
num_vs_threads = 60;
|
||||
num_gs_threads = 0;
|
||||
num_es_threads = 0;
|
||||
num_ps_stack_entries = 128;
|
||||
num_vs_stack_entries = 128;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
case CHIP_RV710:
|
||||
num_ps_gprs = 192;
|
||||
num_vs_gprs = 56;
|
||||
num_temp_gprs = 4;
|
||||
num_gs_gprs = 0;
|
||||
num_es_gprs = 0;
|
||||
num_ps_threads = 144;
|
||||
num_vs_threads = 48;
|
||||
num_gs_threads = 0;
|
||||
num_es_threads = 0;
|
||||
num_ps_stack_entries = 128;
|
||||
num_vs_stack_entries = 128;
|
||||
num_gs_stack_entries = 0;
|
||||
num_es_stack_entries = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((rdev->family == CHIP_RV610) ||
|
||||
(rdev->family == CHIP_RV620) ||
|
||||
(rdev->family == CHIP_RS780) ||
|
||||
(rdev->family == CHIP_RS780) ||
|
||||
(rdev->family == CHIP_RV710))
|
||||
sq_config = 0;
|
||||
else
|
||||
sq_config = VC_ENABLE;
|
||||
|
||||
sq_config |= (DX9_CONSTS |
|
||||
ALU_INST_PREFER_VECTOR |
|
||||
PS_PRIO(0) |
|
||||
VS_PRIO(1) |
|
||||
GS_PRIO(2) |
|
||||
ES_PRIO(3));
|
||||
|
||||
sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(num_ps_gprs) |
|
||||
NUM_VS_GPRS(num_vs_gprs) |
|
||||
NUM_CLAUSE_TEMP_GPRS(num_temp_gprs));
|
||||
sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(num_gs_gprs) |
|
||||
NUM_ES_GPRS(num_es_gprs));
|
||||
sq_thread_resource_mgmt = (NUM_PS_THREADS(num_ps_threads) |
|
||||
NUM_VS_THREADS(num_vs_threads) |
|
||||
NUM_GS_THREADS(num_gs_threads) |
|
||||
NUM_ES_THREADS(num_es_threads));
|
||||
sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(num_ps_stack_entries) |
|
||||
NUM_VS_STACK_ENTRIES(num_vs_stack_entries));
|
||||
sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(num_gs_stack_entries) |
|
||||
NUM_ES_STACK_ENTRIES(num_es_stack_entries));
|
||||
|
||||
/* emit an IB pointing at default state */
|
||||
dwords = (rdev->r600_blit.state_len + 0xf) & ~0xf;
|
||||
gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset;
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
|
||||
radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC);
|
||||
radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
|
||||
radeon_ring_write(rdev, dwords);
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
|
||||
radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* SQ config */
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 6));
|
||||
radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, sq_config);
|
||||
radeon_ring_write(rdev, sq_gpr_resource_mgmt_1);
|
||||
radeon_ring_write(rdev, sq_gpr_resource_mgmt_2);
|
||||
radeon_ring_write(rdev, sq_thread_resource_mgmt);
|
||||
radeon_ring_write(rdev, sq_stack_resource_mgmt_1);
|
||||
radeon_ring_write(rdev, sq_stack_resource_mgmt_2);
|
||||
}
|
||||
|
||||
static inline uint32_t i2f(uint32_t input)
|
||||
{
|
||||
u32 result, i, exponent, fraction;
|
||||
|
||||
if ((input & 0x3fff) == 0)
|
||||
result = 0; /* 0 is a special case */
|
||||
else {
|
||||
exponent = 140; /* exponent biased by 127; */
|
||||
fraction = (input & 0x3fff) << 10; /* cheat and only
|
||||
handle numbers below 2^^15 */
|
||||
for (i = 0; i < 14; i++) {
|
||||
if (fraction & 0x800000)
|
||||
break;
|
||||
else {
|
||||
fraction = fraction << 1; /* keep
|
||||
shifting left until top bit = 1 */
|
||||
exponent = exponent - 1;
|
||||
}
|
||||
}
|
||||
result = exponent << 23 | (fraction & 0x7fffff); /* mask
|
||||
off top bit; assumed 1 */
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int r600_blit_init(struct radeon_device *rdev)
|
||||
{
|
||||
u32 obj_size;
|
||||
int r, dwords;
|
||||
void *ptr;
|
||||
u32 packet2s[16];
|
||||
int num_packet2s = 0;
|
||||
|
||||
rdev->r600_blit.state_offset = 0;
|
||||
|
||||
if (rdev->family >= CHIP_RV770)
|
||||
rdev->r600_blit.state_len = r7xx_default_size;
|
||||
else
|
||||
rdev->r600_blit.state_len = r6xx_default_size;
|
||||
|
||||
dwords = rdev->r600_blit.state_len;
|
||||
while (dwords & 0xf) {
|
||||
packet2s[num_packet2s++] = PACKET2(0);
|
||||
dwords++;
|
||||
}
|
||||
|
||||
obj_size = dwords * 4;
|
||||
obj_size = ALIGN(obj_size, 256);
|
||||
|
||||
rdev->r600_blit.vs_offset = obj_size;
|
||||
obj_size += r6xx_vs_size * 4;
|
||||
obj_size = ALIGN(obj_size, 256);
|
||||
|
||||
rdev->r600_blit.ps_offset = obj_size;
|
||||
obj_size += r6xx_ps_size * 4;
|
||||
obj_size = ALIGN(obj_size, 256);
|
||||
|
||||
r = radeon_object_create(rdev, NULL, obj_size,
|
||||
true, RADEON_GEM_DOMAIN_VRAM,
|
||||
false, &rdev->r600_blit.shader_obj);
|
||||
if (r) {
|
||||
DRM_ERROR("r600 failed to allocate shader\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
DRM_DEBUG("r6xx blit allocated bo %08x vs %08x ps %08x\n",
|
||||
obj_size,
|
||||
rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset);
|
||||
|
||||
r = radeon_object_kmap(rdev->r600_blit.shader_obj, &ptr);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to map blit object %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (rdev->family >= CHIP_RV770)
|
||||
memcpy_toio(ptr + rdev->r600_blit.state_offset,
|
||||
r7xx_default_state, rdev->r600_blit.state_len * 4);
|
||||
else
|
||||
memcpy_toio(ptr + rdev->r600_blit.state_offset,
|
||||
r6xx_default_state, rdev->r600_blit.state_len * 4);
|
||||
if (num_packet2s)
|
||||
memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
|
||||
packet2s, num_packet2s * 4);
|
||||
|
||||
|
||||
memcpy(ptr + rdev->r600_blit.vs_offset, r6xx_vs, r6xx_vs_size * 4);
|
||||
memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
|
||||
|
||||
radeon_object_kunmap(rdev->r600_blit.shader_obj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r600_blit_fini(struct radeon_device *rdev)
|
||||
{
|
||||
radeon_object_unpin(rdev->r600_blit.shader_obj);
|
||||
radeon_object_unref(&rdev->r600_blit.shader_obj);
|
||||
}
|
||||
|
||||
int r600_vb_ib_get(struct radeon_device *rdev)
|
||||
{
|
||||
int r;
|
||||
r = radeon_ib_get(rdev, &rdev->r600_blit.vb_ib);
|
||||
if (r) {
|
||||
DRM_ERROR("failed to get IB for vertex buffer\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
rdev->r600_blit.vb_total = 64*1024;
|
||||
rdev->r600_blit.vb_used = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r600_vb_ib_put(struct radeon_device *rdev)
|
||||
{
|
||||
radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
list_add_tail(&rdev->r600_blit.vb_ib->list, &rdev->ib_pool.scheduled_ibs);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
|
||||
}
|
||||
|
||||
int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
|
||||
{
|
||||
int r;
|
||||
int ring_size, line_size;
|
||||
int max_size;
|
||||
/* loops of emits 64 + fence emit possible */
|
||||
int dwords_per_loop = 76, num_loops;
|
||||
|
||||
r = r600_vb_ib_get(rdev);
|
||||
WARN_ON(r);
|
||||
|
||||
/* set_render_target emits 2 extra dwords on rv6xx */
|
||||
if (rdev->family > CHIP_R600 && rdev->family < CHIP_RV770)
|
||||
dwords_per_loop += 2;
|
||||
|
||||
/* 8 bpp vs 32 bpp for xfer unit */
|
||||
if (size_bytes & 3)
|
||||
line_size = 8192;
|
||||
else
|
||||
line_size = 8192*4;
|
||||
|
||||
max_size = 8192 * line_size;
|
||||
|
||||
/* major loops cover the max size transfer */
|
||||
num_loops = ((size_bytes + max_size) / max_size);
|
||||
/* minor loops cover the extra non aligned bits */
|
||||
num_loops += ((size_bytes % line_size) ? 1 : 0);
|
||||
/* calculate number of loops correctly */
|
||||
ring_size = num_loops * dwords_per_loop;
|
||||
/* set default + shaders */
|
||||
ring_size += 40; /* shaders + def state */
|
||||
ring_size += 3; /* fence emit for VB IB */
|
||||
ring_size += 5; /* done copy */
|
||||
ring_size += 3; /* fence emit for done copy */
|
||||
r = radeon_ring_lock(rdev, ring_size);
|
||||
WARN_ON(r);
|
||||
|
||||
set_default_state(rdev); /* 14 */
|
||||
set_shaders(rdev); /* 26 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence)
|
||||
{
|
||||
int r;
|
||||
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
|
||||
radeon_ring_write(rdev, CACHE_FLUSH_AND_INV_EVENT);
|
||||
/* wait for 3D idle clean */
|
||||
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
|
||||
radeon_ring_write(rdev, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
|
||||
radeon_ring_write(rdev, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit);
|
||||
|
||||
if (rdev->r600_blit.vb_ib)
|
||||
r600_vb_ib_put(rdev);
|
||||
|
||||
if (fence)
|
||||
r = radeon_fence_emit(rdev, fence);
|
||||
|
||||
radeon_ring_unlock_commit(rdev);
|
||||
}
|
||||
|
||||
void r600_kms_blit_copy(struct radeon_device *rdev,
|
||||
u64 src_gpu_addr, u64 dst_gpu_addr,
|
||||
int size_bytes)
|
||||
{
|
||||
int max_bytes;
|
||||
u64 vb_gpu_addr;
|
||||
u32 *vb;
|
||||
|
||||
DRM_DEBUG("emitting copy %16llx %16llx %d %d\n", src_gpu_addr, dst_gpu_addr,
|
||||
size_bytes, rdev->r600_blit.vb_used);
|
||||
vb = (u32 *)(rdev->r600_blit.vb_ib->ptr + rdev->r600_blit.vb_used);
|
||||
if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) {
|
||||
max_bytes = 8192;
|
||||
|
||||
while (size_bytes) {
|
||||
int cur_size = size_bytes;
|
||||
int src_x = src_gpu_addr & 255;
|
||||
int dst_x = dst_gpu_addr & 255;
|
||||
int h = 1;
|
||||
src_gpu_addr = src_gpu_addr & ~255;
|
||||
dst_gpu_addr = dst_gpu_addr & ~255;
|
||||
|
||||
if (!src_x && !dst_x) {
|
||||
h = (cur_size / max_bytes);
|
||||
if (h > 8192)
|
||||
h = 8192;
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
else
|
||||
cur_size = max_bytes;
|
||||
} else {
|
||||
if (cur_size > max_bytes)
|
||||
cur_size = max_bytes;
|
||||
if (cur_size > (max_bytes - dst_x))
|
||||
cur_size = (max_bytes - dst_x);
|
||||
if (cur_size > (max_bytes - src_x))
|
||||
cur_size = (max_bytes - src_x);
|
||||
}
|
||||
|
||||
if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
|
||||
WARN_ON(1);
|
||||
|
||||
#if 0
|
||||
r600_vb_ib_put(rdev);
|
||||
|
||||
r600_nomm_put_vb(dev);
|
||||
r600_nomm_get_vb(dev);
|
||||
if (!dev_priv->blit_vb)
|
||||
return;
|
||||
set_shaders(dev);
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
vb[0] = i2f(dst_x);
|
||||
vb[1] = 0;
|
||||
vb[2] = i2f(src_x);
|
||||
vb[3] = 0;
|
||||
|
||||
vb[4] = i2f(dst_x);
|
||||
vb[5] = i2f(h);
|
||||
vb[6] = i2f(src_x);
|
||||
vb[7] = i2f(h);
|
||||
|
||||
vb[8] = i2f(dst_x + cur_size);
|
||||
vb[9] = i2f(h);
|
||||
vb[10] = i2f(src_x + cur_size);
|
||||
vb[11] = i2f(h);
|
||||
|
||||
/* src 9 */
|
||||
set_tex_resource(rdev, FMT_8,
|
||||
src_x + cur_size, h, src_x + cur_size,
|
||||
src_gpu_addr);
|
||||
|
||||
/* 5 */
|
||||
cp_set_surface_sync(rdev,
|
||||
PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
|
||||
|
||||
/* dst 23 */
|
||||
set_render_target(rdev, COLOR_8,
|
||||
dst_x + cur_size, h,
|
||||
dst_gpu_addr);
|
||||
|
||||
/* scissors 12 */
|
||||
set_scissors(rdev, dst_x, 0, dst_x + cur_size, h);
|
||||
|
||||
/* 14 */
|
||||
vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
|
||||
set_vtx_resource(rdev, vb_gpu_addr);
|
||||
|
||||
/* draw 10 */
|
||||
draw_auto(rdev);
|
||||
|
||||
/* 5 */
|
||||
cp_set_surface_sync(rdev,
|
||||
PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
|
||||
cur_size * h, dst_gpu_addr);
|
||||
|
||||
vb += 12;
|
||||
rdev->r600_blit.vb_used += 12 * 4;
|
||||
|
||||
src_gpu_addr += cur_size * h;
|
||||
dst_gpu_addr += cur_size * h;
|
||||
size_bytes -= cur_size * h;
|
||||
}
|
||||
} else {
|
||||
max_bytes = 8192 * 4;
|
||||
|
||||
while (size_bytes) {
|
||||
int cur_size = size_bytes;
|
||||
int src_x = (src_gpu_addr & 255);
|
||||
int dst_x = (dst_gpu_addr & 255);
|
||||
int h = 1;
|
||||
src_gpu_addr = src_gpu_addr & ~255;
|
||||
dst_gpu_addr = dst_gpu_addr & ~255;
|
||||
|
||||
if (!src_x && !dst_x) {
|
||||
h = (cur_size / max_bytes);
|
||||
if (h > 8192)
|
||||
h = 8192;
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
else
|
||||
cur_size = max_bytes;
|
||||
} else {
|
||||
if (cur_size > max_bytes)
|
||||
cur_size = max_bytes;
|
||||
if (cur_size > (max_bytes - dst_x))
|
||||
cur_size = (max_bytes - dst_x);
|
||||
if (cur_size > (max_bytes - src_x))
|
||||
cur_size = (max_bytes - src_x);
|
||||
}
|
||||
|
||||
if ((rdev->r600_blit.vb_used + 48) > rdev->r600_blit.vb_total) {
|
||||
WARN_ON(1);
|
||||
}
|
||||
#if 0
|
||||
if ((rdev->blit_vb->used + 48) > rdev->blit_vb->total) {
|
||||
r600_nomm_put_vb(dev);
|
||||
r600_nomm_get_vb(dev);
|
||||
if (!rdev->blit_vb)
|
||||
return;
|
||||
|
||||
set_shaders(dev);
|
||||
vb = r600_nomm_get_vb_ptr(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
vb[0] = i2f(dst_x / 4);
|
||||
vb[1] = 0;
|
||||
vb[2] = i2f(src_x / 4);
|
||||
vb[3] = 0;
|
||||
|
||||
vb[4] = i2f(dst_x / 4);
|
||||
vb[5] = i2f(h);
|
||||
vb[6] = i2f(src_x / 4);
|
||||
vb[7] = i2f(h);
|
||||
|
||||
vb[8] = i2f((dst_x + cur_size) / 4);
|
||||
vb[9] = i2f(h);
|
||||
vb[10] = i2f((src_x + cur_size) / 4);
|
||||
vb[11] = i2f(h);
|
||||
|
||||
/* src 9 */
|
||||
set_tex_resource(rdev, FMT_8_8_8_8,
|
||||
(src_x + cur_size) / 4,
|
||||
h, (src_x + cur_size) / 4,
|
||||
src_gpu_addr);
|
||||
/* 5 */
|
||||
cp_set_surface_sync(rdev,
|
||||
PACKET3_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr);
|
||||
|
||||
/* dst 23 */
|
||||
set_render_target(rdev, COLOR_8_8_8_8,
|
||||
dst_x + cur_size, h,
|
||||
dst_gpu_addr);
|
||||
|
||||
/* scissors 12 */
|
||||
set_scissors(rdev, (dst_x / 4), 0, (dst_x + cur_size / 4), h);
|
||||
|
||||
/* Vertex buffer setup 14 */
|
||||
vb_gpu_addr = rdev->r600_blit.vb_ib->gpu_addr + rdev->r600_blit.vb_used;
|
||||
set_vtx_resource(rdev, vb_gpu_addr);
|
||||
|
||||
/* draw 10 */
|
||||
draw_auto(rdev);
|
||||
|
||||
/* 5 */
|
||||
cp_set_surface_sync(rdev,
|
||||
PACKET3_CB_ACTION_ENA | PACKET3_CB0_DEST_BASE_ENA,
|
||||
cur_size * h, dst_gpu_addr);
|
||||
|
||||
/* 78 ring dwords per loop */
|
||||
vb += 12;
|
||||
rdev->r600_blit.vb_used += 12 * 4;
|
||||
|
||||
src_gpu_addr += cur_size * h;
|
||||
dst_gpu_addr += cur_size * h;
|
||||
size_bytes -= cur_size * h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1072
drivers/gpu/drm/radeon/r600_blit_shaders.c
Normal file
1072
drivers/gpu/drm/radeon/r600_blit_shaders.c
Normal file
File diff suppressed because it is too large
Load diff
14
drivers/gpu/drm/radeon/r600_blit_shaders.h
Normal file
14
drivers/gpu/drm/radeon/r600_blit_shaders.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
#ifndef R600_BLIT_SHADERS_H
|
||||
#define R600_BLIT_SHADERS_H
|
||||
|
||||
extern const u32 r6xx_ps[];
|
||||
extern const u32 r6xx_vs[];
|
||||
extern const u32 r7xx_default_state[];
|
||||
extern const u32 r6xx_default_state[];
|
||||
|
||||
|
||||
extern const u32 r6xx_ps_size, r6xx_vs_size;
|
||||
extern const u32 r6xx_default_size, r7xx_default_size;
|
||||
|
||||
#endif
|
|
@ -31,7 +31,38 @@
|
|||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
||||
#include "r600_microcode.h"
|
||||
#define PFP_UCODE_SIZE 576
|
||||
#define PM4_UCODE_SIZE 1792
|
||||
#define R700_PFP_UCODE_SIZE 848
|
||||
#define R700_PM4_UCODE_SIZE 1360
|
||||
|
||||
/* Firmware Names */
|
||||
MODULE_FIRMWARE("radeon/R600_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/R600_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV610_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV610_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV630_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV630_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV620_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV620_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV635_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV635_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV670_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV670_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RS780_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RS780_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV770_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV770_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV730_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV730_me.bin");
|
||||
MODULE_FIRMWARE("radeon/RV710_pfp.bin");
|
||||
MODULE_FIRMWARE("radeon/RV710_me.bin");
|
||||
|
||||
|
||||
int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
|
||||
unsigned family, u32 *ib, int *l);
|
||||
void r600_cs_legacy_init(void);
|
||||
|
||||
|
||||
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
|
||||
# define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1))
|
||||
|
@ -275,11 +306,93 @@ static void r600_vm_init(struct drm_device *dev)
|
|||
r600_vm_flush_gart_range(dev);
|
||||
}
|
||||
|
||||
/* load r600 microcode */
|
||||
static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
const char *chip_name;
|
||||
size_t pfp_req_size, me_req_size;
|
||||
char fw_name[30];
|
||||
int err;
|
||||
|
||||
pdev = platform_device_register_simple("r600_cp", 0, NULL, 0);
|
||||
err = IS_ERR(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "r600_cp: Failed to register firmware\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (dev_priv->flags & RADEON_FAMILY_MASK) {
|
||||
case CHIP_R600: chip_name = "R600"; break;
|
||||
case CHIP_RV610: chip_name = "RV610"; break;
|
||||
case CHIP_RV630: chip_name = "RV630"; break;
|
||||
case CHIP_RV620: chip_name = "RV620"; break;
|
||||
case CHIP_RV635: chip_name = "RV635"; break;
|
||||
case CHIP_RV670: chip_name = "RV670"; break;
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880: chip_name = "RS780"; break;
|
||||
case CHIP_RV770: chip_name = "RV770"; break;
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV740: chip_name = "RV730"; break;
|
||||
case CHIP_RV710: chip_name = "RV710"; break;
|
||||
default: BUG();
|
||||
}
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
|
||||
pfp_req_size = R700_PFP_UCODE_SIZE * 4;
|
||||
me_req_size = R700_PM4_UCODE_SIZE * 4;
|
||||
} else {
|
||||
pfp_req_size = PFP_UCODE_SIZE * 4;
|
||||
me_req_size = PM4_UCODE_SIZE * 12;
|
||||
}
|
||||
|
||||
DRM_INFO("Loading %s CP Microcode\n", chip_name);
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
|
||||
err = request_firmware(&dev_priv->pfp_fw, fw_name, &pdev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
if (dev_priv->pfp_fw->size != pfp_req_size) {
|
||||
printk(KERN_ERR
|
||||
"r600_cp: Bogus length %zu in firmware \"%s\"\n",
|
||||
dev_priv->pfp_fw->size, fw_name);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
|
||||
err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
|
||||
if (err)
|
||||
goto out;
|
||||
if (dev_priv->me_fw->size != me_req_size) {
|
||||
printk(KERN_ERR
|
||||
"r600_cp: Bogus length %zu in firmware \"%s\"\n",
|
||||
dev_priv->me_fw->size, fw_name);
|
||||
err = -EINVAL;
|
||||
}
|
||||
out:
|
||||
platform_device_unregister(pdev);
|
||||
|
||||
if (err) {
|
||||
if (err != -EINVAL)
|
||||
printk(KERN_ERR
|
||||
"r600_cp: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
release_firmware(dev_priv->pfp_fw);
|
||||
dev_priv->pfp_fw = NULL;
|
||||
release_firmware(dev_priv->me_fw);
|
||||
dev_priv->me_fw = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
const __be32 *fw_data;
|
||||
int i;
|
||||
|
||||
if (!dev_priv->me_fw || !dev_priv->pfp_fw)
|
||||
return;
|
||||
|
||||
r600_do_cp_stop(dev_priv);
|
||||
|
||||
RADEON_WRITE(R600_CP_RB_CNTL,
|
||||
|
@ -292,115 +405,18 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
|
|||
DRM_UDELAY(15000);
|
||||
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
|
||||
|
||||
fw_data = (const __be32 *)dev_priv->me_fw->data;
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
for (i = 0; i < PM4_UCODE_SIZE * 3; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
be32_to_cpup(fw_data++));
|
||||
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600)) {
|
||||
DRM_INFO("Loading R600 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
R600_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
R600_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
R600_cp_microcode[i][2]);
|
||||
}
|
||||
fw_data = (const __be32 *)dev_priv->pfp_fw->data;
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA,
|
||||
be32_to_cpup(fw_data++));
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading R600 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, R600_pfp_microcode[i]);
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610)) {
|
||||
DRM_INFO("Loading RV610 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV610_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV610_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV610_cp_microcode[i][2]);
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV610 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV610_pfp_microcode[i]);
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
|
||||
DRM_INFO("Loading RV630 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV630_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV630_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV630_cp_microcode[i][2]);
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV630 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV630_pfp_microcode[i]);
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620)) {
|
||||
DRM_INFO("Loading RV620 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV620_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV620_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV620_cp_microcode[i][2]);
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV620 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV620_pfp_microcode[i]);
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
|
||||
DRM_INFO("Loading RV635 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV635_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV635_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV635_cp_microcode[i][2]);
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV635 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV635_pfp_microcode[i]);
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)) {
|
||||
DRM_INFO("Loading RV670 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV670_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV670_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RV670_cp_microcode[i][2]);
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV670 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
|
||||
DRM_INFO("Loading RS780/RS880 CP Microcode\n");
|
||||
for (i = 0; i < PM4_UCODE_SIZE; i++) {
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RS780_cp_microcode[i][0]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RS780_cp_microcode[i][1]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA,
|
||||
RS780_cp_microcode[i][2]);
|
||||
}
|
||||
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RS780/RS880 PFP Microcode\n");
|
||||
for (i = 0; i < PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RS780_pfp_microcode[i]);
|
||||
}
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
|
||||
|
@ -459,11 +475,14 @@ static void r700_vm_init(struct drm_device *dev)
|
|||
r600_vm_flush_gart_range(dev);
|
||||
}
|
||||
|
||||
/* load r600 microcode */
|
||||
static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
const __be32 *fw_data;
|
||||
int i;
|
||||
|
||||
if (!dev_priv->me_fw || !dev_priv->pfp_fw)
|
||||
return;
|
||||
|
||||
r600_do_cp_stop(dev_priv);
|
||||
|
||||
RADEON_WRITE(R600_CP_RB_CNTL,
|
||||
|
@ -476,48 +495,18 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
|
|||
DRM_UDELAY(15000);
|
||||
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
|
||||
|
||||
fw_data = (const __be32 *)dev_priv->pfp_fw->data;
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV770/RV790 PFP Microcode\n");
|
||||
for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
fw_data = (const __be32 *)dev_priv->me_fw->data;
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
DRM_INFO("Loading RV770/RV790 CP Microcode\n");
|
||||
for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)) {
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV730/RV740 PFP Microcode\n");
|
||||
for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
DRM_INFO("Loading RV730/RV740 CP Microcode\n");
|
||||
for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) {
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
DRM_INFO("Loading RV710 PFP Microcode\n");
|
||||
for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV710_pfp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
DRM_INFO("Loading RV710 CP Microcode\n");
|
||||
for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
|
||||
RADEON_WRITE(R600_CP_ME_RAM_DATA, RV710_cp_microcode[i]);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
|
||||
}
|
||||
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
|
||||
RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
|
||||
|
@ -1874,6 +1863,8 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
|||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
mutex_init(&dev_priv->cs_mutex);
|
||||
r600_cs_legacy_init();
|
||||
/* if we require new memory map but we don't have it fail */
|
||||
if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
|
||||
DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
|
||||
|
@ -1905,7 +1896,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
|||
/* Enable vblank on CRTC1 for older X servers
|
||||
*/
|
||||
dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
|
||||
|
||||
dev_priv->do_boxes = 0;
|
||||
dev_priv->cp_mode = init->cp_mode;
|
||||
|
||||
/* We don't support anything other than bus-mastering ring mode,
|
||||
|
@ -1991,11 +1982,11 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
|
||||
dev_priv->cp_ring->handle = (void *)(unsigned long)dev_priv->cp_ring->offset;
|
||||
dev_priv->ring_rptr->handle =
|
||||
(void *)dev_priv->ring_rptr->offset;
|
||||
(void *)(unsigned long)dev_priv->ring_rptr->offset;
|
||||
dev->agp_buffer_map->handle =
|
||||
(void *)dev->agp_buffer_map->offset;
|
||||
(void *)(unsigned long)dev->agp_buffer_map->offset;
|
||||
|
||||
DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
|
||||
dev_priv->cp_ring->handle);
|
||||
|
@ -2147,6 +2138,14 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
|||
r600_vm_init(dev);
|
||||
}
|
||||
|
||||
if (!dev_priv->me_fw || !dev_priv->pfp_fw) {
|
||||
int err = r600_cp_init_microcode(dev_priv);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to load firmware!\n");
|
||||
r600_do_cleanup_cp(dev);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
|
||||
r700_cp_load_microcode(dev_priv);
|
||||
else
|
||||
|
@ -2291,3 +2290,239 @@ int r600_cp_dispatch_indirect(struct drm_device *dev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_master *master = file_priv->master;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
|
||||
int nbox = sarea_priv->nbox;
|
||||
struct drm_clip_rect *pbox = sarea_priv->boxes;
|
||||
int i, cpp, src_pitch, dst_pitch;
|
||||
uint64_t src, dst;
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888)
|
||||
cpp = 4;
|
||||
else
|
||||
cpp = 2;
|
||||
|
||||
if (sarea_priv->pfCurrentPage == 0) {
|
||||
src_pitch = dev_priv->back_pitch;
|
||||
dst_pitch = dev_priv->front_pitch;
|
||||
src = dev_priv->back_offset + dev_priv->fb_location;
|
||||
dst = dev_priv->front_offset + dev_priv->fb_location;
|
||||
} else {
|
||||
src_pitch = dev_priv->front_pitch;
|
||||
dst_pitch = dev_priv->back_pitch;
|
||||
src = dev_priv->front_offset + dev_priv->fb_location;
|
||||
dst = dev_priv->back_offset + dev_priv->fb_location;
|
||||
}
|
||||
|
||||
if (r600_prepare_blit_copy(dev, file_priv)) {
|
||||
DRM_ERROR("unable to allocate vertex buffer for swap buffer\n");
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < nbox; i++) {
|
||||
int x = pbox[i].x1;
|
||||
int y = pbox[i].y1;
|
||||
int w = pbox[i].x2 - x;
|
||||
int h = pbox[i].y2 - y;
|
||||
|
||||
DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
|
||||
|
||||
r600_blit_swap(dev,
|
||||
src, dst,
|
||||
x, y, x, y, w, h,
|
||||
src_pitch, dst_pitch, cpp);
|
||||
}
|
||||
r600_done_blit_copy(dev);
|
||||
|
||||
/* Increment the frame counter. The client-side 3D driver must
|
||||
* throttle the framerate by waiting for this value before
|
||||
* performing the swapbuffer ioctl.
|
||||
*/
|
||||
sarea_priv->last_frame++;
|
||||
|
||||
BEGIN_RING(3);
|
||||
R600_FRAME_AGE(sarea_priv->last_frame);
|
||||
ADVANCE_RING();
|
||||
}
|
||||
|
||||
int r600_cp_dispatch_texture(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
drm_radeon_texture_t *tex,
|
||||
drm_radeon_tex_image_t *image)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_buf *buf;
|
||||
u32 *buffer;
|
||||
const u8 __user *data;
|
||||
int size, pass_size;
|
||||
u64 src_offset, dst_offset;
|
||||
|
||||
if (!radeon_check_offset(dev_priv, tex->offset)) {
|
||||
DRM_ERROR("Invalid destination offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* this might fail for zero-sized uploads - are those illegal? */
|
||||
if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) {
|
||||
DRM_ERROR("Invalid final destination offset\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = tex->height * tex->pitch;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
dst_offset = tex->offset;
|
||||
|
||||
if (r600_prepare_blit_copy(dev, file_priv)) {
|
||||
DRM_ERROR("unable to allocate vertex buffer for swap buffer\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
do {
|
||||
data = (const u8 __user *)image->data;
|
||||
pass_size = size;
|
||||
|
||||
buf = radeon_freelist_get(dev);
|
||||
if (!buf) {
|
||||
DRM_DEBUG("EAGAIN\n");
|
||||
if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
|
||||
return -EFAULT;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (pass_size > buf->total)
|
||||
pass_size = buf->total;
|
||||
|
||||
/* Dispatch the indirect buffer.
|
||||
*/
|
||||
buffer =
|
||||
(u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
|
||||
|
||||
if (DRM_COPY_FROM_USER(buffer, data, pass_size)) {
|
||||
DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
buf->file_priv = file_priv;
|
||||
buf->used = pass_size;
|
||||
src_offset = dev_priv->gart_buffers_offset + buf->offset;
|
||||
|
||||
r600_blit_copy(dev, src_offset, dst_offset, pass_size);
|
||||
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
|
||||
/* Update the input parameters for next time */
|
||||
image->data = (const u8 __user *)image->data + pass_size;
|
||||
dst_offset += pass_size;
|
||||
size -= pass_size;
|
||||
} while (size > 0);
|
||||
r600_done_blit_copy(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Legacy cs ioctl
|
||||
*/
|
||||
static u32 radeon_cs_id_get(struct drm_radeon_private *radeon)
|
||||
{
|
||||
/* FIXME: check if wrap affect last reported wrap & sequence */
|
||||
radeon->cs_id_scnt = (radeon->cs_id_scnt + 1) & 0x00FFFFFF;
|
||||
if (!radeon->cs_id_scnt) {
|
||||
/* increment wrap counter */
|
||||
radeon->cs_id_wcnt += 0x01000000;
|
||||
/* valid sequence counter start at 1 */
|
||||
radeon->cs_id_scnt = 1;
|
||||
}
|
||||
return (radeon->cs_id_scnt | radeon->cs_id_wcnt);
|
||||
}
|
||||
|
||||
static void r600_cs_id_emit(drm_radeon_private_t *dev_priv, u32 *id)
|
||||
{
|
||||
RING_LOCALS;
|
||||
|
||||
*id = radeon_cs_id_get(dev_priv);
|
||||
|
||||
/* SCRATCH 2 */
|
||||
BEGIN_RING(3);
|
||||
R600_CLEAR_AGE(*id);
|
||||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
}
|
||||
|
||||
static int r600_ib_get(struct drm_device *dev,
|
||||
struct drm_file *fpriv,
|
||||
struct drm_buf **buffer)
|
||||
{
|
||||
struct drm_buf *buf;
|
||||
|
||||
*buffer = NULL;
|
||||
buf = radeon_freelist_get(dev);
|
||||
if (!buf) {
|
||||
return -EBUSY;
|
||||
}
|
||||
buf->file_priv = fpriv;
|
||||
*buffer = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf,
|
||||
struct drm_file *fpriv, int l, int r)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (buf) {
|
||||
if (!r)
|
||||
r600_cp_dispatch_indirect(dev, buf, 0, l * 4);
|
||||
radeon_cp_discard_buffer(dev, fpriv->master, buf);
|
||||
COMMIT_RING();
|
||||
}
|
||||
}
|
||||
|
||||
int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv)
|
||||
{
|
||||
struct drm_radeon_private *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_cs *cs = data;
|
||||
struct drm_buf *buf;
|
||||
unsigned family;
|
||||
int l, r = 0;
|
||||
u32 *ib, cs_id = 0;
|
||||
|
||||
if (dev_priv == NULL) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
family = dev_priv->flags & RADEON_FAMILY_MASK;
|
||||
if (family < CHIP_R600) {
|
||||
DRM_ERROR("cs ioctl valid only for R6XX & R7XX in legacy mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&dev_priv->cs_mutex);
|
||||
/* get ib */
|
||||
r = r600_ib_get(dev, fpriv, &buf);
|
||||
if (r) {
|
||||
DRM_ERROR("ib_get failed\n");
|
||||
goto out;
|
||||
}
|
||||
ib = dev->agp_buffer_map->handle + buf->offset;
|
||||
/* now parse command stream */
|
||||
r = r600_cs_legacy(dev, data, fpriv, family, ib, &l);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
r600_ib_free(dev, buf, fpriv, l, r);
|
||||
/* emit cs id sequence */
|
||||
r600_cs_id_emit(dev_priv, &cs_id);
|
||||
cs->cs_id = cs_id;
|
||||
mutex_unlock(&dev_priv->cs_mutex);
|
||||
return r;
|
||||
}
|
||||
|
|
657
drivers/gpu/drm/radeon/r600_cs.c
Normal file
657
drivers/gpu/drm/radeon/r600_cs.c
Normal file
|
@ -0,0 +1,657 @@
|
|||
/*
|
||||
* Copyright 2008 Advanced Micro Devices, Inc.
|
||||
* Copyright 2008 Red Hat Inc.
|
||||
* Copyright 2009 Jerome Glisse.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#include "drmP.h"
|
||||
#include "radeon.h"
|
||||
#include "r600d.h"
|
||||
#include "avivod.h"
|
||||
|
||||
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc);
|
||||
static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc);
|
||||
typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
|
||||
static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
|
||||
|
||||
/**
|
||||
* r600_cs_packet_parse() - parse cp packet and point ib index to next packet
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @pkt: where to store packet informations
|
||||
*
|
||||
* Assume that chunk_ib_index is properly set. Will return -EINVAL
|
||||
* if packet is bigger than remaining ib size. or if packets is unknown.
|
||||
**/
|
||||
int r600_cs_packet_parse(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
uint32_t header;
|
||||
|
||||
if (idx >= ib_chunk->length_dw) {
|
||||
DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
|
||||
idx, ib_chunk->length_dw);
|
||||
return -EINVAL;
|
||||
}
|
||||
header = ib_chunk->kdata[idx];
|
||||
pkt->idx = idx;
|
||||
pkt->type = CP_PACKET_GET_TYPE(header);
|
||||
pkt->count = CP_PACKET_GET_COUNT(header);
|
||||
pkt->one_reg_wr = 0;
|
||||
switch (pkt->type) {
|
||||
case PACKET_TYPE0:
|
||||
pkt->reg = CP_PACKET0_GET_REG(header);
|
||||
break;
|
||||
case PACKET_TYPE3:
|
||||
pkt->opcode = CP_PACKET3_GET_OPCODE(header);
|
||||
break;
|
||||
case PACKET_TYPE2:
|
||||
pkt->count = -1;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
|
||||
DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
|
||||
pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @data: pointer to relocation data
|
||||
* @offset_start: starting offset
|
||||
* @offset_mask: offset mask (to align start offset on)
|
||||
* @reloc: reloc informations
|
||||
*
|
||||
* Check next packet is relocation packet3, do bo validation and compute
|
||||
* GPU offset using the provided start.
|
||||
**/
|
||||
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_cs_chunk *relocs_chunk;
|
||||
struct radeon_cs_packet p3reloc;
|
||||
unsigned idx;
|
||||
int r;
|
||||
|
||||
if (p->chunk_relocs_idx == -1) {
|
||||
DRM_ERROR("No relocation chunk !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
*cs_reloc = NULL;
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
relocs_chunk = &p->chunks[p->chunk_relocs_idx];
|
||||
r = r600_cs_packet_parse(p, &p3reloc, p->idx);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
p->idx += p3reloc.count + 2;
|
||||
if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
|
||||
DRM_ERROR("No packet3 for relocation for packet at %d.\n",
|
||||
p3reloc.idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
idx = ib_chunk->kdata[p3reloc.idx + 1];
|
||||
if (idx >= relocs_chunk->length_dw) {
|
||||
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
|
||||
idx, relocs_chunk->length_dw);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* FIXME: we assume reloc size is 4 dwords */
|
||||
*cs_reloc = p->relocs_ptr[(idx / 4)];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @data: pointer to relocation data
|
||||
* @offset_start: starting offset
|
||||
* @offset_mask: offset mask (to align start offset on)
|
||||
* @reloc: reloc informations
|
||||
*
|
||||
* Check next packet is relocation packet3, do bo validation and compute
|
||||
* GPU offset using the provided start.
|
||||
**/
|
||||
static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_reloc **cs_reloc)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_cs_chunk *relocs_chunk;
|
||||
struct radeon_cs_packet p3reloc;
|
||||
unsigned idx;
|
||||
int r;
|
||||
|
||||
if (p->chunk_relocs_idx == -1) {
|
||||
DRM_ERROR("No relocation chunk !\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
*cs_reloc = NULL;
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
relocs_chunk = &p->chunks[p->chunk_relocs_idx];
|
||||
r = r600_cs_packet_parse(p, &p3reloc, p->idx);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
p->idx += p3reloc.count + 2;
|
||||
if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
|
||||
DRM_ERROR("No packet3 for relocation for packet at %d.\n",
|
||||
p3reloc.idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
idx = ib_chunk->kdata[p3reloc.idx + 1];
|
||||
if (idx >= relocs_chunk->length_dw) {
|
||||
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
|
||||
idx, relocs_chunk->length_dw);
|
||||
return -EINVAL;
|
||||
}
|
||||
*cs_reloc = &p->relocs[0];
|
||||
(*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
|
||||
(*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r600_packet0_check(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt,
|
||||
unsigned idx, unsigned reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case AVIVO_D1MODE_VLINE_START_END:
|
||||
case AVIVO_D2MODE_VLINE_START_END:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
|
||||
reg, idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt)
|
||||
{
|
||||
unsigned reg, i;
|
||||
unsigned idx;
|
||||
int r;
|
||||
|
||||
idx = pkt->idx + 1;
|
||||
reg = pkt->reg;
|
||||
for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
|
||||
r = r600_packet0_check(p, pkt, idx, reg);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r600_packet3_check(struct radeon_cs_parser *p,
|
||||
struct radeon_cs_packet *pkt)
|
||||
{
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_cs_reloc *reloc;
|
||||
volatile u32 *ib;
|
||||
unsigned idx;
|
||||
unsigned i;
|
||||
unsigned start_reg, end_reg, reg;
|
||||
int r;
|
||||
|
||||
ib = p->ib->ptr;
|
||||
ib_chunk = &p->chunks[p->chunk_ib_idx];
|
||||
idx = pkt->idx + 1;
|
||||
switch (pkt->opcode) {
|
||||
case PACKET3_START_3D_CMDBUF:
|
||||
if (p->family >= CHIP_RV770 || pkt->count) {
|
||||
DRM_ERROR("bad START_3D\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_CONTEXT_CONTROL:
|
||||
if (pkt->count != 1) {
|
||||
DRM_ERROR("bad CONTEXT_CONTROL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_INDEX_TYPE:
|
||||
case PACKET3_NUM_INSTANCES:
|
||||
if (pkt->count) {
|
||||
DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_DRAW_INDEX:
|
||||
if (pkt->count != 3) {
|
||||
DRM_ERROR("bad DRAW_INDEX\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad DRAW_INDEX\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+0] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
|
||||
ib[idx+1] = upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
|
||||
break;
|
||||
case PACKET3_DRAW_INDEX_AUTO:
|
||||
if (pkt->count != 1) {
|
||||
DRM_ERROR("bad DRAW_INDEX_AUTO\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_DRAW_INDEX_IMMD_BE:
|
||||
case PACKET3_DRAW_INDEX_IMMD:
|
||||
if (pkt->count < 2) {
|
||||
DRM_ERROR("bad DRAW_INDEX_IMMD\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_WAIT_REG_MEM:
|
||||
if (pkt->count != 5) {
|
||||
DRM_ERROR("bad WAIT_REG_MEM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* bit 4 is reg (0) or mem (1) */
|
||||
if (ib_chunk->kdata[idx+0] & 0x10) {
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad WAIT_REG_MEM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
|
||||
ib[idx+2] = upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SURFACE_SYNC:
|
||||
if (pkt->count != 3) {
|
||||
DRM_ERROR("bad SURFACE_SYNC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* 0xffffffff/0x0 is flush all cache flag */
|
||||
if (ib_chunk->kdata[idx+1] != 0xffffffff ||
|
||||
ib_chunk->kdata[idx+2] != 0) {
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SURFACE_SYNC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
}
|
||||
break;
|
||||
case PACKET3_EVENT_WRITE:
|
||||
if (pkt->count != 2 && pkt->count != 0) {
|
||||
DRM_ERROR("bad EVENT_WRITE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pkt->count) {
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad EVENT_WRITE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
|
||||
ib[idx+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
|
||||
}
|
||||
break;
|
||||
case PACKET3_EVENT_WRITE_EOP:
|
||||
if (pkt->count != 4) {
|
||||
DRM_ERROR("bad EVENT_WRITE_EOP\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad EVENT_WRITE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
|
||||
ib[idx+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
|
||||
break;
|
||||
case PACKET3_SET_CONFIG_REG:
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_CONFIG_REG_END) ||
|
||||
(end_reg >= PACKET3_SET_CONFIG_REG_END)) {
|
||||
DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < pkt->count; i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
switch (reg) {
|
||||
case CP_COHER_BASE:
|
||||
/* use PACKET3_SURFACE_SYNC */
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_CONTEXT_REG:
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
|
||||
(end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
|
||||
DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < pkt->count; i++) {
|
||||
reg = start_reg + (4 * i);
|
||||
switch (reg) {
|
||||
case DB_DEPTH_BASE:
|
||||
case CB_COLOR0_BASE:
|
||||
case CB_COLOR1_BASE:
|
||||
case CB_COLOR2_BASE:
|
||||
case CB_COLOR3_BASE:
|
||||
case CB_COLOR4_BASE:
|
||||
case CB_COLOR5_BASE:
|
||||
case CB_COLOR6_BASE:
|
||||
case CB_COLOR7_BASE:
|
||||
case SQ_PGM_START_FS:
|
||||
case SQ_PGM_START_ES:
|
||||
case SQ_PGM_START_VS:
|
||||
case SQ_PGM_START_GS:
|
||||
case SQ_PGM_START_PS:
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_CONTEXT_REG "
|
||||
"0x%04X\n", reg);
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
break;
|
||||
case VGT_DMA_BASE:
|
||||
case VGT_DMA_BASE_HI:
|
||||
/* These should be handled by DRAW_INDEX packet 3 */
|
||||
case VGT_STRMOUT_BASE_OFFSET_0:
|
||||
case VGT_STRMOUT_BASE_OFFSET_1:
|
||||
case VGT_STRMOUT_BASE_OFFSET_2:
|
||||
case VGT_STRMOUT_BASE_OFFSET_3:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_0:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_1:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_2:
|
||||
case VGT_STRMOUT_BASE_OFFSET_HI_3:
|
||||
case VGT_STRMOUT_BUFFER_BASE_0:
|
||||
case VGT_STRMOUT_BUFFER_BASE_1:
|
||||
case VGT_STRMOUT_BUFFER_BASE_2:
|
||||
case VGT_STRMOUT_BUFFER_BASE_3:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_0:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_1:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_2:
|
||||
case VGT_STRMOUT_BUFFER_OFFSET_3:
|
||||
/* These should be handled by STRMOUT_BUFFER packet 3 */
|
||||
DRM_ERROR("bad context reg: 0x%08x\n", reg);
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_RESOURCE:
|
||||
if (pkt->count % 7) {
|
||||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_RESOURCE_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_RESOURCE_END) ||
|
||||
(end_reg >= PACKET3_SET_RESOURCE_END)) {
|
||||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < (pkt->count / 7); i++) {
|
||||
switch (G__SQ_VTX_CONSTANT_TYPE(ib[idx+(i*7)+6+1])) {
|
||||
case SQ_TEX_VTX_VALID_TEXTURE:
|
||||
/* tex base */
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
/* tex mip base */
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
|
||||
break;
|
||||
case SQ_TEX_VTX_VALID_BUFFER:
|
||||
/* vtx base */
|
||||
r = r600_cs_packet_next_reloc(p, &reloc);
|
||||
if (r) {
|
||||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
case SQ_TEX_VTX_INVALID_TEXTURE:
|
||||
case SQ_TEX_VTX_INVALID_BUFFER:
|
||||
default:
|
||||
DRM_ERROR("bad SET_RESOURCE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_ALU_CONST:
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_ALU_CONST_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_ALU_CONST_END) ||
|
||||
(end_reg >= PACKET3_SET_ALU_CONST_END)) {
|
||||
DRM_ERROR("bad SET_ALU_CONST\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_BOOL_CONST:
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_BOOL_CONST_END) ||
|
||||
(end_reg >= PACKET3_SET_BOOL_CONST_END)) {
|
||||
DRM_ERROR("bad SET_BOOL_CONST\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_LOOP_CONST:
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_LOOP_CONST_END) ||
|
||||
(end_reg >= PACKET3_SET_LOOP_CONST_END)) {
|
||||
DRM_ERROR("bad SET_LOOP_CONST\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_CTL_CONST:
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_CTL_CONST_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_CTL_CONST_END) ||
|
||||
(end_reg >= PACKET3_SET_CTL_CONST_END)) {
|
||||
DRM_ERROR("bad SET_CTL_CONST\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SET_SAMPLER:
|
||||
if (pkt->count % 3) {
|
||||
DRM_ERROR("bad SET_SAMPLER\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
start_reg = (ib[idx+0] << 2) + PACKET3_SET_SAMPLER_OFFSET;
|
||||
end_reg = 4 * pkt->count + start_reg - 4;
|
||||
if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
|
||||
(start_reg >= PACKET3_SET_SAMPLER_END) ||
|
||||
(end_reg >= PACKET3_SET_SAMPLER_END)) {
|
||||
DRM_ERROR("bad SET_SAMPLER\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_SURFACE_BASE_UPDATE:
|
||||
if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
|
||||
DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pkt->count) {
|
||||
DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PACKET3_NOP:
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r600_cs_parse(struct radeon_cs_parser *p)
|
||||
{
|
||||
struct radeon_cs_packet pkt;
|
||||
int r;
|
||||
|
||||
do {
|
||||
r = r600_cs_packet_parse(p, &pkt, p->idx);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
p->idx += pkt.count + 2;
|
||||
switch (pkt.type) {
|
||||
case PACKET_TYPE0:
|
||||
r = r600_cs_parse_packet0(p, &pkt);
|
||||
break;
|
||||
case PACKET_TYPE2:
|
||||
break;
|
||||
case PACKET_TYPE3:
|
||||
r = r600_packet3_check(p, &pkt);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown packet type %d !\n", pkt.type);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
|
||||
#if 0
|
||||
for (r = 0; r < p->ib->length_dw; r++) {
|
||||
printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
|
||||
mdelay(1);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
|
||||
{
|
||||
if (p->chunk_relocs_idx == -1) {
|
||||
return 0;
|
||||
}
|
||||
p->relocs = kcalloc(1, sizeof(struct radeon_cs_reloc), GFP_KERNEL);
|
||||
if (p->relocs == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cs_parser_fini() - clean parser states
|
||||
* @parser: parser structure holding parsing context.
|
||||
* @error: error number
|
||||
*
|
||||
* If error is set than unvalidate buffer, otherwise just free memory
|
||||
* used by parsing context.
|
||||
**/
|
||||
static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
kfree(parser->relocs);
|
||||
for (i = 0; i < parser->nchunks; i++) {
|
||||
kfree(parser->chunks[i].kdata);
|
||||
}
|
||||
kfree(parser->chunks);
|
||||
kfree(parser->chunks_array);
|
||||
}
|
||||
|
||||
int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
|
||||
unsigned family, u32 *ib, int *l)
|
||||
{
|
||||
struct radeon_cs_parser parser;
|
||||
struct radeon_cs_chunk *ib_chunk;
|
||||
struct radeon_ib fake_ib;
|
||||
int r;
|
||||
|
||||
/* initialize parser */
|
||||
memset(&parser, 0, sizeof(struct radeon_cs_parser));
|
||||
parser.filp = filp;
|
||||
parser.rdev = NULL;
|
||||
parser.family = family;
|
||||
parser.ib = &fake_ib;
|
||||
fake_ib.ptr = ib;
|
||||
r = radeon_cs_parser_init(&parser, data);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to initialize parser !\n");
|
||||
r600_cs_parser_fini(&parser, r);
|
||||
return r;
|
||||
}
|
||||
r = r600_cs_parser_relocs_legacy(&parser);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to parse relocation !\n");
|
||||
r600_cs_parser_fini(&parser, r);
|
||||
return r;
|
||||
}
|
||||
/* Copy the packet into the IB, the parser will read from the
|
||||
* input memory (cached) and write to the IB (which can be
|
||||
* uncached). */
|
||||
ib_chunk = &parser.chunks[parser.chunk_ib_idx];
|
||||
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;
|
||||
r = r600_cs_parse(&parser);
|
||||
if (r) {
|
||||
DRM_ERROR("Invalid command stream !\n");
|
||||
r600_cs_parser_fini(&parser, r);
|
||||
return r;
|
||||
}
|
||||
r600_cs_parser_fini(&parser, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void r600_cs_legacy_init(void)
|
||||
{
|
||||
r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
|
||||
}
|
File diff suppressed because it is too large
Load diff
662
drivers/gpu/drm/radeon/r600d.h
Normal file
662
drivers/gpu/drm/radeon/r600d.h
Normal file
|
@ -0,0 +1,662 @@
|
|||
/*
|
||||
* Copyright 2009 Advanced Micro Devices, Inc.
|
||||
* Copyright 2009 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Dave Airlie
|
||||
* Alex Deucher
|
||||
* Jerome Glisse
|
||||
*/
|
||||
#ifndef R600D_H
|
||||
#define R600D_H
|
||||
|
||||
#define CP_PACKET2 0x80000000
|
||||
#define PACKET2_PAD_SHIFT 0
|
||||
#define PACKET2_PAD_MASK (0x3fffffff << 0)
|
||||
|
||||
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
|
||||
|
||||
#define R6XX_MAX_SH_GPRS 256
|
||||
#define R6XX_MAX_TEMP_GPRS 16
|
||||
#define R6XX_MAX_SH_THREADS 256
|
||||
#define R6XX_MAX_SH_STACK_ENTRIES 4096
|
||||
#define R6XX_MAX_BACKENDS 8
|
||||
#define R6XX_MAX_BACKENDS_MASK 0xff
|
||||
#define R6XX_MAX_SIMDS 8
|
||||
#define R6XX_MAX_SIMDS_MASK 0xff
|
||||
#define R6XX_MAX_PIPES 8
|
||||
#define R6XX_MAX_PIPES_MASK 0xff
|
||||
|
||||
/* PTE flags */
|
||||
#define PTE_VALID (1 << 0)
|
||||
#define PTE_SYSTEM (1 << 1)
|
||||
#define PTE_SNOOPED (1 << 2)
|
||||
#define PTE_READABLE (1 << 5)
|
||||
#define PTE_WRITEABLE (1 << 6)
|
||||
|
||||
/* Registers */
|
||||
#define ARB_POP 0x2418
|
||||
#define ENABLE_TC128 (1 << 30)
|
||||
#define ARB_GDEC_RD_CNTL 0x246C
|
||||
|
||||
#define CC_GC_SHADER_PIPE_CONFIG 0x8950
|
||||
#define CC_RB_BACKEND_DISABLE 0x98F4
|
||||
#define BACKEND_DISABLE(x) ((x) << 16)
|
||||
|
||||
#define CB_COLOR0_BASE 0x28040
|
||||
#define CB_COLOR1_BASE 0x28044
|
||||
#define CB_COLOR2_BASE 0x28048
|
||||
#define CB_COLOR3_BASE 0x2804C
|
||||
#define CB_COLOR4_BASE 0x28050
|
||||
#define CB_COLOR5_BASE 0x28054
|
||||
#define CB_COLOR6_BASE 0x28058
|
||||
#define CB_COLOR7_BASE 0x2805C
|
||||
#define CB_COLOR7_FRAG 0x280FC
|
||||
|
||||
#define CB_COLOR0_SIZE 0x28060
|
||||
#define CB_COLOR0_VIEW 0x28080
|
||||
#define CB_COLOR0_INFO 0x280a0
|
||||
#define CB_COLOR0_TILE 0x280c0
|
||||
#define CB_COLOR0_FRAG 0x280e0
|
||||
#define CB_COLOR0_MASK 0x28100
|
||||
|
||||
#define CONFIG_MEMSIZE 0x5428
|
||||
#define CONFIG_CNTL 0x5424
|
||||
#define CP_STAT 0x8680
|
||||
#define CP_COHER_BASE 0x85F8
|
||||
#define CP_DEBUG 0xC1FC
|
||||
#define R_0086D8_CP_ME_CNTL 0x86D8
|
||||
#define S_0086D8_CP_ME_HALT(x) (((x) & 1)<<28)
|
||||
#define C_0086D8_CP_ME_HALT(x) ((x) & 0xEFFFFFFF)
|
||||
#define CP_ME_RAM_DATA 0xC160
|
||||
#define CP_ME_RAM_RADDR 0xC158
|
||||
#define CP_ME_RAM_WADDR 0xC15C
|
||||
#define CP_MEQ_THRESHOLDS 0x8764
|
||||
#define MEQ_END(x) ((x) << 16)
|
||||
#define ROQ_END(x) ((x) << 24)
|
||||
#define CP_PERFMON_CNTL 0x87FC
|
||||
#define CP_PFP_UCODE_ADDR 0xC150
|
||||
#define CP_PFP_UCODE_DATA 0xC154
|
||||
#define CP_QUEUE_THRESHOLDS 0x8760
|
||||
#define ROQ_IB1_START(x) ((x) << 0)
|
||||
#define ROQ_IB2_START(x) ((x) << 8)
|
||||
#define CP_RB_BASE 0xC100
|
||||
#define CP_RB_CNTL 0xC104
|
||||
#define RB_BUFSZ(x) ((x)<<0)
|
||||
#define RB_BLKSZ(x) ((x)<<8)
|
||||
#define RB_NO_UPDATE (1<<27)
|
||||
#define RB_RPTR_WR_ENA (1<<31)
|
||||
#define BUF_SWAP_32BIT (2 << 16)
|
||||
#define CP_RB_RPTR 0x8700
|
||||
#define CP_RB_RPTR_ADDR 0xC10C
|
||||
#define CP_RB_RPTR_ADDR_HI 0xC110
|
||||
#define CP_RB_RPTR_WR 0xC108
|
||||
#define CP_RB_WPTR 0xC114
|
||||
#define CP_RB_WPTR_ADDR 0xC118
|
||||
#define CP_RB_WPTR_ADDR_HI 0xC11C
|
||||
#define CP_RB_WPTR_DELAY 0x8704
|
||||
#define CP_ROQ_IB1_STAT 0x8784
|
||||
#define CP_ROQ_IB2_STAT 0x8788
|
||||
#define CP_SEM_WAIT_TIMER 0x85BC
|
||||
|
||||
#define DB_DEBUG 0x9830
|
||||
#define PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31)
|
||||
#define DB_DEPTH_BASE 0x2800C
|
||||
#define DB_WATERMARKS 0x9838
|
||||
#define DEPTH_FREE(x) ((x) << 0)
|
||||
#define DEPTH_FLUSH(x) ((x) << 5)
|
||||
#define DEPTH_PENDING_FREE(x) ((x) << 15)
|
||||
#define DEPTH_CACHELINE_FREE(x) ((x) << 20)
|
||||
|
||||
#define DCP_TILING_CONFIG 0x6CA0
|
||||
#define PIPE_TILING(x) ((x) << 1)
|
||||
#define BANK_TILING(x) ((x) << 4)
|
||||
#define GROUP_SIZE(x) ((x) << 6)
|
||||
#define ROW_TILING(x) ((x) << 8)
|
||||
#define BANK_SWAPS(x) ((x) << 11)
|
||||
#define SAMPLE_SPLIT(x) ((x) << 14)
|
||||
#define BACKEND_MAP(x) ((x) << 16)
|
||||
|
||||
#define GB_TILING_CONFIG 0x98F0
|
||||
|
||||
#define GC_USER_SHADER_PIPE_CONFIG 0x8954
|
||||
#define INACTIVE_QD_PIPES(x) ((x) << 8)
|
||||
#define INACTIVE_QD_PIPES_MASK 0x0000FF00
|
||||
#define INACTIVE_SIMDS(x) ((x) << 16)
|
||||
#define INACTIVE_SIMDS_MASK 0x00FF0000
|
||||
|
||||
#define SQ_CONFIG 0x8c00
|
||||
# define VC_ENABLE (1 << 0)
|
||||
# define EXPORT_SRC_C (1 << 1)
|
||||
# define DX9_CONSTS (1 << 2)
|
||||
# define ALU_INST_PREFER_VECTOR (1 << 3)
|
||||
# define DX10_CLAMP (1 << 4)
|
||||
# define CLAUSE_SEQ_PRIO(x) ((x) << 8)
|
||||
# define PS_PRIO(x) ((x) << 24)
|
||||
# define VS_PRIO(x) ((x) << 26)
|
||||
# define GS_PRIO(x) ((x) << 28)
|
||||
# define ES_PRIO(x) ((x) << 30)
|
||||
#define SQ_GPR_RESOURCE_MGMT_1 0x8c04
|
||||
# define NUM_PS_GPRS(x) ((x) << 0)
|
||||
# define NUM_VS_GPRS(x) ((x) << 16)
|
||||
# define NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28)
|
||||
#define SQ_GPR_RESOURCE_MGMT_2 0x8c08
|
||||
# define NUM_GS_GPRS(x) ((x) << 0)
|
||||
# define NUM_ES_GPRS(x) ((x) << 16)
|
||||
#define SQ_THREAD_RESOURCE_MGMT 0x8c0c
|
||||
# define NUM_PS_THREADS(x) ((x) << 0)
|
||||
# define NUM_VS_THREADS(x) ((x) << 8)
|
||||
# define NUM_GS_THREADS(x) ((x) << 16)
|
||||
# define NUM_ES_THREADS(x) ((x) << 24)
|
||||
#define SQ_STACK_RESOURCE_MGMT_1 0x8c10
|
||||
# define NUM_PS_STACK_ENTRIES(x) ((x) << 0)
|
||||
# define NUM_VS_STACK_ENTRIES(x) ((x) << 16)
|
||||
#define SQ_STACK_RESOURCE_MGMT_2 0x8c14
|
||||
# define NUM_GS_STACK_ENTRIES(x) ((x) << 0)
|
||||
# define NUM_ES_STACK_ENTRIES(x) ((x) << 16)
|
||||
|
||||
#define GRBM_CNTL 0x8000
|
||||
# define GRBM_READ_TIMEOUT(x) ((x) << 0)
|
||||
#define GRBM_STATUS 0x8010
|
||||
#define CMDFIFO_AVAIL_MASK 0x0000001F
|
||||
#define GUI_ACTIVE (1<<31)
|
||||
#define GRBM_STATUS2 0x8014
|
||||
#define GRBM_SOFT_RESET 0x8020
|
||||
#define SOFT_RESET_CP (1<<0)
|
||||
|
||||
#define HDP_HOST_PATH_CNTL 0x2C00
|
||||
#define HDP_NONSURFACE_BASE 0x2C04
|
||||
#define HDP_NONSURFACE_INFO 0x2C08
|
||||
#define HDP_NONSURFACE_SIZE 0x2C0C
|
||||
#define HDP_REG_COHERENCY_FLUSH_CNTL 0x54A0
|
||||
#define HDP_TILING_CONFIG 0x2F3C
|
||||
|
||||
#define MC_VM_AGP_TOP 0x2184
|
||||
#define MC_VM_AGP_BOT 0x2188
|
||||
#define MC_VM_AGP_BASE 0x218C
|
||||
#define MC_VM_FB_LOCATION 0x2180
|
||||
#define MC_VM_L1_TLB_MCD_RD_A_CNTL 0x219C
|
||||
#define ENABLE_L1_TLB (1 << 0)
|
||||
#define ENABLE_L1_FRAGMENT_PROCESSING (1 << 1)
|
||||
#define ENABLE_L1_STRICT_ORDERING (1 << 2)
|
||||
#define SYSTEM_ACCESS_MODE_MASK 0x000000C0
|
||||
#define SYSTEM_ACCESS_MODE_SHIFT 6
|
||||
#define SYSTEM_ACCESS_MODE_PA_ONLY (0 << 6)
|
||||
#define SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 6)
|
||||
#define SYSTEM_ACCESS_MODE_IN_SYS (2 << 6)
|
||||
#define SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 6)
|
||||
#define SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 8)
|
||||
#define SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 8)
|
||||
#define ENABLE_SEMAPHORE_MODE (1 << 10)
|
||||
#define ENABLE_WAIT_L2_QUERY (1 << 11)
|
||||
#define EFFECTIVE_L1_TLB_SIZE(x) (((x) & 7) << 12)
|
||||
#define EFFECTIVE_L1_TLB_SIZE_MASK 0x00007000
|
||||
#define EFFECTIVE_L1_TLB_SIZE_SHIFT 12
|
||||
#define EFFECTIVE_L1_QUEUE_SIZE(x) (((x) & 7) << 15)
|
||||
#define EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00038000
|
||||
#define EFFECTIVE_L1_QUEUE_SIZE_SHIFT 15
|
||||
#define MC_VM_L1_TLB_MCD_RD_B_CNTL 0x21A0
|
||||
#define MC_VM_L1_TLB_MCB_RD_GFX_CNTL 0x21FC
|
||||
#define MC_VM_L1_TLB_MCB_RD_HDP_CNTL 0x2204
|
||||
#define MC_VM_L1_TLB_MCB_RD_PDMA_CNTL 0x2208
|
||||
#define MC_VM_L1_TLB_MCB_RD_SEM_CNTL 0x220C
|
||||
#define MC_VM_L1_TLB_MCB_RD_SYS_CNTL 0x2200
|
||||
#define MC_VM_L1_TLB_MCD_WR_A_CNTL 0x21A4
|
||||
#define MC_VM_L1_TLB_MCD_WR_B_CNTL 0x21A8
|
||||
#define MC_VM_L1_TLB_MCB_WR_GFX_CNTL 0x2210
|
||||
#define MC_VM_L1_TLB_MCB_WR_HDP_CNTL 0x2218
|
||||
#define MC_VM_L1_TLB_MCB_WR_PDMA_CNTL 0x221C
|
||||
#define MC_VM_L1_TLB_MCB_WR_SEM_CNTL 0x2220
|
||||
#define MC_VM_L1_TLB_MCB_WR_SYS_CNTL 0x2214
|
||||
#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190
|
||||
#define LOGICAL_PAGE_NUMBER_MASK 0x000FFFFF
|
||||
#define LOGICAL_PAGE_NUMBER_SHIFT 0
|
||||
#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194
|
||||
#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198
|
||||
|
||||
#define PA_CL_ENHANCE 0x8A14
|
||||
#define CLIP_VTX_REORDER_ENA (1 << 0)
|
||||
#define NUM_CLIP_SEQ(x) ((x) << 1)
|
||||
#define PA_SC_AA_CONFIG 0x28C04
|
||||
#define PA_SC_AA_SAMPLE_LOCS_2S 0x8B40
|
||||
#define PA_SC_AA_SAMPLE_LOCS_4S 0x8B44
|
||||
#define PA_SC_AA_SAMPLE_LOCS_8S_WD0 0x8B48
|
||||
#define PA_SC_AA_SAMPLE_LOCS_8S_WD1 0x8B4C
|
||||
#define S0_X(x) ((x) << 0)
|
||||
#define S0_Y(x) ((x) << 4)
|
||||
#define S1_X(x) ((x) << 8)
|
||||
#define S1_Y(x) ((x) << 12)
|
||||
#define S2_X(x) ((x) << 16)
|
||||
#define S2_Y(x) ((x) << 20)
|
||||
#define S3_X(x) ((x) << 24)
|
||||
#define S3_Y(x) ((x) << 28)
|
||||
#define S4_X(x) ((x) << 0)
|
||||
#define S4_Y(x) ((x) << 4)
|
||||
#define S5_X(x) ((x) << 8)
|
||||
#define S5_Y(x) ((x) << 12)
|
||||
#define S6_X(x) ((x) << 16)
|
||||
#define S6_Y(x) ((x) << 20)
|
||||
#define S7_X(x) ((x) << 24)
|
||||
#define S7_Y(x) ((x) << 28)
|
||||
#define PA_SC_CLIPRECT_RULE 0x2820c
|
||||
#define PA_SC_ENHANCE 0x8BF0
|
||||
#define FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0)
|
||||
#define FORCE_EOV_MAX_TILE_CNT(x) ((x) << 12)
|
||||
#define PA_SC_LINE_STIPPLE 0x28A0C
|
||||
#define PA_SC_LINE_STIPPLE_STATE 0x8B10
|
||||
#define PA_SC_MODE_CNTL 0x28A4C
|
||||
#define PA_SC_MULTI_CHIP_CNTL 0x8B20
|
||||
|
||||
#define PA_SC_SCREEN_SCISSOR_TL 0x28030
|
||||
#define PA_SC_GENERIC_SCISSOR_TL 0x28240
|
||||
#define PA_SC_WINDOW_SCISSOR_TL 0x28204
|
||||
|
||||
#define PCIE_PORT_INDEX 0x0038
|
||||
#define PCIE_PORT_DATA 0x003C
|
||||
|
||||
#define RAMCFG 0x2408
|
||||
#define NOOFBANK_SHIFT 0
|
||||
#define NOOFBANK_MASK 0x00000001
|
||||
#define NOOFRANK_SHIFT 1
|
||||
#define NOOFRANK_MASK 0x00000002
|
||||
#define NOOFROWS_SHIFT 2
|
||||
#define NOOFROWS_MASK 0x0000001C
|
||||
#define NOOFCOLS_SHIFT 5
|
||||
#define NOOFCOLS_MASK 0x00000060
|
||||
#define CHANSIZE_SHIFT 7
|
||||
#define CHANSIZE_MASK 0x00000080
|
||||
#define BURSTLENGTH_SHIFT 8
|
||||
#define BURSTLENGTH_MASK 0x00000100
|
||||
#define CHANSIZE_OVERRIDE (1 << 10)
|
||||
|
||||
#define SCRATCH_REG0 0x8500
|
||||
#define SCRATCH_REG1 0x8504
|
||||
#define SCRATCH_REG2 0x8508
|
||||
#define SCRATCH_REG3 0x850C
|
||||
#define SCRATCH_REG4 0x8510
|
||||
#define SCRATCH_REG5 0x8514
|
||||
#define SCRATCH_REG6 0x8518
|
||||
#define SCRATCH_REG7 0x851C
|
||||
#define SCRATCH_UMSK 0x8540
|
||||
#define SCRATCH_ADDR 0x8544
|
||||
|
||||
#define SPI_CONFIG_CNTL 0x9100
|
||||
#define GPR_WRITE_PRIORITY(x) ((x) << 0)
|
||||
#define DISABLE_INTERP_1 (1 << 5)
|
||||
#define SPI_CONFIG_CNTL_1 0x913C
|
||||
#define VTX_DONE_DELAY(x) ((x) << 0)
|
||||
#define INTERP_ONE_PRIM_PER_ROW (1 << 4)
|
||||
#define SPI_INPUT_Z 0x286D8
|
||||
#define SPI_PS_IN_CONTROL_0 0x286CC
|
||||
#define NUM_INTERP(x) ((x)<<0)
|
||||
#define POSITION_ENA (1<<8)
|
||||
#define POSITION_CENTROID (1<<9)
|
||||
#define POSITION_ADDR(x) ((x)<<10)
|
||||
#define PARAM_GEN(x) ((x)<<15)
|
||||
#define PARAM_GEN_ADDR(x) ((x)<<19)
|
||||
#define BARYC_SAMPLE_CNTL(x) ((x)<<26)
|
||||
#define PERSP_GRADIENT_ENA (1<<28)
|
||||
#define LINEAR_GRADIENT_ENA (1<<29)
|
||||
#define POSITION_SAMPLE (1<<30)
|
||||
#define BARYC_AT_SAMPLE_ENA (1<<31)
|
||||
#define SPI_PS_IN_CONTROL_1 0x286D0
|
||||
#define GEN_INDEX_PIX (1<<0)
|
||||
#define GEN_INDEX_PIX_ADDR(x) ((x)<<1)
|
||||
#define FRONT_FACE_ENA (1<<8)
|
||||
#define FRONT_FACE_CHAN(x) ((x)<<9)
|
||||
#define FRONT_FACE_ALL_BITS (1<<11)
|
||||
#define FRONT_FACE_ADDR(x) ((x)<<12)
|
||||
#define FOG_ADDR(x) ((x)<<17)
|
||||
#define FIXED_PT_POSITION_ENA (1<<24)
|
||||
#define FIXED_PT_POSITION_ADDR(x) ((x)<<25)
|
||||
|
||||
#define SQ_MS_FIFO_SIZES 0x8CF0
|
||||
#define CACHE_FIFO_SIZE(x) ((x) << 0)
|
||||
#define FETCH_FIFO_HIWATER(x) ((x) << 8)
|
||||
#define DONE_FIFO_HIWATER(x) ((x) << 16)
|
||||
#define ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24)
|
||||
#define SQ_PGM_START_ES 0x28880
|
||||
#define SQ_PGM_START_FS 0x28894
|
||||
#define SQ_PGM_START_GS 0x2886C
|
||||
#define SQ_PGM_START_PS 0x28840
|
||||
#define SQ_PGM_RESOURCES_PS 0x28850
|
||||
#define SQ_PGM_EXPORTS_PS 0x28854
|
||||
#define SQ_PGM_CF_OFFSET_PS 0x288cc
|
||||
#define SQ_PGM_START_VS 0x28858
|
||||
#define SQ_PGM_RESOURCES_VS 0x28868
|
||||
#define SQ_PGM_CF_OFFSET_VS 0x288d0
|
||||
#define SQ_VTX_CONSTANT_WORD6_0 0x38018
|
||||
#define S__SQ_VTX_CONSTANT_TYPE(x) (((x) & 3) << 30)
|
||||
#define G__SQ_VTX_CONSTANT_TYPE(x) (((x) >> 30) & 3)
|
||||
#define SQ_TEX_VTX_INVALID_TEXTURE 0x0
|
||||
#define SQ_TEX_VTX_INVALID_BUFFER 0x1
|
||||
#define SQ_TEX_VTX_VALID_TEXTURE 0x2
|
||||
#define SQ_TEX_VTX_VALID_BUFFER 0x3
|
||||
|
||||
|
||||
#define SX_MISC 0x28350
|
||||
#define SX_DEBUG_1 0x9054
|
||||
#define SMX_EVENT_RELEASE (1 << 0)
|
||||
#define ENABLE_NEW_SMX_ADDRESS (1 << 16)
|
||||
|
||||
#define TA_CNTL_AUX 0x9508
|
||||
#define DISABLE_CUBE_WRAP (1 << 0)
|
||||
#define DISABLE_CUBE_ANISO (1 << 1)
|
||||
#define SYNC_GRADIENT (1 << 24)
|
||||
#define SYNC_WALKER (1 << 25)
|
||||
#define SYNC_ALIGNER (1 << 26)
|
||||
#define BILINEAR_PRECISION_6_BIT (0 << 31)
|
||||
#define BILINEAR_PRECISION_8_BIT (1 << 31)
|
||||
|
||||
#define TC_CNTL 0x9608
|
||||
#define TC_L2_SIZE(x) ((x)<<5)
|
||||
#define L2_DISABLE_LATE_HIT (1<<9)
|
||||
|
||||
|
||||
#define VGT_CACHE_INVALIDATION 0x88C4
|
||||
#define CACHE_INVALIDATION(x) ((x)<<0)
|
||||
#define VC_ONLY 0
|
||||
#define TC_ONLY 1
|
||||
#define VC_AND_TC 2
|
||||
#define VGT_DMA_BASE 0x287E8
|
||||
#define VGT_DMA_BASE_HI 0x287E4
|
||||
#define VGT_ES_PER_GS 0x88CC
|
||||
#define VGT_GS_PER_ES 0x88C8
|
||||
#define VGT_GS_PER_VS 0x88E8
|
||||
#define VGT_GS_VERTEX_REUSE 0x88D4
|
||||
#define VGT_PRIMITIVE_TYPE 0x8958
|
||||
#define VGT_NUM_INSTANCES 0x8974
|
||||
#define VGT_OUT_DEALLOC_CNTL 0x28C5C
|
||||
#define DEALLOC_DIST_MASK 0x0000007F
|
||||
#define VGT_STRMOUT_BASE_OFFSET_0 0x28B10
|
||||
#define VGT_STRMOUT_BASE_OFFSET_1 0x28B14
|
||||
#define VGT_STRMOUT_BASE_OFFSET_2 0x28B18
|
||||
#define VGT_STRMOUT_BASE_OFFSET_3 0x28B1c
|
||||
#define VGT_STRMOUT_BASE_OFFSET_HI_0 0x28B44
|
||||
#define VGT_STRMOUT_BASE_OFFSET_HI_1 0x28B48
|
||||
#define VGT_STRMOUT_BASE_OFFSET_HI_2 0x28B4c
|
||||
#define VGT_STRMOUT_BASE_OFFSET_HI_3 0x28B50
|
||||
#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8
|
||||
#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8
|
||||
#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8
|
||||
#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08
|
||||
#define VGT_STRMOUT_BUFFER_OFFSET_0 0x28ADC
|
||||
#define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC
|
||||
#define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC
|
||||
#define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C
|
||||
#define VGT_STRMOUT_EN 0x28AB0
|
||||
#define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58
|
||||
#define VTX_REUSE_DEPTH_MASK 0x000000FF
|
||||
#define VGT_EVENT_INITIATOR 0x28a90
|
||||
# define CACHE_FLUSH_AND_INV_EVENT (0x16 << 0)
|
||||
|
||||
#define VM_CONTEXT0_CNTL 0x1410
|
||||
#define ENABLE_CONTEXT (1 << 0)
|
||||
#define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1)
|
||||
#define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4)
|
||||
#define VM_CONTEXT0_INVALIDATION_LOW_ADDR 0x1490
|
||||
#define VM_CONTEXT0_INVALIDATION_HIGH_ADDR 0x14B0
|
||||
#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x1574
|
||||
#define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x1594
|
||||
#define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x15B4
|
||||
#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x1554
|
||||
#define VM_CONTEXT0_REQUEST_RESPONSE 0x1470
|
||||
#define REQUEST_TYPE(x) (((x) & 0xf) << 0)
|
||||
#define RESPONSE_TYPE_MASK 0x000000F0
|
||||
#define RESPONSE_TYPE_SHIFT 4
|
||||
#define VM_L2_CNTL 0x1400
|
||||
#define ENABLE_L2_CACHE (1 << 0)
|
||||
#define ENABLE_L2_FRAGMENT_PROCESSING (1 << 1)
|
||||
#define ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE (1 << 9)
|
||||
#define EFFECTIVE_L2_QUEUE_SIZE(x) (((x) & 7) << 13)
|
||||
#define VM_L2_CNTL2 0x1404
|
||||
#define INVALIDATE_ALL_L1_TLBS (1 << 0)
|
||||
#define INVALIDATE_L2_CACHE (1 << 1)
|
||||
#define VM_L2_CNTL3 0x1408
|
||||
#define BANK_SELECT_0(x) (((x) & 0x1f) << 0)
|
||||
#define BANK_SELECT_1(x) (((x) & 0x1f) << 5)
|
||||
#define L2_CACHE_UPDATE_MODE(x) (((x) & 3) << 10)
|
||||
#define VM_L2_STATUS 0x140C
|
||||
#define L2_BUSY (1 << 0)
|
||||
|
||||
#define WAIT_UNTIL 0x8040
|
||||
#define WAIT_2D_IDLE_bit (1 << 14)
|
||||
#define WAIT_3D_IDLE_bit (1 << 15)
|
||||
#define WAIT_2D_IDLECLEAN_bit (1 << 16)
|
||||
#define WAIT_3D_IDLECLEAN_bit (1 << 17)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* PM4
|
||||
*/
|
||||
#define PACKET_TYPE0 0
|
||||
#define PACKET_TYPE1 1
|
||||
#define PACKET_TYPE2 2
|
||||
#define PACKET_TYPE3 3
|
||||
|
||||
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
|
||||
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
|
||||
#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
|
||||
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
|
||||
#define PACKET0(reg, n) ((PACKET_TYPE0 << 30) | \
|
||||
(((reg) >> 2) & 0xFFFF) | \
|
||||
((n) & 0x3FFF) << 16)
|
||||
#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \
|
||||
(((op) & 0xFF) << 8) | \
|
||||
((n) & 0x3FFF) << 16)
|
||||
|
||||
/* Packet 3 types */
|
||||
#define PACKET3_NOP 0x10
|
||||
#define PACKET3_INDIRECT_BUFFER_END 0x17
|
||||
#define PACKET3_SET_PREDICATION 0x20
|
||||
#define PACKET3_REG_RMW 0x21
|
||||
#define PACKET3_COND_EXEC 0x22
|
||||
#define PACKET3_PRED_EXEC 0x23
|
||||
#define PACKET3_START_3D_CMDBUF 0x24
|
||||
#define PACKET3_DRAW_INDEX_2 0x27
|
||||
#define PACKET3_CONTEXT_CONTROL 0x28
|
||||
#define PACKET3_DRAW_INDEX_IMMD_BE 0x29
|
||||
#define PACKET3_INDEX_TYPE 0x2A
|
||||
#define PACKET3_DRAW_INDEX 0x2B
|
||||
#define PACKET3_DRAW_INDEX_AUTO 0x2D
|
||||
#define PACKET3_DRAW_INDEX_IMMD 0x2E
|
||||
#define PACKET3_NUM_INSTANCES 0x2F
|
||||
#define PACKET3_STRMOUT_BUFFER_UPDATE 0x34
|
||||
#define PACKET3_INDIRECT_BUFFER_MP 0x38
|
||||
#define PACKET3_MEM_SEMAPHORE 0x39
|
||||
#define PACKET3_MPEG_INDEX 0x3A
|
||||
#define PACKET3_WAIT_REG_MEM 0x3C
|
||||
#define PACKET3_MEM_WRITE 0x3D
|
||||
#define PACKET3_INDIRECT_BUFFER 0x32
|
||||
#define PACKET3_CP_INTERRUPT 0x40
|
||||
#define PACKET3_SURFACE_SYNC 0x43
|
||||
# define PACKET3_CB0_DEST_BASE_ENA (1 << 6)
|
||||
# define PACKET3_TC_ACTION_ENA (1 << 23)
|
||||
# define PACKET3_VC_ACTION_ENA (1 << 24)
|
||||
# define PACKET3_CB_ACTION_ENA (1 << 25)
|
||||
# define PACKET3_DB_ACTION_ENA (1 << 26)
|
||||
# define PACKET3_SH_ACTION_ENA (1 << 27)
|
||||
# define PACKET3_SMX_ACTION_ENA (1 << 28)
|
||||
#define PACKET3_ME_INITIALIZE 0x44
|
||||
#define PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
|
||||
#define PACKET3_COND_WRITE 0x45
|
||||
#define PACKET3_EVENT_WRITE 0x46
|
||||
#define PACKET3_EVENT_WRITE_EOP 0x47
|
||||
#define PACKET3_ONE_REG_WRITE 0x57
|
||||
#define PACKET3_SET_CONFIG_REG 0x68
|
||||
#define PACKET3_SET_CONFIG_REG_OFFSET 0x00008000
|
||||
#define PACKET3_SET_CONFIG_REG_END 0x0000ac00
|
||||
#define PACKET3_SET_CONTEXT_REG 0x69
|
||||
#define PACKET3_SET_CONTEXT_REG_OFFSET 0x00028000
|
||||
#define PACKET3_SET_CONTEXT_REG_END 0x00029000
|
||||
#define PACKET3_SET_ALU_CONST 0x6A
|
||||
#define PACKET3_SET_ALU_CONST_OFFSET 0x00030000
|
||||
#define PACKET3_SET_ALU_CONST_END 0x00032000
|
||||
#define PACKET3_SET_BOOL_CONST 0x6B
|
||||
#define PACKET3_SET_BOOL_CONST_OFFSET 0x0003e380
|
||||
#define PACKET3_SET_BOOL_CONST_END 0x00040000
|
||||
#define PACKET3_SET_LOOP_CONST 0x6C
|
||||
#define PACKET3_SET_LOOP_CONST_OFFSET 0x0003e200
|
||||
#define PACKET3_SET_LOOP_CONST_END 0x0003e380
|
||||
#define PACKET3_SET_RESOURCE 0x6D
|
||||
#define PACKET3_SET_RESOURCE_OFFSET 0x00038000
|
||||
#define PACKET3_SET_RESOURCE_END 0x0003c000
|
||||
#define PACKET3_SET_SAMPLER 0x6E
|
||||
#define PACKET3_SET_SAMPLER_OFFSET 0x0003c000
|
||||
#define PACKET3_SET_SAMPLER_END 0x0003cff0
|
||||
#define PACKET3_SET_CTL_CONST 0x6F
|
||||
#define PACKET3_SET_CTL_CONST_OFFSET 0x0003cff0
|
||||
#define PACKET3_SET_CTL_CONST_END 0x0003e200
|
||||
#define PACKET3_SURFACE_BASE_UPDATE 0x73
|
||||
|
||||
|
||||
#define R_008020_GRBM_SOFT_RESET 0x8020
|
||||
#define S_008020_SOFT_RESET_CP(x) (((x) & 1) << 0)
|
||||
#define S_008020_SOFT_RESET_CB(x) (((x) & 1) << 1)
|
||||
#define S_008020_SOFT_RESET_CR(x) (((x) & 1) << 2)
|
||||
#define S_008020_SOFT_RESET_DB(x) (((x) & 1) << 3)
|
||||
#define S_008020_SOFT_RESET_PA(x) (((x) & 1) << 5)
|
||||
#define S_008020_SOFT_RESET_SC(x) (((x) & 1) << 6)
|
||||
#define S_008020_SOFT_RESET_SMX(x) (((x) & 1) << 7)
|
||||
#define S_008020_SOFT_RESET_SPI(x) (((x) & 1) << 8)
|
||||
#define S_008020_SOFT_RESET_SH(x) (((x) & 1) << 9)
|
||||
#define S_008020_SOFT_RESET_SX(x) (((x) & 1) << 10)
|
||||
#define S_008020_SOFT_RESET_TC(x) (((x) & 1) << 11)
|
||||
#define S_008020_SOFT_RESET_TA(x) (((x) & 1) << 12)
|
||||
#define S_008020_SOFT_RESET_VC(x) (((x) & 1) << 13)
|
||||
#define S_008020_SOFT_RESET_VGT(x) (((x) & 1) << 14)
|
||||
#define R_008010_GRBM_STATUS 0x8010
|
||||
#define S_008010_CMDFIFO_AVAIL(x) (((x) & 0x1F) << 0)
|
||||
#define S_008010_CP_RQ_PENDING(x) (((x) & 1) << 6)
|
||||
#define S_008010_CF_RQ_PENDING(x) (((x) & 1) << 7)
|
||||
#define S_008010_PF_RQ_PENDING(x) (((x) & 1) << 8)
|
||||
#define S_008010_GRBM_EE_BUSY(x) (((x) & 1) << 10)
|
||||
#define S_008010_VC_BUSY(x) (((x) & 1) << 11)
|
||||
#define S_008010_DB03_CLEAN(x) (((x) & 1) << 12)
|
||||
#define S_008010_CB03_CLEAN(x) (((x) & 1) << 13)
|
||||
#define S_008010_VGT_BUSY_NO_DMA(x) (((x) & 1) << 16)
|
||||
#define S_008010_VGT_BUSY(x) (((x) & 1) << 17)
|
||||
#define S_008010_TA03_BUSY(x) (((x) & 1) << 18)
|
||||
#define S_008010_TC_BUSY(x) (((x) & 1) << 19)
|
||||
#define S_008010_SX_BUSY(x) (((x) & 1) << 20)
|
||||
#define S_008010_SH_BUSY(x) (((x) & 1) << 21)
|
||||
#define S_008010_SPI03_BUSY(x) (((x) & 1) << 22)
|
||||
#define S_008010_SMX_BUSY(x) (((x) & 1) << 23)
|
||||
#define S_008010_SC_BUSY(x) (((x) & 1) << 24)
|
||||
#define S_008010_PA_BUSY(x) (((x) & 1) << 25)
|
||||
#define S_008010_DB03_BUSY(x) (((x) & 1) << 26)
|
||||
#define S_008010_CR_BUSY(x) (((x) & 1) << 27)
|
||||
#define S_008010_CP_COHERENCY_BUSY(x) (((x) & 1) << 28)
|
||||
#define S_008010_CP_BUSY(x) (((x) & 1) << 29)
|
||||
#define S_008010_CB03_BUSY(x) (((x) & 1) << 30)
|
||||
#define S_008010_GUI_ACTIVE(x) (((x) & 1) << 31)
|
||||
#define G_008010_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x1F)
|
||||
#define G_008010_CP_RQ_PENDING(x) (((x) >> 6) & 1)
|
||||
#define G_008010_CF_RQ_PENDING(x) (((x) >> 7) & 1)
|
||||
#define G_008010_PF_RQ_PENDING(x) (((x) >> 8) & 1)
|
||||
#define G_008010_GRBM_EE_BUSY(x) (((x) >> 10) & 1)
|
||||
#define G_008010_VC_BUSY(x) (((x) >> 11) & 1)
|
||||
#define G_008010_DB03_CLEAN(x) (((x) >> 12) & 1)
|
||||
#define G_008010_CB03_CLEAN(x) (((x) >> 13) & 1)
|
||||
#define G_008010_VGT_BUSY_NO_DMA(x) (((x) >> 16) & 1)
|
||||
#define G_008010_VGT_BUSY(x) (((x) >> 17) & 1)
|
||||
#define G_008010_TA03_BUSY(x) (((x) >> 18) & 1)
|
||||
#define G_008010_TC_BUSY(x) (((x) >> 19) & 1)
|
||||
#define G_008010_SX_BUSY(x) (((x) >> 20) & 1)
|
||||
#define G_008010_SH_BUSY(x) (((x) >> 21) & 1)
|
||||
#define G_008010_SPI03_BUSY(x) (((x) >> 22) & 1)
|
||||
#define G_008010_SMX_BUSY(x) (((x) >> 23) & 1)
|
||||
#define G_008010_SC_BUSY(x) (((x) >> 24) & 1)
|
||||
#define G_008010_PA_BUSY(x) (((x) >> 25) & 1)
|
||||
#define G_008010_DB03_BUSY(x) (((x) >> 26) & 1)
|
||||
#define G_008010_CR_BUSY(x) (((x) >> 27) & 1)
|
||||
#define G_008010_CP_COHERENCY_BUSY(x) (((x) >> 28) & 1)
|
||||
#define G_008010_CP_BUSY(x) (((x) >> 29) & 1)
|
||||
#define G_008010_CB03_BUSY(x) (((x) >> 30) & 1)
|
||||
#define G_008010_GUI_ACTIVE(x) (((x) >> 31) & 1)
|
||||
#define R_008014_GRBM_STATUS2 0x8014
|
||||
#define S_008014_CR_CLEAN(x) (((x) & 1) << 0)
|
||||
#define S_008014_SMX_CLEAN(x) (((x) & 1) << 1)
|
||||
#define S_008014_SPI0_BUSY(x) (((x) & 1) << 8)
|
||||
#define S_008014_SPI1_BUSY(x) (((x) & 1) << 9)
|
||||
#define S_008014_SPI2_BUSY(x) (((x) & 1) << 10)
|
||||
#define S_008014_SPI3_BUSY(x) (((x) & 1) << 11)
|
||||
#define S_008014_TA0_BUSY(x) (((x) & 1) << 12)
|
||||
#define S_008014_TA1_BUSY(x) (((x) & 1) << 13)
|
||||
#define S_008014_TA2_BUSY(x) (((x) & 1) << 14)
|
||||
#define S_008014_TA3_BUSY(x) (((x) & 1) << 15)
|
||||
#define S_008014_DB0_BUSY(x) (((x) & 1) << 16)
|
||||
#define S_008014_DB1_BUSY(x) (((x) & 1) << 17)
|
||||
#define S_008014_DB2_BUSY(x) (((x) & 1) << 18)
|
||||
#define S_008014_DB3_BUSY(x) (((x) & 1) << 19)
|
||||
#define S_008014_CB0_BUSY(x) (((x) & 1) << 20)
|
||||
#define S_008014_CB1_BUSY(x) (((x) & 1) << 21)
|
||||
#define S_008014_CB2_BUSY(x) (((x) & 1) << 22)
|
||||
#define S_008014_CB3_BUSY(x) (((x) & 1) << 23)
|
||||
#define G_008014_CR_CLEAN(x) (((x) >> 0) & 1)
|
||||
#define G_008014_SMX_CLEAN(x) (((x) >> 1) & 1)
|
||||
#define G_008014_SPI0_BUSY(x) (((x) >> 8) & 1)
|
||||
#define G_008014_SPI1_BUSY(x) (((x) >> 9) & 1)
|
||||
#define G_008014_SPI2_BUSY(x) (((x) >> 10) & 1)
|
||||
#define G_008014_SPI3_BUSY(x) (((x) >> 11) & 1)
|
||||
#define G_008014_TA0_BUSY(x) (((x) >> 12) & 1)
|
||||
#define G_008014_TA1_BUSY(x) (((x) >> 13) & 1)
|
||||
#define G_008014_TA2_BUSY(x) (((x) >> 14) & 1)
|
||||
#define G_008014_TA3_BUSY(x) (((x) >> 15) & 1)
|
||||
#define G_008014_DB0_BUSY(x) (((x) >> 16) & 1)
|
||||
#define G_008014_DB1_BUSY(x) (((x) >> 17) & 1)
|
||||
#define G_008014_DB2_BUSY(x) (((x) >> 18) & 1)
|
||||
#define G_008014_DB3_BUSY(x) (((x) >> 19) & 1)
|
||||
#define G_008014_CB0_BUSY(x) (((x) >> 20) & 1)
|
||||
#define G_008014_CB1_BUSY(x) (((x) >> 21) & 1)
|
||||
#define G_008014_CB2_BUSY(x) (((x) >> 22) & 1)
|
||||
#define G_008014_CB3_BUSY(x) (((x) >> 23) & 1)
|
||||
#define R_000E50_SRBM_STATUS 0x0E50
|
||||
#define G_000E50_RLC_RQ_PENDING(x) (((x) >> 3) & 1)
|
||||
#define G_000E50_RCU_RQ_PENDING(x) (((x) >> 4) & 1)
|
||||
#define G_000E50_GRBM_RQ_PENDING(x) (((x) >> 5) & 1)
|
||||
#define G_000E50_HI_RQ_PENDING(x) (((x) >> 6) & 1)
|
||||
#define G_000E50_IO_EXTERN_SIGNAL(x) (((x) >> 7) & 1)
|
||||
#define G_000E50_VMC_BUSY(x) (((x) >> 8) & 1)
|
||||
#define G_000E50_MCB_BUSY(x) (((x) >> 9) & 1)
|
||||
#define G_000E50_MCDZ_BUSY(x) (((x) >> 10) & 1)
|
||||
#define G_000E50_MCDY_BUSY(x) (((x) >> 11) & 1)
|
||||
#define G_000E50_MCDX_BUSY(x) (((x) >> 12) & 1)
|
||||
#define G_000E50_MCDW_BUSY(x) (((x) >> 13) & 1)
|
||||
#define G_000E50_SEM_BUSY(x) (((x) >> 14) & 1)
|
||||
#define G_000E50_RLC_BUSY(x) (((x) >> 15) & 1)
|
||||
#define R_000E60_SRBM_SOFT_RESET 0x0E60
|
||||
#define S_000E60_SOFT_RESET_BIF(x) (((x) & 1) << 1)
|
||||
#define S_000E60_SOFT_RESET_CG(x) (((x) & 1) << 2)
|
||||
#define S_000E60_SOFT_RESET_CMC(x) (((x) & 1) << 3)
|
||||
#define S_000E60_SOFT_RESET_CSC(x) (((x) & 1) << 4)
|
||||
#define S_000E60_SOFT_RESET_DC(x) (((x) & 1) << 5)
|
||||
#define S_000E60_SOFT_RESET_GRBM(x) (((x) & 1) << 8)
|
||||
#define S_000E60_SOFT_RESET_HDP(x) (((x) & 1) << 9)
|
||||
#define S_000E60_SOFT_RESET_IH(x) (((x) & 1) << 10)
|
||||
#define S_000E60_SOFT_RESET_MC(x) (((x) & 1) << 11)
|
||||
#define S_000E60_SOFT_RESET_RLC(x) (((x) & 1) << 13)
|
||||
#define S_000E60_SOFT_RESET_ROM(x) (((x) & 1) << 14)
|
||||
#define S_000E60_SOFT_RESET_SEM(x) (((x) & 1) << 15)
|
||||
#define S_000E60_SOFT_RESET_TSC(x) (((x) & 1) << 16)
|
||||
#define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17)
|
||||
|
||||
#endif
|
|
@ -51,7 +51,6 @@
|
|||
|
||||
#include "radeon_mode.h"
|
||||
#include "radeon_reg.h"
|
||||
#include "r300.h"
|
||||
|
||||
/*
|
||||
* Modules parameters.
|
||||
|
@ -66,6 +65,7 @@ extern int radeon_gart_size;
|
|||
extern int radeon_benchmarking;
|
||||
extern int radeon_testing;
|
||||
extern int radeon_connector_table;
|
||||
extern int radeon_tv;
|
||||
|
||||
/*
|
||||
* Copy from radeon_drv.h so we don't have to include both and have conflicting
|
||||
|
@ -75,6 +75,7 @@ extern int radeon_connector_table;
|
|||
#define RADEON_IB_POOL_SIZE 16
|
||||
#define RADEON_DEBUGFS_MAX_NUM_FILES 32
|
||||
#define RADEONFB_CONN_LIMIT 4
|
||||
#define RADEON_BIOS_NUM_SCRATCH 8
|
||||
|
||||
enum radeon_family {
|
||||
CHIP_R100,
|
||||
|
@ -107,14 +108,15 @@ enum radeon_family {
|
|||
CHIP_R600,
|
||||
CHIP_RV610,
|
||||
CHIP_RV630,
|
||||
CHIP_RV670,
|
||||
CHIP_RV620,
|
||||
CHIP_RV635,
|
||||
CHIP_RV670,
|
||||
CHIP_RS780,
|
||||
CHIP_RS880,
|
||||
CHIP_RV770,
|
||||
CHIP_RV730,
|
||||
CHIP_RV710,
|
||||
CHIP_RS880,
|
||||
CHIP_RV740,
|
||||
CHIP_LAST,
|
||||
};
|
||||
|
||||
|
@ -151,10 +153,21 @@ struct radeon_device;
|
|||
*/
|
||||
bool radeon_get_bios(struct radeon_device *rdev);
|
||||
|
||||
|
||||
/*
|
||||
* Dummy page
|
||||
*/
|
||||
struct radeon_dummy_page {
|
||||
struct page *page;
|
||||
dma_addr_t addr;
|
||||
};
|
||||
int radeon_dummy_page_init(struct radeon_device *rdev);
|
||||
void radeon_dummy_page_fini(struct radeon_device *rdev);
|
||||
|
||||
|
||||
/*
|
||||
* Clocks
|
||||
*/
|
||||
|
||||
struct radeon_clock {
|
||||
struct radeon_pll p1pll;
|
||||
struct radeon_pll p2pll;
|
||||
|
@ -165,6 +178,7 @@ struct radeon_clock {
|
|||
uint32_t default_sclk;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Fences.
|
||||
*/
|
||||
|
@ -331,14 +345,18 @@ struct radeon_mc {
|
|||
resource_size_t aper_size;
|
||||
resource_size_t aper_base;
|
||||
resource_size_t agp_base;
|
||||
unsigned gtt_location;
|
||||
unsigned gtt_size;
|
||||
unsigned vram_location;
|
||||
/* for some chips with <= 32MB we need to lie
|
||||
* about vram size near mc fb location */
|
||||
unsigned mc_vram_size;
|
||||
u64 mc_vram_size;
|
||||
u64 gtt_location;
|
||||
u64 gtt_size;
|
||||
u64 gtt_start;
|
||||
u64 gtt_end;
|
||||
u64 vram_location;
|
||||
u64 vram_start;
|
||||
u64 vram_end;
|
||||
unsigned vram_width;
|
||||
unsigned real_vram_size;
|
||||
u64 real_vram_size;
|
||||
int vram_mtrr;
|
||||
bool vram_is_ddr;
|
||||
};
|
||||
|
@ -385,6 +403,10 @@ struct radeon_ib {
|
|||
uint32_t length_dw;
|
||||
};
|
||||
|
||||
/*
|
||||
* locking -
|
||||
* mutex protects scheduled_ibs, ready, alloc_bm
|
||||
*/
|
||||
struct radeon_ib_pool {
|
||||
struct mutex mutex;
|
||||
struct radeon_object *robj;
|
||||
|
@ -410,6 +432,16 @@ struct radeon_cp {
|
|||
bool ready;
|
||||
};
|
||||
|
||||
struct r600_blit {
|
||||
struct radeon_object *shader_obj;
|
||||
u64 shader_gpu_addr;
|
||||
u32 vs_offset, ps_offset;
|
||||
u32 state_offset;
|
||||
u32 state_len;
|
||||
u32 vb_used, vb_total;
|
||||
struct radeon_ib *vb_ib;
|
||||
};
|
||||
|
||||
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib);
|
||||
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
|
||||
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||
|
@ -462,6 +494,7 @@ struct radeon_cs_parser {
|
|||
int chunk_relocs_idx;
|
||||
struct radeon_ib *ib;
|
||||
void *track;
|
||||
unsigned family;
|
||||
};
|
||||
|
||||
struct radeon_cs_packet {
|
||||
|
@ -558,13 +591,19 @@ int r100_debugfs_cp_init(struct radeon_device *rdev);
|
|||
*/
|
||||
struct radeon_asic {
|
||||
int (*init)(struct radeon_device *rdev);
|
||||
void (*fini)(struct radeon_device *rdev);
|
||||
int (*resume)(struct radeon_device *rdev);
|
||||
int (*suspend)(struct radeon_device *rdev);
|
||||
void (*errata)(struct radeon_device *rdev);
|
||||
void (*vram_info)(struct radeon_device *rdev);
|
||||
void (*vga_set_state)(struct radeon_device *rdev, bool state);
|
||||
int (*gpu_reset)(struct radeon_device *rdev);
|
||||
int (*mc_init)(struct radeon_device *rdev);
|
||||
void (*mc_fini)(struct radeon_device *rdev);
|
||||
int (*wb_init)(struct radeon_device *rdev);
|
||||
void (*wb_fini)(struct radeon_device *rdev);
|
||||
int (*gart_init)(struct radeon_device *rdev);
|
||||
void (*gart_fini)(struct radeon_device *rdev);
|
||||
int (*gart_enable)(struct radeon_device *rdev);
|
||||
void (*gart_disable)(struct radeon_device *rdev);
|
||||
void (*gart_tlb_flush)(struct radeon_device *rdev);
|
||||
|
@ -572,7 +611,11 @@ struct radeon_asic {
|
|||
int (*cp_init)(struct radeon_device *rdev, unsigned ring_size);
|
||||
void (*cp_fini)(struct radeon_device *rdev);
|
||||
void (*cp_disable)(struct radeon_device *rdev);
|
||||
void (*cp_commit)(struct radeon_device *rdev);
|
||||
void (*ring_start)(struct radeon_device *rdev);
|
||||
int (*ring_test)(struct radeon_device *rdev);
|
||||
void (*ring_ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||
int (*ib_test)(struct radeon_device *rdev);
|
||||
int (*irq_set)(struct radeon_device *rdev);
|
||||
int (*irq_process)(struct radeon_device *rdev);
|
||||
u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc);
|
||||
|
@ -604,8 +647,60 @@ struct radeon_asic {
|
|||
void (*bandwidth_update)(struct radeon_device *rdev);
|
||||
};
|
||||
|
||||
/*
|
||||
* Asic structures
|
||||
*/
|
||||
struct r100_asic {
|
||||
const unsigned *reg_safe_bm;
|
||||
unsigned reg_safe_bm_size;
|
||||
};
|
||||
|
||||
struct r300_asic {
|
||||
const unsigned *reg_safe_bm;
|
||||
unsigned reg_safe_bm_size;
|
||||
};
|
||||
|
||||
struct r600_asic {
|
||||
unsigned max_pipes;
|
||||
unsigned max_tile_pipes;
|
||||
unsigned max_simds;
|
||||
unsigned max_backends;
|
||||
unsigned max_gprs;
|
||||
unsigned max_threads;
|
||||
unsigned max_stack_entries;
|
||||
unsigned max_hw_contexts;
|
||||
unsigned max_gs_threads;
|
||||
unsigned sx_max_export_size;
|
||||
unsigned sx_max_export_pos_size;
|
||||
unsigned sx_max_export_smx_size;
|
||||
unsigned sq_num_cf_insts;
|
||||
};
|
||||
|
||||
struct rv770_asic {
|
||||
unsigned max_pipes;
|
||||
unsigned max_tile_pipes;
|
||||
unsigned max_simds;
|
||||
unsigned max_backends;
|
||||
unsigned max_gprs;
|
||||
unsigned max_threads;
|
||||
unsigned max_stack_entries;
|
||||
unsigned max_hw_contexts;
|
||||
unsigned max_gs_threads;
|
||||
unsigned sx_max_export_size;
|
||||
unsigned sx_max_export_pos_size;
|
||||
unsigned sx_max_export_smx_size;
|
||||
unsigned sq_num_cf_insts;
|
||||
unsigned sx_num_of_sets;
|
||||
unsigned sc_prim_fifo_size;
|
||||
unsigned sc_hiz_tile_fifo_size;
|
||||
unsigned sc_earlyz_tile_fifo_fize;
|
||||
};
|
||||
|
||||
union radeon_asic_config {
|
||||
struct r300_asic r300;
|
||||
struct r100_asic r100;
|
||||
struct r600_asic r600;
|
||||
struct rv770_asic rv770;
|
||||
};
|
||||
|
||||
|
||||
|
@ -646,6 +741,7 @@ typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t);
|
|||
typedef void (*radeon_wreg_t)(struct radeon_device*, uint32_t, uint32_t);
|
||||
|
||||
struct radeon_device {
|
||||
struct device *dev;
|
||||
struct drm_device *ddev;
|
||||
struct pci_dev *pdev;
|
||||
/* ASIC */
|
||||
|
@ -689,13 +785,20 @@ struct radeon_device {
|
|||
struct radeon_asic *asic;
|
||||
struct radeon_gem gem;
|
||||
struct radeon_pm pm;
|
||||
uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH];
|
||||
struct mutex cs_mutex;
|
||||
struct radeon_wb wb;
|
||||
struct radeon_dummy_page dummy_page;
|
||||
bool gpu_lockup;
|
||||
bool shutdown;
|
||||
bool suspend;
|
||||
bool need_dma32;
|
||||
bool new_init_path;
|
||||
bool accel_working;
|
||||
struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
|
||||
const struct firmware *me_fw; /* all family ME firmware */
|
||||
const struct firmware *pfp_fw; /* r6/700 PFP firmware */
|
||||
struct r600_blit r600_blit;
|
||||
};
|
||||
|
||||
int radeon_device_init(struct radeon_device *rdev,
|
||||
|
@ -705,6 +808,13 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
void radeon_device_fini(struct radeon_device *rdev);
|
||||
int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
|
||||
|
||||
/* r600 blit */
|
||||
int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
|
||||
void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
|
||||
void r600_kms_blit_copy(struct radeon_device *rdev,
|
||||
u64 src_gpu_addr, u64 dst_gpu_addr,
|
||||
int size_bytes);
|
||||
|
||||
static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
|
||||
{
|
||||
if (reg < 0x10000)
|
||||
|
@ -732,6 +842,7 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32
|
|||
#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
|
||||
#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
|
||||
#define RREG32(reg) r100_mm_rreg(rdev, (reg))
|
||||
#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
|
||||
#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
|
||||
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
|
||||
|
@ -755,6 +866,7 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32
|
|||
tmp_ |= ((val) & ~(mask)); \
|
||||
WREG32_PLL(reg, tmp_); \
|
||||
} while (0)
|
||||
#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg)))
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
|
@ -819,51 +931,6 @@ void radeon_atombios_fini(struct radeon_device *rdev);
|
|||
/*
|
||||
* RING helpers.
|
||||
*/
|
||||
#define CP_PACKET0 0x00000000
|
||||
#define PACKET0_BASE_INDEX_SHIFT 0
|
||||
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0)
|
||||
#define PACKET0_COUNT_SHIFT 16
|
||||
#define PACKET0_COUNT_MASK (0x3fff << 16)
|
||||
#define CP_PACKET1 0x40000000
|
||||
#define CP_PACKET2 0x80000000
|
||||
#define PACKET2_PAD_SHIFT 0
|
||||
#define PACKET2_PAD_MASK (0x3fffffff << 0)
|
||||
#define CP_PACKET3 0xC0000000
|
||||
#define PACKET3_IT_OPCODE_SHIFT 8
|
||||
#define PACKET3_IT_OPCODE_MASK (0xff << 8)
|
||||
#define PACKET3_COUNT_SHIFT 16
|
||||
#define PACKET3_COUNT_MASK (0x3fff << 16)
|
||||
/* PACKET3 op code */
|
||||
#define PACKET3_NOP 0x10
|
||||
#define PACKET3_3D_DRAW_VBUF 0x28
|
||||
#define PACKET3_3D_DRAW_IMMD 0x29
|
||||
#define PACKET3_3D_DRAW_INDX 0x2A
|
||||
#define PACKET3_3D_LOAD_VBPNTR 0x2F
|
||||
#define PACKET3_INDX_BUFFER 0x33
|
||||
#define PACKET3_3D_DRAW_VBUF_2 0x34
|
||||
#define PACKET3_3D_DRAW_IMMD_2 0x35
|
||||
#define PACKET3_3D_DRAW_INDX_2 0x36
|
||||
#define PACKET3_BITBLT_MULTI 0x9B
|
||||
|
||||
#define PACKET0(reg, n) (CP_PACKET0 | \
|
||||
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \
|
||||
REG_SET(PACKET0_COUNT, (n)))
|
||||
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
|
||||
#define PACKET3(op, n) (CP_PACKET3 | \
|
||||
REG_SET(PACKET3_IT_OPCODE, (op)) | \
|
||||
REG_SET(PACKET3_COUNT, (n)))
|
||||
|
||||
#define PACKET_TYPE0 0
|
||||
#define PACKET_TYPE1 1
|
||||
#define PACKET_TYPE2 2
|
||||
#define PACKET_TYPE3 3
|
||||
|
||||
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
|
||||
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
|
||||
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
|
||||
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
|
||||
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
|
||||
|
||||
static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
||||
{
|
||||
#if DRM_DEBUG_CODE
|
||||
|
@ -882,14 +949,20 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
|||
* ASICs macro.
|
||||
*/
|
||||
#define radeon_init(rdev) (rdev)->asic->init((rdev))
|
||||
#define radeon_fini(rdev) (rdev)->asic->fini((rdev))
|
||||
#define radeon_resume(rdev) (rdev)->asic->resume((rdev))
|
||||
#define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
|
||||
#define radeon_cs_parse(p) rdev->asic->cs_parse((p))
|
||||
#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
|
||||
#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
|
||||
#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
|
||||
#define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev))
|
||||
#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev))
|
||||
#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev))
|
||||
#define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev))
|
||||
#define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev))
|
||||
#define radeon_gpu_gart_init(rdev) (rdev)->asic->gart_init((rdev))
|
||||
#define radeon_gpu_gart_fini(rdev) (rdev)->asic->gart_fini((rdev))
|
||||
#define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev))
|
||||
#define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev))
|
||||
#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev))
|
||||
|
@ -897,7 +970,11 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
|||
#define radeon_cp_init(rdev,rsize) (rdev)->asic->cp_init((rdev), (rsize))
|
||||
#define radeon_cp_fini(rdev) (rdev)->asic->cp_fini((rdev))
|
||||
#define radeon_cp_disable(rdev) (rdev)->asic->cp_disable((rdev))
|
||||
#define radeon_cp_commit(rdev) (rdev)->asic->cp_commit((rdev))
|
||||
#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
|
||||
#define radeon_ring_test(rdev) (rdev)->asic->ring_test((rdev))
|
||||
#define radeon_ring_ib_execute(rdev, ib) (rdev)->asic->ring_ib_execute((rdev), (ib))
|
||||
#define radeon_ib_test(rdev) (rdev)->asic->ib_test((rdev))
|
||||
#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
|
||||
#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
|
||||
#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc))
|
||||
|
@ -913,4 +990,88 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
|
|||
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
|
||||
#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
|
||||
|
||||
/* Common functions */
|
||||
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
|
||||
extern int radeon_modeset_init(struct radeon_device *rdev);
|
||||
extern void radeon_modeset_fini(struct radeon_device *rdev);
|
||||
extern bool radeon_card_posted(struct radeon_device *rdev);
|
||||
extern int radeon_clocks_init(struct radeon_device *rdev);
|
||||
extern void radeon_clocks_fini(struct radeon_device *rdev);
|
||||
extern void radeon_scratch_init(struct radeon_device *rdev);
|
||||
extern void radeon_surface_init(struct radeon_device *rdev);
|
||||
extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
|
||||
|
||||
/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
|
||||
struct r100_mc_save {
|
||||
u32 GENMO_WT;
|
||||
u32 CRTC_EXT_CNTL;
|
||||
u32 CRTC_GEN_CNTL;
|
||||
u32 CRTC2_GEN_CNTL;
|
||||
u32 CUR_OFFSET;
|
||||
u32 CUR2_OFFSET;
|
||||
};
|
||||
extern void r100_cp_disable(struct radeon_device *rdev);
|
||||
extern int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
|
||||
extern void r100_cp_fini(struct radeon_device *rdev);
|
||||
extern void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
|
||||
extern int r100_pci_gart_init(struct radeon_device *rdev);
|
||||
extern void r100_pci_gart_fini(struct radeon_device *rdev);
|
||||
extern int r100_pci_gart_enable(struct radeon_device *rdev);
|
||||
extern void r100_pci_gart_disable(struct radeon_device *rdev);
|
||||
extern int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
|
||||
extern int r100_debugfs_mc_info_init(struct radeon_device *rdev);
|
||||
extern int r100_gui_wait_for_idle(struct radeon_device *rdev);
|
||||
extern void r100_ib_fini(struct radeon_device *rdev);
|
||||
extern int r100_ib_init(struct radeon_device *rdev);
|
||||
extern void r100_irq_disable(struct radeon_device *rdev);
|
||||
extern int r100_irq_set(struct radeon_device *rdev);
|
||||
extern void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save);
|
||||
extern void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save);
|
||||
extern void r100_vram_init_sizes(struct radeon_device *rdev);
|
||||
extern void r100_wb_disable(struct radeon_device *rdev);
|
||||
extern void r100_wb_fini(struct radeon_device *rdev);
|
||||
extern int r100_wb_init(struct radeon_device *rdev);
|
||||
|
||||
/* r300,r350,rv350,rv370,rv380 */
|
||||
extern void r300_set_reg_safe(struct radeon_device *rdev);
|
||||
extern void r300_mc_program(struct radeon_device *rdev);
|
||||
extern void r300_vram_info(struct radeon_device *rdev);
|
||||
extern int rv370_pcie_gart_init(struct radeon_device *rdev);
|
||||
extern void rv370_pcie_gart_fini(struct radeon_device *rdev);
|
||||
extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
|
||||
extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
|
||||
|
||||
/* r420,r423,rv410 */
|
||||
extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
|
||||
extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
|
||||
extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
|
||||
|
||||
/* rv515 */
|
||||
extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
|
||||
|
||||
/* rs690, rs740 */
|
||||
extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
|
||||
struct drm_display_mode *mode1,
|
||||
struct drm_display_mode *mode2);
|
||||
|
||||
/* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
|
||||
extern bool r600_card_posted(struct radeon_device *rdev);
|
||||
extern void r600_cp_stop(struct radeon_device *rdev);
|
||||
extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
|
||||
extern int r600_cp_resume(struct radeon_device *rdev);
|
||||
extern int r600_count_pipe_bits(uint32_t val);
|
||||
extern int r600_gart_clear_page(struct radeon_device *rdev, int i);
|
||||
extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
|
||||
extern int r600_pcie_gart_init(struct radeon_device *rdev);
|
||||
extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
|
||||
extern int r600_ib_test(struct radeon_device *rdev);
|
||||
extern int r600_ring_test(struct radeon_device *rdev);
|
||||
extern int r600_wb_init(struct radeon_device *rdev);
|
||||
extern void r600_wb_fini(struct radeon_device *rdev);
|
||||
extern void r600_scratch_init(struct radeon_device *rdev);
|
||||
extern int r600_blit_init(struct radeon_device *rdev);
|
||||
extern void r600_blit_fini(struct radeon_device *rdev);
|
||||
extern int r600_cp_init_microcode(struct radeon_device *rdev);
|
||||
extern int r600_gpu_reset(struct radeon_device *rdev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,23 +42,28 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
|
|||
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
|
||||
*/
|
||||
int r100_init(struct radeon_device *rdev);
|
||||
int r200_init(struct radeon_device *rdev);
|
||||
uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
|
||||
void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||
void r100_errata(struct radeon_device *rdev);
|
||||
void r100_vram_info(struct radeon_device *rdev);
|
||||
void r100_vga_set_state(struct radeon_device *rdev, bool state);
|
||||
int r100_gpu_reset(struct radeon_device *rdev);
|
||||
int r100_mc_init(struct radeon_device *rdev);
|
||||
void r100_mc_fini(struct radeon_device *rdev);
|
||||
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
|
||||
int r100_wb_init(struct radeon_device *rdev);
|
||||
void r100_wb_fini(struct radeon_device *rdev);
|
||||
int r100_gart_enable(struct radeon_device *rdev);
|
||||
int r100_pci_gart_init(struct radeon_device *rdev);
|
||||
void r100_pci_gart_fini(struct radeon_device *rdev);
|
||||
int r100_pci_gart_enable(struct radeon_device *rdev);
|
||||
void r100_pci_gart_disable(struct radeon_device *rdev);
|
||||
void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
|
||||
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
|
||||
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
|
||||
void r100_cp_fini(struct radeon_device *rdev);
|
||||
void r100_cp_disable(struct radeon_device *rdev);
|
||||
void r100_cp_commit(struct radeon_device *rdev);
|
||||
void r100_ring_start(struct radeon_device *rdev);
|
||||
int r100_irq_set(struct radeon_device *rdev);
|
||||
int r100_irq_process(struct radeon_device *rdev);
|
||||
|
@ -77,24 +82,34 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
|
|||
uint32_t offset, uint32_t obj_size);
|
||||
int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
|
||||
void r100_bandwidth_update(struct radeon_device *rdev);
|
||||
void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||
int r100_ib_test(struct radeon_device *rdev);
|
||||
int r100_ring_test(struct radeon_device *rdev);
|
||||
|
||||
static struct radeon_asic r100_asic = {
|
||||
.init = &r100_init,
|
||||
.errata = &r100_errata,
|
||||
.vram_info = &r100_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r100_gpu_reset,
|
||||
.mc_init = &r100_mc_init,
|
||||
.mc_fini = &r100_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_enable = &r100_gart_enable,
|
||||
.gart_init = &r100_pci_gart_init,
|
||||
.gart_fini = &r100_pci_gart_fini,
|
||||
.gart_enable = &r100_pci_gart_enable,
|
||||
.gart_disable = &r100_pci_gart_disable,
|
||||
.gart_tlb_flush = &r100_pci_gart_tlb_flush,
|
||||
.gart_set_page = &r100_pci_gart_set_page,
|
||||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r100_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &r100_irq_set,
|
||||
.irq_process = &r100_irq_process,
|
||||
.get_vblank_counter = &r100_get_vblank_counter,
|
||||
|
@ -126,7 +141,9 @@ void r300_ring_start(struct radeon_device *rdev);
|
|||
void r300_fence_ring_emit(struct radeon_device *rdev,
|
||||
struct radeon_fence *fence);
|
||||
int r300_cs_parse(struct radeon_cs_parser *p);
|
||||
int r300_gart_enable(struct radeon_device *rdev);
|
||||
int rv370_pcie_gart_init(struct radeon_device *rdev);
|
||||
void rv370_pcie_gart_fini(struct radeon_device *rdev);
|
||||
int rv370_pcie_gart_enable(struct radeon_device *rdev);
|
||||
void rv370_pcie_gart_disable(struct radeon_device *rdev);
|
||||
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
|
||||
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
|
||||
|
@ -143,19 +160,26 @@ static struct radeon_asic r300_asic = {
|
|||
.init = &r300_init,
|
||||
.errata = &r300_errata,
|
||||
.vram_info = &r300_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r300_gpu_reset,
|
||||
.mc_init = &r300_mc_init,
|
||||
.mc_fini = &r300_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_enable = &r300_gart_enable,
|
||||
.gart_init = &r100_pci_gart_init,
|
||||
.gart_fini = &r100_pci_gart_fini,
|
||||
.gart_enable = &r100_pci_gart_enable,
|
||||
.gart_disable = &r100_pci_gart_disable,
|
||||
.gart_tlb_flush = &r100_pci_gart_tlb_flush,
|
||||
.gart_set_page = &r100_pci_gart_set_page,
|
||||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r300_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &r100_irq_set,
|
||||
.irq_process = &r100_irq_process,
|
||||
.get_vblank_counter = &r100_get_vblank_counter,
|
||||
|
@ -176,27 +200,35 @@ static struct radeon_asic r300_asic = {
|
|||
/*
|
||||
* r420,r423,rv410
|
||||
*/
|
||||
void r420_errata(struct radeon_device *rdev);
|
||||
void r420_vram_info(struct radeon_device *rdev);
|
||||
int r420_mc_init(struct radeon_device *rdev);
|
||||
void r420_mc_fini(struct radeon_device *rdev);
|
||||
extern int r420_init(struct radeon_device *rdev);
|
||||
extern void r420_fini(struct radeon_device *rdev);
|
||||
extern int r420_suspend(struct radeon_device *rdev);
|
||||
extern int r420_resume(struct radeon_device *rdev);
|
||||
static struct radeon_asic r420_asic = {
|
||||
.init = &r300_init,
|
||||
.errata = &r420_errata,
|
||||
.vram_info = &r420_vram_info,
|
||||
.init = &r420_init,
|
||||
.fini = &r420_fini,
|
||||
.suspend = &r420_suspend,
|
||||
.resume = &r420_resume,
|
||||
.errata = NULL,
|
||||
.vram_info = NULL,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r300_gpu_reset,
|
||||
.mc_init = &r420_mc_init,
|
||||
.mc_fini = &r420_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_enable = &r300_gart_enable,
|
||||
.gart_disable = &rv370_pcie_gart_disable,
|
||||
.mc_init = NULL,
|
||||
.mc_fini = NULL,
|
||||
.wb_init = NULL,
|
||||
.wb_fini = NULL,
|
||||
.gart_enable = NULL,
|
||||
.gart_disable = NULL,
|
||||
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rv370_pcie_gart_set_page,
|
||||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_init = NULL,
|
||||
.cp_fini = NULL,
|
||||
.cp_disable = NULL,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r300_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = NULL,
|
||||
.irq_set = &r100_irq_set,
|
||||
.irq_process = &r100_irq_process,
|
||||
.get_vblank_counter = &r100_get_vblank_counter,
|
||||
|
@ -222,6 +254,8 @@ void rs400_errata(struct radeon_device *rdev);
|
|||
void rs400_vram_info(struct radeon_device *rdev);
|
||||
int rs400_mc_init(struct radeon_device *rdev);
|
||||
void rs400_mc_fini(struct radeon_device *rdev);
|
||||
int rs400_gart_init(struct radeon_device *rdev);
|
||||
void rs400_gart_fini(struct radeon_device *rdev);
|
||||
int rs400_gart_enable(struct radeon_device *rdev);
|
||||
void rs400_gart_disable(struct radeon_device *rdev);
|
||||
void rs400_gart_tlb_flush(struct radeon_device *rdev);
|
||||
|
@ -232,11 +266,14 @@ static struct radeon_asic rs400_asic = {
|
|||
.init = &r300_init,
|
||||
.errata = &rs400_errata,
|
||||
.vram_info = &rs400_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r300_gpu_reset,
|
||||
.mc_init = &rs400_mc_init,
|
||||
.mc_fini = &rs400_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_init = &rs400_gart_init,
|
||||
.gart_fini = &rs400_gart_fini,
|
||||
.gart_enable = &rs400_gart_enable,
|
||||
.gart_disable = &rs400_gart_disable,
|
||||
.gart_tlb_flush = &rs400_gart_tlb_flush,
|
||||
|
@ -244,7 +281,11 @@ static struct radeon_asic rs400_asic = {
|
|||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r300_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &r100_irq_set,
|
||||
.irq_process = &r100_irq_process,
|
||||
.get_vblank_counter = &r100_get_vblank_counter,
|
||||
|
@ -266,7 +307,7 @@ static struct radeon_asic rs400_asic = {
|
|||
/*
|
||||
* rs600.
|
||||
*/
|
||||
int rs600_init(struct radeon_device *dev);
|
||||
int rs600_init(struct radeon_device *rdev);
|
||||
void rs600_errata(struct radeon_device *rdev);
|
||||
void rs600_vram_info(struct radeon_device *rdev);
|
||||
int rs600_mc_init(struct radeon_device *rdev);
|
||||
|
@ -274,6 +315,8 @@ void rs600_mc_fini(struct radeon_device *rdev);
|
|||
int rs600_irq_set(struct radeon_device *rdev);
|
||||
int rs600_irq_process(struct radeon_device *rdev);
|
||||
u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
|
||||
int rs600_gart_init(struct radeon_device *rdev);
|
||||
void rs600_gart_fini(struct radeon_device *rdev);
|
||||
int rs600_gart_enable(struct radeon_device *rdev);
|
||||
void rs600_gart_disable(struct radeon_device *rdev);
|
||||
void rs600_gart_tlb_flush(struct radeon_device *rdev);
|
||||
|
@ -285,11 +328,14 @@ static struct radeon_asic rs600_asic = {
|
|||
.init = &rs600_init,
|
||||
.errata = &rs600_errata,
|
||||
.vram_info = &rs600_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r300_gpu_reset,
|
||||
.mc_init = &rs600_mc_init,
|
||||
.mc_fini = &rs600_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_init = &rs600_gart_init,
|
||||
.gart_fini = &rs600_gart_fini,
|
||||
.gart_enable = &rs600_gart_enable,
|
||||
.gart_disable = &rs600_gart_disable,
|
||||
.gart_tlb_flush = &rs600_gart_tlb_flush,
|
||||
|
@ -297,7 +343,11 @@ static struct radeon_asic rs600_asic = {
|
|||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r300_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &rs600_irq_set,
|
||||
.irq_process = &rs600_irq_process,
|
||||
.get_vblank_counter = &rs600_get_vblank_counter,
|
||||
|
@ -328,11 +378,14 @@ static struct radeon_asic rs690_asic = {
|
|||
.init = &rs600_init,
|
||||
.errata = &rs690_errata,
|
||||
.vram_info = &rs690_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &r300_gpu_reset,
|
||||
.mc_init = &rs690_mc_init,
|
||||
.mc_fini = &rs690_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_init = &rs400_gart_init,
|
||||
.gart_fini = &rs400_gart_fini,
|
||||
.gart_enable = &rs400_gart_enable,
|
||||
.gart_disable = &rs400_gart_disable,
|
||||
.gart_tlb_flush = &rs400_gart_tlb_flush,
|
||||
|
@ -340,7 +393,11 @@ static struct radeon_asic rs690_asic = {
|
|||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &r300_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &rs600_irq_set,
|
||||
.irq_process = &rs600_irq_process,
|
||||
.get_vblank_counter = &rs600_get_vblank_counter,
|
||||
|
@ -378,19 +435,26 @@ static struct radeon_asic rv515_asic = {
|
|||
.init = &rv515_init,
|
||||
.errata = &rv515_errata,
|
||||
.vram_info = &rv515_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &rv515_gpu_reset,
|
||||
.mc_init = &rv515_mc_init,
|
||||
.mc_fini = &rv515_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_enable = &r300_gart_enable,
|
||||
.gart_init = &rv370_pcie_gart_init,
|
||||
.gart_fini = &rv370_pcie_gart_fini,
|
||||
.gart_enable = &rv370_pcie_gart_enable,
|
||||
.gart_disable = &rv370_pcie_gart_disable,
|
||||
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rv370_pcie_gart_set_page,
|
||||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &rv515_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &rs600_irq_set,
|
||||
.irq_process = &rs600_irq_process,
|
||||
.get_vblank_counter = &rs600_get_vblank_counter,
|
||||
|
@ -421,19 +485,26 @@ static struct radeon_asic r520_asic = {
|
|||
.init = &rv515_init,
|
||||
.errata = &r520_errata,
|
||||
.vram_info = &r520_vram_info,
|
||||
.vga_set_state = &r100_vga_set_state,
|
||||
.gpu_reset = &rv515_gpu_reset,
|
||||
.mc_init = &r520_mc_init,
|
||||
.mc_fini = &r520_mc_fini,
|
||||
.wb_init = &r100_wb_init,
|
||||
.wb_fini = &r100_wb_fini,
|
||||
.gart_enable = &r300_gart_enable,
|
||||
.gart_init = &rv370_pcie_gart_init,
|
||||
.gart_fini = &rv370_pcie_gart_fini,
|
||||
.gart_enable = &rv370_pcie_gart_enable,
|
||||
.gart_disable = &rv370_pcie_gart_disable,
|
||||
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rv370_pcie_gart_set_page,
|
||||
.cp_init = &r100_cp_init,
|
||||
.cp_fini = &r100_cp_fini,
|
||||
.cp_disable = &r100_cp_disable,
|
||||
.cp_commit = &r100_cp_commit,
|
||||
.ring_start = &rv515_ring_start,
|
||||
.ring_test = &r100_ring_test,
|
||||
.ring_ib_execute = &r100_ring_ib_execute,
|
||||
.ib_test = &r100_ib_test,
|
||||
.irq_set = &rs600_irq_set,
|
||||
.irq_process = &rs600_irq_process,
|
||||
.get_vblank_counter = &rs600_get_vblank_counter,
|
||||
|
@ -452,9 +523,130 @@ static struct radeon_asic r520_asic = {
|
|||
};
|
||||
|
||||
/*
|
||||
* r600,rv610,rv630,rv620,rv635,rv670,rs780,rv770,rv730,rv710
|
||||
* r600,rv610,rv630,rv620,rv635,rv670,rs780,rs880
|
||||
*/
|
||||
int r600_init(struct radeon_device *rdev);
|
||||
void r600_fini(struct radeon_device *rdev);
|
||||
int r600_suspend(struct radeon_device *rdev);
|
||||
int r600_resume(struct radeon_device *rdev);
|
||||
void r600_vga_set_state(struct radeon_device *rdev, bool state);
|
||||
int r600_wb_init(struct radeon_device *rdev);
|
||||
void r600_wb_fini(struct radeon_device *rdev);
|
||||
void r600_cp_commit(struct radeon_device *rdev);
|
||||
void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
|
||||
uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
|
||||
void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
|
||||
int r600_cs_parse(struct radeon_cs_parser *p);
|
||||
void r600_fence_ring_emit(struct radeon_device *rdev,
|
||||
struct radeon_fence *fence);
|
||||
int r600_copy_dma(struct radeon_device *rdev,
|
||||
uint64_t src_offset,
|
||||
uint64_t dst_offset,
|
||||
unsigned num_pages,
|
||||
struct radeon_fence *fence);
|
||||
int r600_irq_process(struct radeon_device *rdev);
|
||||
int r600_irq_set(struct radeon_device *rdev);
|
||||
int r600_gpu_reset(struct radeon_device *rdev);
|
||||
int r600_set_surface_reg(struct radeon_device *rdev, int reg,
|
||||
uint32_t tiling_flags, uint32_t pitch,
|
||||
uint32_t offset, uint32_t obj_size);
|
||||
int r600_clear_surface_reg(struct radeon_device *rdev, int reg);
|
||||
void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||
int r600_ib_test(struct radeon_device *rdev);
|
||||
int r600_ring_test(struct radeon_device *rdev);
|
||||
int r600_copy_blit(struct radeon_device *rdev,
|
||||
uint64_t src_offset, uint64_t dst_offset,
|
||||
unsigned num_pages, struct radeon_fence *fence);
|
||||
|
||||
static struct radeon_asic r600_asic = {
|
||||
.errata = NULL,
|
||||
.init = &r600_init,
|
||||
.fini = &r600_fini,
|
||||
.suspend = &r600_suspend,
|
||||
.resume = &r600_resume,
|
||||
.cp_commit = &r600_cp_commit,
|
||||
.vram_info = NULL,
|
||||
.vga_set_state = &r600_vga_set_state,
|
||||
.gpu_reset = &r600_gpu_reset,
|
||||
.mc_init = NULL,
|
||||
.mc_fini = NULL,
|
||||
.wb_init = &r600_wb_init,
|
||||
.wb_fini = &r600_wb_fini,
|
||||
.gart_enable = NULL,
|
||||
.gart_disable = NULL,
|
||||
.gart_tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rs600_gart_set_page,
|
||||
.cp_init = NULL,
|
||||
.cp_fini = NULL,
|
||||
.cp_disable = NULL,
|
||||
.ring_start = NULL,
|
||||
.ring_test = &r600_ring_test,
|
||||
.ring_ib_execute = &r600_ring_ib_execute,
|
||||
.ib_test = &r600_ib_test,
|
||||
.irq_set = &r600_irq_set,
|
||||
.irq_process = &r600_irq_process,
|
||||
.fence_ring_emit = &r600_fence_ring_emit,
|
||||
.cs_parse = &r600_cs_parse,
|
||||
.copy_blit = &r600_copy_blit,
|
||||
.copy_dma = &r600_copy_blit,
|
||||
.copy = &r600_copy_blit,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r600_set_surface_reg,
|
||||
.clear_surface_reg = r600_clear_surface_reg,
|
||||
.bandwidth_update = &r520_bandwidth_update,
|
||||
};
|
||||
|
||||
/*
|
||||
* rv770,rv730,rv710,rv740
|
||||
*/
|
||||
int rv770_init(struct radeon_device *rdev);
|
||||
void rv770_fini(struct radeon_device *rdev);
|
||||
int rv770_suspend(struct radeon_device *rdev);
|
||||
int rv770_resume(struct radeon_device *rdev);
|
||||
int rv770_gpu_reset(struct radeon_device *rdev);
|
||||
|
||||
static struct radeon_asic rv770_asic = {
|
||||
.errata = NULL,
|
||||
.init = &rv770_init,
|
||||
.fini = &rv770_fini,
|
||||
.suspend = &rv770_suspend,
|
||||
.resume = &rv770_resume,
|
||||
.cp_commit = &r600_cp_commit,
|
||||
.vram_info = NULL,
|
||||
.gpu_reset = &rv770_gpu_reset,
|
||||
.vga_set_state = &r600_vga_set_state,
|
||||
.mc_init = NULL,
|
||||
.mc_fini = NULL,
|
||||
.wb_init = &r600_wb_init,
|
||||
.wb_fini = &r600_wb_fini,
|
||||
.gart_enable = NULL,
|
||||
.gart_disable = NULL,
|
||||
.gart_tlb_flush = &r600_pcie_gart_tlb_flush,
|
||||
.gart_set_page = &rs600_gart_set_page,
|
||||
.cp_init = NULL,
|
||||
.cp_fini = NULL,
|
||||
.cp_disable = NULL,
|
||||
.ring_start = NULL,
|
||||
.ring_test = &r600_ring_test,
|
||||
.ring_ib_execute = &r600_ring_ib_execute,
|
||||
.ib_test = &r600_ib_test,
|
||||
.irq_set = &r600_irq_set,
|
||||
.irq_process = &r600_irq_process,
|
||||
.fence_ring_emit = &r600_fence_ring_emit,
|
||||
.cs_parse = &r600_cs_parse,
|
||||
.copy_blit = &r600_copy_blit,
|
||||
.copy_dma = &r600_copy_blit,
|
||||
.copy = &r600_copy_blit,
|
||||
.set_engine_clock = &radeon_atom_set_engine_clock,
|
||||
.set_memory_clock = &radeon_atom_set_memory_clock,
|
||||
.set_pcie_lanes = NULL,
|
||||
.set_clock_gating = &radeon_atom_set_clock_gating,
|
||||
.set_surface_reg = r600_set_surface_reg,
|
||||
.clear_surface_reg = r600_clear_surface_reg,
|
||||
.bandwidth_update = &r520_bandwidth_update,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,7 +104,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
|
|||
uint32_t supported_device,
|
||||
int *connector_type,
|
||||
struct radeon_i2c_bus_rec *i2c_bus,
|
||||
uint8_t *line_mux)
|
||||
uint16_t *line_mux)
|
||||
{
|
||||
|
||||
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
|
||||
|
@ -143,20 +143,31 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* some BIOSes seem to report DAC on HDMI - they hurt me with their lies */
|
||||
if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) ||
|
||||
(*connector_type == DRM_MODE_CONNECTOR_HDMIB)) {
|
||||
if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* ASUS HD 3600 XT board lists the DVI port as HDMI */
|
||||
if ((dev->pdev->device == 0x9598) &&
|
||||
(dev->pdev->subsystem_vendor == 0x1043) &&
|
||||
(dev->pdev->subsystem_device == 0x01da)) {
|
||||
if (*connector_type == DRM_MODE_CONNECTOR_HDMIB) {
|
||||
*connector_type = DRM_MODE_CONNECTOR_DVID;
|
||||
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
*connector_type = DRM_MODE_CONNECTOR_DVII;
|
||||
}
|
||||
}
|
||||
|
||||
/* ASUS HD 3450 board lists the DVI port as HDMI */
|
||||
if ((dev->pdev->device == 0x95C5) &&
|
||||
(dev->pdev->subsystem_vendor == 0x1043) &&
|
||||
(dev->pdev->subsystem_device == 0x01e2)) {
|
||||
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
*connector_type = DRM_MODE_CONNECTOR_DVII;
|
||||
}
|
||||
}
|
||||
|
||||
/* some BIOSes seem to report DAC on HDMI - usually this is a board with
|
||||
* HDMI + VGA reporting as HDMI
|
||||
*/
|
||||
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
|
||||
*connector_type = DRM_MODE_CONNECTOR_VGA;
|
||||
*line_mux = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,11 +203,11 @@ const int object_connector_convert[] = {
|
|||
DRM_MODE_CONNECTOR_Composite,
|
||||
DRM_MODE_CONNECTOR_SVIDEO,
|
||||
DRM_MODE_CONNECTOR_Unknown,
|
||||
DRM_MODE_CONNECTOR_Unknown,
|
||||
DRM_MODE_CONNECTOR_9PinDIN,
|
||||
DRM_MODE_CONNECTOR_Unknown,
|
||||
DRM_MODE_CONNECTOR_HDMIA,
|
||||
DRM_MODE_CONNECTOR_HDMIB,
|
||||
DRM_MODE_CONNECTOR_HDMIB,
|
||||
DRM_MODE_CONNECTOR_LVDS,
|
||||
DRM_MODE_CONNECTOR_9PinDIN,
|
||||
DRM_MODE_CONNECTOR_Unknown,
|
||||
|
@ -218,7 +229,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|||
ATOM_OBJECT_HEADER *obj_header;
|
||||
int i, j, path_size, device_support;
|
||||
int connector_type;
|
||||
uint16_t igp_lane_info;
|
||||
uint16_t igp_lane_info, conn_id;
|
||||
bool linkb;
|
||||
struct radeon_i2c_bus_rec ddc_bus;
|
||||
|
||||
|
@ -370,10 +381,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|||
&& record->
|
||||
ucRecordType <=
|
||||
ATOM_MAX_OBJECT_RECORD_NUMBER) {
|
||||
DRM_ERROR
|
||||
("record type %d\n",
|
||||
record->
|
||||
ucRecordType);
|
||||
switch (record->
|
||||
ucRecordType) {
|
||||
case ATOM_I2C_RECORD_TYPE:
|
||||
|
@ -409,9 +416,15 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|||
else
|
||||
ddc_bus = radeon_lookup_gpio(dev, line_mux);
|
||||
|
||||
conn_id = le16_to_cpu(path->usConnObjectId);
|
||||
|
||||
if (!radeon_atom_apply_quirks
|
||||
(dev, le16_to_cpu(path->usDeviceTag), &connector_type,
|
||||
&ddc_bus, &conn_id))
|
||||
continue;
|
||||
|
||||
radeon_add_atom_connector(dev,
|
||||
le16_to_cpu(path->
|
||||
usConnObjectId),
|
||||
conn_id,
|
||||
le16_to_cpu(path->
|
||||
usDeviceTag),
|
||||
connector_type, &ddc_bus,
|
||||
|
@ -427,7 +440,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|||
|
||||
struct bios_connector {
|
||||
bool valid;
|
||||
uint8_t line_mux;
|
||||
uint16_t line_mux;
|
||||
uint16_t devices;
|
||||
int connector_type;
|
||||
struct radeon_i2c_bus_rec ddc_bus;
|
||||
|
@ -471,11 +484,6 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
|
|||
continue;
|
||||
}
|
||||
|
||||
if (i == ATOM_DEVICE_TV1_INDEX) {
|
||||
DRM_DEBUG("Skipping TV Out\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
bios_connectors[i].connector_type =
|
||||
supported_devices_connector_convert[ci.sucConnectorInfo.
|
||||
sbfAccess.
|
||||
|
@ -711,9 +719,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
|
|||
return false;
|
||||
}
|
||||
|
||||
struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct
|
||||
radeon_encoder
|
||||
*encoder)
|
||||
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
|
||||
struct radeon_encoder_int_tmds *tmds)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
@ -724,7 +731,6 @@ struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct
|
|||
uint8_t frev, crev;
|
||||
uint16_t maxfreq;
|
||||
int i;
|
||||
struct radeon_encoder_int_tmds *tmds = NULL;
|
||||
|
||||
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
|
||||
&crev, &data_offset);
|
||||
|
@ -734,12 +740,6 @@ struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct
|
|||
data_offset);
|
||||
|
||||
if (tmds_info) {
|
||||
tmds =
|
||||
kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
|
||||
|
||||
if (!tmds)
|
||||
return NULL;
|
||||
|
||||
maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
|
||||
for (i = 0; i < 4; i++) {
|
||||
tmds->tmds_pll[i].freq =
|
||||
|
@ -765,8 +765,9 @@ struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct
|
|||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return tmds;
|
||||
return false;
|
||||
}
|
||||
|
||||
union lvds_info {
|
||||
|
@ -858,6 +859,72 @@ radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder)
|
|||
return p_dac;
|
||||
}
|
||||
|
||||
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
|
||||
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
|
||||
int32_t *pixel_clock)
|
||||
{
|
||||
struct radeon_mode_info *mode_info = &rdev->mode_info;
|
||||
ATOM_ANALOG_TV_INFO *tv_info;
|
||||
ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
|
||||
ATOM_DTD_FORMAT *dtd_timings;
|
||||
int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
|
||||
u8 frev, crev;
|
||||
uint16_t data_offset;
|
||||
|
||||
atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
|
||||
|
||||
switch (crev) {
|
||||
case 1:
|
||||
tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
|
||||
if (index > MAX_SUPPORTED_TV_TIMING)
|
||||
return false;
|
||||
|
||||
crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
|
||||
crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
|
||||
crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
|
||||
crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
|
||||
|
||||
crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
|
||||
crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
|
||||
crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
|
||||
crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
|
||||
|
||||
crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
|
||||
|
||||
crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
|
||||
crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
|
||||
crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
|
||||
crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
|
||||
*pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
|
||||
|
||||
if (index == 1) {
|
||||
/* PAL timings appear to have wrong values for totals */
|
||||
crtc_timing->usH_Total -= 1;
|
||||
crtc_timing->usV_Total -= 1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
|
||||
if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
|
||||
return false;
|
||||
|
||||
dtd_timings = &tv_info_v1_2->aModeTimings[index];
|
||||
crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
|
||||
crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive);
|
||||
crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
|
||||
crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth);
|
||||
crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
|
||||
crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive);
|
||||
crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
|
||||
crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth);
|
||||
|
||||
crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
|
||||
*pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct radeon_encoder_tv_dac *
|
||||
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
|
||||
{
|
||||
|
@ -948,10 +1015,10 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
|
|||
uint32_t bios_2_scratch, bios_6_scratch;
|
||||
|
||||
if (rdev->family >= CHIP_R600) {
|
||||
bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH);
|
||||
bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
|
||||
bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
|
||||
} else {
|
||||
bios_2_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
|
||||
bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
|
||||
bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
|
||||
}
|
||||
|
||||
|
@ -971,6 +1038,34 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
|
|||
|
||||
}
|
||||
|
||||
void radeon_save_bios_scratch_regs(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t scratch_reg;
|
||||
int i;
|
||||
|
||||
if (rdev->family >= CHIP_R600)
|
||||
scratch_reg = R600_BIOS_0_SCRATCH;
|
||||
else
|
||||
scratch_reg = RADEON_BIOS_0_SCRATCH;
|
||||
|
||||
for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
|
||||
rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
|
||||
}
|
||||
|
||||
void radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t scratch_reg;
|
||||
int i;
|
||||
|
||||
if (rdev->family >= CHIP_R600)
|
||||
scratch_reg = R600_BIOS_0_SCRATCH;
|
||||
else
|
||||
scratch_reg = RADEON_BIOS_0_SCRATCH;
|
||||
|
||||
for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
|
||||
WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
|
||||
}
|
||||
|
||||
void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
|
|
@ -102,10 +102,12 @@ void radeon_get_clock_info(struct drm_device *dev)
|
|||
p1pll->reference_div = 12;
|
||||
if (p2pll->reference_div < 2)
|
||||
p2pll->reference_div = 12;
|
||||
if (spll->reference_div < 2)
|
||||
spll->reference_div =
|
||||
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
|
||||
RADEON_M_SPLL_REF_DIV_MASK;
|
||||
if (rdev->family < CHIP_RS600) {
|
||||
if (spll->reference_div < 2)
|
||||
spll->reference_div =
|
||||
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
|
||||
RADEON_M_SPLL_REF_DIV_MASK;
|
||||
}
|
||||
if (mpll->reference_div < 2)
|
||||
mpll->reference_div = spll->reference_div;
|
||||
} else {
|
||||
|
|
|
@ -863,8 +863,10 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
|
|||
int tmp, i;
|
||||
struct radeon_encoder_lvds *lvds = NULL;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return radeon_legacy_get_lvds_info_from_regs(rdev);
|
||||
if (rdev->bios == NULL) {
|
||||
lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
|
||||
|
||||
|
@ -965,11 +967,13 @@ struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder
|
|||
lvds->native_mode.flags = 0;
|
||||
}
|
||||
}
|
||||
encoder->native_mode = lvds->native_mode;
|
||||
} else {
|
||||
DRM_INFO("No panel info found in BIOS\n");
|
||||
return radeon_legacy_get_lvds_info_from_regs(rdev);
|
||||
lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
|
||||
}
|
||||
out:
|
||||
if (lvds)
|
||||
encoder->native_mode = lvds->native_mode;
|
||||
return lvds;
|
||||
}
|
||||
|
||||
|
@ -994,48 +998,37 @@ static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = {
|
|||
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS480 */
|
||||
};
|
||||
|
||||
static struct radeon_encoder_int_tmds
|
||||
*radeon_legacy_get_tmds_info_from_table(struct radeon_device *rdev)
|
||||
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
|
||||
struct radeon_encoder_int_tmds *tmds)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
int i;
|
||||
struct radeon_encoder_int_tmds *tmds = NULL;
|
||||
|
||||
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
|
||||
|
||||
if (!tmds)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
tmds->tmds_pll[i].value =
|
||||
default_tmds_pll[rdev->family][i].value;
|
||||
default_tmds_pll[rdev->family][i].value;
|
||||
tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq;
|
||||
}
|
||||
|
||||
return tmds;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct
|
||||
radeon_encoder
|
||||
*encoder)
|
||||
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
|
||||
struct radeon_encoder_int_tmds *tmds)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint16_t tmds_info;
|
||||
int i, n;
|
||||
uint8_t ver;
|
||||
struct radeon_encoder_int_tmds *tmds = NULL;
|
||||
|
||||
if (rdev->bios == NULL)
|
||||
return radeon_legacy_get_tmds_info_from_table(rdev);
|
||||
return false;
|
||||
|
||||
tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
|
||||
|
||||
if (tmds_info) {
|
||||
tmds =
|
||||
kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
|
||||
|
||||
if (!tmds)
|
||||
return NULL;
|
||||
|
||||
ver = RBIOS8(tmds_info);
|
||||
DRM_INFO("DFP table revision: %d\n", ver);
|
||||
|
@ -1073,6 +1066,23 @@ struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct
|
|||
}
|
||||
} else
|
||||
DRM_INFO("No TMDS info found in BIOS\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct radeon_encoder *encoder)
|
||||
{
|
||||
struct radeon_encoder_int_tmds *tmds = NULL;
|
||||
bool ret;
|
||||
|
||||
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
|
||||
|
||||
if (!tmds)
|
||||
return NULL;
|
||||
|
||||
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
|
||||
if (ret == false)
|
||||
radeon_legacy_get_tmds_info_from_table(encoder, tmds);
|
||||
|
||||
return tmds;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "drm_crtc_helper.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
|
||||
extern void
|
||||
radeon_combios_connected_scratch_regs(struct drm_connector *connector,
|
||||
|
@ -38,6 +39,15 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
|
|||
struct drm_encoder *encoder,
|
||||
bool connected);
|
||||
|
||||
static void radeon_property_change_mode(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
|
||||
if (crtc && crtc->enabled) {
|
||||
drm_crtc_helper_set_mode(crtc, &crtc->mode,
|
||||
crtc->x, crtc->y, crtc->fb);
|
||||
}
|
||||
}
|
||||
static void
|
||||
radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status)
|
||||
{
|
||||
|
@ -77,6 +87,27 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
|
|||
}
|
||||
}
|
||||
|
||||
struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
|
||||
{
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
if (connector->encoder_ids[i] == 0)
|
||||
break;
|
||||
|
||||
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
encoder = obj_to_encoder(obj);
|
||||
if (encoder->encoder_type == encoder_type)
|
||||
return encoder;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
|
||||
{
|
||||
int enc_id = connector->encoder_ids[0];
|
||||
|
@ -94,6 +125,53 @@ struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* radeon_connector_analog_encoder_conflict_solve
|
||||
* - search for other connectors sharing this encoder
|
||||
* if priority is true, then set them disconnected if this is connected
|
||||
* if priority is false, set us disconnected if they are connected
|
||||
*/
|
||||
static enum drm_connector_status
|
||||
radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
|
||||
struct drm_encoder *encoder,
|
||||
enum drm_connector_status current_status,
|
||||
bool priority)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_connector *conflict;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
|
||||
if (conflict == connector)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
if (conflict->encoder_ids[i] == 0)
|
||||
break;
|
||||
|
||||
/* if the IDs match */
|
||||
if (conflict->encoder_ids[i] == encoder->base.id) {
|
||||
if (conflict->status != connector_status_connected)
|
||||
continue;
|
||||
|
||||
if (priority == true) {
|
||||
DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict));
|
||||
DRM_INFO("in favor of %s\n", drm_get_connector_name(connector));
|
||||
conflict->status = connector_status_disconnected;
|
||||
radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
|
||||
} else {
|
||||
DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector));
|
||||
DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict));
|
||||
current_status = connector_status_disconnected;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return current_status;
|
||||
|
||||
}
|
||||
|
||||
static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
@ -126,12 +204,171 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode
|
|||
return mode;
|
||||
}
|
||||
|
||||
static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct drm_display_mode *mode = NULL;
|
||||
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
|
||||
int i;
|
||||
struct mode_size {
|
||||
int w;
|
||||
int h;
|
||||
} common_modes[17] = {
|
||||
{ 640, 480},
|
||||
{ 720, 480},
|
||||
{ 800, 600},
|
||||
{ 848, 480},
|
||||
{1024, 768},
|
||||
{1152, 768},
|
||||
{1280, 720},
|
||||
{1280, 800},
|
||||
{1280, 854},
|
||||
{1280, 960},
|
||||
{1280, 1024},
|
||||
{1440, 900},
|
||||
{1400, 1050},
|
||||
{1680, 1050},
|
||||
{1600, 1200},
|
||||
{1920, 1080},
|
||||
{1920, 1200}
|
||||
};
|
||||
|
||||
for (i = 0; i < 17; i++) {
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
if (common_modes[i].w > native_mode->panel_xres ||
|
||||
common_modes[i].h > native_mode->panel_yres ||
|
||||
(common_modes[i].w == native_mode->panel_xres &&
|
||||
common_modes[i].h == native_mode->panel_yres))
|
||||
continue;
|
||||
}
|
||||
if (common_modes[i].w < 320 || common_modes[i].h < 200)
|
||||
continue;
|
||||
|
||||
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
}
|
||||
}
|
||||
|
||||
int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
|
||||
uint64_t val)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_encoder *encoder;
|
||||
struct radeon_encoder *radeon_encoder;
|
||||
|
||||
if (property == rdev->mode_info.coherent_mode_property) {
|
||||
struct radeon_encoder_atom_dig *dig;
|
||||
|
||||
/* need to find digital encoder on connector */
|
||||
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
|
||||
if (!encoder)
|
||||
return 0;
|
||||
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return 0;
|
||||
|
||||
dig = radeon_encoder->enc_priv;
|
||||
dig->coherent_mode = val ? true : false;
|
||||
radeon_property_change_mode(&radeon_encoder->base);
|
||||
}
|
||||
|
||||
if (property == rdev->mode_info.tv_std_property) {
|
||||
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC);
|
||||
if (!encoder) {
|
||||
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC);
|
||||
}
|
||||
|
||||
if (!encoder)
|
||||
return 0;
|
||||
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
if (!radeon_encoder->enc_priv)
|
||||
return 0;
|
||||
if (rdev->is_atom_bios) {
|
||||
struct radeon_encoder_atom_dac *dac_int;
|
||||
dac_int = radeon_encoder->enc_priv;
|
||||
dac_int->tv_std = val;
|
||||
} else {
|
||||
struct radeon_encoder_tv_dac *dac_int;
|
||||
dac_int = radeon_encoder->enc_priv;
|
||||
dac_int->tv_std = val;
|
||||
}
|
||||
radeon_property_change_mode(&radeon_encoder->base);
|
||||
}
|
||||
|
||||
if (property == rdev->mode_info.load_detect_property) {
|
||||
struct radeon_connector *radeon_connector =
|
||||
to_radeon_connector(connector);
|
||||
|
||||
if (val == 0)
|
||||
radeon_connector->dac_load_detect = false;
|
||||
else
|
||||
radeon_connector->dac_load_detect = true;
|
||||
}
|
||||
|
||||
if (property == rdev->mode_info.tmds_pll_property) {
|
||||
struct radeon_encoder_int_tmds *tmds = NULL;
|
||||
bool ret = false;
|
||||
/* need to find digital encoder on connector */
|
||||
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
|
||||
if (!encoder)
|
||||
return 0;
|
||||
|
||||
radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
tmds = radeon_encoder->enc_priv;
|
||||
if (!tmds)
|
||||
return 0;
|
||||
|
||||
if (val == 0) {
|
||||
if (rdev->is_atom_bios)
|
||||
ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds);
|
||||
else
|
||||
ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds);
|
||||
}
|
||||
if (val == 1 || ret == false) {
|
||||
radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds);
|
||||
}
|
||||
radeon_property_change_mode(&radeon_encoder->base);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
|
||||
|
||||
/* Try to get native mode details from EDID if necessary */
|
||||
if (!native_mode->dotclock) {
|
||||
struct drm_display_mode *t, *mode;
|
||||
|
||||
list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
|
||||
if (mode->hdisplay == native_mode->panel_xres &&
|
||||
mode->vdisplay == native_mode->panel_yres) {
|
||||
native_mode->hblank = mode->htotal - mode->hdisplay;
|
||||
native_mode->hoverplus = mode->hsync_start - mode->hdisplay;
|
||||
native_mode->hsync_width = mode->hsync_end - mode->hsync_start;
|
||||
native_mode->vblank = mode->vtotal - mode->vdisplay;
|
||||
native_mode->voverplus = mode->vsync_start - mode->vdisplay;
|
||||
native_mode->vsync_width = mode->vsync_end - mode->vsync_start;
|
||||
native_mode->dotclock = mode->clock;
|
||||
DRM_INFO("Determined LVDS native mode details from EDID\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!native_mode->dotclock) {
|
||||
DRM_INFO("No LVDS native mode details, disabling RMX\n");
|
||||
radeon_encoder->rmx_type = RMX_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static int radeon_lvds_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
|
@ -143,6 +380,12 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
|
|||
if (radeon_connector->ddc_bus) {
|
||||
ret = radeon_ddc_get_modes(radeon_connector);
|
||||
if (ret > 0) {
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (encoder) {
|
||||
radeon_fixup_lvds_native_mode(encoder, connector);
|
||||
/* add scaled modes */
|
||||
radeon_add_common_modes(encoder, connector);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +399,10 @@ static int radeon_lvds_get_modes(struct drm_connector *connector)
|
|||
if (mode) {
|
||||
ret = 1;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
/* add scaled modes */
|
||||
radeon_add_common_modes(encoder, connector);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -186,6 +432,42 @@ static void radeon_connector_destroy(struct drm_connector *connector)
|
|||
kfree(connector);
|
||||
}
|
||||
|
||||
static int radeon_lvds_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct radeon_encoder *radeon_encoder;
|
||||
enum radeon_rmx_type rmx_type;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
if (property != dev->mode_config.scaling_mode_property)
|
||||
return 0;
|
||||
|
||||
if (connector->encoder)
|
||||
radeon_encoder = to_radeon_encoder(connector->encoder);
|
||||
else {
|
||||
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
|
||||
radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
|
||||
case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
|
||||
case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
|
||||
default:
|
||||
case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
|
||||
}
|
||||
if (radeon_encoder->rmx_type == rmx_type)
|
||||
return 0;
|
||||
|
||||
radeon_encoder->rmx_type = rmx_type;
|
||||
|
||||
radeon_property_change_mode(&radeon_encoder->base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
|
||||
.get_modes = radeon_lvds_get_modes,
|
||||
.mode_valid = radeon_lvds_mode_valid,
|
||||
|
@ -197,7 +479,7 @@ struct drm_connector_funcs radeon_lvds_connector_funcs = {
|
|||
.detect = radeon_lvds_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = radeon_connector_destroy,
|
||||
.set_property = radeon_connector_set_property,
|
||||
.set_property = radeon_lvds_set_property,
|
||||
};
|
||||
|
||||
static int radeon_vga_get_modes(struct drm_connector *connector)
|
||||
|
@ -213,7 +495,6 @@ static int radeon_vga_get_modes(struct drm_connector *connector)
|
|||
static int radeon_vga_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
|
@ -225,22 +506,24 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
|
|||
bool dret;
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
ret = connector_status_disconnected;
|
||||
|
||||
radeon_i2c_do_lock(radeon_connector, 1);
|
||||
dret = radeon_ddc_probe(radeon_connector);
|
||||
radeon_i2c_do_lock(radeon_connector, 0);
|
||||
if (dret)
|
||||
ret = connector_status_connected;
|
||||
else {
|
||||
/* if EDID fails to a load detect */
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
ret = connector_status_disconnected;
|
||||
else {
|
||||
if (radeon_connector->dac_load_detect) {
|
||||
encoder_funcs = encoder->helper_private;
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == connector_status_connected)
|
||||
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
|
||||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -259,21 +542,97 @@ struct drm_connector_funcs radeon_vga_connector_funcs = {
|
|||
.set_property = radeon_connector_set_property,
|
||||
};
|
||||
|
||||
static int radeon_tv_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_display_mode *tv_mode;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
return 0;
|
||||
|
||||
/* avivo chips can scale any mode */
|
||||
if (rdev->family >= CHIP_RS600)
|
||||
/* add scaled modes */
|
||||
radeon_add_common_modes(encoder, connector);
|
||||
else {
|
||||
/* only 800x600 is supported right now on pre-avivo chips */
|
||||
tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false);
|
||||
tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(connector, tv_mode);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int radeon_tv_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
|
||||
if (!radeon_connector->dac_load_detect)
|
||||
return ret;
|
||||
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (!encoder)
|
||||
ret = connector_status_disconnected;
|
||||
else {
|
||||
encoder_funcs = encoder->helper_private;
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
}
|
||||
if (ret == connector_status_connected)
|
||||
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
|
||||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = {
|
||||
.get_modes = radeon_tv_get_modes,
|
||||
.mode_valid = radeon_tv_mode_valid,
|
||||
.best_encoder = radeon_best_single_encoder,
|
||||
};
|
||||
|
||||
struct drm_connector_funcs radeon_tv_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = radeon_tv_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = radeon_connector_destroy,
|
||||
.set_property = radeon_connector_set_property,
|
||||
};
|
||||
|
||||
static int radeon_dvi_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
int ret;
|
||||
|
||||
ret = radeon_ddc_get_modes(radeon_connector);
|
||||
/* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */
|
||||
radeon_connector_update_scratch_regs(connector, connector_status_connected);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* DVI is complicated
|
||||
* Do a DDC probe, if DDC probe passes, get the full EDID so
|
||||
* we can do analog/digital monitor detection at this point.
|
||||
* If the monitor is an analog monitor or we got no DDC,
|
||||
* we need to find the DAC encoder object for this connector.
|
||||
* If we got no DDC, we do load detection on the DAC encoder object.
|
||||
* If we got analog DDC or load detection passes on the DAC encoder
|
||||
* we have to check if this analog encoder is shared with anyone else (TV)
|
||||
* if its shared we have to set the other connector to disconnected.
|
||||
*/
|
||||
static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_encoder *encoder = NULL;
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
struct drm_mode_object *obj;
|
||||
int i;
|
||||
|
@ -283,9 +642,29 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
|
|||
radeon_i2c_do_lock(radeon_connector, 1);
|
||||
dret = radeon_ddc_probe(radeon_connector);
|
||||
radeon_i2c_do_lock(radeon_connector, 0);
|
||||
if (dret)
|
||||
ret = connector_status_connected;
|
||||
else {
|
||||
if (dret) {
|
||||
radeon_i2c_do_lock(radeon_connector, 1);
|
||||
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector, 0);
|
||||
|
||||
if (!radeon_connector->edid) {
|
||||
DRM_ERROR("DDC responded but not EDID found for %s\n",
|
||||
drm_get_connector_name(connector));
|
||||
} else {
|
||||
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
|
||||
/* if this isn't a digital monitor
|
||||
then we need to make sure we don't have any
|
||||
TV conflicts */
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
|
||||
goto out;
|
||||
|
||||
/* find analog encoder */
|
||||
if (radeon_connector->dac_load_detect) {
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
if (connector->encoder_ids[i] == 0)
|
||||
break;
|
||||
|
@ -300,15 +679,23 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
|
|||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (encoder_funcs->detect) {
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = 0;
|
||||
break;
|
||||
if (ret != connector_status_connected) {
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) &&
|
||||
encoder) {
|
||||
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
|
||||
}
|
||||
|
||||
out:
|
||||
/* updated in get modes as well since we need to know if it's analog or digital */
|
||||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
return ret;
|
||||
|
@ -332,7 +719,7 @@ struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
|
|||
|
||||
encoder = obj_to_encoder(obj);
|
||||
|
||||
if (radeon_connector->use_digital) {
|
||||
if (radeon_connector->use_digital == true) {
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
|
||||
return encoder;
|
||||
} else {
|
||||
|
@ -379,16 +766,14 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
bool linkb,
|
||||
uint32_t igp_lane_info)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector;
|
||||
uint32_t subpixel_order = SubPixelNone;
|
||||
|
||||
/* fixme - tv/cv/din */
|
||||
if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
|
||||
(connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
|
||||
(connector_type == DRM_MODE_CONNECTOR_Composite) ||
|
||||
(connector_type == DRM_MODE_CONNECTOR_9PinDIN))
|
||||
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
|
||||
return;
|
||||
|
||||
/* see if we already added it */
|
||||
|
@ -417,6 +802,9 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVIA:
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
||||
|
@ -426,6 +814,9 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
|
@ -443,6 +834,12 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
goto failed;
|
||||
}
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.coherent_mode_property,
|
||||
1);
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
case DRM_MODE_CONNECTOR_HDMIB:
|
||||
|
@ -459,6 +856,9 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.coherent_mode_property,
|
||||
1);
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
|
@ -480,6 +880,13 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_9PinDIN:
|
||||
if (radeon_tv == 1) {
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
|
||||
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
|
||||
|
@ -495,6 +902,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_mode_create_scaling_mode_property(dev);
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
DRM_MODE_SCALE_FULLSCREEN);
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
break;
|
||||
}
|
||||
|
@ -517,15 +928,13 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|||
int connector_type,
|
||||
struct radeon_i2c_bus_rec *i2c_bus)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct radeon_connector *radeon_connector;
|
||||
uint32_t subpixel_order = SubPixelNone;
|
||||
|
||||
/* fixme - tv/cv/din */
|
||||
if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
|
||||
(connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
|
||||
(connector_type == DRM_MODE_CONNECTOR_Composite) ||
|
||||
(connector_type == DRM_MODE_CONNECTOR_9PinDIN))
|
||||
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
|
||||
return;
|
||||
|
||||
/* see if we already added it */
|
||||
|
@ -554,6 +963,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVIA:
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
||||
|
@ -563,6 +975,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
|
@ -572,12 +987,22 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|||
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
|
||||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
}
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_SVIDEO:
|
||||
case DRM_MODE_CONNECTOR_Composite:
|
||||
case DRM_MODE_CONNECTOR_9PinDIN:
|
||||
if (radeon_tv == 1) {
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
|
||||
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
}
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
|
||||
|
@ -587,6 +1012,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|||
if (!radeon_connector->ddc_bus)
|
||||
goto failed;
|
||||
}
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
DRM_MODE_SCALE_FULLSCREEN);
|
||||
subpixel_order = SubPixelHorizontalRGB;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -36,10 +36,25 @@
|
|||
#include "radeon_drv.h"
|
||||
#include "r300_reg.h"
|
||||
|
||||
#include "radeon_microcode.h"
|
||||
|
||||
#define RADEON_FIFO_DEBUG 0
|
||||
|
||||
/* Firmware Names */
|
||||
#define FIRMWARE_R100 "radeon/R100_cp.bin"
|
||||
#define FIRMWARE_R200 "radeon/R200_cp.bin"
|
||||
#define FIRMWARE_R300 "radeon/R300_cp.bin"
|
||||
#define FIRMWARE_R420 "radeon/R420_cp.bin"
|
||||
#define FIRMWARE_RS690 "radeon/RS690_cp.bin"
|
||||
#define FIRMWARE_RS600 "radeon/RS600_cp.bin"
|
||||
#define FIRMWARE_R520 "radeon/R520_cp.bin"
|
||||
|
||||
MODULE_FIRMWARE(FIRMWARE_R100);
|
||||
MODULE_FIRMWARE(FIRMWARE_R200);
|
||||
MODULE_FIRMWARE(FIRMWARE_R300);
|
||||
MODULE_FIRMWARE(FIRMWARE_R420);
|
||||
MODULE_FIRMWARE(FIRMWARE_RS690);
|
||||
MODULE_FIRMWARE(FIRMWARE_RS600);
|
||||
MODULE_FIRMWARE(FIRMWARE_R520);
|
||||
|
||||
static int radeon_do_cleanup_cp(struct drm_device * dev);
|
||||
static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
|
||||
|
||||
|
@ -460,37 +475,34 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
|
|||
*/
|
||||
|
||||
/* Load the microcode for the CP */
|
||||
static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
|
||||
static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
int i;
|
||||
struct platform_device *pdev;
|
||||
const char *fw_name = NULL;
|
||||
int err;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
radeon_do_wait_for_idle(dev_priv);
|
||||
pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
|
||||
err = IS_ERR(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
|
||||
if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
|
||||
DRM_INFO("Loading R100 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
R100_cp_microcode[i][1]);
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
R100_cp_microcode[i][0]);
|
||||
}
|
||||
fw_name = FIRMWARE_R100;
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
|
||||
DRM_INFO("Loading R200 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
R200_cp_microcode[i][1]);
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
R200_cp_microcode[i][0]);
|
||||
}
|
||||
fw_name = FIRMWARE_R200;
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
|
||||
|
@ -498,39 +510,19 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
|
|||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
|
||||
DRM_INFO("Loading R300 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
R300_cp_microcode[i][1]);
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
R300_cp_microcode[i][0]);
|
||||
}
|
||||
fw_name = FIRMWARE_R300;
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
|
||||
DRM_INFO("Loading R400 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
R420_cp_microcode[i][1]);
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
R420_cp_microcode[i][0]);
|
||||
}
|
||||
fw_name = FIRMWARE_R420;
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
|
||||
DRM_INFO("Loading RS690/RS740 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
RS690_cp_microcode[i][1]);
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
RS690_cp_microcode[i][0]);
|
||||
}
|
||||
fw_name = FIRMWARE_RS690;
|
||||
} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
|
||||
DRM_INFO("Loading RS600 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
RS600_cp_microcode[i][1]);
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
RS600_cp_microcode[i][0]);
|
||||
}
|
||||
fw_name = FIRMWARE_RS600;
|
||||
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
|
||||
|
@ -538,11 +530,41 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
|
|||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
|
||||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
|
||||
DRM_INFO("Loading R500 Microcode\n");
|
||||
for (i = 0; i < 256; i++) {
|
||||
fw_name = FIRMWARE_R520;
|
||||
}
|
||||
|
||||
err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
|
||||
platform_device_unregister(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n",
|
||||
fw_name);
|
||||
} else if (dev_priv->me_fw->size % 8) {
|
||||
printk(KERN_ERR
|
||||
"radeon_cp: Bogus length %zu in firmware \"%s\"\n",
|
||||
dev_priv->me_fw->size, fw_name);
|
||||
err = -EINVAL;
|
||||
release_firmware(dev_priv->me_fw);
|
||||
dev_priv->me_fw = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
|
||||
{
|
||||
const __be32 *fw_data;
|
||||
int i, size;
|
||||
|
||||
radeon_do_wait_for_idle(dev_priv);
|
||||
|
||||
if (dev_priv->me_fw) {
|
||||
size = dev_priv->me_fw->size / 4;
|
||||
fw_data = (const __be32 *)&dev_priv->me_fw->data[0];
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
|
||||
for (i = 0; i < size; i += 2) {
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
|
||||
R520_cp_microcode[i][1]);
|
||||
be32_to_cpup(&fw_data[i]));
|
||||
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
|
||||
R520_cp_microcode[i][0]);
|
||||
be32_to_cpup(&fw_data[i + 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -594,6 +616,18 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
|
|||
|
||||
dev_priv->cp_running = 1;
|
||||
|
||||
/* on r420, any DMA from CP to system memory while 2D is active
|
||||
* can cause a hang. workaround is to queue a CP RESYNC token
|
||||
*/
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
|
||||
BEGIN_RING(3);
|
||||
OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
|
||||
OUT_RING(5); /* scratch reg 5 */
|
||||
OUT_RING(0xdeadbeef);
|
||||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
}
|
||||
|
||||
BEGIN_RING(8);
|
||||
/* isync can only be written through cp on r5xx write it here */
|
||||
OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
|
||||
|
@ -631,8 +665,19 @@ static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
|
|||
*/
|
||||
static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
|
||||
{
|
||||
RING_LOCALS;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* finish the pending CP_RESYNC token */
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
|
||||
BEGIN_RING(2);
|
||||
OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
|
||||
OUT_RING(R300_RB3D_DC_FINISH);
|
||||
ADVANCE_RING();
|
||||
COMMIT_RING();
|
||||
radeon_do_wait_for_idle(dev_priv);
|
||||
}
|
||||
|
||||
RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
|
||||
|
||||
dev_priv->cp_running = 0;
|
||||
|
@ -1495,6 +1540,14 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
|
|||
radeon_set_pcigart(dev_priv, 1);
|
||||
}
|
||||
|
||||
if (!dev_priv->me_fw) {
|
||||
int err = radeon_cp_init_microcode(dev_priv);
|
||||
if (err) {
|
||||
DRM_ERROR("Failed to load firmware!\n");
|
||||
radeon_do_cleanup_cp(dev);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
radeon_cp_load_microcode(dev_priv);
|
||||
radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
|
||||
|
||||
|
@ -1764,6 +1817,14 @@ void radeon_do_release(struct drm_device * dev)
|
|||
r600_do_cleanup_cp(dev);
|
||||
else
|
||||
radeon_do_cleanup_cp(dev);
|
||||
if (dev_priv->me_fw) {
|
||||
release_firmware(dev_priv->me_fw);
|
||||
dev_priv->me_fw = NULL;
|
||||
}
|
||||
if (dev_priv->pfp_fw) {
|
||||
release_firmware(dev_priv->pfp_fw);
|
||||
dev_priv->pfp_fw = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
|
|||
cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
|
||||
|
||||
size = p->chunks[i].length_dw * sizeof(uint32_t);
|
||||
p->chunks[i].kdata = kzalloc(size, GFP_KERNEL);
|
||||
p->chunks[i].kdata = kmalloc(size, GFP_KERNEL);
|
||||
if (p->chunks[i].kdata == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -185,6 +185,7 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
|
|||
mutex_unlock(&parser->rdev->ddev->struct_mutex);
|
||||
}
|
||||
}
|
||||
kfree(parser->track);
|
||||
kfree(parser->relocs);
|
||||
kfree(parser->relocs_ptr);
|
||||
for (i = 0; i < parser->nchunks; i++) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
#include "radeon_asic.h"
|
||||
|
@ -37,7 +38,7 @@
|
|||
/*
|
||||
* Clear GPU surface registers.
|
||||
*/
|
||||
static void radeon_surface_init(struct radeon_device *rdev)
|
||||
void radeon_surface_init(struct radeon_device *rdev)
|
||||
{
|
||||
/* FIXME: check this out */
|
||||
if (rdev->family < CHIP_R600) {
|
||||
|
@ -56,7 +57,7 @@ static void radeon_surface_init(struct radeon_device *rdev)
|
|||
/*
|
||||
* GPU scratch registers helpers function.
|
||||
*/
|
||||
static void radeon_scratch_init(struct radeon_device *rdev)
|
||||
void radeon_scratch_init(struct radeon_device *rdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -156,16 +157,18 @@ int radeon_mc_setup(struct radeon_device *rdev)
|
|||
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
|
||||
rdev->mc.gtt_location = tmp;
|
||||
}
|
||||
DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20);
|
||||
rdev->mc.vram_start = rdev->mc.vram_location;
|
||||
rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
|
||||
rdev->mc.gtt_start = rdev->mc.gtt_location;
|
||||
rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
|
||||
DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20));
|
||||
DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
|
||||
rdev->mc.vram_location,
|
||||
rdev->mc.vram_location + rdev->mc.mc_vram_size - 1);
|
||||
if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size)
|
||||
DRM_INFO("radeon: VRAM less than aperture workaround enabled\n");
|
||||
DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20);
|
||||
(unsigned)rdev->mc.vram_location,
|
||||
(unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1));
|
||||
DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20));
|
||||
DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
|
||||
rdev->mc.gtt_location,
|
||||
rdev->mc.gtt_location + rdev->mc.gtt_size - 1);
|
||||
(unsigned)rdev->mc.gtt_location,
|
||||
(unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -173,7 +176,7 @@ int radeon_mc_setup(struct radeon_device *rdev)
|
|||
/*
|
||||
* GPU helpers function.
|
||||
*/
|
||||
static bool radeon_card_posted(struct radeon_device *rdev)
|
||||
bool radeon_card_posted(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
|
@ -205,6 +208,31 @@ static bool radeon_card_posted(struct radeon_device *rdev)
|
|||
|
||||
}
|
||||
|
||||
int radeon_dummy_page_init(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO);
|
||||
if (rdev->dummy_page.page == NULL)
|
||||
return -ENOMEM;
|
||||
rdev->dummy_page.addr = pci_map_page(rdev->pdev, rdev->dummy_page.page,
|
||||
0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
if (!rdev->dummy_page.addr) {
|
||||
__free_page(rdev->dummy_page.page);
|
||||
rdev->dummy_page.page = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_dummy_page_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->dummy_page.page == NULL)
|
||||
return;
|
||||
pci_unmap_page(rdev->pdev, rdev->dummy_page.addr,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
__free_page(rdev->dummy_page.page);
|
||||
rdev->dummy_page.page = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Registers accessors functions.
|
||||
|
@ -243,6 +271,10 @@ void radeon_register_accessor_init(struct radeon_device *rdev)
|
|||
rdev->pll_rreg = &r100_pll_rreg;
|
||||
rdev->pll_wreg = &r100_pll_wreg;
|
||||
}
|
||||
if (rdev->family >= CHIP_R420) {
|
||||
rdev->mc_rreg = &r420_mc_rreg;
|
||||
rdev->mc_wreg = &r420_mc_wreg;
|
||||
}
|
||||
if (rdev->family >= CHIP_RV515) {
|
||||
rdev->mc_rreg = &rv515_mc_rreg;
|
||||
rdev->mc_wreg = &rv515_mc_wreg;
|
||||
|
@ -289,6 +321,14 @@ int radeon_asic_init(struct radeon_device *rdev)
|
|||
case CHIP_RV350:
|
||||
case CHIP_RV380:
|
||||
rdev->asic = &r300_asic;
|
||||
if (rdev->flags & RADEON_IS_PCIE) {
|
||||
rdev->asic->gart_init = &rv370_pcie_gart_init;
|
||||
rdev->asic->gart_fini = &rv370_pcie_gart_fini;
|
||||
rdev->asic->gart_enable = &rv370_pcie_gart_enable;
|
||||
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
|
||||
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
|
||||
}
|
||||
break;
|
||||
case CHIP_R420:
|
||||
case CHIP_R423:
|
||||
|
@ -323,9 +363,15 @@ int radeon_asic_init(struct radeon_device *rdev)
|
|||
case CHIP_RV635:
|
||||
case CHIP_RV670:
|
||||
case CHIP_RS780:
|
||||
case CHIP_RS880:
|
||||
rdev->asic = &r600_asic;
|
||||
break;
|
||||
case CHIP_RV770:
|
||||
case CHIP_RV730:
|
||||
case CHIP_RV710:
|
||||
case CHIP_RV740:
|
||||
rdev->asic = &rv770_asic;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: not supported yet */
|
||||
return -EINVAL;
|
||||
|
@ -341,7 +387,6 @@ int radeon_clocks_init(struct radeon_device *rdev)
|
|||
{
|
||||
int r;
|
||||
|
||||
radeon_get_clock_info(rdev->ddev);
|
||||
r = radeon_static_clocks_init(rdev->ddev);
|
||||
if (r) {
|
||||
return r;
|
||||
|
@ -436,10 +481,18 @@ void radeon_combios_fini(struct radeon_device *rdev)
|
|||
{
|
||||
}
|
||||
|
||||
int radeon_modeset_init(struct radeon_device *rdev);
|
||||
void radeon_modeset_fini(struct radeon_device *rdev);
|
||||
|
||||
/* if we get transitioned to only one device, tak VGA back */
|
||||
static unsigned int radeon_vga_set_decode(void *cookie, bool state)
|
||||
{
|
||||
struct radeon_device *rdev = cookie;
|
||||
|
||||
radeon_vga_set_state(rdev, state);
|
||||
if (state)
|
||||
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
|
||||
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
|
||||
else
|
||||
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
|
||||
}
|
||||
/*
|
||||
* Radeon device.
|
||||
*/
|
||||
|
@ -448,11 +501,12 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
struct pci_dev *pdev,
|
||||
uint32_t flags)
|
||||
{
|
||||
int r, ret;
|
||||
int r;
|
||||
int dma_bits;
|
||||
|
||||
DRM_INFO("radeon: Initializing kernel modesetting.\n");
|
||||
rdev->shutdown = false;
|
||||
rdev->dev = &pdev->dev;
|
||||
rdev->ddev = ddev;
|
||||
rdev->pdev = pdev;
|
||||
rdev->flags = flags;
|
||||
|
@ -461,35 +515,45 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT;
|
||||
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
|
||||
rdev->gpu_lockup = false;
|
||||
rdev->accel_working = false;
|
||||
/* mutex initialization are all done here so we
|
||||
* can recall function without having locking issues */
|
||||
mutex_init(&rdev->cs_mutex);
|
||||
mutex_init(&rdev->ib_pool.mutex);
|
||||
mutex_init(&rdev->cp.mutex);
|
||||
rwlock_init(&rdev->fence_drv.lock);
|
||||
|
||||
if (radeon_agpmode == -1) {
|
||||
rdev->flags &= ~RADEON_IS_AGP;
|
||||
if (rdev->family > CHIP_RV515 ||
|
||||
rdev->family == CHIP_RV380 ||
|
||||
rdev->family == CHIP_RV410 ||
|
||||
rdev->family == CHIP_R423) {
|
||||
DRM_INFO("Forcing AGP to PCIE mode\n");
|
||||
rdev->flags |= RADEON_IS_PCIE;
|
||||
} else {
|
||||
DRM_INFO("Forcing AGP to PCI mode\n");
|
||||
rdev->flags |= RADEON_IS_PCI;
|
||||
}
|
||||
}
|
||||
INIT_LIST_HEAD(&rdev->gem.objects);
|
||||
|
||||
/* Set asic functions */
|
||||
r = radeon_asic_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = radeon_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
|
||||
if (radeon_agpmode == -1) {
|
||||
rdev->flags &= ~RADEON_IS_AGP;
|
||||
if (rdev->family >= CHIP_RV515 ||
|
||||
rdev->family == CHIP_RV380 ||
|
||||
rdev->family == CHIP_RV410 ||
|
||||
rdev->family == CHIP_R423) {
|
||||
DRM_INFO("Forcing AGP to PCIE mode\n");
|
||||
rdev->flags |= RADEON_IS_PCIE;
|
||||
rdev->asic->gart_init = &rv370_pcie_gart_init;
|
||||
rdev->asic->gart_fini = &rv370_pcie_gart_fini;
|
||||
rdev->asic->gart_enable = &rv370_pcie_gart_enable;
|
||||
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
|
||||
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
|
||||
} else {
|
||||
DRM_INFO("Forcing AGP to PCI mode\n");
|
||||
rdev->flags |= RADEON_IS_PCI;
|
||||
rdev->asic->gart_init = &r100_pci_gart_init;
|
||||
rdev->asic->gart_fini = &r100_pci_gart_fini;
|
||||
rdev->asic->gart_enable = &r100_pci_gart_enable;
|
||||
rdev->asic->gart_disable = &r100_pci_gart_disable;
|
||||
rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
|
||||
rdev->asic->gart_set_page = &r100_pci_gart_set_page;
|
||||
}
|
||||
}
|
||||
|
||||
/* set DMA mask + need_dma32 flags.
|
||||
|
@ -521,156 +585,150 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
|
||||
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
|
||||
|
||||
/* Setup errata flags */
|
||||
radeon_errata(rdev);
|
||||
/* Initialize scratch registers */
|
||||
radeon_scratch_init(rdev);
|
||||
/* Initialize surface registers */
|
||||
radeon_surface_init(rdev);
|
||||
rdev->new_init_path = false;
|
||||
r = radeon_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* TODO: disable VGA need to use VGA request */
|
||||
/* BIOS*/
|
||||
if (!radeon_get_bios(rdev)) {
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
return -EINVAL;
|
||||
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
|
||||
r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
|
||||
if (r) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rdev->is_atom_bios) {
|
||||
r = radeon_atombios_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
|
||||
if (!rdev->new_init_path) {
|
||||
/* Setup errata flags */
|
||||
radeon_errata(rdev);
|
||||
/* Initialize scratch registers */
|
||||
radeon_scratch_init(rdev);
|
||||
/* Initialize surface registers */
|
||||
radeon_surface_init(rdev);
|
||||
|
||||
/* BIOS*/
|
||||
if (!radeon_get_bios(rdev)) {
|
||||
if (ASIC_IS_AVIVO(rdev))
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
r = radeon_combios_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
|
||||
if (radeon_gpu_reset(rdev)) {
|
||||
/* FIXME: what do we want to do here ? */
|
||||
}
|
||||
/* check if cards are posted or not */
|
||||
if (!radeon_card_posted(rdev) && rdev->bios) {
|
||||
DRM_INFO("GPU not posted. posting now...\n");
|
||||
if (rdev->is_atom_bios) {
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
r = radeon_atombios_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
radeon_combios_asic_init(rdev->ddev);
|
||||
r = radeon_combios_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
|
||||
if (radeon_gpu_reset(rdev)) {
|
||||
/* FIXME: what do we want to do here ? */
|
||||
}
|
||||
/* check if cards are posted or not */
|
||||
if (!radeon_card_posted(rdev) && rdev->bios) {
|
||||
DRM_INFO("GPU not posted. posting now...\n");
|
||||
if (rdev->is_atom_bios) {
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
} else {
|
||||
radeon_combios_asic_init(rdev->ddev);
|
||||
}
|
||||
}
|
||||
/* Get clock & vram information */
|
||||
radeon_get_clock_info(rdev->ddev);
|
||||
radeon_vram_info(rdev);
|
||||
/* Initialize clocks */
|
||||
r = radeon_clocks_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* Initialize clocks */
|
||||
r = radeon_clocks_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Get vram informations */
|
||||
radeon_vram_info(rdev);
|
||||
|
||||
/* Add an MTRR for the VRAM */
|
||||
rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
|
||||
MTRR_TYPE_WRCOMB, 1);
|
||||
DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n",
|
||||
rdev->mc.real_vram_size >> 20,
|
||||
(unsigned)rdev->mc.aper_size >> 20);
|
||||
DRM_INFO("RAM width %dbits %cDR\n",
|
||||
rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = radeon_mc_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = radeon_irq_kms_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Memory manager */
|
||||
r = radeon_object_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Initialize GART (initialize after TTM so we can allocate
|
||||
* memory through TTM but finalize after TTM) */
|
||||
r = radeon_gart_enable(rdev);
|
||||
if (!r) {
|
||||
r = radeon_gem_init(rdev);
|
||||
}
|
||||
/* Initialize memory controller (also test AGP) */
|
||||
r = radeon_mc_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Fence driver */
|
||||
r = radeon_fence_driver_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = radeon_irq_kms_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
/* Memory manager */
|
||||
r = radeon_object_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
r = radeon_gpu_gart_init(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
/* Initialize GART (initialize after TTM so we can allocate
|
||||
* memory through TTM but finalize after TTM) */
|
||||
r = radeon_gart_enable(rdev);
|
||||
if (r)
|
||||
return 0;
|
||||
r = radeon_gem_init(rdev);
|
||||
if (r)
|
||||
return 0;
|
||||
|
||||
/* 1M ring buffer */
|
||||
if (!r) {
|
||||
/* 1M ring buffer */
|
||||
r = radeon_cp_init(rdev, 1024 * 1024);
|
||||
}
|
||||
if (!r) {
|
||||
if (r)
|
||||
return 0;
|
||||
r = radeon_wb_init(rdev);
|
||||
if (r) {
|
||||
if (r)
|
||||
DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if (!r) {
|
||||
r = radeon_ib_pool_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if (!r) {
|
||||
if (r)
|
||||
return 0;
|
||||
r = radeon_ib_test(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failled testing IB (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
ret = r;
|
||||
r = radeon_modeset_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
if (!ret) {
|
||||
DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
|
||||
if (r)
|
||||
return 0;
|
||||
rdev->accel_working = true;
|
||||
}
|
||||
DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
|
||||
if (radeon_testing) {
|
||||
radeon_test_moves(rdev);
|
||||
}
|
||||
if (radeon_benchmarking) {
|
||||
radeon_benchmark(rdev);
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_device_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev == NULL || rdev->rmmio == NULL) {
|
||||
return;
|
||||
}
|
||||
DRM_INFO("radeon: finishing device.\n");
|
||||
rdev->shutdown = true;
|
||||
/* Order matter so becarefull if you rearrange anythings */
|
||||
radeon_modeset_fini(rdev);
|
||||
radeon_ib_pool_fini(rdev);
|
||||
radeon_cp_fini(rdev);
|
||||
radeon_wb_fini(rdev);
|
||||
radeon_gem_fini(rdev);
|
||||
radeon_object_fini(rdev);
|
||||
/* mc_fini must be after object_fini */
|
||||
radeon_mc_fini(rdev);
|
||||
if (!rdev->new_init_path) {
|
||||
radeon_ib_pool_fini(rdev);
|
||||
radeon_cp_fini(rdev);
|
||||
radeon_wb_fini(rdev);
|
||||
radeon_gpu_gart_fini(rdev);
|
||||
radeon_gem_fini(rdev);
|
||||
radeon_mc_fini(rdev);
|
||||
#if __OS_HAS_AGP
|
||||
radeon_agp_fini(rdev);
|
||||
radeon_agp_fini(rdev);
|
||||
#endif
|
||||
radeon_irq_kms_fini(rdev);
|
||||
radeon_fence_driver_fini(rdev);
|
||||
radeon_clocks_fini(rdev);
|
||||
if (rdev->is_atom_bios) {
|
||||
radeon_atombios_fini(rdev);
|
||||
radeon_irq_kms_fini(rdev);
|
||||
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
||||
radeon_fence_driver_fini(rdev);
|
||||
radeon_clocks_fini(rdev);
|
||||
radeon_object_fini(rdev);
|
||||
if (rdev->is_atom_bios) {
|
||||
radeon_atombios_fini(rdev);
|
||||
} else {
|
||||
radeon_combios_fini(rdev);
|
||||
}
|
||||
kfree(rdev->bios);
|
||||
rdev->bios = NULL;
|
||||
} else {
|
||||
radeon_combios_fini(rdev);
|
||||
radeon_fini(rdev);
|
||||
}
|
||||
kfree(rdev->bios);
|
||||
rdev->bios = NULL;
|
||||
iounmap(rdev->rmmio);
|
||||
rdev->rmmio = NULL;
|
||||
}
|
||||
|
@ -708,15 +766,19 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
|
|||
/* wait for gpu to finish processing current batch */
|
||||
radeon_fence_wait_last(rdev);
|
||||
|
||||
radeon_cp_disable(rdev);
|
||||
radeon_gart_disable(rdev);
|
||||
radeon_save_bios_scratch_regs(rdev);
|
||||
|
||||
if (!rdev->new_init_path) {
|
||||
radeon_cp_disable(rdev);
|
||||
radeon_gart_disable(rdev);
|
||||
rdev->irq.sw_int = false;
|
||||
radeon_irq_set(rdev);
|
||||
} else {
|
||||
radeon_suspend(rdev);
|
||||
}
|
||||
/* evict remaining vram memory */
|
||||
radeon_object_evict_vram(rdev);
|
||||
|
||||
rdev->irq.sw_int = false;
|
||||
radeon_irq_set(rdev);
|
||||
|
||||
pci_save_state(dev->pdev);
|
||||
if (state.event == PM_EVENT_SUSPEND) {
|
||||
/* Shut down the device */
|
||||
|
@ -743,38 +805,43 @@ int radeon_resume_kms(struct drm_device *dev)
|
|||
}
|
||||
pci_set_master(dev->pdev);
|
||||
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
|
||||
if (radeon_gpu_reset(rdev)) {
|
||||
/* FIXME: what do we want to do here ? */
|
||||
}
|
||||
/* post card */
|
||||
if (rdev->is_atom_bios) {
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
if (!rdev->new_init_path) {
|
||||
if (radeon_gpu_reset(rdev)) {
|
||||
/* FIXME: what do we want to do here ? */
|
||||
}
|
||||
/* post card */
|
||||
if (rdev->is_atom_bios) {
|
||||
atom_asic_init(rdev->mode_info.atom_context);
|
||||
} else {
|
||||
radeon_combios_asic_init(rdev->ddev);
|
||||
}
|
||||
/* Initialize clocks */
|
||||
r = radeon_clocks_init(rdev);
|
||||
if (r) {
|
||||
release_console_sem();
|
||||
return r;
|
||||
}
|
||||
/* Enable IRQ */
|
||||
rdev->irq.sw_int = true;
|
||||
radeon_irq_set(rdev);
|
||||
/* Initialize GPU Memory Controller */
|
||||
r = radeon_mc_init(rdev);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
r = radeon_gart_enable(rdev);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
r = radeon_cp_init(rdev, rdev->cp.ring_size);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
radeon_combios_asic_init(rdev->ddev);
|
||||
}
|
||||
/* Initialize clocks */
|
||||
r = radeon_clocks_init(rdev);
|
||||
if (r) {
|
||||
release_console_sem();
|
||||
return r;
|
||||
}
|
||||
/* Enable IRQ */
|
||||
rdev->irq.sw_int = true;
|
||||
radeon_irq_set(rdev);
|
||||
/* Initialize GPU Memory Controller */
|
||||
r = radeon_mc_init(rdev);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
r = radeon_gart_enable(rdev);
|
||||
if (r) {
|
||||
goto out;
|
||||
}
|
||||
r = radeon_cp_init(rdev, rdev->cp.ring_size);
|
||||
if (r) {
|
||||
goto out;
|
||||
radeon_resume(rdev);
|
||||
}
|
||||
out:
|
||||
radeon_restore_bios_scratch_regs(rdev);
|
||||
fb_set_suspend(rdev->fbdev_info, 0);
|
||||
release_console_sem();
|
||||
|
||||
|
|
|
@ -158,9 +158,6 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc)
|
|||
{
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
|
||||
if (radeon_crtc->mode_set.mode) {
|
||||
drm_mode_destroy(crtc->dev, radeon_crtc->mode_set.mode);
|
||||
}
|
||||
drm_crtc_cleanup(crtc);
|
||||
kfree(radeon_crtc);
|
||||
}
|
||||
|
@ -189,9 +186,11 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
|
|||
radeon_crtc->crtc_id = index;
|
||||
rdev->mode_info.crtcs[index] = radeon_crtc;
|
||||
|
||||
#if 0
|
||||
radeon_crtc->mode_set.crtc = &radeon_crtc->base;
|
||||
radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
|
||||
radeon_crtc->mode_set.num_connectors = 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
radeon_crtc->lut_r[i] = i << 2;
|
||||
|
@ -313,7 +312,7 @@ static void radeon_print_display_setup(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
bool radeon_setup_enc_conn(struct drm_device *dev)
|
||||
static bool radeon_setup_enc_conn(struct drm_device *dev)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_connector *drm_connector;
|
||||
|
@ -347,9 +346,13 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
|
|||
|
||||
if (!radeon_connector->ddc_bus)
|
||||
return -1;
|
||||
radeon_i2c_do_lock(radeon_connector, 1);
|
||||
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector, 0);
|
||||
if (!radeon_connector->edid) {
|
||||
radeon_i2c_do_lock(radeon_connector, 1);
|
||||
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
|
||||
radeon_i2c_do_lock(radeon_connector, 0);
|
||||
} else
|
||||
edid = radeon_connector->edid;
|
||||
|
||||
if (edid) {
|
||||
/* update digital bits here */
|
||||
if (edid->input & DRM_EDID_INPUT_DIGITAL)
|
||||
|
@ -362,7 +365,7 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
|
|||
return ret;
|
||||
}
|
||||
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeon_ddc_dump(struct drm_connector *connector)
|
||||
|
@ -620,6 +623,83 @@ static const struct drm_mode_config_funcs radeon_mode_funcs = {
|
|||
.fb_changed = radeonfb_probe,
|
||||
};
|
||||
|
||||
struct drm_prop_enum_list {
|
||||
int type;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] =
|
||||
{ { 0, "driver" },
|
||||
{ 1, "bios" },
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list radeon_tv_std_enum_list[] =
|
||||
{ { TV_STD_NTSC, "ntsc" },
|
||||
{ TV_STD_PAL, "pal" },
|
||||
{ TV_STD_PAL_M, "pal-m" },
|
||||
{ TV_STD_PAL_60, "pal-60" },
|
||||
{ TV_STD_NTSC_J, "ntsc-j" },
|
||||
{ TV_STD_SCART_PAL, "scart-pal" },
|
||||
{ TV_STD_PAL_CN, "pal-cn" },
|
||||
{ TV_STD_SECAM, "secam" },
|
||||
};
|
||||
|
||||
int radeon_modeset_create_props(struct radeon_device *rdev)
|
||||
{
|
||||
int i, sz;
|
||||
|
||||
if (rdev->is_atom_bios) {
|
||||
rdev->mode_info.coherent_mode_property =
|
||||
drm_property_create(rdev->ddev,
|
||||
DRM_MODE_PROP_RANGE,
|
||||
"coherent", 2);
|
||||
if (!rdev->mode_info.coherent_mode_property)
|
||||
return -ENOMEM;
|
||||
|
||||
rdev->mode_info.coherent_mode_property->values[0] = 0;
|
||||
rdev->mode_info.coherent_mode_property->values[0] = 1;
|
||||
}
|
||||
|
||||
if (!ASIC_IS_AVIVO(rdev)) {
|
||||
sz = ARRAY_SIZE(radeon_tmds_pll_enum_list);
|
||||
rdev->mode_info.tmds_pll_property =
|
||||
drm_property_create(rdev->ddev,
|
||||
DRM_MODE_PROP_ENUM,
|
||||
"tmds_pll", sz);
|
||||
for (i = 0; i < sz; i++) {
|
||||
drm_property_add_enum(rdev->mode_info.tmds_pll_property,
|
||||
i,
|
||||
radeon_tmds_pll_enum_list[i].type,
|
||||
radeon_tmds_pll_enum_list[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
rdev->mode_info.load_detect_property =
|
||||
drm_property_create(rdev->ddev,
|
||||
DRM_MODE_PROP_RANGE,
|
||||
"load detection", 2);
|
||||
if (!rdev->mode_info.load_detect_property)
|
||||
return -ENOMEM;
|
||||
rdev->mode_info.load_detect_property->values[0] = 0;
|
||||
rdev->mode_info.load_detect_property->values[0] = 1;
|
||||
|
||||
drm_mode_create_scaling_mode_property(rdev->ddev);
|
||||
|
||||
sz = ARRAY_SIZE(radeon_tv_std_enum_list);
|
||||
rdev->mode_info.tv_std_property =
|
||||
drm_property_create(rdev->ddev,
|
||||
DRM_MODE_PROP_ENUM,
|
||||
"tv standard", sz);
|
||||
for (i = 0; i < sz; i++) {
|
||||
drm_property_add_enum(rdev->mode_info.tv_std_property,
|
||||
i,
|
||||
radeon_tv_std_enum_list[i].type,
|
||||
radeon_tv_std_enum_list[i].name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radeon_modeset_init(struct radeon_device *rdev)
|
||||
{
|
||||
int num_crtc = 2, i;
|
||||
|
@ -640,6 +720,10 @@ int radeon_modeset_init(struct radeon_device *rdev)
|
|||
|
||||
rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
|
||||
|
||||
ret = radeon_modeset_create_props(rdev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
/* allocate crtcs - TODO single crtc */
|
||||
for (i = 0; i < num_crtc; i++) {
|
||||
radeon_crtc_init(rdev->ddev, i);
|
||||
|
@ -678,7 +762,6 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
|||
continue;
|
||||
if (first) {
|
||||
radeon_crtc->rmx_type = radeon_encoder->rmx_type;
|
||||
radeon_crtc->devices = radeon_encoder->devices;
|
||||
memcpy(&radeon_crtc->native_mode,
|
||||
&radeon_encoder->native_mode,
|
||||
sizeof(struct radeon_native_mode));
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <linux/console.h>
|
||||
|
||||
|
||||
#if defined(CONFIG_DRM_RADEON_KMS)
|
||||
/*
|
||||
* KMS wrapper.
|
||||
*/
|
||||
|
@ -77,11 +76,9 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
|
|||
int radeon_debugfs_init(struct drm_minor *minor);
|
||||
void radeon_debugfs_cleanup(struct drm_minor *minor);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
int radeon_no_wb;
|
||||
#if defined(CONFIG_DRM_RADEON_KMS)
|
||||
int radeon_modeset = -1;
|
||||
int radeon_dynclks = -1;
|
||||
int radeon_r4xx_atom = 0;
|
||||
|
@ -91,12 +88,11 @@ int radeon_gart_size = 512; /* default gart size */
|
|||
int radeon_benchmarking = 0;
|
||||
int radeon_testing = 0;
|
||||
int radeon_connector_table = 0;
|
||||
#endif
|
||||
int radeon_tv = 1;
|
||||
|
||||
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
|
||||
module_param_named(no_wb, radeon_no_wb, int, 0444);
|
||||
|
||||
#if defined(CONFIG_DRM_RADEON_KMS)
|
||||
MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
|
||||
module_param_named(modeset, radeon_modeset, int, 0400);
|
||||
|
||||
|
@ -123,7 +119,9 @@ module_param_named(test, radeon_testing, int, 0444);
|
|||
|
||||
MODULE_PARM_DESC(connector_table, "Force connector table");
|
||||
module_param_named(connector_table, radeon_connector_table, int, 0444);
|
||||
#endif
|
||||
|
||||
MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
|
||||
module_param_named(tv, radeon_tv, int, 0444);
|
||||
|
||||
static int radeon_suspend(struct drm_device *dev, pm_message_t state)
|
||||
{
|
||||
|
@ -215,7 +213,6 @@ static struct drm_driver driver_old = {
|
|||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DRM_RADEON_KMS)
|
||||
static struct drm_driver kms_driver;
|
||||
|
||||
static int __devinit
|
||||
|
@ -289,7 +286,7 @@ static struct drm_driver kms_driver = {
|
|||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = NULL,
|
||||
.compat_ioctl = radeon_kms_compat_ioctl,
|
||||
#endif
|
||||
},
|
||||
|
||||
|
@ -309,7 +306,6 @@ static struct drm_driver kms_driver = {
|
|||
.minor = KMS_DRIVER_MINOR,
|
||||
.patchlevel = KMS_DRIVER_PATCHLEVEL,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct drm_driver *driver;
|
||||
|
||||
|
@ -317,7 +313,6 @@ static int __init radeon_init(void)
|
|||
{
|
||||
driver = &driver_old;
|
||||
driver->num_ioctls = radeon_max_ioctl;
|
||||
#if defined(CONFIG_DRM_RADEON_KMS)
|
||||
#ifdef CONFIG_VGA_CONSOLE
|
||||
if (vgacon_text_force() && radeon_modeset == -1) {
|
||||
DRM_INFO("VGACON disable radeon kernel modesetting.\n");
|
||||
|
@ -328,8 +323,13 @@ static int __init radeon_init(void)
|
|||
#endif
|
||||
/* if enabled by default */
|
||||
if (radeon_modeset == -1) {
|
||||
DRM_INFO("radeon default to kernel modesetting.\n");
|
||||
#ifdef CONFIG_DRM_RADEON_KMS
|
||||
DRM_INFO("radeon defaulting to kernel modesetting.\n");
|
||||
radeon_modeset = 1;
|
||||
#else
|
||||
DRM_INFO("radeon defaulting to userspace modesetting.\n");
|
||||
radeon_modeset = 0;
|
||||
#endif
|
||||
}
|
||||
if (radeon_modeset == 1) {
|
||||
DRM_INFO("radeon kernel modesetting enabled.\n");
|
||||
|
@ -339,7 +339,6 @@ static int __init radeon_init(void)
|
|||
}
|
||||
/* if the vga console setting is enabled still
|
||||
* let modprobe override it */
|
||||
#endif
|
||||
return drm_init(driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#ifndef __RADEON_DRV_H__
|
||||
#define __RADEON_DRV_H__
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/* General customization:
|
||||
*/
|
||||
|
||||
|
@ -353,6 +356,14 @@ typedef struct drm_radeon_private {
|
|||
int r700_sc_hiz_tile_fifo_size;
|
||||
int r700_sc_earlyz_tile_fifo_fize;
|
||||
|
||||
struct mutex cs_mutex;
|
||||
u32 cs_id_scnt;
|
||||
u32 cs_id_wcnt;
|
||||
/* r6xx/r7xx drm blit vertex buffer */
|
||||
struct drm_buf *blit_vb;
|
||||
|
||||
/* firmware */
|
||||
const struct firmware *me_fw, *pfp_fw;
|
||||
} drm_radeon_private_t;
|
||||
|
||||
typedef struct drm_radeon_buf_priv {
|
||||
|
@ -391,6 +402,9 @@ static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
|
|||
(off >= gart_start && off <= gart_end));
|
||||
}
|
||||
|
||||
/* radeon_state.c */
|
||||
extern void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf);
|
||||
|
||||
/* radeon_cp.c */
|
||||
extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
|
@ -457,6 +471,8 @@ extern int radeon_driver_open(struct drm_device *dev,
|
|||
struct drm_file *file_priv);
|
||||
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
extern long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
extern int radeon_master_create(struct drm_device *dev, struct drm_master *master);
|
||||
extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master);
|
||||
|
@ -482,6 +498,22 @@ extern int r600_cp_dispatch_indirect(struct drm_device *dev,
|
|||
struct drm_buf *buf, int start, int end);
|
||||
extern int r600_page_table_init(struct drm_device *dev);
|
||||
extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info);
|
||||
extern int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv);
|
||||
extern void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv);
|
||||
extern int r600_cp_dispatch_texture(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
drm_radeon_texture_t *tex,
|
||||
drm_radeon_tex_image_t *image);
|
||||
/* r600_blit.c */
|
||||
extern int r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv);
|
||||
extern void r600_done_blit_copy(struct drm_device *dev);
|
||||
extern void r600_blit_copy(struct drm_device *dev,
|
||||
uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
|
||||
int size_bytes);
|
||||
extern void r600_blit_swap(struct drm_device *dev,
|
||||
uint64_t src_gpu_addr, uint64_t dst_gpu_addr,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h, int src_pitch, int dst_pitch, int cpp);
|
||||
|
||||
/* Flags for stats.boxes
|
||||
*/
|
||||
|
@ -1067,6 +1099,9 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
|
|||
# define RADEON_CSQ_PRIBM_INDBM (4 << 28)
|
||||
# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28)
|
||||
|
||||
#define R300_CP_RESYNC_ADDR 0x0778
|
||||
#define R300_CP_RESYNC_DATA 0x077c
|
||||
|
||||
#define RADEON_AIC_CNTL 0x01d0
|
||||
# define RADEON_PCIGART_TRANSLATE_EN (1 << 0)
|
||||
# define RS400_MSI_REARM (1 << 3)
|
||||
|
@ -1109,13 +1144,71 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
|
|||
# define RADEON_CNTL_BITBLT_MULTI 0x00009B00
|
||||
# define RADEON_CNTL_SET_SCISSORS 0xC0001E00
|
||||
|
||||
# define R600_IT_INDIRECT_BUFFER 0x00003200
|
||||
# define R600_IT_ME_INITIALIZE 0x00004400
|
||||
# define R600_IT_INDIRECT_BUFFER_END 0x00001700
|
||||
# define R600_IT_SET_PREDICATION 0x00002000
|
||||
# define R600_IT_REG_RMW 0x00002100
|
||||
# define R600_IT_COND_EXEC 0x00002200
|
||||
# define R600_IT_PRED_EXEC 0x00002300
|
||||
# define R600_IT_START_3D_CMDBUF 0x00002400
|
||||
# define R600_IT_DRAW_INDEX_2 0x00002700
|
||||
# define R600_IT_CONTEXT_CONTROL 0x00002800
|
||||
# define R600_IT_DRAW_INDEX_IMMD_BE 0x00002900
|
||||
# define R600_IT_INDEX_TYPE 0x00002A00
|
||||
# define R600_IT_DRAW_INDEX 0x00002B00
|
||||
# define R600_IT_DRAW_INDEX_AUTO 0x00002D00
|
||||
# define R600_IT_DRAW_INDEX_IMMD 0x00002E00
|
||||
# define R600_IT_NUM_INSTANCES 0x00002F00
|
||||
# define R600_IT_STRMOUT_BUFFER_UPDATE 0x00003400
|
||||
# define R600_IT_INDIRECT_BUFFER_MP 0x00003800
|
||||
# define R600_IT_MEM_SEMAPHORE 0x00003900
|
||||
# define R600_IT_MPEG_INDEX 0x00003A00
|
||||
# define R600_IT_WAIT_REG_MEM 0x00003C00
|
||||
# define R600_IT_MEM_WRITE 0x00003D00
|
||||
# define R600_IT_INDIRECT_BUFFER 0x00003200
|
||||
# define R600_IT_CP_INTERRUPT 0x00004000
|
||||
# define R600_IT_SURFACE_SYNC 0x00004300
|
||||
# define R600_CB0_DEST_BASE_ENA (1 << 6)
|
||||
# define R600_TC_ACTION_ENA (1 << 23)
|
||||
# define R600_VC_ACTION_ENA (1 << 24)
|
||||
# define R600_CB_ACTION_ENA (1 << 25)
|
||||
# define R600_DB_ACTION_ENA (1 << 26)
|
||||
# define R600_SH_ACTION_ENA (1 << 27)
|
||||
# define R600_SMX_ACTION_ENA (1 << 28)
|
||||
# define R600_IT_ME_INITIALIZE 0x00004400
|
||||
# define R600_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
|
||||
# define R600_IT_EVENT_WRITE 0x00004600
|
||||
# define R600_IT_SET_CONFIG_REG 0x00006800
|
||||
# define R600_SET_CONFIG_REG_OFFSET 0x00008000
|
||||
# define R600_SET_CONFIG_REG_END 0x0000ac00
|
||||
# define R600_IT_COND_WRITE 0x00004500
|
||||
# define R600_IT_EVENT_WRITE 0x00004600
|
||||
# define R600_IT_EVENT_WRITE_EOP 0x00004700
|
||||
# define R600_IT_ONE_REG_WRITE 0x00005700
|
||||
# define R600_IT_SET_CONFIG_REG 0x00006800
|
||||
# define R600_SET_CONFIG_REG_OFFSET 0x00008000
|
||||
# define R600_SET_CONFIG_REG_END 0x0000ac00
|
||||
# define R600_IT_SET_CONTEXT_REG 0x00006900
|
||||
# define R600_SET_CONTEXT_REG_OFFSET 0x00028000
|
||||
# define R600_SET_CONTEXT_REG_END 0x00029000
|
||||
# define R600_IT_SET_ALU_CONST 0x00006A00
|
||||
# define R600_SET_ALU_CONST_OFFSET 0x00030000
|
||||
# define R600_SET_ALU_CONST_END 0x00032000
|
||||
# define R600_IT_SET_BOOL_CONST 0x00006B00
|
||||
# define R600_SET_BOOL_CONST_OFFSET 0x0003e380
|
||||
# define R600_SET_BOOL_CONST_END 0x00040000
|
||||
# define R600_IT_SET_LOOP_CONST 0x00006C00
|
||||
# define R600_SET_LOOP_CONST_OFFSET 0x0003e200
|
||||
# define R600_SET_LOOP_CONST_END 0x0003e380
|
||||
# define R600_IT_SET_RESOURCE 0x00006D00
|
||||
# define R600_SET_RESOURCE_OFFSET 0x00038000
|
||||
# define R600_SET_RESOURCE_END 0x0003c000
|
||||
# define R600_SQ_TEX_VTX_INVALID_TEXTURE 0x0
|
||||
# define R600_SQ_TEX_VTX_INVALID_BUFFER 0x1
|
||||
# define R600_SQ_TEX_VTX_VALID_TEXTURE 0x2
|
||||
# define R600_SQ_TEX_VTX_VALID_BUFFER 0x3
|
||||
# define R600_IT_SET_SAMPLER 0x00006E00
|
||||
# define R600_SET_SAMPLER_OFFSET 0x0003c000
|
||||
# define R600_SET_SAMPLER_END 0x0003cff0
|
||||
# define R600_IT_SET_CTL_CONST 0x00006F00
|
||||
# define R600_SET_CTL_CONST_OFFSET 0x0003cff0
|
||||
# define R600_SET_CTL_CONST_END 0x0003e200
|
||||
# define R600_IT_SURFACE_BASE_UPDATE 0x00007300
|
||||
|
||||
#define RADEON_CP_PACKET_MASK 0xC0000000
|
||||
#define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000
|
||||
|
@ -1593,6 +1686,52 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
|
|||
#define R600_CB_COLOR7_BASE 0x2805c
|
||||
#define R600_CB_COLOR7_FRAG 0x280fc
|
||||
|
||||
#define R600_CB_COLOR0_SIZE 0x28060
|
||||
#define R600_CB_COLOR0_VIEW 0x28080
|
||||
#define R600_CB_COLOR0_INFO 0x280a0
|
||||
#define R600_CB_COLOR0_TILE 0x280c0
|
||||
#define R600_CB_COLOR0_FRAG 0x280e0
|
||||
#define R600_CB_COLOR0_MASK 0x28100
|
||||
|
||||
#define AVIVO_D1MODE_VLINE_START_END 0x6538
|
||||
#define AVIVO_D2MODE_VLINE_START_END 0x6d38
|
||||
#define R600_CP_COHER_BASE 0x85f8
|
||||
#define R600_DB_DEPTH_BASE 0x2800c
|
||||
#define R600_SQ_PGM_START_FS 0x28894
|
||||
#define R600_SQ_PGM_START_ES 0x28880
|
||||
#define R600_SQ_PGM_START_VS 0x28858
|
||||
#define R600_SQ_PGM_RESOURCES_VS 0x28868
|
||||
#define R600_SQ_PGM_CF_OFFSET_VS 0x288d0
|
||||
#define R600_SQ_PGM_START_GS 0x2886c
|
||||
#define R600_SQ_PGM_START_PS 0x28840
|
||||
#define R600_SQ_PGM_RESOURCES_PS 0x28850
|
||||
#define R600_SQ_PGM_EXPORTS_PS 0x28854
|
||||
#define R600_SQ_PGM_CF_OFFSET_PS 0x288cc
|
||||
#define R600_VGT_DMA_BASE 0x287e8
|
||||
#define R600_VGT_DMA_BASE_HI 0x287e4
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_0 0x28b10
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_1 0x28b14
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_2 0x28b18
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_3 0x28b1c
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_HI_0 0x28b44
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_HI_1 0x28b48
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_HI_2 0x28b4c
|
||||
#define R600_VGT_STRMOUT_BASE_OFFSET_HI_3 0x28b50
|
||||
#define R600_VGT_STRMOUT_BUFFER_BASE_0 0x28ad8
|
||||
#define R600_VGT_STRMOUT_BUFFER_BASE_1 0x28ae8
|
||||
#define R600_VGT_STRMOUT_BUFFER_BASE_2 0x28af8
|
||||
#define R600_VGT_STRMOUT_BUFFER_BASE_3 0x28b08
|
||||
#define R600_VGT_STRMOUT_BUFFER_OFFSET_0 0x28adc
|
||||
#define R600_VGT_STRMOUT_BUFFER_OFFSET_1 0x28aec
|
||||
#define R600_VGT_STRMOUT_BUFFER_OFFSET_2 0x28afc
|
||||
#define R600_VGT_STRMOUT_BUFFER_OFFSET_3 0x28b0c
|
||||
|
||||
#define R600_VGT_PRIMITIVE_TYPE 0x8958
|
||||
|
||||
#define R600_PA_SC_SCREEN_SCISSOR_TL 0x28030
|
||||
#define R600_PA_SC_GENERIC_SCISSOR_TL 0x28240
|
||||
#define R600_PA_SC_WINDOW_SCISSOR_TL 0x28204
|
||||
|
||||
#define R600_TC_CNTL 0x9608
|
||||
# define R600_TC_L2_SIZE(x) ((x) << 5)
|
||||
# define R600_L2_DISABLE_LATE_HIT (1 << 9)
|
||||
|
|
|
@ -126,6 +126,23 @@ radeon_link_encoder_connector(struct drm_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
void radeon_encoder_set_active_device(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder == encoder) {
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
|
||||
DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n",
|
||||
radeon_encoder->active_device, radeon_encoder->devices,
|
||||
radeon_connector->devices, encoder->encoder_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct drm_connector *
|
||||
radeon_get_connector_for_encoder(struct drm_encoder *encoder)
|
||||
{
|
||||
|
@ -224,9 +241,12 @@ atombios_dac_setup(struct drm_encoder *encoder, int action)
|
|||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
DAC_ENCODER_CONTROL_PS_ALLOCATION args;
|
||||
int index = 0, num = 0;
|
||||
/* fixme - fill in enc_priv for atom dac */
|
||||
struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
|
||||
enum radeon_tv_std tv_std = TV_STD_NTSC;
|
||||
|
||||
if (dac_info->tv_std)
|
||||
tv_std = dac_info->tv_std;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
|
@ -244,9 +264,9 @@ atombios_dac_setup(struct drm_encoder *encoder, int action)
|
|||
|
||||
args.ucAction = action;
|
||||
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
|
||||
args.ucDacStandard = ATOM_DAC1_PS2;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
args.ucDacStandard = ATOM_DAC1_CV;
|
||||
else {
|
||||
switch (tv_std) {
|
||||
|
@ -279,16 +299,19 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)
|
|||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
TV_ENCODER_CONTROL_PS_ALLOCATION args;
|
||||
int index = 0;
|
||||
/* fixme - fill in enc_priv for atom dac */
|
||||
struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
|
||||
enum radeon_tv_std tv_std = TV_STD_NTSC;
|
||||
|
||||
if (dac_info->tv_std)
|
||||
tv_std = dac_info->tv_std;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
|
||||
|
||||
args.sTVEncoder.ucAction = action;
|
||||
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
|
||||
else {
|
||||
switch (tv_std) {
|
||||
|
@ -520,6 +543,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
|||
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
|
||||
if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
|
||||
return ATOM_ENCODER_MODE_HDMI;
|
||||
else if (radeon_connector->use_digital)
|
||||
|
@ -529,7 +553,6 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
|||
break;
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
case DRM_MODE_CONNECTOR_HDMIB:
|
||||
default:
|
||||
if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
|
||||
return ATOM_ENCODER_MODE_HDMI;
|
||||
|
@ -825,10 +848,10 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
|
|||
|
||||
/* XXX: fix up scratch reg handling */
|
||||
temp = RREG32(reg);
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
|
||||
WREG32(reg, (ATOM_S3_TV1_ACTIVE |
|
||||
(radeon_crtc->crtc_id << 18)));
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
|
||||
else
|
||||
WREG32(reg, 0);
|
||||
|
@ -851,9 +874,19 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
|
||||
int index = 0;
|
||||
bool is_dig = false;
|
||||
int devices;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
||||
/* on DPMS off we have no idea if active device is meaningful */
|
||||
if (mode != DRM_MODE_DPMS_ON && !radeon_encoder->active_device)
|
||||
devices = radeon_encoder->devices;
|
||||
else
|
||||
devices = radeon_encoder->active_device;
|
||||
|
||||
DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
|
||||
radeon_encoder->encoder_id, mode, radeon_encoder->devices,
|
||||
radeon_encoder->active_device);
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
|
||||
|
@ -881,18 +914,18 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
|
||||
else
|
||||
index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DAC2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
|
||||
else
|
||||
index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
|
||||
|
@ -979,18 +1012,18 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
|
|||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
|
||||
args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
|
||||
else
|
||||
args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DAC2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
|
||||
args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
|
||||
else
|
||||
args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
|
||||
|
@ -1019,17 +1052,17 @@ atombios_set_encoder_crtc_source(struct drm_encoder *encoder)
|
|||
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
|
||||
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
|
||||
else
|
||||
args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
|
||||
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
|
||||
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
|
||||
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
|
||||
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
|
||||
else
|
||||
args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
|
||||
|
@ -1097,7 +1130,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|||
atombios_set_encoder_crtc_source(encoder);
|
||||
|
||||
if (ASIC_IS_AVIVO(rdev)) {
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
|
||||
atombios_yuv_setup(encoder, true);
|
||||
else
|
||||
atombios_yuv_setup(encoder, false);
|
||||
|
@ -1135,7 +1168,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|||
case ENCODER_OBJECT_ID_INTERNAL_DAC2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
|
||||
atombios_dac_setup(encoder, ATOM_ENABLE);
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
|
||||
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
|
||||
atombios_tv_setup(encoder, ATOM_ENABLE);
|
||||
break;
|
||||
}
|
||||
|
@ -1143,11 +1176,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
|
|||
}
|
||||
|
||||
static bool
|
||||
atombios_dac_load_detect(struct drm_encoder *encoder)
|
||||
atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
|
||||
ATOM_DEVICE_CV_SUPPORT |
|
||||
|
@ -1168,15 +1202,15 @@ atombios_dac_load_detect(struct drm_encoder *encoder)
|
|||
else
|
||||
args.sDacload.ucDacType = ATOM_DAC_B;
|
||||
|
||||
if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT)
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
|
||||
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
|
||||
else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT)
|
||||
else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
|
||||
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
|
||||
else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
|
||||
else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
|
||||
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
|
||||
if (crev >= 3)
|
||||
args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
|
||||
} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
|
||||
} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
|
||||
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
|
||||
if (crev >= 3)
|
||||
args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
|
||||
|
@ -1195,9 +1229,10 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
|
|||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
uint32_t bios_0_scratch;
|
||||
|
||||
if (!atombios_dac_load_detect(encoder)) {
|
||||
if (!atombios_dac_load_detect(encoder, connector)) {
|
||||
DRM_DEBUG("detect returned false \n");
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
@ -1207,17 +1242,20 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
|
|||
else
|
||||
bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
|
||||
|
||||
DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch);
|
||||
if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
|
||||
DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
|
||||
if (bios_0_scratch & ATOM_S0_CRT1_MASK)
|
||||
return connector_status_connected;
|
||||
} else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
|
||||
}
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
|
||||
if (bios_0_scratch & ATOM_S0_CRT2_MASK)
|
||||
return connector_status_connected;
|
||||
} else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
|
||||
}
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
|
||||
if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
|
||||
return connector_status_connected;
|
||||
} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
|
||||
}
|
||||
if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
|
||||
if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
|
||||
return connector_status_connected; /* CTV */
|
||||
else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
|
||||
|
@ -1230,6 +1268,8 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
|
|||
{
|
||||
radeon_atom_output_lock(encoder, true);
|
||||
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
}
|
||||
|
||||
static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
|
||||
|
@ -1238,12 +1278,20 @@ static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
|
|||
radeon_atom_output_lock(encoder, false);
|
||||
}
|
||||
|
||||
static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
radeon_encoder->active_device = 0;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
|
||||
.dpms = radeon_atom_encoder_dpms,
|
||||
.mode_fixup = radeon_atom_mode_fixup,
|
||||
.prepare = radeon_atom_encoder_prepare,
|
||||
.mode_set = radeon_atom_encoder_mode_set,
|
||||
.commit = radeon_atom_encoder_commit,
|
||||
.disable = radeon_atom_encoder_disable,
|
||||
/* no detect for TMDS/LVDS yet */
|
||||
};
|
||||
|
||||
|
@ -1268,6 +1316,18 @@ static const struct drm_encoder_funcs radeon_atom_enc_funcs = {
|
|||
.destroy = radeon_enc_destroy,
|
||||
};
|
||||
|
||||
struct radeon_encoder_atom_dac *
|
||||
radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
|
||||
{
|
||||
struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
|
||||
|
||||
if (!dac)
|
||||
return NULL;
|
||||
|
||||
dac->tv_std = TV_STD_NTSC;
|
||||
return dac;
|
||||
}
|
||||
|
||||
struct radeon_encoder_atom_dig *
|
||||
radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
|
||||
{
|
||||
|
@ -1336,6 +1396,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
|
|||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
|
||||
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
|
||||
radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
|
||||
drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DVO1:
|
||||
|
@ -1345,8 +1406,14 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
|
|||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
|
||||
radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
|
||||
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
||||
radeon_encoder->rmx_type = RMX_FULL;
|
||||
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
|
||||
radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
|
||||
} else {
|
||||
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
|
||||
radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
|
||||
}
|
||||
drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,15 +28,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
|
@ -45,375 +37,24 @@
|
|||
#include "radeon_drm.h"
|
||||
#include "radeon.h"
|
||||
|
||||
#include "drm_fb_helper.h"
|
||||
|
||||
struct radeon_fb_device {
|
||||
struct radeon_device *rdev;
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_fb_helper helper;
|
||||
struct radeon_framebuffer *rfb;
|
||||
int crtc_count;
|
||||
/* crtc currently bound to this */
|
||||
uint32_t crtc_ids[2];
|
||||
struct radeon_device *rdev;
|
||||
};
|
||||
|
||||
static int radeonfb_setcolreg(unsigned regno,
|
||||
unsigned red,
|
||||
unsigned green,
|
||||
unsigned blue,
|
||||
unsigned transp,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
struct drm_device *dev = rfbdev->rdev->ddev;
|
||||
struct drm_crtc *crtc;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_mode_set *modeset = &radeon_crtc->mode_set;
|
||||
struct drm_framebuffer *fb = modeset->fb;
|
||||
|
||||
for (i = 0; i < rfbdev->crtc_count; i++) {
|
||||
if (crtc->base.id == rfbdev->crtc_ids[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == rfbdev->crtc_count) {
|
||||
continue;
|
||||
}
|
||||
if (regno > 255) {
|
||||
return 1;
|
||||
}
|
||||
if (fb->depth == 8) {
|
||||
radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (regno < 16) {
|
||||
switch (fb->depth) {
|
||||
case 15:
|
||||
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
|
||||
((green & 0xf800) >> 6) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 16:
|
||||
fb->pseudo_palette[regno] = (red & 0xf800) |
|
||||
((green & 0xfc00) >> 5) |
|
||||
((blue & 0xf800) >> 11);
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
fb->pseudo_palette[regno] =
|
||||
(((red >> 8) & 0xff) << info->var.red.offset) |
|
||||
(((green >> 8) & 0xff) << info->var.green.offset) |
|
||||
(((blue >> 8) & 0xff) << info->var.blue.offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeonfb_check_var(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
struct radeon_framebuffer *rfb = rfbdev->rfb;
|
||||
struct drm_framebuffer *fb = &rfb->base;
|
||||
int depth;
|
||||
|
||||
if (var->pixclock == -1 || !var->pixclock) {
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Need to resize the fb object !!! */
|
||||
if (var->xres > fb->width || var->yres > fb->height) {
|
||||
DRM_ERROR("Requested width/height is greater than current fb "
|
||||
"object %dx%d > %dx%d\n", var->xres, var->yres,
|
||||
fb->width, fb->height);
|
||||
DRM_ERROR("Need resizing code.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
depth = (var->green.length == 6) ? 16 : 15;
|
||||
break;
|
||||
case 32:
|
||||
depth = (var->transp.length > 0) ? 32 : 24;
|
||||
break;
|
||||
default:
|
||||
depth = var->bits_per_pixel;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
var->red.offset = 0;
|
||||
var->green.offset = 0;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 5;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 1;
|
||||
var->transp.offset = 15;
|
||||
break;
|
||||
case 16:
|
||||
var->red.offset = 11;
|
||||
var->green.offset = 5;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.length = 5;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 32:
|
||||
var->red.offset = 16;
|
||||
var->green.offset = 8;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 8;
|
||||
var->transp.offset = 24;
|
||||
break;
|
||||
#else
|
||||
case 24:
|
||||
var->red.offset = 8;
|
||||
var->green.offset = 16;
|
||||
var->blue.offset = 24;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 0;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
case 32:
|
||||
var->red.offset = 8;
|
||||
var->green.offset = 16;
|
||||
var->blue.offset = 24;
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->transp.length = 8;
|
||||
var->transp.offset = 0;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this will let fbcon do the mode init */
|
||||
static int radeonfb_set_par(struct fb_info *info)
|
||||
{
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
struct drm_device *dev = rfbdev->rdev->ddev;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct drm_crtc *crtc;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (var->pixclock != -1) {
|
||||
DRM_ERROR("PIXEL CLCOK SET\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
|
||||
for (i = 0; i < rfbdev->crtc_count; i++) {
|
||||
if (crtc->base.id == rfbdev->crtc_ids[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == rfbdev->crtc_count) {
|
||||
continue;
|
||||
}
|
||||
if (crtc->fb == radeon_crtc->mode_set.fb) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = crtc->funcs->set_config(&radeon_crtc->mode_set);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radeonfb_pan_display(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
struct drm_device *dev = rfbdev->rdev->ddev;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_crtc *crtc;
|
||||
struct radeon_crtc *radeon_crtc;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
for (i = 0; i < rfbdev->crtc_count; i++) {
|
||||
if (crtc->base.id == rfbdev->crtc_ids[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == rfbdev->crtc_count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
radeon_crtc = to_radeon_crtc(crtc);
|
||||
modeset = &radeon_crtc->mode_set;
|
||||
|
||||
modeset->x = var->xoffset;
|
||||
modeset->y = var->yoffset;
|
||||
|
||||
if (modeset->num_connectors) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
ret = crtc->funcs->set_config(modeset);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
if (!ret) {
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void radeonfb_on(struct fb_info *info)
|
||||
{
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
struct drm_device *dev = rfbdev->rdev->ddev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, find all associated encoders
|
||||
* and turn them off, then turn off the CRTC.
|
||||
*/
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
for (i = 0; i < rfbdev->crtc_count; i++) {
|
||||
if (crtc->base.id == rfbdev->crtc_ids[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
/* Found a CRTC on this fb, now find encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void radeonfb_off(struct fb_info *info, int dpms_mode)
|
||||
{
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
struct drm_device *dev = rfbdev->rdev->ddev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* For each CRTC in this fb, find all associated encoders
|
||||
* and turn them off, then turn off the CRTC.
|
||||
*/
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
for (i = 0; i < rfbdev->crtc_count; i++) {
|
||||
if (crtc->base.id == rfbdev->crtc_ids[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found a CRTC on this fb, now find encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
encoder_funcs->dpms(encoder, dpms_mode);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
}
|
||||
if (dpms_mode == DRM_MODE_DPMS_OFF) {
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
crtc_funcs->dpms(crtc, dpms_mode);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int radeonfb_blank(int blank, struct fb_info *info)
|
||||
{
|
||||
switch (blank) {
|
||||
case FB_BLANK_UNBLANK:
|
||||
radeonfb_on(info);
|
||||
break;
|
||||
case FB_BLANK_NORMAL:
|
||||
radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
case FB_BLANK_HSYNC_SUSPEND:
|
||||
radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
|
||||
break;
|
||||
case FB_BLANK_VSYNC_SUSPEND:
|
||||
radeonfb_off(info, DRM_MODE_DPMS_SUSPEND);
|
||||
break;
|
||||
case FB_BLANK_POWERDOWN:
|
||||
radeonfb_off(info, DRM_MODE_DPMS_OFF);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fb_ops radeonfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_check_var = radeonfb_check_var,
|
||||
.fb_set_par = radeonfb_set_par,
|
||||
.fb_setcolreg = radeonfb_setcolreg,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_setcolreg = drm_fb_helper_setcolreg,
|
||||
.fb_fillrect = cfb_fillrect,
|
||||
.fb_copyarea = cfb_copyarea,
|
||||
.fb_imageblit = cfb_imageblit,
|
||||
.fb_pan_display = radeonfb_pan_display,
|
||||
.fb_blank = radeonfb_blank,
|
||||
.fb_pan_display = drm_fb_helper_pan_display,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -456,21 +97,6 @@ int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
|
|||
}
|
||||
EXPORT_SYMBOL(radeonfb_resize);
|
||||
|
||||
static struct drm_mode_set panic_mode;
|
||||
|
||||
int radeonfb_panic(struct notifier_block *n, unsigned long ununsed,
|
||||
void *panic_str)
|
||||
{
|
||||
DRM_ERROR("panic occurred, switching back to text console\n");
|
||||
drm_crtc_helper_set_config(&panic_mode);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(radeonfb_panic);
|
||||
|
||||
static struct notifier_block paniced = {
|
||||
.notifier_call = radeonfb_panic,
|
||||
};
|
||||
|
||||
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
|
||||
{
|
||||
int aligned = width;
|
||||
|
@ -495,11 +121,16 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo
|
|||
return aligned;
|
||||
}
|
||||
|
||||
int radeonfb_create(struct radeon_device *rdev,
|
||||
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
|
||||
.gamma_set = radeon_crtc_fb_gamma_set,
|
||||
};
|
||||
|
||||
int radeonfb_create(struct drm_device *dev,
|
||||
uint32_t fb_width, uint32_t fb_height,
|
||||
uint32_t surface_width, uint32_t surface_height,
|
||||
struct radeon_framebuffer **rfb_p)
|
||||
struct drm_framebuffer **fb_p)
|
||||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct fb_info *info;
|
||||
struct radeon_fb_device *rfbdev;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
|
@ -513,6 +144,7 @@ int radeonfb_create(struct radeon_device *rdev,
|
|||
void *fbptr = NULL;
|
||||
unsigned long tmp;
|
||||
bool fb_tiled = false; /* useful for testing */
|
||||
u32 tiling_flags = 0;
|
||||
|
||||
mode_cmd.width = surface_width;
|
||||
mode_cmd.height = surface_height;
|
||||
|
@ -537,7 +169,22 @@ int radeonfb_create(struct radeon_device *rdev,
|
|||
robj = gobj->driver_private;
|
||||
|
||||
if (fb_tiled)
|
||||
radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
|
||||
tiling_flags = RADEON_TILING_MACRO;
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
switch (mode_cmd.bpp) {
|
||||
case 32:
|
||||
tiling_flags |= RADEON_TILING_SWAP_32BIT;
|
||||
break;
|
||||
case 16:
|
||||
tiling_flags |= RADEON_TILING_SWAP_16BIT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tiling_flags)
|
||||
radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch);
|
||||
mutex_lock(&rdev->ddev->struct_mutex);
|
||||
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
|
||||
if (fb == NULL) {
|
||||
|
@ -554,8 +201,8 @@ int radeonfb_create(struct radeon_device *rdev,
|
|||
|
||||
list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
|
||||
|
||||
*fb_p = fb;
|
||||
rfb = to_radeon_framebuffer(fb);
|
||||
*rfb_p = rfb;
|
||||
rdev->fbdev_rfb = rfb;
|
||||
rdev->fbdev_robj = robj;
|
||||
|
||||
|
@ -564,7 +211,15 @@ int radeonfb_create(struct radeon_device *rdev,
|
|||
ret = -ENOMEM;
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
rdev->fbdev_info = info;
|
||||
rfbdev = info->par;
|
||||
rfbdev->helper.funcs = &radeon_fb_helper_funcs;
|
||||
rfbdev->helper.dev = dev;
|
||||
ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, 2,
|
||||
RADEONFB_CONN_LIMIT);
|
||||
if (ret)
|
||||
goto out_unref;
|
||||
|
||||
if (fb_tiled)
|
||||
radeon_object_check_tiling(robj, 0, 0);
|
||||
|
@ -577,33 +232,19 @@ int radeonfb_create(struct radeon_device *rdev,
|
|||
memset_io(fbptr, 0, aligned_size);
|
||||
|
||||
strcpy(info->fix.id, "radeondrmfb");
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
info->fix.type_aux = 0;
|
||||
info->fix.xpanstep = 1; /* doing it in hw */
|
||||
info->fix.ypanstep = 1; /* doing it in hw */
|
||||
info->fix.ywrapstep = 0;
|
||||
info->fix.accel = FB_ACCEL_NONE;
|
||||
info->fix.type_aux = 0;
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitch);
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &radeonfb_ops;
|
||||
info->fix.line_length = fb->pitch;
|
||||
|
||||
tmp = fb_gpuaddr - rdev->mc.vram_location;
|
||||
info->fix.smem_start = rdev->mc.aper_base + tmp;
|
||||
info->fix.smem_len = size;
|
||||
info->screen_base = fbptr;
|
||||
info->screen_size = size;
|
||||
info->pseudo_palette = fb->pseudo_palette;
|
||||
info->var.xres_virtual = fb->width;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->bits_per_pixel;
|
||||
info->var.xoffset = 0;
|
||||
info->var.yoffset = 0;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
info->var.height = -1;
|
||||
info->var.width = -1;
|
||||
info->var.xres = fb_width;
|
||||
info->var.yres = fb_height;
|
||||
|
||||
drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
info->aperture_base = rdev->ddev->mode_config.fb_base;
|
||||
|
@ -626,83 +267,6 @@ int radeonfb_create(struct radeon_device *rdev,
|
|||
DRM_INFO("fb depth is %d\n", fb->depth);
|
||||
DRM_INFO(" pitch is %d\n", fb->pitch);
|
||||
|
||||
switch (fb->depth) {
|
||||
case 8:
|
||||
info->var.red.offset = 0;
|
||||
info->var.green.offset = 0;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8; /* 8bit DAC */
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
case 15:
|
||||
info->var.red.offset = 10;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 5;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 15;
|
||||
info->var.transp.length = 1;
|
||||
break;
|
||||
case 16:
|
||||
info->var.red.offset = 11;
|
||||
info->var.green.offset = 5;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 5;
|
||||
info->var.green.length = 6;
|
||||
info->var.blue.length = 5;
|
||||
info->var.transp.offset = 0;
|
||||
break;
|
||||
case 24:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 32:
|
||||
info->var.red.offset = 16;
|
||||
info->var.green.offset = 8;
|
||||
info->var.blue.offset = 0;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 24;
|
||||
info->var.transp.length = 8;
|
||||
break;
|
||||
#else
|
||||
case 24:
|
||||
info->var.red.offset = 8;
|
||||
info->var.green.offset = 16;
|
||||
info->var.blue.offset = 24;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 0;
|
||||
break;
|
||||
case 32:
|
||||
info->var.red.offset = 8;
|
||||
info->var.green.offset = 16;
|
||||
info->var.blue.offset = 24;
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
info->var.transp.offset = 0;
|
||||
info->var.transp.length = 8;
|
||||
break;
|
||||
default:
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
fb->fbdev = info;
|
||||
rfbdev->rfb = rfb;
|
||||
rfbdev->rdev = rdev;
|
||||
|
@ -726,145 +290,10 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int radeonfb_single_fb_probe(struct radeon_device *rdev)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
|
||||
unsigned int surface_width = 0, surface_height = 0;
|
||||
int new_fb = 0;
|
||||
int crtc_count = 0;
|
||||
int ret, i, conn_count = 0;
|
||||
struct radeon_framebuffer *rfb;
|
||||
struct fb_info *info;
|
||||
struct radeon_fb_device *rfbdev;
|
||||
struct drm_mode_set *modeset = NULL;
|
||||
|
||||
/* first up get a count of crtcs now in use and new min/maxes width/heights */
|
||||
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
|
||||
if (drm_helper_crtc_in_use(crtc)) {
|
||||
if (crtc->desired_mode) {
|
||||
if (crtc->desired_mode->hdisplay < fb_width)
|
||||
fb_width = crtc->desired_mode->hdisplay;
|
||||
|
||||
if (crtc->desired_mode->vdisplay < fb_height)
|
||||
fb_height = crtc->desired_mode->vdisplay;
|
||||
|
||||
if (crtc->desired_mode->hdisplay > surface_width)
|
||||
surface_width = crtc->desired_mode->hdisplay;
|
||||
|
||||
if (crtc->desired_mode->vdisplay > surface_height)
|
||||
surface_height = crtc->desired_mode->vdisplay;
|
||||
}
|
||||
crtc_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
|
||||
/* hmm everyone went away - assume VGA cable just fell out
|
||||
and will come back later. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do we have an fb already? */
|
||||
if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) {
|
||||
/* create an fb if we don't have one */
|
||||
ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb);
|
||||
if (ret) {
|
||||
return -EINVAL;
|
||||
}
|
||||
new_fb = 1;
|
||||
} else {
|
||||
struct drm_framebuffer *fb;
|
||||
fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head);
|
||||
rfb = to_radeon_framebuffer(fb);
|
||||
|
||||
/* if someone hotplugs something bigger than we have already allocated, we are pwned.
|
||||
As really we can't resize an fbdev that is in the wild currently due to fbdev
|
||||
not really being designed for the lower layers moving stuff around under it.
|
||||
- so in the grand style of things - punt. */
|
||||
if ((fb->width < surface_width) || (fb->height < surface_height)) {
|
||||
DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
info = rfb->base.fbdev;
|
||||
rdev->fbdev_info = info;
|
||||
rfbdev = info->par;
|
||||
|
||||
crtc_count = 0;
|
||||
/* okay we need to setup new connector sets in the crtcs */
|
||||
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
modeset = &radeon_crtc->mode_set;
|
||||
modeset->fb = &rfb->base;
|
||||
conn_count = 0;
|
||||
list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) {
|
||||
if (connector->encoder)
|
||||
if (connector->encoder->crtc == modeset->crtc) {
|
||||
modeset->connectors[conn_count] = connector;
|
||||
conn_count++;
|
||||
if (conn_count > RADEONFB_CONN_LIMIT)
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++)
|
||||
modeset->connectors[i] = NULL;
|
||||
|
||||
|
||||
rfbdev->crtc_ids[crtc_count++] = crtc->base.id;
|
||||
|
||||
modeset->num_connectors = conn_count;
|
||||
if (modeset->crtc->desired_mode) {
|
||||
if (modeset->mode) {
|
||||
drm_mode_destroy(rdev->ddev, modeset->mode);
|
||||
}
|
||||
modeset->mode = drm_mode_duplicate(rdev->ddev,
|
||||
modeset->crtc->desired_mode);
|
||||
}
|
||||
}
|
||||
rfbdev->crtc_count = crtc_count;
|
||||
|
||||
if (new_fb) {
|
||||
info->var.pixclock = -1;
|
||||
if (register_framebuffer(info) < 0)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
radeonfb_set_par(info);
|
||||
}
|
||||
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
|
||||
info->fix.id);
|
||||
|
||||
/* Switch back to kernel console on panic */
|
||||
panic_mode = *modeset;
|
||||
atomic_notifier_chain_register(&panic_notifier_list, &paniced);
|
||||
printk(KERN_INFO "registered panic notifier\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radeonfb_probe(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* something has changed in the lower levels of hell - deal with it
|
||||
here */
|
||||
|
||||
/* two modes : a) 1 fb to rule all crtcs.
|
||||
b) one fb per crtc.
|
||||
two actions 1) new connected device
|
||||
2) device removed.
|
||||
case a/1 : if the fb surface isn't big enough - resize the surface fb.
|
||||
if the fb size isn't big enough - resize fb into surface.
|
||||
if everything big enough configure the new crtc/etc.
|
||||
case a/2 : undo the configuration
|
||||
possibly resize down the fb to fit the new configuration.
|
||||
case b/1 : see if it is on a new crtc - setup a new fb and add it.
|
||||
case b/2 : teardown the new fb.
|
||||
*/
|
||||
ret = radeonfb_single_fb_probe(dev->dev_private);
|
||||
ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(radeonfb_probe);
|
||||
|
@ -880,16 +309,17 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
|
|||
}
|
||||
info = fb->fbdev;
|
||||
if (info) {
|
||||
struct radeon_fb_device *rfbdev = info->par;
|
||||
robj = rfb->obj->driver_private;
|
||||
unregister_framebuffer(info);
|
||||
radeon_object_kunmap(robj);
|
||||
radeon_object_unpin(robj);
|
||||
drm_fb_helper_free(&rfbdev->helper);
|
||||
framebuffer_release(info);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "unregistered panic notifier\n");
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
|
||||
memset(&panic_mode, 0, sizeof(struct drm_mode_set));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(radeonfb_remove);
|
||||
|
|
|
@ -53,9 +53,9 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
|
|||
* away
|
||||
*/
|
||||
WREG32(rdev->fence_drv.scratch_reg, fence->seq);
|
||||
} else {
|
||||
} else
|
||||
radeon_fence_ring_emit(rdev, fence);
|
||||
}
|
||||
|
||||
fence->emited = true;
|
||||
fence->timeout = jiffies + ((2000 * HZ) / 1000);
|
||||
list_del(&fence->list);
|
||||
|
@ -168,7 +168,38 @@ bool radeon_fence_signaled(struct radeon_fence *fence)
|
|||
return signaled;
|
||||
}
|
||||
|
||||
int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
|
||||
int r600_fence_wait(struct radeon_fence *fence, bool intr, bool lazy)
|
||||
{
|
||||
struct radeon_device *rdev;
|
||||
int ret = 0;
|
||||
|
||||
rdev = fence->rdev;
|
||||
|
||||
__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
||||
|
||||
while (1) {
|
||||
if (radeon_fence_signaled(fence))
|
||||
break;
|
||||
|
||||
if (time_after_eq(jiffies, fence->timeout)) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lazy)
|
||||
schedule_timeout(1);
|
||||
|
||||
if (intr && signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int radeon_fence_wait(struct radeon_fence *fence, bool intr)
|
||||
{
|
||||
struct radeon_device *rdev;
|
||||
unsigned long cur_jiffies;
|
||||
|
@ -176,7 +207,6 @@ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
|
|||
bool expired = false;
|
||||
int r;
|
||||
|
||||
|
||||
if (fence == NULL) {
|
||||
WARN(1, "Querying an invalid fence : %p !\n", fence);
|
||||
return 0;
|
||||
|
@ -185,13 +215,22 @@ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
|
|||
if (radeon_fence_signaled(fence)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rdev->family >= CHIP_R600) {
|
||||
r = r600_fence_wait(fence, intr, 0);
|
||||
if (r == -ERESTARTSYS)
|
||||
return -EBUSY;
|
||||
return r;
|
||||
}
|
||||
|
||||
retry:
|
||||
cur_jiffies = jiffies;
|
||||
timeout = HZ / 100;
|
||||
if (time_after(fence->timeout, cur_jiffies)) {
|
||||
timeout = fence->timeout - cur_jiffies;
|
||||
}
|
||||
if (interruptible) {
|
||||
|
||||
if (intr) {
|
||||
r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
|
||||
radeon_fence_signaled(fence), timeout);
|
||||
if (unlikely(r == -ERESTARTSYS)) {
|
||||
|
|
|
@ -75,7 +75,6 @@ void radeon_gart_table_ram_free(struct radeon_device *rdev)
|
|||
|
||||
int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
|
||||
{
|
||||
uint64_t gpu_addr;
|
||||
int r;
|
||||
|
||||
if (rdev->gart.table.vram.robj == NULL) {
|
||||
|
@ -88,6 +87,14 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
|
|||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radeon_gart_table_vram_pin(struct radeon_device *rdev)
|
||||
{
|
||||
uint64_t gpu_addr;
|
||||
int r;
|
||||
|
||||
r = radeon_object_pin(rdev->gart.table.vram.robj,
|
||||
RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
|
||||
if (r) {
|
||||
|
|
|
@ -422,3 +422,18 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned int nr = DRM_IOCTL_NR(cmd);
|
||||
int ret;
|
||||
|
||||
if (nr < DRM_COMMAND_BASE)
|
||||
return drm_compat_ioctl(filp, cmd, arg);
|
||||
|
||||
lock_kernel(); /* XXX for now */
|
||||
ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
|
||||
unlock_kernel();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -188,6 +188,9 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
u32 stat;
|
||||
u32 r500_disp_int;
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
return IRQ_NONE;
|
||||
|
||||
/* Only consider the bits we're interested in - others could be used
|
||||
* outside the DRM
|
||||
*/
|
||||
|
@ -286,6 +289,9 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
drm_radeon_irq_emit_t *emit = data;
|
||||
int result;
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
return -EINVAL;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
if (!dev_priv) {
|
||||
|
@ -315,6 +321,9 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
return -EINVAL;
|
||||
|
||||
return radeon_wait_irq(dev, irqwait->irq_seq);
|
||||
}
|
||||
|
||||
|
@ -326,6 +335,9 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
|
|||
(drm_radeon_private_t *) dev->dev_private;
|
||||
u32 dummy;
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
return;
|
||||
|
||||
/* Disable *all* interrupts */
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
|
||||
RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
|
||||
|
@ -345,6 +357,9 @@ int radeon_driver_irq_postinstall(struct drm_device *dev)
|
|||
|
||||
dev->max_vblank_count = 0x001fffff;
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
return 0;
|
||||
|
||||
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
|
||||
|
||||
return 0;
|
||||
|
@ -357,6 +372,9 @@ void radeon_driver_irq_uninstall(struct drm_device * dev)
|
|||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
return;
|
||||
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
|
||||
RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
|
||||
/* Disable *all* interrupts */
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "drmP.h"
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_reg.h"
|
||||
#include "radeon_microcode.h"
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
|
||||
|
|
|
@ -54,12 +54,23 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
|||
flags |= RADEON_IS_PCI;
|
||||
}
|
||||
|
||||
/* radeon_device_init should report only fatal error
|
||||
* like memory allocation failure or iomapping failure,
|
||||
* or memory manager initialization failure, it must
|
||||
* properly initialize the GPU MC controller and permit
|
||||
* VRAM allocation
|
||||
*/
|
||||
r = radeon_device_init(rdev, dev, dev->pdev, flags);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n");
|
||||
radeon_device_fini(rdev);
|
||||
kfree(rdev);
|
||||
dev->dev_private = NULL;
|
||||
DRM_ERROR("Fatal error while trying to initialize radeon.\n");
|
||||
return r;
|
||||
}
|
||||
/* Again modeset_init should fail only on fatal error
|
||||
* otherwise it should provide enough functionalities
|
||||
* for shadowfb to run
|
||||
*/
|
||||
r = radeon_modeset_init(rdev);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
|
@ -69,6 +80,9 @@ int radeon_driver_unload_kms(struct drm_device *dev)
|
|||
{
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
||||
if (rdev == NULL)
|
||||
return 0;
|
||||
radeon_modeset_fini(rdev);
|
||||
radeon_device_fini(rdev);
|
||||
kfree(rdev);
|
||||
dev->dev_private = NULL;
|
||||
|
@ -98,6 +112,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
|||
case RADEON_INFO_NUM_Z_PIPES:
|
||||
value = rdev->num_z_pipes;
|
||||
break;
|
||||
case RADEON_INFO_ACCEL_WORKING:
|
||||
value = rdev->accel_working;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Invalid request %d\n", info->request);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <drm/radeon_drm.h>
|
||||
#include "radeon_fixed.h"
|
||||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
|
||||
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
|
@ -340,6 +341,9 @@ void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
|
|||
uint32_t crtc_pitch;
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
format = 2;
|
||||
break;
|
||||
case 15: /* 555 */
|
||||
format = 3;
|
||||
break;
|
||||
|
@ -400,11 +404,33 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
|
||||
uint32_t crtc_pitch, pitch_pixels;
|
||||
uint32_t tiling_flags;
|
||||
int format;
|
||||
uint32_t gen_cntl_reg, gen_cntl_val;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
radeon_fb = to_radeon_framebuffer(crtc->fb);
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
format = 2;
|
||||
break;
|
||||
case 15: /* 555 */
|
||||
format = 3;
|
||||
break;
|
||||
case 16: /* 565 */
|
||||
format = 4;
|
||||
break;
|
||||
case 24: /* RGB */
|
||||
format = 5;
|
||||
break;
|
||||
case 32: /* xRGB */
|
||||
format = 6;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
obj = radeon_fb->obj;
|
||||
if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
|
||||
return -EINVAL;
|
||||
|
@ -457,6 +483,9 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
} else {
|
||||
int offset = y * pitch_pixels + x;
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
offset *= 1;
|
||||
break;
|
||||
case 15:
|
||||
case 16:
|
||||
offset *= 2;
|
||||
|
@ -475,6 +504,16 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
|
||||
base &= ~7;
|
||||
|
||||
if (radeon_crtc->crtc_id == 1)
|
||||
gen_cntl_reg = RADEON_CRTC2_GEN_CNTL;
|
||||
else
|
||||
gen_cntl_reg = RADEON_CRTC_GEN_CNTL;
|
||||
|
||||
gen_cntl_val = RREG32(gen_cntl_reg);
|
||||
gen_cntl_val &= ~(0xf << 8);
|
||||
gen_cntl_val |= (format << 8);
|
||||
WREG32(gen_cntl_reg, gen_cntl_val);
|
||||
|
||||
crtc_offset = (u32)base;
|
||||
|
||||
WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr);
|
||||
|
@ -501,6 +540,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
|||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_encoder *encoder;
|
||||
int format;
|
||||
int hsync_start;
|
||||
int hsync_wid;
|
||||
|
@ -509,10 +549,24 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
|||
uint32_t crtc_h_sync_strt_wid;
|
||||
uint32_t crtc_v_total_disp;
|
||||
uint32_t crtc_v_sync_strt_wid;
|
||||
bool is_tv = false;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
|
||||
is_tv = true;
|
||||
DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (crtc->fb->bits_per_pixel) {
|
||||
case 8:
|
||||
format = 2;
|
||||
break;
|
||||
case 15: /* 555 */
|
||||
format = 3;
|
||||
break;
|
||||
|
@ -642,6 +696,11 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
|
|||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
}
|
||||
|
||||
if (is_tv)
|
||||
radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp,
|
||||
&crtc_h_sync_strt_wid, &crtc_v_total_disp,
|
||||
&crtc_v_sync_strt_wid);
|
||||
|
||||
WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
|
||||
WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
|
||||
|
@ -668,7 +727,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
uint32_t pll_ref_div = 0;
|
||||
uint32_t pll_fb_post_div = 0;
|
||||
uint32_t htotal_cntl = 0;
|
||||
|
||||
bool is_tv = false;
|
||||
struct radeon_pll *pll;
|
||||
|
||||
struct {
|
||||
|
@ -703,6 +762,13 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
if (encoder->crtc == crtc) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
|
||||
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
|
||||
is_tv = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
|
||||
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
|
||||
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
|
||||
|
@ -766,6 +832,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
|
||||
RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
|
||||
|
||||
if (is_tv) {
|
||||
radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl,
|
||||
&pll_ref_div, &pll_fb_post_div,
|
||||
&pixclks_cntl);
|
||||
}
|
||||
|
||||
WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
|
||||
RADEON_PIX2CLK_SRC_SEL_CPUCLK,
|
||||
~(RADEON_PIX2CLK_SRC_SEL_MASK));
|
||||
|
@ -820,6 +892,15 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
} else {
|
||||
uint32_t pixclks_cntl;
|
||||
|
||||
|
||||
if (is_tv) {
|
||||
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
|
||||
radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div,
|
||||
&pll_fb_post_div, &pixclks_cntl);
|
||||
}
|
||||
|
||||
if (rdev->flags & RADEON_IS_MOBILITY) {
|
||||
/* A temporal workaround for the occational blanking on certain laptop panels.
|
||||
This appears to related to the PLL divider registers (fail to lock?).
|
||||
|
@ -914,6 +995,8 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
|||
RADEON_VCLK_SRC_SEL_PPLLCLK,
|
||||
~(RADEON_VCLK_SRC_SEL_MASK));
|
||||
|
||||
if (is_tv)
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,15 @@
|
|||
#include "radeon.h"
|
||||
#include "atom.h"
|
||||
|
||||
static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
radeon_encoder->active_device = 0;
|
||||
}
|
||||
|
||||
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
|
@ -98,6 +107,8 @@ static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
|
|||
else
|
||||
radeon_combios_output_lock(encoder, true);
|
||||
radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
}
|
||||
|
||||
static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
|
||||
|
@ -195,6 +206,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
|
|||
.prepare = radeon_legacy_lvds_prepare,
|
||||
.mode_set = radeon_legacy_lvds_mode_set,
|
||||
.commit = radeon_legacy_lvds_commit,
|
||||
.disable = radeon_legacy_encoder_disable,
|
||||
};
|
||||
|
||||
|
||||
|
@ -260,6 +272,7 @@ static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
|
|||
else
|
||||
radeon_combios_output_lock(encoder, true);
|
||||
radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
}
|
||||
|
||||
static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
|
||||
|
@ -402,6 +415,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_fu
|
|||
.mode_set = radeon_legacy_primary_dac_mode_set,
|
||||
.commit = radeon_legacy_primary_dac_commit,
|
||||
.detect = radeon_legacy_primary_dac_detect,
|
||||
.disable = radeon_legacy_encoder_disable,
|
||||
};
|
||||
|
||||
|
||||
|
@ -454,6 +468,7 @@ static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
|
|||
else
|
||||
radeon_combios_output_lock(encoder, true);
|
||||
radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
}
|
||||
|
||||
static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
|
||||
|
@ -566,6 +581,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs
|
|||
.prepare = radeon_legacy_tmds_int_prepare,
|
||||
.mode_set = radeon_legacy_tmds_int_mode_set,
|
||||
.commit = radeon_legacy_tmds_int_commit,
|
||||
.disable = radeon_legacy_encoder_disable,
|
||||
};
|
||||
|
||||
|
||||
|
@ -620,6 +636,7 @@ static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
|
|||
else
|
||||
radeon_combios_output_lock(encoder, true);
|
||||
radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
}
|
||||
|
||||
static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
|
||||
|
@ -706,6 +723,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs
|
|||
.prepare = radeon_legacy_tmds_ext_prepare,
|
||||
.mode_set = radeon_legacy_tmds_ext_mode_set,
|
||||
.commit = radeon_legacy_tmds_ext_commit,
|
||||
.disable = radeon_legacy_encoder_disable,
|
||||
};
|
||||
|
||||
|
||||
|
@ -727,17 +745,21 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
|||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
|
||||
/* uint32_t tv_master_cntl = 0; */
|
||||
|
||||
uint32_t tv_master_cntl = 0;
|
||||
bool is_tv;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
|
||||
|
||||
if (rdev->family == CHIP_R200)
|
||||
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
else {
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
/* FIXME TV */
|
||||
/* tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); */
|
||||
if (is_tv)
|
||||
tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
|
||||
else
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
}
|
||||
|
||||
|
@ -746,20 +768,23 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
|||
if (rdev->family == CHIP_R200) {
|
||||
fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
|
||||
} else {
|
||||
crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
|
||||
/* tv_master_cntl |= RADEON_TV_ON; */
|
||||
if (is_tv)
|
||||
tv_master_cntl |= RADEON_TV_ON;
|
||||
else
|
||||
crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
|
||||
|
||||
if (rdev->family == CHIP_R420 ||
|
||||
rdev->family == CHIP_R423 ||
|
||||
rdev->family == CHIP_RV410)
|
||||
rdev->family == CHIP_R423 ||
|
||||
rdev->family == CHIP_RV410)
|
||||
tv_dac_cntl &= ~(R420_TV_DAC_RDACPD |
|
||||
R420_TV_DAC_GDACPD |
|
||||
R420_TV_DAC_BDACPD |
|
||||
RADEON_TV_DAC_BGSLEEP);
|
||||
R420_TV_DAC_GDACPD |
|
||||
R420_TV_DAC_BDACPD |
|
||||
RADEON_TV_DAC_BGSLEEP);
|
||||
else
|
||||
tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD |
|
||||
RADEON_TV_DAC_GDACPD |
|
||||
RADEON_TV_DAC_BDACPD |
|
||||
RADEON_TV_DAC_BGSLEEP);
|
||||
RADEON_TV_DAC_GDACPD |
|
||||
RADEON_TV_DAC_BDACPD |
|
||||
RADEON_TV_DAC_BGSLEEP);
|
||||
}
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
|
@ -768,8 +793,11 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
|||
if (rdev->family == CHIP_R200)
|
||||
fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
|
||||
else {
|
||||
crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
|
||||
/* tv_master_cntl &= ~RADEON_TV_ON; */
|
||||
if (is_tv)
|
||||
tv_master_cntl &= ~RADEON_TV_ON;
|
||||
else
|
||||
crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
|
||||
|
||||
if (rdev->family == CHIP_R420 ||
|
||||
rdev->family == CHIP_R423 ||
|
||||
rdev->family == CHIP_RV410)
|
||||
|
@ -789,8 +817,10 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
|||
if (rdev->family == CHIP_R200) {
|
||||
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
|
||||
} else {
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
/* WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); */
|
||||
if (is_tv)
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
|
||||
else
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
}
|
||||
|
||||
|
@ -809,6 +839,7 @@ static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
|
|||
else
|
||||
radeon_combios_output_lock(encoder, true);
|
||||
radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
radeon_encoder_set_active_device(encoder);
|
||||
}
|
||||
|
||||
static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
|
||||
|
@ -831,11 +862,15 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
|
|||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
|
||||
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0;
|
||||
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
|
||||
bool is_tv = false;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
|
||||
|
||||
if (rdev->family != CHIP_R200) {
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
if (rdev->family == CHIP_R420 ||
|
||||
|
@ -858,7 +893,7 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
|
|||
}
|
||||
|
||||
/* FIXME TV */
|
||||
if (radeon_encoder->enc_priv) {
|
||||
if (tv_dac) {
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
|
||||
RADEON_TV_DAC_NHOLD |
|
||||
|
@ -875,44 +910,93 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
|
|||
if (ASIC_IS_R300(rdev)) {
|
||||
gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
} else if (rdev->family == CHIP_R200)
|
||||
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
}
|
||||
|
||||
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
|
||||
disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
|
||||
else
|
||||
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
|
||||
|
||||
dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
|
||||
if (rdev->family == CHIP_R200)
|
||||
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
|
||||
if (radeon_crtc->crtc_id == 0) {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
|
||||
} else if (rdev->family == CHIP_R200) {
|
||||
fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
|
||||
RADEON_FP2_DVO_RATE_SEL_SDR);
|
||||
} else
|
||||
disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
|
||||
if (is_tv) {
|
||||
uint32_t dac_cntl;
|
||||
|
||||
dac_cntl = RREG32(RADEON_DAC_CNTL);
|
||||
dac_cntl &= ~RADEON_DAC_TVO_EN;
|
||||
WREG32(RADEON_DAC_CNTL, dac_cntl);
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
|
||||
|
||||
dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
|
||||
if (radeon_crtc->crtc_id == 0) {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
|
||||
RADEON_DISP_TV_SOURCE_CRTC);
|
||||
}
|
||||
if (rdev->family >= CHIP_R200) {
|
||||
disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
|
||||
} else {
|
||||
disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
|
||||
}
|
||||
} else {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
|
||||
}
|
||||
if (rdev->family >= CHIP_R200) {
|
||||
disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
|
||||
} else {
|
||||
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
|
||||
}
|
||||
}
|
||||
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
|
||||
} else {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
} else if (rdev->family == CHIP_R200) {
|
||||
fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
|
||||
RADEON_FP2_DVO_RATE_SEL_SDR);
|
||||
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
|
||||
} else
|
||||
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
|
||||
}
|
||||
|
||||
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
|
||||
dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
|
||||
|
||||
if (radeon_crtc->crtc_id == 0) {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC;
|
||||
} else if (rdev->family == CHIP_R200) {
|
||||
fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
|
||||
RADEON_FP2_DVO_RATE_SEL_SDR);
|
||||
} else
|
||||
disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
|
||||
} else {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
} else if (rdev->family == CHIP_R200) {
|
||||
fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
|
||||
RADEON_FP2_DVO_RATE_SEL_SDR);
|
||||
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2;
|
||||
} else
|
||||
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
|
||||
}
|
||||
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
|
||||
}
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl);
|
||||
} else if (rdev->family == CHIP_R200)
|
||||
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
}
|
||||
|
||||
if (rdev->family >= CHIP_R200)
|
||||
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
|
||||
else
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
|
||||
if (rdev->family == CHIP_R200)
|
||||
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
|
||||
|
||||
if (is_tv)
|
||||
radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
|
||||
|
||||
if (rdev->is_atom_bios)
|
||||
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
|
||||
else
|
||||
|
@ -920,6 +1004,141 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
|
|||
|
||||
}
|
||||
|
||||
static bool r300_legacy_tv_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t disp_output_cntl, gpiopad_a, tmp;
|
||||
bool found = false;
|
||||
|
||||
/* save regs needed */
|
||||
gpiopad_a = RREG32(RADEON_GPIOPAD_A);
|
||||
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
|
||||
WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
|
||||
|
||||
WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL,
|
||||
RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
|
||||
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
|
||||
WREG32(RADEON_DAC_EXT_CNTL,
|
||||
RADEON_DAC2_FORCE_BLANK_OFF_EN |
|
||||
RADEON_DAC2_FORCE_DATA_EN |
|
||||
RADEON_DAC_FORCE_DATA_SEL_RGB |
|
||||
(0xec << RADEON_DAC_FORCE_DATA_SHIFT));
|
||||
|
||||
WREG32(RADEON_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_STD_NTSC |
|
||||
(8 << RADEON_TV_DAC_BGADJ_SHIFT) |
|
||||
(6 << RADEON_TV_DAC_DACADJ_SHIFT));
|
||||
|
||||
RREG32(RADEON_TV_DAC_CNTL);
|
||||
mdelay(4);
|
||||
|
||||
WREG32(RADEON_TV_DAC_CNTL,
|
||||
RADEON_TV_DAC_NBLANK |
|
||||
RADEON_TV_DAC_NHOLD |
|
||||
RADEON_TV_MONITOR_DETECT_EN |
|
||||
RADEON_TV_DAC_STD_NTSC |
|
||||
(8 << RADEON_TV_DAC_BGADJ_SHIFT) |
|
||||
(6 << RADEON_TV_DAC_DACADJ_SHIFT));
|
||||
|
||||
RREG32(RADEON_TV_DAC_CNTL);
|
||||
mdelay(6);
|
||||
|
||||
tmp = RREG32(RADEON_TV_DAC_CNTL);
|
||||
if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
|
||||
found = true;
|
||||
DRM_DEBUG("S-video TV connection detected\n");
|
||||
} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
|
||||
found = true;
|
||||
DRM_DEBUG("Composite TV connection detected\n");
|
||||
}
|
||||
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t tv_dac_cntl, dac_cntl2;
|
||||
uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
|
||||
bool found = false;
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
return r300_legacy_tv_detect(encoder, connector);
|
||||
|
||||
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
|
||||
tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
config_cntl = RREG32(RADEON_CONFIG_CNTL);
|
||||
tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
|
||||
|
||||
tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
|
||||
WREG32(RADEON_DAC_CNTL2, tmp);
|
||||
|
||||
tmp = tv_master_cntl | RADEON_TV_ON;
|
||||
tmp &= ~(RADEON_TV_ASYNC_RST |
|
||||
RADEON_RESTART_PHASE_FIX |
|
||||
RADEON_CRT_FIFO_CE_EN |
|
||||
RADEON_TV_FIFO_CE_EN |
|
||||
RADEON_RE_SYNC_NOW_SEL_MASK);
|
||||
tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tmp);
|
||||
|
||||
tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
|
||||
RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
|
||||
(8 << RADEON_TV_DAC_BGADJ_SHIFT);
|
||||
|
||||
if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
|
||||
tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
|
||||
else
|
||||
tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tmp);
|
||||
|
||||
tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
|
||||
RADEON_RED_MX_FORCE_DAC_DATA |
|
||||
RADEON_GRN_MX_FORCE_DAC_DATA |
|
||||
RADEON_BLU_MX_FORCE_DAC_DATA |
|
||||
(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
|
||||
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
|
||||
|
||||
mdelay(3);
|
||||
tmp = RREG32(RADEON_TV_DAC_CNTL);
|
||||
if (tmp & RADEON_TV_DAC_GDACDET) {
|
||||
found = true;
|
||||
DRM_DEBUG("S-video TV connection detected\n");
|
||||
} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
|
||||
found = true;
|
||||
DRM_DEBUG("Composite TV connection detected\n");
|
||||
}
|
||||
|
||||
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
|
||||
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
|
||||
return found;
|
||||
}
|
||||
|
||||
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
|
@ -928,9 +1147,29 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
|||
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
|
||||
enum drm_connector_status found = connector_status_disconnected;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
bool color = true;
|
||||
|
||||
/* FIXME tv */
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
|
||||
bool tv_detect;
|
||||
|
||||
if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
|
||||
return connector_status_disconnected;
|
||||
|
||||
tv_detect = radeon_legacy_tv_detect(encoder, connector);
|
||||
if (tv_detect && tv_dac)
|
||||
found = connector_status_connected;
|
||||
return found;
|
||||
}
|
||||
|
||||
/* don't probe if the encoder is being used for something else not CRT related */
|
||||
if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
|
||||
DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
/* save the regs we need */
|
||||
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
|
||||
|
@ -1013,8 +1252,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
|||
}
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
|
||||
/* return found; */
|
||||
return connector_status_disconnected;
|
||||
return found;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1025,6 +1263,7 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs =
|
|||
.mode_set = radeon_legacy_tv_dac_mode_set,
|
||||
.commit = radeon_legacy_tv_dac_commit,
|
||||
.detect = radeon_legacy_tv_dac_detect,
|
||||
.disable = radeon_legacy_encoder_disable,
|
||||
};
|
||||
|
||||
|
||||
|
@ -1032,6 +1271,30 @@ static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = {
|
|||
.destroy = radeon_enc_destroy,
|
||||
};
|
||||
|
||||
|
||||
static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder_int_tmds *tmds = NULL;
|
||||
bool ret;
|
||||
|
||||
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
|
||||
|
||||
if (!tmds)
|
||||
return NULL;
|
||||
|
||||
if (rdev->is_atom_bios)
|
||||
ret = radeon_atombios_get_tmds_info(encoder, tmds);
|
||||
else
|
||||
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
|
||||
|
||||
if (ret == false)
|
||||
radeon_legacy_get_tmds_info_from_table(encoder, tmds);
|
||||
|
||||
return tmds;
|
||||
}
|
||||
|
||||
void
|
||||
radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
|
||||
{
|
||||
|
@ -1078,10 +1341,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
|
|||
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
|
||||
drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
|
||||
drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
|
||||
if (rdev->is_atom_bios)
|
||||
radeon_encoder->enc_priv = radeon_atombios_get_tmds_info(radeon_encoder);
|
||||
else
|
||||
radeon_encoder->enc_priv = radeon_combios_get_tmds_info(radeon_encoder);
|
||||
radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
|
||||
break;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
|
||||
drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
|
||||
|
|
904
drivers/gpu/drm/radeon/radeon_legacy_tv.c
Normal file
904
drivers/gpu/drm/radeon/radeon_legacy_tv.c
Normal file
|
@ -0,0 +1,904 @@
|
|||
#include "drmP.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "radeon.h"
|
||||
|
||||
/*
|
||||
* Integrated TV out support based on the GATOS code by
|
||||
* Federico Ulivi <fulivi@lycos.com>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Limits of h/v positions (hPos & vPos)
|
||||
*/
|
||||
#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */
|
||||
#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */
|
||||
|
||||
/*
|
||||
* Unit for hPos (in TV clock periods)
|
||||
*/
|
||||
#define H_POS_UNIT 10
|
||||
|
||||
/*
|
||||
* Indexes in h. code timing table for horizontal line position adjustment
|
||||
*/
|
||||
#define H_TABLE_POS1 6
|
||||
#define H_TABLE_POS2 8
|
||||
|
||||
/*
|
||||
* Limits of hor. size (hSize)
|
||||
*/
|
||||
#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */
|
||||
|
||||
/* tv standard constants */
|
||||
#define NTSC_TV_CLOCK_T 233
|
||||
#define NTSC_TV_VFTOTAL 1
|
||||
#define NTSC_TV_LINES_PER_FRAME 525
|
||||
#define NTSC_TV_ZERO_H_SIZE 479166
|
||||
#define NTSC_TV_H_SIZE_UNIT 9478
|
||||
|
||||
#define PAL_TV_CLOCK_T 188
|
||||
#define PAL_TV_VFTOTAL 3
|
||||
#define PAL_TV_LINES_PER_FRAME 625
|
||||
#define PAL_TV_ZERO_H_SIZE 473200
|
||||
#define PAL_TV_H_SIZE_UNIT 9360
|
||||
|
||||
/* tv pll setting for 27 mhz ref clk */
|
||||
#define NTSC_TV_PLL_M_27 22
|
||||
#define NTSC_TV_PLL_N_27 175
|
||||
#define NTSC_TV_PLL_P_27 5
|
||||
|
||||
#define PAL_TV_PLL_M_27 113
|
||||
#define PAL_TV_PLL_N_27 668
|
||||
#define PAL_TV_PLL_P_27 3
|
||||
|
||||
/* tv pll setting for 14 mhz ref clk */
|
||||
#define NTSC_TV_PLL_M_14 33
|
||||
#define NTSC_TV_PLL_N_14 693
|
||||
#define NTSC_TV_PLL_P_14 7
|
||||
|
||||
#define VERT_LEAD_IN_LINES 2
|
||||
#define FRAC_BITS 0xe
|
||||
#define FRAC_MASK 0x3fff
|
||||
|
||||
struct radeon_tv_mode_constants {
|
||||
uint16_t hor_resolution;
|
||||
uint16_t ver_resolution;
|
||||
enum radeon_tv_std standard;
|
||||
uint16_t hor_total;
|
||||
uint16_t ver_total;
|
||||
uint16_t hor_start;
|
||||
uint16_t hor_syncstart;
|
||||
uint16_t ver_syncstart;
|
||||
unsigned def_restart;
|
||||
uint16_t crtcPLL_N;
|
||||
uint8_t crtcPLL_M;
|
||||
uint8_t crtcPLL_post_div;
|
||||
unsigned pix_to_tv;
|
||||
};
|
||||
|
||||
static const uint16_t hor_timing_NTSC[] = {
|
||||
0x0007,
|
||||
0x003f,
|
||||
0x0263,
|
||||
0x0a24,
|
||||
0x2a6b,
|
||||
0x0a36,
|
||||
0x126d, /* H_TABLE_POS1 */
|
||||
0x1bfe,
|
||||
0x1a8f, /* H_TABLE_POS2 */
|
||||
0x1ec7,
|
||||
0x3863,
|
||||
0x1bfe,
|
||||
0x1bfe,
|
||||
0x1a2a,
|
||||
0x1e95,
|
||||
0x0e31,
|
||||
0x201b,
|
||||
0
|
||||
};
|
||||
|
||||
static const uint16_t vert_timing_NTSC[] = {
|
||||
0x2001,
|
||||
0x200d,
|
||||
0x1006,
|
||||
0x0c06,
|
||||
0x1006,
|
||||
0x1818,
|
||||
0x21e3,
|
||||
0x1006,
|
||||
0x0c06,
|
||||
0x1006,
|
||||
0x1817,
|
||||
0x21d4,
|
||||
0x0002,
|
||||
0
|
||||
};
|
||||
|
||||
static const uint16_t hor_timing_PAL[] = {
|
||||
0x0007,
|
||||
0x0058,
|
||||
0x027c,
|
||||
0x0a31,
|
||||
0x2a77,
|
||||
0x0a95,
|
||||
0x124f, /* H_TABLE_POS1 */
|
||||
0x1bfe,
|
||||
0x1b22, /* H_TABLE_POS2 */
|
||||
0x1ef9,
|
||||
0x387c,
|
||||
0x1bfe,
|
||||
0x1bfe,
|
||||
0x1b31,
|
||||
0x1eb5,
|
||||
0x0e43,
|
||||
0x201b,
|
||||
0
|
||||
};
|
||||
|
||||
static const uint16_t vert_timing_PAL[] = {
|
||||
0x2001,
|
||||
0x200c,
|
||||
0x1005,
|
||||
0x0c05,
|
||||
0x1005,
|
||||
0x1401,
|
||||
0x1821,
|
||||
0x2240,
|
||||
0x1005,
|
||||
0x0c05,
|
||||
0x1005,
|
||||
0x1401,
|
||||
0x1822,
|
||||
0x2230,
|
||||
0x0002,
|
||||
0
|
||||
};
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* availableModes
|
||||
*
|
||||
* Table of all allowed modes for tv output
|
||||
*
|
||||
**********************************************************************/
|
||||
static const struct radeon_tv_mode_constants available_tv_modes[] = {
|
||||
{ /* NTSC timing for 27 Mhz ref clk */
|
||||
800, /* horResolution */
|
||||
600, /* verResolution */
|
||||
TV_STD_NTSC, /* standard */
|
||||
990, /* horTotal */
|
||||
740, /* verTotal */
|
||||
813, /* horStart */
|
||||
824, /* horSyncStart */
|
||||
632, /* verSyncStart */
|
||||
625592, /* defRestart */
|
||||
592, /* crtcPLL_N */
|
||||
91, /* crtcPLL_M */
|
||||
4, /* crtcPLL_postDiv */
|
||||
1022, /* pixToTV */
|
||||
},
|
||||
{ /* PAL timing for 27 Mhz ref clk */
|
||||
800, /* horResolution */
|
||||
600, /* verResolution */
|
||||
TV_STD_PAL, /* standard */
|
||||
1144, /* horTotal */
|
||||
706, /* verTotal */
|
||||
812, /* horStart */
|
||||
824, /* horSyncStart */
|
||||
669, /* verSyncStart */
|
||||
696700, /* defRestart */
|
||||
1382, /* crtcPLL_N */
|
||||
231, /* crtcPLL_M */
|
||||
4, /* crtcPLL_postDiv */
|
||||
759, /* pixToTV */
|
||||
},
|
||||
{ /* NTSC timing for 14 Mhz ref clk */
|
||||
800, /* horResolution */
|
||||
600, /* verResolution */
|
||||
TV_STD_NTSC, /* standard */
|
||||
1018, /* horTotal */
|
||||
727, /* verTotal */
|
||||
813, /* horStart */
|
||||
840, /* horSyncStart */
|
||||
633, /* verSyncStart */
|
||||
630627, /* defRestart */
|
||||
347, /* crtcPLL_N */
|
||||
14, /* crtcPLL_M */
|
||||
8, /* crtcPLL_postDiv */
|
||||
1022, /* pixToTV */
|
||||
},
|
||||
};
|
||||
|
||||
#define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
|
||||
|
||||
static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder,
|
||||
uint16_t *pll_ref_freq)
|
||||
{
|
||||
struct drm_device *dev = radeon_encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_crtc *radeon_crtc;
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
const struct radeon_tv_mode_constants *const_ptr;
|
||||
struct radeon_pll *pll;
|
||||
|
||||
radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
|
||||
if (radeon_crtc->crtc_id == 1)
|
||||
pll = &rdev->clock.p2pll;
|
||||
else
|
||||
pll = &rdev->clock.p1pll;
|
||||
|
||||
if (pll_ref_freq)
|
||||
*pll_ref_freq = pll->reference_freq;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M) {
|
||||
if (pll->reference_freq == 2700)
|
||||
const_ptr = &available_tv_modes[0];
|
||||
else
|
||||
const_ptr = &available_tv_modes[2];
|
||||
} else {
|
||||
if (pll->reference_freq == 2700)
|
||||
const_ptr = &available_tv_modes[1];
|
||||
else
|
||||
const_ptr = &available_tv_modes[1]; /* FIX ME */
|
||||
}
|
||||
return const_ptr;
|
||||
}
|
||||
|
||||
static long YCOEF_value[5] = { 2, 2, 0, 4, 0 };
|
||||
static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 };
|
||||
static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
|
||||
static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
|
||||
|
||||
static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests,
|
||||
unsigned n_wait_loops, unsigned cnt_threshold)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t save_pll_test;
|
||||
unsigned int i, j;
|
||||
|
||||
WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
|
||||
save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL);
|
||||
WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B);
|
||||
|
||||
WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
|
||||
for (i = 0; i < n_tests; i++) {
|
||||
WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
|
||||
for (j = 0; j < n_wait_loops; j++)
|
||||
if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold)
|
||||
break;
|
||||
}
|
||||
WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test);
|
||||
WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
|
||||
}
|
||||
|
||||
|
||||
static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder,
|
||||
uint16_t addr, uint32_t value)
|
||||
{
|
||||
struct drm_device *dev = radeon_encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t tmp;
|
||||
int i = 0;
|
||||
|
||||
WREG32(RADEON_TV_HOST_WRITE_DATA, value);
|
||||
|
||||
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
|
||||
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
|
||||
|
||||
do {
|
||||
tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
|
||||
if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
|
||||
break;
|
||||
i++;
|
||||
} while (i < 10000);
|
||||
WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
|
||||
}
|
||||
|
||||
#if 0 /* included for completeness */
|
||||
static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr)
|
||||
{
|
||||
struct drm_device *dev = radeon_encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t tmp;
|
||||
int i = 0;
|
||||
|
||||
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
|
||||
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
|
||||
|
||||
do {
|
||||
tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
|
||||
if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
|
||||
break;
|
||||
i++;
|
||||
} while (i < 10000);
|
||||
WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
|
||||
return RREG32(RADEON_TV_HOST_READ_DATA);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)
|
||||
{
|
||||
uint16_t h_table;
|
||||
|
||||
switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
|
||||
case 0:
|
||||
h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
|
||||
break;
|
||||
case 1:
|
||||
h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
|
||||
break;
|
||||
case 2:
|
||||
h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
|
||||
break;
|
||||
default:
|
||||
h_table = 0;
|
||||
break;
|
||||
}
|
||||
return h_table;
|
||||
}
|
||||
|
||||
static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)
|
||||
{
|
||||
uint16_t v_table;
|
||||
|
||||
switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
|
||||
case 0:
|
||||
v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
|
||||
break;
|
||||
case 1:
|
||||
v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
|
||||
break;
|
||||
case 2:
|
||||
v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
|
||||
break;
|
||||
default:
|
||||
v_table = 0;
|
||||
break;
|
||||
}
|
||||
return v_table;
|
||||
}
|
||||
|
||||
static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder)
|
||||
{
|
||||
struct drm_device *dev = radeon_encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
uint16_t h_table, v_table;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr);
|
||||
h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr);
|
||||
v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr);
|
||||
|
||||
for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) {
|
||||
tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]);
|
||||
radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp);
|
||||
if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0)
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) {
|
||||
tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]);
|
||||
radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp);
|
||||
if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder)
|
||||
{
|
||||
struct drm_device *dev = radeon_encoder->base.dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart);
|
||||
WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart);
|
||||
WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart);
|
||||
}
|
||||
|
||||
static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
struct radeon_crtc *radeon_crtc;
|
||||
int restart;
|
||||
unsigned int h_total, v_total, f_total;
|
||||
int v_offset, h_offset;
|
||||
u16 p1, p2, h_inc;
|
||||
bool h_changed;
|
||||
const struct radeon_tv_mode_constants *const_ptr;
|
||||
struct radeon_pll *pll;
|
||||
|
||||
radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
|
||||
if (radeon_crtc->crtc_id == 1)
|
||||
pll = &rdev->clock.p2pll;
|
||||
else
|
||||
pll = &rdev->clock.p1pll;
|
||||
|
||||
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
|
||||
if (!const_ptr)
|
||||
return false;
|
||||
|
||||
h_total = const_ptr->hor_total;
|
||||
v_total = const_ptr->ver_total;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M ||
|
||||
tv_dac->tv_std == TV_STD_PAL_60)
|
||||
f_total = NTSC_TV_VFTOTAL + 1;
|
||||
else
|
||||
f_total = PAL_TV_VFTOTAL + 1;
|
||||
|
||||
/* adjust positions 1&2 in hor. cod timing table */
|
||||
h_offset = tv_dac->h_pos * H_POS_UNIT;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M) {
|
||||
h_offset -= 50;
|
||||
p1 = hor_timing_NTSC[H_TABLE_POS1];
|
||||
p2 = hor_timing_NTSC[H_TABLE_POS2];
|
||||
} else {
|
||||
p1 = hor_timing_PAL[H_TABLE_POS1];
|
||||
p2 = hor_timing_PAL[H_TABLE_POS2];
|
||||
}
|
||||
|
||||
p1 = (u16)((int)p1 + h_offset);
|
||||
p2 = (u16)((int)p2 - h_offset);
|
||||
|
||||
h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] ||
|
||||
p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]);
|
||||
|
||||
tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1;
|
||||
tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2;
|
||||
|
||||
/* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */
|
||||
h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000;
|
||||
|
||||
/* adjust restart */
|
||||
restart = const_ptr->def_restart;
|
||||
|
||||
/*
|
||||
* convert v_pos TV lines to n. of CRTC pixels
|
||||
*/
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M ||
|
||||
tv_dac->tv_std == TV_STD_PAL_60)
|
||||
v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME);
|
||||
else
|
||||
v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME);
|
||||
|
||||
restart -= v_offset + h_offset;
|
||||
|
||||
DRM_DEBUG("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n",
|
||||
const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart);
|
||||
|
||||
tv_dac->tv.hrestart = restart % h_total;
|
||||
restart /= h_total;
|
||||
tv_dac->tv.vrestart = restart % v_total;
|
||||
restart /= v_total;
|
||||
tv_dac->tv.frestart = restart % f_total;
|
||||
|
||||
DRM_DEBUG("compute_restart: F/H/V=%u,%u,%u\n",
|
||||
(unsigned)tv_dac->tv.frestart,
|
||||
(unsigned)tv_dac->tv.vrestart,
|
||||
(unsigned)tv_dac->tv.hrestart);
|
||||
|
||||
/* compute h_inc from hsize */
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M)
|
||||
h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) /
|
||||
(tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE)));
|
||||
else
|
||||
h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) /
|
||||
(tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE)));
|
||||
|
||||
tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) |
|
||||
((u32)h_inc << RADEON_H_INC_SHIFT);
|
||||
|
||||
DRM_DEBUG("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc);
|
||||
|
||||
return h_changed;
|
||||
}
|
||||
|
||||
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
const struct radeon_tv_mode_constants *const_ptr;
|
||||
struct radeon_crtc *radeon_crtc;
|
||||
int i;
|
||||
uint16_t pll_ref_freq;
|
||||
uint32_t vert_space, flicker_removal, tmp;
|
||||
uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl;
|
||||
uint32_t tv_modulator_cntl1, tv_modulator_cntl2;
|
||||
uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2;
|
||||
uint32_t tv_pll_cntl, tv_pll_cntl1, tv_ftotal;
|
||||
uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl;
|
||||
uint32_t m, n, p;
|
||||
const uint16_t *hor_timing;
|
||||
const uint16_t *vert_timing;
|
||||
|
||||
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq);
|
||||
if (!const_ptr)
|
||||
return;
|
||||
|
||||
radeon_crtc = to_radeon_crtc(encoder->crtc);
|
||||
|
||||
tv_master_cntl = (RADEON_VIN_ASYNC_RST |
|
||||
RADEON_CRT_FIFO_CE_EN |
|
||||
RADEON_TV_FIFO_CE_EN |
|
||||
RADEON_TV_ON);
|
||||
|
||||
if (!ASIC_IS_R300(rdev))
|
||||
tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J)
|
||||
tv_master_cntl |= RADEON_RESTART_PHASE_FIX;
|
||||
|
||||
tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT |
|
||||
RADEON_SYNC_TIP_LEVEL |
|
||||
RADEON_YFLT_EN |
|
||||
RADEON_UVFLT_EN |
|
||||
(6 << RADEON_CY_FILT_BLEND_SHIFT));
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J) {
|
||||
tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) |
|
||||
(0x3b << RADEON_BLANK_LEVEL_SHIFT);
|
||||
tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) |
|
||||
((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
|
||||
} else if (tv_dac->tv_std == TV_STD_SCART_PAL) {
|
||||
tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN;
|
||||
tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) |
|
||||
((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
|
||||
} else {
|
||||
tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN |
|
||||
(0x3b << RADEON_SET_UP_LEVEL_SHIFT) |
|
||||
(0x3b << RADEON_BLANK_LEVEL_SHIFT);
|
||||
tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) |
|
||||
((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
|
||||
}
|
||||
|
||||
|
||||
tv_rgb_cntl = (RADEON_RGB_DITHER_EN
|
||||
| RADEON_TVOUT_SCALE_EN
|
||||
| (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT)
|
||||
| (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)
|
||||
| RADEON_RGB_ATTEN_SEL(0x3)
|
||||
| RADEON_RGB_ATTEN_VAL(0xc));
|
||||
|
||||
if (radeon_crtc->crtc_id == 1)
|
||||
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2;
|
||||
else {
|
||||
if (radeon_crtc->rmx_type != RMX_OFF)
|
||||
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX;
|
||||
else
|
||||
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1;
|
||||
}
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M ||
|
||||
tv_dac->tv_std == TV_STD_PAL_60)
|
||||
vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME;
|
||||
else
|
||||
vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME;
|
||||
|
||||
tmp = RREG32(RADEON_TV_VSCALER_CNTL1);
|
||||
tmp &= 0xe3ff0000;
|
||||
tmp |= (vert_space * (1 << FRAC_BITS) / 10000);
|
||||
tv_vscaler_cntl1 = tmp;
|
||||
|
||||
if (pll_ref_freq == 2700)
|
||||
tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
|
||||
|
||||
if (const_ptr->hor_resolution == 1024)
|
||||
tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
|
||||
else
|
||||
tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT);
|
||||
|
||||
/* scale up for int divide */
|
||||
tmp = const_ptr->ver_total * 2 * 1000;
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M ||
|
||||
tv_dac->tv_std == TV_STD_PAL_60) {
|
||||
tmp /= NTSC_TV_LINES_PER_FRAME;
|
||||
} else {
|
||||
tmp /= PAL_TV_LINES_PER_FRAME;
|
||||
}
|
||||
flicker_removal = (tmp + 500) / 1000;
|
||||
|
||||
if (flicker_removal < 3)
|
||||
flicker_removal = 3;
|
||||
for (i = 0; i < 6; ++i) {
|
||||
if (flicker_removal == SLOPE_limit[i])
|
||||
break;
|
||||
}
|
||||
|
||||
tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) +
|
||||
5001) / 10000 / 8 | ((SLOPE_value[i] *
|
||||
(1 << (FRAC_BITS - 1)) / 8) << 16);
|
||||
tv_y_fall_cntl =
|
||||
(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) |
|
||||
RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) /
|
||||
1024;
|
||||
tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG|
|
||||
(flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024;
|
||||
|
||||
tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0;
|
||||
tv_vscaler_cntl2 |= (0x10 << 24) |
|
||||
RADEON_DITHER_MODE |
|
||||
RADEON_Y_OUTPUT_DITHER_EN |
|
||||
RADEON_UV_OUTPUT_DITHER_EN |
|
||||
RADEON_UV_TO_BUF_DITHER_EN;
|
||||
|
||||
tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK;
|
||||
tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
|
||||
tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000;
|
||||
tv_dac->tv.timing_cntl = tmp;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M ||
|
||||
tv_dac->tv_std == TV_STD_PAL_60)
|
||||
tv_dac_cntl = tv_dac->ntsc_tvdac_adj;
|
||||
else
|
||||
tv_dac_cntl = tv_dac->pal_tvdac_adj;
|
||||
|
||||
tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J)
|
||||
tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
|
||||
else
|
||||
tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J) {
|
||||
if (pll_ref_freq == 2700) {
|
||||
m = NTSC_TV_PLL_M_27;
|
||||
n = NTSC_TV_PLL_N_27;
|
||||
p = NTSC_TV_PLL_P_27;
|
||||
} else {
|
||||
m = NTSC_TV_PLL_M_14;
|
||||
n = NTSC_TV_PLL_N_14;
|
||||
p = NTSC_TV_PLL_P_14;
|
||||
}
|
||||
} else {
|
||||
if (pll_ref_freq == 2700) {
|
||||
m = PAL_TV_PLL_M_27;
|
||||
n = PAL_TV_PLL_N_27;
|
||||
p = PAL_TV_PLL_P_27;
|
||||
} else {
|
||||
m = PAL_TV_PLL_M_27;
|
||||
n = PAL_TV_PLL_N_27;
|
||||
p = PAL_TV_PLL_P_27;
|
||||
}
|
||||
}
|
||||
|
||||
tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
|
||||
(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
|
||||
((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
|
||||
(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
|
||||
((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
|
||||
|
||||
tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK) << RADEON_TVPCP_SHIFT) |
|
||||
((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) |
|
||||
((1 & RADEON_TVPDC_MASK) << RADEON_TVPDC_SHIFT) |
|
||||
RADEON_TVCLK_SRC_SEL_TVPLL |
|
||||
RADEON_TVPLL_TEST_DIS);
|
||||
|
||||
tv_dac->tv.tv_uv_adr = 0xc8;
|
||||
|
||||
if (tv_dac->tv_std == TV_STD_NTSC ||
|
||||
tv_dac->tv_std == TV_STD_NTSC_J ||
|
||||
tv_dac->tv_std == TV_STD_PAL_M ||
|
||||
tv_dac->tv_std == TV_STD_PAL_60) {
|
||||
tv_ftotal = NTSC_TV_VFTOTAL;
|
||||
hor_timing = hor_timing_NTSC;
|
||||
vert_timing = vert_timing_NTSC;
|
||||
} else {
|
||||
hor_timing = hor_timing_PAL;
|
||||
vert_timing = vert_timing_PAL;
|
||||
tv_ftotal = PAL_TV_VFTOTAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) {
|
||||
if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) {
|
||||
if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
radeon_legacy_tv_init_restarts(encoder);
|
||||
|
||||
/* play with DAC_CNTL */
|
||||
/* play with GPIOPAD_A */
|
||||
/* DISP_OUTPUT_CNTL */
|
||||
/* use reference freq */
|
||||
|
||||
/* program the TV registers */
|
||||
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
|
||||
RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST));
|
||||
|
||||
tmp = RREG32(RADEON_TV_DAC_CNTL);
|
||||
tmp &= ~RADEON_TV_DAC_NBLANK;
|
||||
tmp |= RADEON_TV_DAC_BGSLEEP |
|
||||
RADEON_TV_DAC_RDACPD |
|
||||
RADEON_TV_DAC_GDACPD |
|
||||
RADEON_TV_DAC_BDACPD;
|
||||
WREG32(RADEON_TV_DAC_CNTL, tmp);
|
||||
|
||||
/* TV PLL */
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
|
||||
WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl);
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
|
||||
|
||||
radeon_wait_pll_lock(encoder, 200, 800, 135);
|
||||
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
|
||||
|
||||
radeon_wait_pll_lock(encoder, 300, 160, 27);
|
||||
radeon_wait_pll_lock(encoder, 200, 800, 135);
|
||||
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf);
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
|
||||
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
|
||||
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
|
||||
|
||||
/* TV HV */
|
||||
WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl);
|
||||
WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1);
|
||||
WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1);
|
||||
WREG32(RADEON_TV_HSTART, const_ptr->hor_start);
|
||||
|
||||
WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1);
|
||||
WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1);
|
||||
WREG32(RADEON_TV_FTOTAL, tv_ftotal);
|
||||
WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1);
|
||||
WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2);
|
||||
|
||||
WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl);
|
||||
WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl);
|
||||
WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl);
|
||||
|
||||
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
|
||||
RADEON_CRT_ASYNC_RST));
|
||||
|
||||
/* TV restarts */
|
||||
radeon_legacy_write_tv_restarts(radeon_encoder);
|
||||
|
||||
/* tv timings */
|
||||
radeon_restore_tv_timing_tables(radeon_encoder);
|
||||
|
||||
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST));
|
||||
|
||||
/* tv std */
|
||||
WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE));
|
||||
WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl);
|
||||
WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1);
|
||||
WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2);
|
||||
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN |
|
||||
RADEON_C_GRN_EN |
|
||||
RADEON_CMP_BLU_EN |
|
||||
RADEON_DAC_DITHER_EN));
|
||||
|
||||
WREG32(RADEON_TV_CRC_CNTL, 0);
|
||||
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
|
||||
|
||||
WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) |
|
||||
(0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT)));
|
||||
WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) |
|
||||
(0x100 << RADEON_Y_GAIN_SHIFT)));
|
||||
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
|
||||
}
|
||||
|
||||
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
|
||||
uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
|
||||
uint32_t *v_total_disp, uint32_t *v_sync_strt_wid)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
const struct radeon_tv_mode_constants *const_ptr;
|
||||
uint32_t tmp;
|
||||
|
||||
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
|
||||
if (!const_ptr)
|
||||
return;
|
||||
|
||||
*h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
|
||||
(((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
|
||||
|
||||
tmp = *h_sync_strt_wid;
|
||||
tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR);
|
||||
tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
|
||||
(const_ptr->hor_syncstart & 7);
|
||||
*h_sync_strt_wid = tmp;
|
||||
|
||||
*v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
|
||||
((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
|
||||
|
||||
tmp = *v_sync_strt_wid;
|
||||
tmp &= ~RADEON_CRTC_V_SYNC_STRT;
|
||||
tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
|
||||
*v_sync_strt_wid = tmp;
|
||||
}
|
||||
|
||||
static inline int get_post_div(int value)
|
||||
{
|
||||
int post_div;
|
||||
switch (value) {
|
||||
case 1: post_div = 0; break;
|
||||
case 2: post_div = 1; break;
|
||||
case 3: post_div = 4; break;
|
||||
case 4: post_div = 2; break;
|
||||
case 6: post_div = 6; break;
|
||||
case 8: post_div = 3; break;
|
||||
case 12: post_div = 7; break;
|
||||
case 16:
|
||||
default: post_div = 5; break;
|
||||
}
|
||||
return post_div;
|
||||
}
|
||||
|
||||
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
|
||||
uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
|
||||
uint32_t *ppll_div_3, uint32_t *pixclks_cntl)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
const struct radeon_tv_mode_constants *const_ptr;
|
||||
|
||||
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
|
||||
if (!const_ptr)
|
||||
return;
|
||||
|
||||
*htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN;
|
||||
|
||||
*ppll_ref_div = const_ptr->crtcPLL_M;
|
||||
|
||||
*ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
|
||||
*pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL);
|
||||
*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK;
|
||||
}
|
||||
|
||||
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
|
||||
uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
|
||||
uint32_t *p2pll_div_0, uint32_t *pixclks_cntl)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
const struct radeon_tv_mode_constants *const_ptr;
|
||||
|
||||
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
|
||||
if (!const_ptr)
|
||||
return;
|
||||
|
||||
*htotal2_cntl = (const_ptr->hor_total & 0x7);
|
||||
|
||||
*p2pll_ref_div = const_ptr->crtcPLL_M;
|
||||
|
||||
*p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
|
||||
*pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
|
||||
*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -175,6 +175,15 @@ struct radeon_mode_info {
|
|||
enum radeon_connector_table connector_table;
|
||||
bool mode_config_initialized;
|
||||
struct radeon_crtc *crtcs[2];
|
||||
/* DVI-I properties */
|
||||
struct drm_property *coherent_mode_property;
|
||||
/* DAC enable load detect */
|
||||
struct drm_property *load_detect_property;
|
||||
/* TV standard load detect */
|
||||
struct drm_property *tv_std_property;
|
||||
/* legacy TMDS PLL detect */
|
||||
struct drm_property *tmds_pll_property;
|
||||
|
||||
};
|
||||
|
||||
struct radeon_native_mode {
|
||||
|
@ -188,6 +197,21 @@ struct radeon_native_mode {
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
#define MAX_H_CODE_TIMING_LEN 32
|
||||
#define MAX_V_CODE_TIMING_LEN 32
|
||||
|
||||
/* need to store these as reading
|
||||
back code tables is excessive */
|
||||
struct radeon_tv_regs {
|
||||
uint32_t tv_uv_adr;
|
||||
uint32_t timing_cntl;
|
||||
uint32_t hrestart;
|
||||
uint32_t vrestart;
|
||||
uint32_t frestart;
|
||||
uint16_t h_code_timing[MAX_H_CODE_TIMING_LEN];
|
||||
uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN];
|
||||
};
|
||||
|
||||
struct radeon_crtc {
|
||||
struct drm_crtc base;
|
||||
int crtc_id;
|
||||
|
@ -195,8 +219,6 @@ struct radeon_crtc {
|
|||
bool enabled;
|
||||
bool can_tile;
|
||||
uint32_t crtc_offset;
|
||||
struct radeon_framebuffer *fbdev_fb;
|
||||
struct drm_mode_set mode_set;
|
||||
struct drm_gem_object *cursor_bo;
|
||||
uint64_t cursor_addr;
|
||||
int cursor_width;
|
||||
|
@ -204,7 +226,6 @@ struct radeon_crtc {
|
|||
uint32_t legacy_display_base_addr;
|
||||
uint32_t legacy_cursor_offset;
|
||||
enum radeon_rmx_type rmx_type;
|
||||
uint32_t devices;
|
||||
fixed20_12 vsc;
|
||||
fixed20_12 hsc;
|
||||
struct radeon_native_mode native_mode;
|
||||
|
@ -236,7 +257,13 @@ struct radeon_encoder_tv_dac {
|
|||
uint32_t ntsc_tvdac_adj;
|
||||
uint32_t pal_tvdac_adj;
|
||||
|
||||
int h_pos;
|
||||
int v_pos;
|
||||
int h_size;
|
||||
int supported_tv_stds;
|
||||
bool tv_on;
|
||||
enum radeon_tv_std tv_std;
|
||||
struct radeon_tv_regs tv;
|
||||
};
|
||||
|
||||
struct radeon_encoder_int_tmds {
|
||||
|
@ -255,10 +282,15 @@ struct radeon_encoder_atom_dig {
|
|||
struct radeon_native_mode native_mode;
|
||||
};
|
||||
|
||||
struct radeon_encoder_atom_dac {
|
||||
enum radeon_tv_std tv_std;
|
||||
};
|
||||
|
||||
struct radeon_encoder {
|
||||
struct drm_encoder base;
|
||||
uint32_t encoder_id;
|
||||
uint32_t devices;
|
||||
uint32_t active_device;
|
||||
uint32_t flags;
|
||||
uint32_t pixel_clock;
|
||||
enum radeon_rmx_type rmx_type;
|
||||
|
@ -276,8 +308,12 @@ struct radeon_connector {
|
|||
uint32_t connector_id;
|
||||
uint32_t devices;
|
||||
struct radeon_i2c_chan *ddc_bus;
|
||||
int use_digital;
|
||||
bool use_digital;
|
||||
/* we need to mind the EDID between detect
|
||||
and get modes due to analog/digital/tvencoder */
|
||||
struct edid *edid;
|
||||
void *con_priv;
|
||||
bool dac_load_detect;
|
||||
};
|
||||
|
||||
struct radeon_framebuffer {
|
||||
|
@ -310,6 +346,7 @@ struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, i
|
|||
struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
|
||||
extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
|
||||
extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
|
||||
extern void radeon_encoder_set_active_device(struct drm_encoder *encoder);
|
||||
|
||||
extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
|
||||
extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
|
@ -337,16 +374,18 @@ extern bool radeon_atom_get_clock_info(struct drm_device *dev);
|
|||
extern bool radeon_combios_get_clock_info(struct drm_device *dev);
|
||||
extern struct radeon_encoder_atom_dig *
|
||||
radeon_atombios_get_lvds_info(struct radeon_encoder *encoder);
|
||||
extern struct radeon_encoder_int_tmds *
|
||||
radeon_atombios_get_tmds_info(struct radeon_encoder *encoder);
|
||||
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
|
||||
struct radeon_encoder_int_tmds *tmds);
|
||||
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
|
||||
struct radeon_encoder_int_tmds *tmds);
|
||||
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
|
||||
struct radeon_encoder_int_tmds *tmds);
|
||||
extern struct radeon_encoder_primary_dac *
|
||||
radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder);
|
||||
extern struct radeon_encoder_tv_dac *
|
||||
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder);
|
||||
extern struct radeon_encoder_lvds *
|
||||
radeon_combios_get_lvds_info(struct radeon_encoder *encoder);
|
||||
extern struct radeon_encoder_int_tmds *
|
||||
radeon_combios_get_tmds_info(struct radeon_encoder *encoder);
|
||||
extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder);
|
||||
extern struct radeon_encoder_tv_dac *
|
||||
radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
|
||||
|
@ -356,6 +395,8 @@ extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock);
|
|||
extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
|
||||
extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
|
||||
extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev);
|
||||
extern void radeon_save_bios_scratch_regs(struct radeon_device *rdev);
|
||||
extern void radeon_restore_bios_scratch_regs(struct radeon_device *rdev);
|
||||
extern void
|
||||
radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc);
|
||||
extern void
|
||||
|
@ -396,6 +437,19 @@ extern int radeon_static_clocks_init(struct drm_device *dev);
|
|||
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
void atom_rv515_force_tv_scaler(struct radeon_device *rdev);
|
||||
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc);
|
||||
|
||||
/* legacy tv */
|
||||
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
|
||||
uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
|
||||
uint32_t *v_total_disp, uint32_t *v_sync_strt_wid);
|
||||
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
|
||||
uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
|
||||
uint32_t *ppll_div_3, uint32_t *pixclks_cntl);
|
||||
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
|
||||
uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
|
||||
uint32_t *p2pll_div_0, uint32_t *pixclks_cntl);
|
||||
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
#endif
|
||||
|
|
|
@ -188,6 +188,7 @@ int radeon_object_kmap(struct radeon_object *robj, void **ptr)
|
|||
if (ptr) {
|
||||
*ptr = robj->kptr;
|
||||
}
|
||||
radeon_object_check_tiling(robj, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -200,6 +201,7 @@ void radeon_object_kunmap(struct radeon_object *robj)
|
|||
}
|
||||
robj->kptr = NULL;
|
||||
spin_unlock(&robj->tobj.lock);
|
||||
radeon_object_check_tiling(robj, 0, 0);
|
||||
ttm_bo_kunmap(&robj->kmap);
|
||||
}
|
||||
|
||||
|
@ -369,6 +371,14 @@ void radeon_object_force_delete(struct radeon_device *rdev)
|
|||
|
||||
int radeon_object_init(struct radeon_device *rdev)
|
||||
{
|
||||
/* Add an MTRR for the VRAM */
|
||||
rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
|
||||
MTRR_TYPE_WRCOMB, 1);
|
||||
DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n",
|
||||
rdev->mc.mc_vram_size >> 20,
|
||||
(unsigned long long)rdev->mc.aper_size >> 20);
|
||||
DRM_INFO("RAM width %dbits %cDR\n",
|
||||
rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
|
||||
return radeon_ttm_init(rdev);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
* TTM.
|
||||
*/
|
||||
struct radeon_mman {
|
||||
struct ttm_bo_global_ref bo_global_ref;
|
||||
struct ttm_global_reference mem_global_ref;
|
||||
bool mem_global_referenced;
|
||||
struct ttm_bo_device bdev;
|
||||
|
|
|
@ -1945,6 +1945,11 @@
|
|||
# define RADEON_TXFORMAT_DXT1 (12 << 0)
|
||||
# define RADEON_TXFORMAT_DXT23 (14 << 0)
|
||||
# define RADEON_TXFORMAT_DXT45 (15 << 0)
|
||||
# define RADEON_TXFORMAT_SHADOW16 (16 << 0)
|
||||
# define RADEON_TXFORMAT_SHADOW32 (17 << 0)
|
||||
# define RADEON_TXFORMAT_DUDV88 (18 << 0)
|
||||
# define RADEON_TXFORMAT_LDUDV655 (19 << 0)
|
||||
# define RADEON_TXFORMAT_LDUDUV8888 (20 << 0)
|
||||
# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0)
|
||||
# define RADEON_TXFORMAT_FORMAT_SHIFT 0
|
||||
# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5)
|
||||
|
@ -2203,7 +2208,7 @@
|
|||
# define RADEON_ROP_ENABLE (1 << 6)
|
||||
# define RADEON_STENCIL_ENABLE (1 << 7)
|
||||
# define RADEON_Z_ENABLE (1 << 8)
|
||||
# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9)
|
||||
# define RADEON_DEPTHXY_OFFSET_ENABLE (1 << 9)
|
||||
# define RADEON_RB3D_COLOR_FORMAT_SHIFT 10
|
||||
|
||||
# define RADEON_COLOR_FORMAT_ARGB1555 3
|
||||
|
@ -2773,7 +2778,12 @@
|
|||
# define R200_TXFORMAT_DXT1 (12 << 0)
|
||||
# define R200_TXFORMAT_DXT23 (14 << 0)
|
||||
# define R200_TXFORMAT_DXT45 (15 << 0)
|
||||
# define R200_TXFORMAT_DVDU88 (18 << 0)
|
||||
# define R200_TXFORMAT_LDVDU655 (19 << 0)
|
||||
# define R200_TXFORMAT_LDVDU8888 (20 << 0)
|
||||
# define R200_TXFORMAT_GR1616 (21 << 0)
|
||||
# define R200_TXFORMAT_ABGR8888 (22 << 0)
|
||||
# define R200_TXFORMAT_BGR111110 (23 << 0)
|
||||
# define R200_TXFORMAT_FORMAT_MASK (31 << 0)
|
||||
# define R200_TXFORMAT_FORMAT_SHIFT 0
|
||||
# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6)
|
||||
|
@ -2818,6 +2828,13 @@
|
|||
#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */
|
||||
#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */
|
||||
|
||||
#define R200_PP_CUBIC_FACES_0 0x2c18
|
||||
#define R200_PP_CUBIC_FACES_1 0x2c38
|
||||
#define R200_PP_CUBIC_FACES_2 0x2c58
|
||||
#define R200_PP_CUBIC_FACES_3 0x2c78
|
||||
#define R200_PP_CUBIC_FACES_4 0x2c98
|
||||
#define R200_PP_CUBIC_FACES_5 0x2cb8
|
||||
|
||||
#define R200_PP_TXOFFSET_0 0x2d00
|
||||
# define R200_TXO_ENDIAN_NO_SWAP (0 << 0)
|
||||
# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0)
|
||||
|
@ -2829,11 +2846,44 @@
|
|||
# define R200_TXO_MICRO_TILE (1 << 3)
|
||||
# define R200_TXO_OFFSET_MASK 0xffffffe0
|
||||
# define R200_TXO_OFFSET_SHIFT 5
|
||||
#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04
|
||||
#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08
|
||||
#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c
|
||||
#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10
|
||||
#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14
|
||||
|
||||
#define R200_PP_TXOFFSET_1 0x2d18
|
||||
#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c
|
||||
#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20
|
||||
#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24
|
||||
#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28
|
||||
#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c
|
||||
|
||||
#define R200_PP_TXOFFSET_2 0x2d30
|
||||
#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34
|
||||
#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38
|
||||
#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c
|
||||
#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40
|
||||
#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44
|
||||
|
||||
#define R200_PP_TXOFFSET_3 0x2d48
|
||||
#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c
|
||||
#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50
|
||||
#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54
|
||||
#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58
|
||||
#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c
|
||||
#define R200_PP_TXOFFSET_4 0x2d60
|
||||
#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64
|
||||
#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68
|
||||
#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c
|
||||
#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70
|
||||
#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74
|
||||
#define R200_PP_TXOFFSET_5 0x2d78
|
||||
#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c
|
||||
#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80
|
||||
#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84
|
||||
#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88
|
||||
#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c
|
||||
|
||||
#define R200_PP_TFACTOR_0 0x2ee0
|
||||
#define R200_PP_TFACTOR_1 0x2ee4
|
||||
|
@ -3175,6 +3225,11 @@
|
|||
# define R200_FORCE_INORDER_PROC (1<<31)
|
||||
#define R200_PP_CNTL_X 0x2cc4
|
||||
#define R200_PP_TXMULTI_CTL_0 0x2c1c
|
||||
#define R200_PP_TXMULTI_CTL_1 0x2c3c
|
||||
#define R200_PP_TXMULTI_CTL_2 0x2c5c
|
||||
#define R200_PP_TXMULTI_CTL_3 0x2c7c
|
||||
#define R200_PP_TXMULTI_CTL_4 0x2c9c
|
||||
#define R200_PP_TXMULTI_CTL_5 0x2cbc
|
||||
#define R200_SE_VTX_STATE_CNTL 0x2180
|
||||
# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16)
|
||||
|
||||
|
@ -3200,6 +3255,24 @@
|
|||
#define RADEON_CP_RB_WPTR 0x0714
|
||||
#define RADEON_CP_RB_RPTR_WR 0x071c
|
||||
|
||||
#define RADEON_SCRATCH_UMSK 0x0770
|
||||
#define RADEON_SCRATCH_ADDR 0x0774
|
||||
|
||||
#define R600_CP_RB_BASE 0xc100
|
||||
#define R600_CP_RB_CNTL 0xc104
|
||||
# define R600_RB_BUFSZ(x) ((x) << 0)
|
||||
# define R600_RB_BLKSZ(x) ((x) << 8)
|
||||
# define R600_RB_NO_UPDATE (1 << 27)
|
||||
# define R600_RB_RPTR_WR_ENA (1 << 31)
|
||||
#define R600_CP_RB_RPTR_WR 0xc108
|
||||
#define R600_CP_RB_RPTR_ADDR 0xc10c
|
||||
#define R600_CP_RB_RPTR_ADDR_HI 0xc110
|
||||
#define R600_CP_RB_WPTR 0xc114
|
||||
#define R600_CP_RB_WPTR_ADDR 0xc118
|
||||
#define R600_CP_RB_WPTR_ADDR_HI 0xc11c
|
||||
#define R600_CP_RB_RPTR 0x8700
|
||||
#define R600_CP_RB_WPTR_DELAY 0x8704
|
||||
|
||||
#define RADEON_CP_IB_BASE 0x0738
|
||||
#define RADEON_CP_IB_BUFSZ 0x073c
|
||||
|
||||
|
@ -3407,7 +3480,9 @@
|
|||
# define RADEON_RGB_CONVERT_BY_PASS (1 << 10)
|
||||
# define RADEON_UVRAM_READ_MARGIN_SHIFT 16
|
||||
# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20
|
||||
# define RADEON_TVOUT_SCALE_EN (1 << 26)
|
||||
# define RADEON_RGB_ATTEN_SEL(x) ((x) << 24)
|
||||
# define RADEON_TVOUT_SCALE_EN (1 << 26)
|
||||
# define RADEON_RGB_ATTEN_VAL(x) ((x) << 28)
|
||||
#define RADEON_TV_SYNC_CNTL 0x0808
|
||||
# define RADEON_SYNC_OE (1 << 0)
|
||||
# define RADEON_SYNC_OUT (1 << 1)
|
||||
|
|
|
@ -56,10 +56,12 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
|
|||
set_bit(i, rdev->ib_pool.alloc_bm);
|
||||
rdev->ib_pool.ibs[i].length_dw = 0;
|
||||
*ib = &rdev->ib_pool.ibs[i];
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
goto out;
|
||||
}
|
||||
if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
|
||||
/* we go do nothings here */
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
DRM_ERROR("all IB allocated none scheduled.\n");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
|
@ -69,10 +71,13 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
|
|||
struct radeon_ib, list);
|
||||
if (nib->fence == NULL) {
|
||||
/* we go do nothings here */
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
|
||||
r = radeon_fence_wait(nib->fence, false);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
|
||||
|
@ -81,12 +86,17 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
|
|||
goto out;
|
||||
}
|
||||
radeon_fence_unref(&nib->fence);
|
||||
|
||||
nib->length_dw = 0;
|
||||
|
||||
/* scheduled list is accessed here */
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
list_del(&nib->list);
|
||||
INIT_LIST_HEAD(&nib->list);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
|
||||
*ib = nib;
|
||||
out:
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
if (r) {
|
||||
radeon_fence_unref(&fence);
|
||||
} else {
|
||||
|
@ -111,47 +121,36 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
|
|||
}
|
||||
list_del(&tmp->list);
|
||||
INIT_LIST_HEAD(&tmp->list);
|
||||
if (tmp->fence) {
|
||||
if (tmp->fence)
|
||||
radeon_fence_unref(&tmp->fence);
|
||||
}
|
||||
|
||||
tmp->length_dw = 0;
|
||||
clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
}
|
||||
|
||||
static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
|
||||
{
|
||||
while ((ib->length_dw & rdev->cp.align_mask)) {
|
||||
ib->ptr[ib->length_dw++] = PACKET2(0);
|
||||
}
|
||||
}
|
||||
|
||||
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
radeon_ib_align(rdev, ib);
|
||||
if (!ib->length_dw || !rdev->cp.ready) {
|
||||
/* TODO: Nothings in the ib we should report. */
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 64 dwords should be enough for fence too */
|
||||
r = radeon_ring_lock(rdev, 64);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
return r;
|
||||
}
|
||||
radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1));
|
||||
radeon_ring_write(rdev, ib->gpu_addr);
|
||||
radeon_ring_write(rdev, ib->length_dw);
|
||||
radeon_ring_ib_execute(rdev, ib);
|
||||
radeon_fence_emit(rdev, ib->fence);
|
||||
radeon_ring_unlock_commit(rdev);
|
||||
mutex_lock(&rdev->ib_pool.mutex);
|
||||
list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
|
||||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
radeon_ring_unlock_commit(rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -162,6 +161,8 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
|
|||
int i;
|
||||
int r = 0;
|
||||
|
||||
if (rdev->ib_pool.robj)
|
||||
return 0;
|
||||
/* Allocate 1M object buffer */
|
||||
INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
|
||||
r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
|
||||
|
@ -215,69 +216,16 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
|
|||
mutex_unlock(&rdev->ib_pool.mutex);
|
||||
}
|
||||
|
||||
int radeon_ib_test(struct radeon_device *rdev)
|
||||
{
|
||||
struct radeon_ib *ib;
|
||||
uint32_t scratch;
|
||||
uint32_t tmp = 0;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
r = radeon_scratch_get(rdev, &scratch);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
WREG32(scratch, 0xCAFEDEAD);
|
||||
r = radeon_ib_get(rdev, &ib);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
ib->ptr[0] = PACKET0(scratch, 0);
|
||||
ib->ptr[1] = 0xDEADBEEF;
|
||||
ib->ptr[2] = PACKET2(0);
|
||||
ib->ptr[3] = PACKET2(0);
|
||||
ib->ptr[4] = PACKET2(0);
|
||||
ib->ptr[5] = PACKET2(0);
|
||||
ib->ptr[6] = PACKET2(0);
|
||||
ib->ptr[7] = PACKET2(0);
|
||||
ib->length_dw = 8;
|
||||
r = radeon_ib_schedule(rdev, ib);
|
||||
if (r) {
|
||||
radeon_scratch_free(rdev, scratch);
|
||||
radeon_ib_free(rdev, &ib);
|
||||
return r;
|
||||
}
|
||||
r = radeon_fence_wait(ib->fence, false);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||
tmp = RREG32(scratch);
|
||||
if (tmp == 0xDEADBEEF) {
|
||||
break;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
if (i < rdev->usec_timeout) {
|
||||
DRM_INFO("ib test succeeded in %u usecs\n", i);
|
||||
} else {
|
||||
DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
|
||||
scratch, tmp);
|
||||
r = -EINVAL;
|
||||
}
|
||||
radeon_scratch_free(rdev, scratch);
|
||||
radeon_ib_free(rdev, &ib);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ring.
|
||||
*/
|
||||
void radeon_ring_free_size(struct radeon_device *rdev)
|
||||
{
|
||||
rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
|
||||
if (rdev->family >= CHIP_R600)
|
||||
rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
|
||||
else
|
||||
rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
|
||||
/* This works because ring_size is a power of 2 */
|
||||
rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4));
|
||||
rdev->cp.ring_free_dw -= rdev->cp.wptr;
|
||||
|
@ -320,11 +268,10 @@ void radeon_ring_unlock_commit(struct radeon_device *rdev)
|
|||
count_dw_pad = (rdev->cp.align_mask + 1) -
|
||||
(rdev->cp.wptr & rdev->cp.align_mask);
|
||||
for (i = 0; i < count_dw_pad; i++) {
|
||||
radeon_ring_write(rdev, PACKET2(0));
|
||||
radeon_ring_write(rdev, 2 << 30);
|
||||
}
|
||||
DRM_MEMORYBARRIER();
|
||||
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
|
||||
(void)RREG32(RADEON_CP_RB_WPTR);
|
||||
radeon_cp_commit(rdev);
|
||||
mutex_unlock(&rdev->cp.mutex);
|
||||
}
|
||||
|
||||
|
@ -334,46 +281,6 @@ void radeon_ring_unlock_undo(struct radeon_device *rdev)
|
|||
mutex_unlock(&rdev->cp.mutex);
|
||||
}
|
||||
|
||||
int radeon_ring_test(struct radeon_device *rdev)
|
||||
{
|
||||
uint32_t scratch;
|
||||
uint32_t tmp = 0;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
r = radeon_scratch_get(rdev, &scratch);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r);
|
||||
return r;
|
||||
}
|
||||
WREG32(scratch, 0xCAFEDEAD);
|
||||
r = radeon_ring_lock(rdev, 2);
|
||||
if (r) {
|
||||
DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
|
||||
radeon_scratch_free(rdev, scratch);
|
||||
return r;
|
||||
}
|
||||
radeon_ring_write(rdev, PACKET0(scratch, 0));
|
||||
radeon_ring_write(rdev, 0xDEADBEEF);
|
||||
radeon_ring_unlock_commit(rdev);
|
||||
for (i = 0; i < rdev->usec_timeout; i++) {
|
||||
tmp = RREG32(scratch);
|
||||
if (tmp == 0xDEADBEEF) {
|
||||
break;
|
||||
}
|
||||
DRM_UDELAY(1);
|
||||
}
|
||||
if (i < rdev->usec_timeout) {
|
||||
DRM_INFO("ring test succeeded in %d usecs\n", i);
|
||||
} else {
|
||||
DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n",
|
||||
scratch, tmp);
|
||||
r = -EINVAL;
|
||||
}
|
||||
radeon_scratch_free(rdev, scratch);
|
||||
return r;
|
||||
}
|
||||
|
||||
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
|
||||
{
|
||||
int r;
|
||||
|
|
|
@ -1,39 +0,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 __RADEON_SHARE_H__
|
||||
#define __RADEON_SHARE_H__
|
||||
|
||||
void r100_vram_init_sizes(struct radeon_device *rdev);
|
||||
|
||||
void rs690_line_buffer_adjust(struct radeon_device *rdev,
|
||||
struct drm_display_mode *mode1,
|
||||
struct drm_display_mode *mode2);
|
||||
|
||||
void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
|
||||
|
||||
#endif
|
|
@ -1546,7 +1546,7 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,
|
|||
} while (i < nbox);
|
||||
}
|
||||
|
||||
static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
|
||||
void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_radeon_master_private *master_priv = master->driver_priv;
|
||||
|
@ -2213,7 +2213,10 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
|
|||
if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
|
||||
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
|
||||
|
||||
radeon_cp_dispatch_swap(dev, file_priv->master);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
r600_cp_dispatch_swap(dev, file_priv);
|
||||
else
|
||||
radeon_cp_dispatch_swap(dev, file_priv->master);
|
||||
sarea_priv->ctx_owner = 0;
|
||||
|
||||
COMMIT_RING();
|
||||
|
@ -2412,7 +2415,10 @@ static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file
|
|||
RING_SPACE_TEST_WITH_RETURN(dev_priv);
|
||||
VB_AGE_TEST_WITH_RETURN(dev_priv);
|
||||
|
||||
ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
ret = r600_cp_dispatch_texture(dev, file_priv, tex, &image);
|
||||
else
|
||||
ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2495,8 +2501,9 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
|
|||
radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
|
||||
}
|
||||
|
||||
if (indirect->discard)
|
||||
if (indirect->discard) {
|
||||
radeon_cp_discard_buffer(dev, file_priv->master, buf);
|
||||
}
|
||||
|
||||
COMMIT_RING();
|
||||
return 0;
|
||||
|
@ -3027,7 +3034,10 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
|
|||
value = GET_SCRATCH(dev_priv, 2);
|
||||
break;
|
||||
case RADEON_PARAM_IRQ_NR:
|
||||
value = drm_dev_to_irq(dev);
|
||||
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
|
||||
value = 0;
|
||||
else
|
||||
value = drm_dev_to_irq(dev);
|
||||
break;
|
||||
case RADEON_PARAM_GART_BASE:
|
||||
value = dev_priv->gart_vm_start;
|
||||
|
@ -3227,7 +3237,8 @@ struct drm_ioctl_desc radeon_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH)
|
||||
DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH)
|
||||
};
|
||||
|
||||
int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
|
||||
|
|
|
@ -35,11 +35,14 @@
|
|||
#include <ttm/ttm_module.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/radeon_drm.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "radeon_reg.h"
|
||||
#include "radeon.h"
|
||||
|
||||
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
|
||||
|
||||
static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
|
||||
|
||||
static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev)
|
||||
{
|
||||
struct radeon_mman *mman;
|
||||
|
@ -77,9 +80,25 @@ static int radeon_ttm_global_init(struct radeon_device *rdev)
|
|||
global_ref->release = &radeon_ttm_mem_global_release;
|
||||
r = ttm_global_item_ref(global_ref);
|
||||
if (r != 0) {
|
||||
DRM_ERROR("Failed referencing a global TTM memory object.\n");
|
||||
DRM_ERROR("Failed setting up TTM memory accounting "
|
||||
"subsystem.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
rdev->mman.bo_global_ref.mem_glob =
|
||||
rdev->mman.mem_global_ref.object;
|
||||
global_ref = &rdev->mman.bo_global_ref.ref;
|
||||
global_ref->global_type = TTM_GLOBAL_TTM_BO;
|
||||
global_ref->size = sizeof(struct ttm_bo_global);
|
||||
global_ref->init = &ttm_bo_global_init;
|
||||
global_ref->release = &ttm_bo_global_release;
|
||||
r = ttm_global_item_ref(global_ref);
|
||||
if (r != 0) {
|
||||
DRM_ERROR("Failed setting up TTM BO subsystem.\n");
|
||||
ttm_global_item_unref(&rdev->mman.mem_global_ref);
|
||||
return r;
|
||||
}
|
||||
|
||||
rdev->mman.mem_global_referenced = true;
|
||||
return 0;
|
||||
}
|
||||
|
@ -87,6 +106,7 @@ static int radeon_ttm_global_init(struct radeon_device *rdev)
|
|||
static void radeon_ttm_global_fini(struct radeon_device *rdev)
|
||||
{
|
||||
if (rdev->mman.mem_global_referenced) {
|
||||
ttm_global_item_unref(&rdev->mman.bo_global_ref.ref);
|
||||
ttm_global_item_unref(&rdev->mman.mem_global_ref);
|
||||
rdev->mman.mem_global_referenced = false;
|
||||
}
|
||||
|
@ -286,9 +306,11 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
|
|||
r = ttm_bo_move_ttm(bo, true, no_wait, new_mem);
|
||||
out_cleanup:
|
||||
if (tmp_mem.mm_node) {
|
||||
spin_lock(&rdev->mman.bdev.lru_lock);
|
||||
struct ttm_bo_global *glob = rdev->mman.bdev.glob;
|
||||
|
||||
spin_lock(&glob->lru_lock);
|
||||
drm_mm_put_block(tmp_mem.mm_node);
|
||||
spin_unlock(&rdev->mman.bdev.lru_lock);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
return r;
|
||||
}
|
||||
return r;
|
||||
|
@ -323,9 +345,11 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
|
|||
}
|
||||
out_cleanup:
|
||||
if (tmp_mem.mm_node) {
|
||||
spin_lock(&rdev->mman.bdev.lru_lock);
|
||||
struct ttm_bo_global *glob = rdev->mman.bdev.glob;
|
||||
|
||||
spin_lock(&glob->lru_lock);
|
||||
drm_mm_put_block(tmp_mem.mm_node);
|
||||
spin_unlock(&rdev->mman.bdev.lru_lock);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
return r;
|
||||
}
|
||||
return r;
|
||||
|
@ -352,9 +376,8 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
|
|||
radeon_move_null(bo, new_mem);
|
||||
return 0;
|
||||
}
|
||||
if (!rdev->cp.ready) {
|
||||
if (!rdev->cp.ready || rdev->asic->copy == NULL) {
|
||||
/* use memcpy */
|
||||
DRM_ERROR("CP is not ready use memcpy.\n");
|
||||
goto memcpy;
|
||||
}
|
||||
|
||||
|
@ -446,7 +469,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
|
|||
}
|
||||
/* No others user of address space so set it to 0 */
|
||||
r = ttm_bo_device_init(&rdev->mman.bdev,
|
||||
rdev->mman.mem_global_ref.object,
|
||||
rdev->mman.bo_global_ref.ref.object,
|
||||
&radeon_bo_driver, DRM_FILE_PAGE_OFFSET,
|
||||
rdev->need_dma32);
|
||||
if (r) {
|
||||
|
@ -471,7 +494,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
|
|||
return r;
|
||||
}
|
||||
DRM_INFO("radeon: %uM of VRAM memory ready\n",
|
||||
rdev->mc.real_vram_size / (1024 * 1024));
|
||||
(unsigned)rdev->mc.real_vram_size / (1024 * 1024));
|
||||
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
|
||||
((rdev->mc.gtt_size) >> PAGE_SHIFT));
|
||||
if (r) {
|
||||
|
@ -479,10 +502,16 @@ int radeon_ttm_init(struct radeon_device *rdev)
|
|||
return r;
|
||||
}
|
||||
DRM_INFO("radeon: %uM of GTT memory ready.\n",
|
||||
rdev->mc.gtt_size / (1024 * 1024));
|
||||
(unsigned)(rdev->mc.gtt_size / (1024 * 1024)));
|
||||
if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
|
||||
rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
|
||||
}
|
||||
|
||||
r = radeon_ttm_debugfs_init(rdev);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to init debugfs\n");
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -657,3 +686,50 @@ struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev)
|
|||
gtt->bound = false;
|
||||
return >t->backend;
|
||||
}
|
||||
|
||||
#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)
|
||||
static int radeon_mm_dump_table(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *)m->private;
|
||||
struct drm_mm *mm = (struct drm_mm *)node->info_ent->data;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
int ret;
|
||||
struct ttm_bo_global *glob = rdev->mman.bdev.glob;
|
||||
|
||||
spin_lock(&glob->lru_lock);
|
||||
ret = drm_mm_dump_table(m, mm);
|
||||
spin_unlock(&glob->lru_lock);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) {
|
||||
if (i == 0)
|
||||
sprintf(radeon_mem_types_names[i], "radeon_vram_mm");
|
||||
else
|
||||
sprintf(radeon_mem_types_names[i], "radeon_gtt_mm");
|
||||
radeon_mem_types_list[i].name = radeon_mem_types_names[i];
|
||||
radeon_mem_types_list[i].show = &radeon_mm_dump_table;
|
||||
radeon_mem_types_list[i].driver_features = 0;
|
||||
if (i == 0)
|
||||
radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_VRAM].manager;
|
||||
else
|
||||
radeon_mem_types_list[i].data = &rdev->mman.bdev.man[TTM_PL_TT].manager;
|
||||
|
||||
}
|
||||
return radeon_debugfs_add_files(rdev, radeon_mem_types_list, RADEON_DEBUGFS_MEM_TYPES);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
105
drivers/gpu/drm/radeon/reg_srcs/r100
Normal file
105
drivers/gpu/drm/radeon/reg_srcs/r100
Normal file
|
@ -0,0 +1,105 @@
|
|||
r100 0x3294
|
||||
0x1434 SRC_Y_X
|
||||
0x1438 DST_Y_X
|
||||
0x143C DST_HEIGHT_WIDTH
|
||||
0x146C DP_GUI_MASTER_CNTL
|
||||
0x1474 BRUSH_Y_X
|
||||
0x1478 DP_BRUSH_BKGD_CLR
|
||||
0x147C DP_BRUSH_FRGD_CLR
|
||||
0x1480 BRUSH_DATA0
|
||||
0x1484 BRUSH_DATA1
|
||||
0x1598 DST_WIDTH_HEIGHT
|
||||
0x15C0 CLR_CMP_CNTL
|
||||
0x15C4 CLR_CMP_CLR_SRC
|
||||
0x15C8 CLR_CMP_CLR_DST
|
||||
0x15CC CLR_CMP_MSK
|
||||
0x15D8 DP_SRC_FRGD_CLR
|
||||
0x15DC DP_SRC_BKGD_CLR
|
||||
0x1600 DST_LINE_START
|
||||
0x1604 DST_LINE_END
|
||||
0x1608 DST_LINE_PATCOUNT
|
||||
0x16C0 DP_CNTL
|
||||
0x16CC DP_WRITE_MSK
|
||||
0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR
|
||||
0x16E8 DEFAULT_SC_BOTTOM_RIGHT
|
||||
0x16EC SC_TOP_LEFT
|
||||
0x16F0 SC_BOTTOM_RIGHT
|
||||
0x16F4 SRC_SC_BOTTOM_RIGHT
|
||||
0x1714 DSTCACHE_CTLSTAT
|
||||
0x1720 WAIT_UNTIL
|
||||
0x172C RBBM_GUICNTL
|
||||
0x1810 FOG_3D_TABLE_START
|
||||
0x1814 FOG_3D_TABLE_END
|
||||
0x1a14 FOG_TABLE_INDEX
|
||||
0x1a18 FOG_TABLE_DATA
|
||||
0x1c14 PP_MISC
|
||||
0x1c18 PP_FOG_COLOR
|
||||
0x1c1c RE_SOLID_COLOR
|
||||
0x1c20 RB3D_BLENDCNTL
|
||||
0x1c4c SE_CNTL
|
||||
0x1c50 SE_COORD_FMT
|
||||
0x1c60 PP_TXCBLEND_0
|
||||
0x1c64 PP_TXABLEND_0
|
||||
0x1c68 PP_TFACTOR_0
|
||||
0x1c78 PP_TXCBLEND_1
|
||||
0x1c7c PP_TXABLEND_1
|
||||
0x1c80 PP_TFACTOR_1
|
||||
0x1c90 PP_TXCBLEND_2
|
||||
0x1c94 PP_TXABLEND_2
|
||||
0x1c98 PP_TFACTOR_2
|
||||
0x1cc8 RE_STIPPLE_ADDR
|
||||
0x1ccc RE_STIPPLE_DATA
|
||||
0x1cd0 RE_LINE_PATTERN
|
||||
0x1cd4 RE_LINE_STATE
|
||||
0x1d40 PP_BORDER_COLOR0
|
||||
0x1d44 PP_BORDER_COLOR1
|
||||
0x1d48 PP_BORDER_COLOR2
|
||||
0x1d7c RB3D_STENCILREFMASK
|
||||
0x1d80 RB3D_ROPCNTL
|
||||
0x1d84 RB3D_PLANEMASK
|
||||
0x1d98 VAP_VPORT_XSCALE
|
||||
0x1d9C VAP_VPORT_XOFFSET
|
||||
0x1da0 VAP_VPORT_YSCALE
|
||||
0x1da4 VAP_VPORT_YOFFSET
|
||||
0x1da8 VAP_VPORT_ZSCALE
|
||||
0x1dac VAP_VPORT_ZOFFSET
|
||||
0x1db0 SE_ZBIAS_FACTOR
|
||||
0x1db4 SE_ZBIAS_CONSTANT
|
||||
0x1db8 SE_LINE_WIDTH
|
||||
0x2140 SE_CNTL_STATUS
|
||||
0x2200 SE_TCL_VECTOR_INDX_REG
|
||||
0x2204 SE_TCL_VECTOR_DATA_REG
|
||||
0x2208 SE_TCL_SCALAR_INDX_REG
|
||||
0x220c SE_TCL_SCALAR_DATA_REG
|
||||
0x2210 SE_TCL_MATERIAL_EMISSIVE_RED
|
||||
0x2214 SE_TCL_MATERIAL_EMISSIVE_GREEN
|
||||
0x2218 SE_TCL_MATERIAL_EMISSIVE_BLUE
|
||||
0x221c SE_TCL_MATERIAL_EMISSIVE_ALPHA
|
||||
0x2220 SE_TCL_MATERIAL_AMBIENT_RED
|
||||
0x2224 SE_TCL_MATERIAL_AMBIENT_GREEN
|
||||
0x2228 SE_TCL_MATERIAL_AMBIENT_BLUE
|
||||
0x222c SE_TCL_MATERIAL_AMBIENT_ALPHA
|
||||
0x2230 SE_TCL_MATERIAL_DIFFUSE_RED
|
||||
0x2234 SE_TCL_MATERIAL_DIFFUSE_GREEN
|
||||
0x2238 SE_TCL_MATERIAL_DIFFUSE_BLUE
|
||||
0x223c SE_TCL_MATERIAL_DIFFUSE_ALPHA
|
||||
0x2240 SE_TCL_MATERIAL_SPECULAR_RED
|
||||
0x2244 SE_TCL_MATERIAL_SPECULAR_GREEN
|
||||
0x2248 SE_TCL_MATERIAL_SPECULAR_BLUE
|
||||
0x224c SE_TCL_MATERIAL_SPECULAR_ALPHA
|
||||
0x2250 SE_TCL_SHININESS
|
||||
0x2254 SE_TCL_OUTPUT_VTX_FMT
|
||||
0x2258 SE_TCL_OUTPUT_VTX_SEL
|
||||
0x225c SE_TCL_MATRIX_SELECT_0
|
||||
0x2260 SE_TCL_MATRIX_SELECT_1
|
||||
0x2264 SE_TCL_UCP_VERT_BLEND_CNTL
|
||||
0x2268 SE_TCL_TEXTURE_PROC_CTL
|
||||
0x226c SE_TCL_LIGHT_MODEL_CTL
|
||||
0x2270 SE_TCL_PER_LIGHT_CTL_0
|
||||
0x2274 SE_TCL_PER_LIGHT_CTL_1
|
||||
0x2278 SE_TCL_PER_LIGHT_CTL_2
|
||||
0x227c SE_TCL_PER_LIGHT_CTL_3
|
||||
0x2284 SE_TCL_STATE_FLUSH
|
||||
0x26c0 RE_TOP_LEFT
|
||||
0x26c4 RE_MISC
|
||||
0x3290 RB3D_ZPASS_DATA
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue