提交 44040f10 编写于 作者: L Linus Torvalds

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.
......@@ -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");
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),
......
此差异已折叠。
/*
* 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);
/*
* 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 @@ drm_gem_handle_create(struct drm_file *file_priv,
/* 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 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
}
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 @@ static int i915_error_state(struct seq_file *m, void *unused)
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 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
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 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 RING_LOCALS volatile unsigned int *ring_virt__;
#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 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
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,
......
......@@ -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__ */
此差异已折叠。
......@@ -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 @@ void intel_lvds_init(struct drm_device *dev)
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);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册