mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
Merge branch 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (204 commits) agp: intel-agp: do not use PCI resources before pci_enable_device() agp: efficeon-agp: do not use PCI resources before pci_enable_device() drm: kill BKL from common code drm/kms: Simplify setup of the initial I2C encoder config. drm,io-mapping: Specify slot to use for atomic mappings drm/radeon/kms: only expose underscan on avivo chips drm/radeon: add new pci ids drm: Cleanup after failing to create master->unique and dev->name drm/radeon: tone down overchatty acpi debug messages. drm/radeon/kms: enable underscan option for digital connectors drm/radeon/kms: fix calculation of h/v scaling factors drm/radeon/kms/igp: sideport is AMD only drm/radeon/kms: handle the case of no active displays properly in the bandwidth code drm: move ttm global code to core drm drm/i915: Clear the Ironlake dithering flags when the pipe doesn't want it. drm/radeon/kms: make sure HPD is set to NONE on analog-only connectors drm/radeon/kms: make sure rio_mem is valid before unmapping it drm/agp/i915: trim stolen space to 32M drm/i915: Unset cursor if out-of-bounds upon mode change (v4) drm/i915: Unreference object not handle on creation ...
This commit is contained in:
commit
fc1caf6eaf
@ -371,6 +371,17 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
|
||||
bridge->dev = pdev;
|
||||
bridge->capndx = cap_ptr;
|
||||
|
||||
/*
|
||||
* If the device has not been properly setup, the following will catch
|
||||
* the problem and should stop the system from crashing.
|
||||
* 20030610 - hamish@zot.org
|
||||
*/
|
||||
if (pci_enable_device(pdev)) {
|
||||
printk(KERN_ERR PFX "Unable to Enable PCI device\n");
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following fixes the case where the BIOS has "forgotten" to
|
||||
* provide an address range for the GART.
|
||||
@ -385,17 +396,6 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device has not been properly setup, the following will catch
|
||||
* the problem and should stop the system from crashing.
|
||||
* 20030610 - hamish@zot.org
|
||||
*/
|
||||
if (pci_enable_device(pdev)) {
|
||||
printk(KERN_ERR PFX "Unable to Enable PCI device\n");
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Fill in the mode register */
|
||||
if (cap_ptr) {
|
||||
pci_read_config_dword(pdev,
|
||||
|
@ -816,9 +816,9 @@ static const struct intel_driver_description {
|
||||
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
|
||||
"HD Graphics", NULL, &intel_i965_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG,
|
||||
"Sandybridge", NULL, &intel_i965_driver },
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG,
|
||||
"Sandybridge", NULL, &intel_i965_driver },
|
||||
"Sandybridge", NULL, &intel_gen6_driver },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -907,6 +907,17 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
||||
|
||||
dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
|
||||
|
||||
/*
|
||||
* If the device has not been properly setup, the following will catch
|
||||
* the problem and should stop the system from crashing.
|
||||
* 20030610 - hamish@zot.org
|
||||
*/
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_err(&pdev->dev, "can't enable PCI device\n");
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following fixes the case where the BIOS has "forgotten" to
|
||||
* provide an address range for the GART.
|
||||
@ -921,17 +932,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device has not been properly setup, the following will catch
|
||||
* the problem and should stop the system from crashing.
|
||||
* 20030610 - hamish@zot.org
|
||||
*/
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_err(&pdev->dev, "can't enable PCI device\n");
|
||||
agp_put_bridge(bridge);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Fill in the mode register */
|
||||
if (cap_ptr) {
|
||||
pci_read_config_dword(pdev,
|
||||
|
@ -60,6 +60,12 @@
|
||||
#define I810_PTE_LOCAL 0x00000002
|
||||
#define I810_PTE_VALID 0x00000001
|
||||
#define I830_PTE_SYSTEM_CACHED 0x00000006
|
||||
/* GT PTE cache control fields */
|
||||
#define GEN6_PTE_UNCACHED 0x00000002
|
||||
#define GEN6_PTE_LLC 0x00000004
|
||||
#define GEN6_PTE_LLC_MLC 0x00000006
|
||||
#define GEN6_PTE_GFDT 0x00000008
|
||||
|
||||
#define I810_SMRAM_MISCC 0x70
|
||||
#define I810_GFX_MEM_WIN_SIZE 0x00010000
|
||||
#define I810_GFX_MEM_WIN_32M 0x00010000
|
||||
|
@ -25,6 +25,10 @@
|
||||
#define USE_PCI_DMA_API 1
|
||||
#endif
|
||||
|
||||
/* Max amount of stolen space, anything above will be returned to Linux */
|
||||
int intel_max_stolen = 32 * 1024 * 1024;
|
||||
EXPORT_SYMBOL(intel_max_stolen);
|
||||
|
||||
static const struct aper_size_info_fixed intel_i810_sizes[] =
|
||||
{
|
||||
{64, 16384, 4},
|
||||
@ -104,7 +108,7 @@ static int intel_agp_map_memory(struct agp_memory *mem)
|
||||
DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
|
||||
|
||||
if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
goto err;
|
||||
|
||||
mem->sg_list = sg = st.sgl;
|
||||
|
||||
@ -113,11 +117,14 @@ static int intel_agp_map_memory(struct agp_memory *mem)
|
||||
|
||||
mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
|
||||
mem->page_count, PCI_DMA_BIDIRECTIONAL);
|
||||
if (unlikely(!mem->num_sg)) {
|
||||
intel_agp_free_sglist(mem);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (unlikely(!mem->num_sg))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
sg_free_table(&st);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void intel_agp_unmap_memory(struct agp_memory *mem)
|
||||
@ -176,7 +183,7 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
|
||||
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
||||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
||||
{
|
||||
cache_bits = I830_PTE_SYSTEM_CACHED;
|
||||
cache_bits = GEN6_PTE_LLC_MLC;
|
||||
}
|
||||
|
||||
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
||||
@ -710,7 +717,12 @@ static void intel_i830_init_gtt_entries(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gtt_entries > 0) {
|
||||
if (!local && gtt_entries > intel_max_stolen) {
|
||||
dev_info(&agp_bridge->dev->dev,
|
||||
"detected %dK stolen memory, trimming to %dK\n",
|
||||
gtt_entries / KB(1), intel_max_stolen / KB(1));
|
||||
gtt_entries = intel_max_stolen / KB(4);
|
||||
} else if (gtt_entries > 0) {
|
||||
dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
|
||||
gtt_entries / KB(1), local ? "local" : "stolen");
|
||||
gtt_entries /= KB(4);
|
||||
@ -797,6 +809,10 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
|
||||
|
||||
/* we have to call this as early as possible after the MMIO base address is known */
|
||||
intel_i830_init_gtt_entries();
|
||||
if (intel_private.gtt_entries == 0) {
|
||||
iounmap(intel_private.registers);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
agp_bridge->gatt_table = NULL;
|
||||
|
||||
@ -1282,6 +1298,11 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
|
||||
|
||||
/* we have to call this as early as possible after the MMIO base address is known */
|
||||
intel_i830_init_gtt_entries();
|
||||
if (intel_private.gtt_entries == 0) {
|
||||
iounmap(intel_private.gtt);
|
||||
iounmap(intel_private.registers);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
agp_bridge->gatt_table = NULL;
|
||||
|
||||
@ -1309,6 +1330,16 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
|
||||
return addr | bridge->driver->masks[type].mask;
|
||||
}
|
||||
|
||||
static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
|
||||
dma_addr_t addr, int type)
|
||||
{
|
||||
/* Shift high bits down */
|
||||
addr |= (addr >> 28) & 0xff;
|
||||
|
||||
/* Type checking must be done elsewhere */
|
||||
return addr | bridge->driver->masks[type].mask;
|
||||
}
|
||||
|
||||
static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
|
||||
{
|
||||
u16 snb_gmch_ctl;
|
||||
@ -1390,6 +1421,11 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
|
||||
|
||||
/* we have to call this as early as possible after the MMIO base address is known */
|
||||
intel_i830_init_gtt_entries();
|
||||
if (intel_private.gtt_entries == 0) {
|
||||
iounmap(intel_private.gtt);
|
||||
iounmap(intel_private.registers);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
agp_bridge->gatt_table = NULL;
|
||||
|
||||
@ -1517,6 +1553,39 @@ static const struct agp_bridge_driver intel_i965_driver = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct agp_bridge_driver intel_gen6_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.aperture_sizes = intel_i830_sizes,
|
||||
.size_type = FIXED_APER_SIZE,
|
||||
.num_aperture_sizes = 4,
|
||||
.needs_scratch_page = true,
|
||||
.configure = intel_i9xx_configure,
|
||||
.fetch_size = intel_i9xx_fetch_size,
|
||||
.cleanup = intel_i915_cleanup,
|
||||
.mask_memory = intel_gen6_mask_memory,
|
||||
.masks = intel_i810_masks,
|
||||
.agp_enable = intel_i810_agp_enable,
|
||||
.cache_flush = global_cache_flush,
|
||||
.create_gatt_table = intel_i965_create_gatt_table,
|
||||
.free_gatt_table = intel_i830_free_gatt_table,
|
||||
.insert_memory = intel_i915_insert_entries,
|
||||
.remove_memory = intel_i915_remove_entries,
|
||||
.alloc_by_type = intel_i830_alloc_by_type,
|
||||
.free_by_type = intel_i810_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
||||
.chipset_flush = intel_i915_chipset_flush,
|
||||
#ifdef USE_PCI_DMA_API
|
||||
.agp_map_page = intel_agp_map_page,
|
||||
.agp_unmap_page = intel_agp_unmap_page,
|
||||
.agp_map_memory = intel_agp_map_memory,
|
||||
.agp_unmap_memory = intel_agp_unmap_memory,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct agp_bridge_driver intel_g33_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.aperture_sizes = intel_i830_sizes,
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
menuconfig DRM
|
||||
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
|
||||
depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU
|
||||
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
select SLOW_WORK
|
||||
@ -17,7 +17,7 @@ menuconfig DRM
|
||||
These modules provide support for synchronization, security, and
|
||||
DMA transfers. Please see <http://dri.sourceforge.net/> for more
|
||||
details. You should also select and configure AGP
|
||||
(/dev/agpgart) support.
|
||||
(/dev/agpgart) support if it is available for your platform.
|
||||
|
||||
config DRM_KMS_HELPER
|
||||
tristate
|
||||
@ -61,6 +61,7 @@ config DRM_RADEON
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_TTM
|
||||
select POWER_SUPPLY
|
||||
select HWMON
|
||||
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
|
||||
@ -130,7 +131,7 @@ endchoice
|
||||
|
||||
config DRM_MGA
|
||||
tristate "Matrox g200/g400"
|
||||
depends on DRM
|
||||
depends on DRM && PCI
|
||||
select FW_LOADER
|
||||
help
|
||||
Choose this option if you have a Matrox G200, G400 or G450 graphics
|
||||
@ -148,14 +149,14 @@ config DRM_SIS
|
||||
|
||||
config DRM_VIA
|
||||
tristate "Via unichrome video cards"
|
||||
depends on DRM
|
||||
depends on DRM && PCI
|
||||
help
|
||||
Choose this option if you have a Via unichrome or compatible video
|
||||
chipset. If M is selected the module will be called via.
|
||||
|
||||
config DRM_SAVAGE
|
||||
tristate "Savage video cards"
|
||||
depends on DRM
|
||||
depends on DRM && PCI
|
||||
help
|
||||
Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
|
||||
chipset. If M is selected the module will be called savage.
|
||||
|
@ -9,9 +9,10 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
|
||||
drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.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_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
|
||||
drm_crtc.o drm_modes.o drm_edid.o \
|
||||
drm_info.o drm_debugfs.o drm_encoder_slave.o
|
||||
drm_info.o drm_debugfs.o drm_encoder_slave.o \
|
||||
drm_trace_points.o drm_global.o
|
||||
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
|
||||
@ -19,6 +20,8 @@ drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o
|
||||
|
||||
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
||||
|
||||
CFLAGS_drm_trace_points.o := -I$(src)
|
||||
|
||||
obj-$(CONFIG_DRM) += drm.o
|
||||
obj-$(CONFIG_DRM_TTM) += ttm/
|
||||
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
||||
|
@ -39,19 +39,6 @@
|
||||
#include <asm/shmparam.h>
|
||||
#include "drmP.h"
|
||||
|
||||
resource_size_t drm_get_resource_start(struct drm_device *dev, unsigned int resource)
|
||||
{
|
||||
return pci_resource_start(dev->pdev, resource);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_resource_start);
|
||||
|
||||
resource_size_t drm_get_resource_len(struct drm_device *dev, unsigned int resource)
|
||||
{
|
||||
return pci_resource_len(dev->pdev, resource);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_get_resource_len);
|
||||
|
||||
static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
|
||||
struct drm_local_map *map)
|
||||
{
|
||||
@ -189,7 +176,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
|
||||
switch (map->type) {
|
||||
case _DRM_REGISTERS:
|
||||
case _DRM_FRAME_BUFFER:
|
||||
#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
|
||||
#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__)
|
||||
if (map->offset + (map->size-1) < map->offset ||
|
||||
map->offset < virt_to_phys(high_memory)) {
|
||||
kfree(map);
|
||||
|
@ -80,6 +80,7 @@ static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_DITHERING_OFF, "Off" },
|
||||
{ DRM_MODE_DITHERING_ON, "On" },
|
||||
{ DRM_MODE_DITHERING_AUTO, "Automatic" },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1126,7 +1127,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_KMS("CRTC ID is %d\n", crtc->base.id);
|
||||
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
|
||||
if (put_user(crtc->base.id, crtc_id + copied)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
@ -1154,8 +1155,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
||||
list_for_each_entry(encoder,
|
||||
&dev->mode_config.encoder_list,
|
||||
head) {
|
||||
DRM_DEBUG_KMS("ENCODER ID is %d\n",
|
||||
encoder->base.id);
|
||||
DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
|
||||
drm_get_encoder_name(encoder));
|
||||
if (put_user(encoder->base.id, encoder_id +
|
||||
copied)) {
|
||||
ret = -EFAULT;
|
||||
@ -1185,8 +1186,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
||||
list_for_each_entry(connector,
|
||||
&dev->mode_config.connector_list,
|
||||
head) {
|
||||
DRM_DEBUG_KMS("CONNECTOR ID is %d\n",
|
||||
connector->base.id);
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id,
|
||||
drm_get_connector_name(connector));
|
||||
if (put_user(connector->base.id,
|
||||
connector_id + copied)) {
|
||||
ret = -EFAULT;
|
||||
@ -1209,7 +1211,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
|
||||
}
|
||||
card_res->count_connectors = connector_count;
|
||||
|
||||
DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs,
|
||||
DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
|
||||
card_res->count_connectors, card_res->count_encoders);
|
||||
|
||||
out:
|
||||
@ -1312,7 +1314,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
|
||||
|
||||
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
|
||||
|
||||
DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id);
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
@ -1493,6 +1495,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
||||
goto out;
|
||||
}
|
||||
crtc = obj_to_crtc(obj);
|
||||
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
|
||||
|
||||
if (crtc_req->mode_valid) {
|
||||
/* If we have a mode we need a framebuffer. */
|
||||
@ -1569,6 +1572,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
||||
goto out;
|
||||
}
|
||||
connector = obj_to_connector(obj);
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id,
|
||||
drm_get_connector_name(connector));
|
||||
|
||||
connector_set[i] = connector;
|
||||
}
|
||||
@ -1684,6 +1690,7 @@ int drm_mode_addfb(struct drm_device *dev,
|
||||
|
||||
r->fb_id = fb->base.id;
|
||||
list_add(&fb->filp_head, &file_priv->fbs);
|
||||
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
@ -2610,6 +2617,15 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
||||
goto out;
|
||||
crtc = obj_to_crtc(obj);
|
||||
|
||||
if (crtc->fb == NULL) {
|
||||
/* The framebuffer is currently unbound, presumably
|
||||
* due to a hotplug event, that userspace has not
|
||||
* yet discovered.
|
||||
*/
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (crtc->funcs->page_flip == NULL)
|
||||
goto out;
|
||||
|
||||
|
@ -86,7 +86,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
||||
int count = 0;
|
||||
int mode_flags = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
|
||||
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,8 +103,8 @@ 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_KMS("%s is disconnected\n",
|
||||
drm_get_connector_name(connector));
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
|
||||
connector->base.id, drm_get_connector_name(connector));
|
||||
drm_mode_connector_update_edid_property(connector, NULL);
|
||||
goto prune;
|
||||
}
|
||||
@ -141,8 +142,8 @@ prune:
|
||||
|
||||
drm_mode_sort(&connector->modes);
|
||||
|
||||
DRM_DEBUG_KMS("Probed modes for %s\n",
|
||||
drm_get_connector_name(connector));
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
|
||||
drm_get_connector_name(connector));
|
||||
list_for_each_entry_safe(mode, t, &connector->modes, head) {
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
@ -201,6 +202,17 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_crtc_in_use);
|
||||
|
||||
static void
|
||||
drm_encoder_disable(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
|
||||
|
||||
if (encoder_funcs->disable)
|
||||
(*encoder_funcs->disable)(encoder);
|
||||
else
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_helper_disable_unused_functions - disable unused objects
|
||||
* @dev: DRM device
|
||||
@ -215,7 +227,6 @@ 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) {
|
||||
@ -226,12 +237,8 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
|
||||
}
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (!drm_helper_encoder_in_use(encoder)) {
|
||||
if (encoder_funcs->disable)
|
||||
(*encoder_funcs->disable)(encoder);
|
||||
else
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
drm_encoder_disable(encoder);
|
||||
/* disconnector encoder from any connector */
|
||||
encoder->crtc = NULL;
|
||||
}
|
||||
@ -241,7 +248,10 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
crtc->enabled = drm_helper_crtc_in_use(crtc);
|
||||
if (!crtc->enabled) {
|
||||
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
if (crtc_funcs->disable)
|
||||
(*crtc_funcs->disable)(crtc);
|
||||
else
|
||||
(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
|
||||
crtc->fb = NULL;
|
||||
}
|
||||
}
|
||||
@ -292,11 +302,11 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
|
||||
encoder_funcs = encoder->helper_private;
|
||||
/* Disable unused encoders */
|
||||
if (encoder->crtc == NULL)
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
drm_encoder_disable(encoder);
|
||||
/* Disable encoders whose CRTC is about to change */
|
||||
if (encoder_funcs->get_crtc &&
|
||||
encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
|
||||
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||
drm_encoder_disable(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,6 +375,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
|
||||
goto done;
|
||||
}
|
||||
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
|
||||
|
||||
/* Prepare the encoders and CRTCs before setting the mode. */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
@ -392,8 +403,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
if (encoder->crtc != crtc)
|
||||
continue;
|
||||
|
||||
DRM_DEBUG("%s: set mode %s %x\n", drm_get_encoder_name(encoder),
|
||||
mode->name, mode->base.id);
|
||||
DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
|
||||
encoder->base.id, drm_get_encoder_name(encoder),
|
||||
mode->base.id, mode->name);
|
||||
encoder_funcs = encoder->helper_private;
|
||||
encoder_funcs->mode_set(encoder, mode, adjusted_mode);
|
||||
}
|
||||
@ -469,10 +481,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
|
||||
crtc_funcs = set->crtc->helper_private;
|
||||
|
||||
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);
|
||||
if (set->fb) {
|
||||
DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
|
||||
set->crtc->base.id, set->fb->base.id,
|
||||
(int)set->num_connectors, set->x, set->y);
|
||||
} else {
|
||||
DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n",
|
||||
set->crtc->base.id, (int)set->num_connectors,
|
||||
set->x, set->y);
|
||||
}
|
||||
|
||||
dev = set->crtc->dev;
|
||||
|
||||
@ -601,8 +618,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
mode_changed = true;
|
||||
connector->encoder->crtc = new_crtc;
|
||||
}
|
||||
DRM_DEBUG_KMS("setting connector %d crtc to %p\n",
|
||||
connector->base.id, new_crtc);
|
||||
if (new_crtc) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
|
||||
connector->base.id, drm_get_connector_name(connector),
|
||||
new_crtc->base.id);
|
||||
} else {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
|
||||
connector->base.id, drm_get_connector_name(connector));
|
||||
}
|
||||
}
|
||||
|
||||
/* mode_set_base is not a required function */
|
||||
@ -620,8 +643,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
|
||||
set->x, set->y,
|
||||
old_fb)) {
|
||||
DRM_ERROR("failed to set mode on crtc %p\n",
|
||||
set->crtc);
|
||||
DRM_ERROR("failed to set mode on [CRTC:%d]\n",
|
||||
set->crtc->base.id);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -243,47 +243,20 @@ int drm_lastclose(struct drm_device * dev)
|
||||
*
|
||||
* Initializes an array of drm_device structures, and attempts to
|
||||
* initialize all available devices, using consecutive minors, registering the
|
||||
* stubs and initializing the AGP device.
|
||||
* stubs and initializing the device.
|
||||
*
|
||||
* Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
|
||||
* after the initialization for driver customization.
|
||||
*/
|
||||
int drm_init(struct drm_driver *driver)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
const struct pci_device_id *pid;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
INIT_LIST_HEAD(&driver->device_list);
|
||||
|
||||
if (driver->driver_features & DRIVER_MODESET)
|
||||
return pci_register_driver(&driver->pci_driver);
|
||||
|
||||
/* If not using KMS, fall back to stealth mode manual scanning. */
|
||||
for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
|
||||
pid = &driver->pci_driver.id_table[i];
|
||||
|
||||
/* Loop around setting up a DRM device for each PCI device
|
||||
* matching our ID and device class. If we had the internal
|
||||
* function that pci_get_subsys and pci_get_class used, we'd
|
||||
* be able to just pass pid in instead of doing a two-stage
|
||||
* thing.
|
||||
*/
|
||||
pdev = NULL;
|
||||
while ((pdev =
|
||||
pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
|
||||
pid->subdevice, pdev)) != NULL) {
|
||||
if ((pdev->class & pid->class_mask) != pid->class)
|
||||
continue;
|
||||
|
||||
/* stealth mode requires a manual probe */
|
||||
pci_dev_get(pdev);
|
||||
drm_get_dev(pdev, pid, driver);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
|
||||
return drm_platform_init(driver);
|
||||
else
|
||||
return drm_pci_init(driver);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(drm_init);
|
||||
@ -315,6 +288,7 @@ static int __init drm_core_init(void)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
|
||||
drm_global_init();
|
||||
idr_init(&drm_minors_idr);
|
||||
|
||||
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
|
||||
@ -362,6 +336,7 @@ static void __exit drm_core_exit(void)
|
||||
|
||||
unregister_chrdev(DRM_MAJOR, "drm");
|
||||
|
||||
idr_remove_all(&drm_minors_idr);
|
||||
idr_destroy(&drm_minors_idr);
|
||||
}
|
||||
|
||||
@ -506,9 +481,9 @@ long drm_ioctl(struct file *filp,
|
||||
if (ioctl->flags & DRM_UNLOCKED)
|
||||
retcode = func(dev, kdata, file_priv);
|
||||
else {
|
||||
lock_kernel();
|
||||
mutex_lock(&drm_global_mutex);
|
||||
retcode = func(dev, kdata, file_priv);
|
||||
unlock_kernel();
|
||||
mutex_unlock(&drm_global_mutex);
|
||||
}
|
||||
|
||||
if (cmd & IOC_OUT) {
|
||||
|
@ -282,7 +282,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
||||
return block;
|
||||
|
||||
carp:
|
||||
dev_warn(&connector->dev->pdev->dev, "%s: EDID block %d invalid.\n",
|
||||
dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
|
||||
drm_get_connector_name(connector), j);
|
||||
|
||||
out:
|
||||
@ -1623,7 +1623,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
||||
return 0;
|
||||
}
|
||||
if (!drm_edid_is_valid(edid)) {
|
||||
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
|
||||
dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
|
||||
drm_get_connector_name(connector));
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,6 +41,9 @@
|
||||
* &drm_encoder_slave. The @slave_funcs field will be initialized with
|
||||
* the hooks provided by the slave driver.
|
||||
*
|
||||
* If @info->platform_data is non-NULL it will be used as the initial
|
||||
* slave config.
|
||||
*
|
||||
* Returns 0 on success or a negative errno on failure, in particular,
|
||||
* -ENODEV is returned when no matching driver is found.
|
||||
*/
|
||||
@ -85,6 +88,10 @@ int drm_i2c_encoder_init(struct drm_device *dev,
|
||||
if (err)
|
||||
goto fail_unregister;
|
||||
|
||||
if (info->platform_data)
|
||||
encoder->slave_funcs->set_config(&encoder->base,
|
||||
info->platform_data);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unregister:
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
/* from BKL pushdown: note that nothing else serializes idr_find() */
|
||||
DEFINE_MUTEX(drm_global_mutex);
|
||||
|
||||
static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
struct drm_device * dev);
|
||||
|
||||
@ -175,8 +178,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
/* BKL pushdown: note that nothing else serializes idr_find() */
|
||||
lock_kernel();
|
||||
mutex_lock(&drm_global_mutex);
|
||||
minor = idr_find(&drm_minors_idr, minor_id);
|
||||
if (!minor)
|
||||
goto out;
|
||||
@ -197,7 +199,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
|
||||
fops_put(old_fops);
|
||||
|
||||
out:
|
||||
unlock_kernel();
|
||||
mutex_unlock(&drm_global_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -472,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
int retcode = 0;
|
||||
|
||||
lock_kernel();
|
||||
mutex_lock(&drm_global_mutex);
|
||||
|
||||
DRM_DEBUG("open_count = %d\n", dev->open_count);
|
||||
|
||||
@ -573,17 +575,14 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
if (atomic_read(&dev->ioctl_count)) {
|
||||
DRM_ERROR("Device busy: %d\n",
|
||||
atomic_read(&dev->ioctl_count));
|
||||
spin_unlock(&dev->count_lock);
|
||||
unlock_kernel();
|
||||
return -EBUSY;
|
||||
retcode = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&dev->count_lock);
|
||||
unlock_kernel();
|
||||
return drm_lastclose(dev);
|
||||
retcode = drm_lastclose(dev);
|
||||
}
|
||||
out:
|
||||
spin_unlock(&dev->count_lock);
|
||||
|
||||
unlock_kernel();
|
||||
mutex_unlock(&drm_global_mutex);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
@ -68,8 +68,18 @@
|
||||
* We make up offsets for buffer objects so we can recognize them at
|
||||
* mmap time.
|
||||
*/
|
||||
|
||||
/* pgoff in mmap is an unsigned long, so we need to make sure that
|
||||
* the faked up offset will fit
|
||||
*/
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
|
||||
#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
|
||||
#else
|
||||
#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1)
|
||||
#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize the GEM device fields
|
||||
@ -419,6 +429,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
|
||||
idr_for_each(&file_private->object_idr,
|
||||
&drm_gem_object_release_handle, NULL);
|
||||
|
||||
idr_remove_all(&file_private->object_idr);
|
||||
idr_destroy(&file_private->object_idr);
|
||||
}
|
||||
|
||||
|
@ -28,45 +28,45 @@
|
||||
* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
|
||||
*/
|
||||
|
||||
#include "ttm/ttm_module.h"
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include "drm_global.h"
|
||||
|
||||
struct ttm_global_item {
|
||||
struct drm_global_item {
|
||||
struct mutex mutex;
|
||||
void *object;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
static struct ttm_global_item glob[TTM_GLOBAL_NUM];
|
||||
static struct drm_global_item glob[DRM_GLOBAL_NUM];
|
||||
|
||||
void ttm_global_init(void)
|
||||
void drm_global_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TTM_GLOBAL_NUM; ++i) {
|
||||
struct ttm_global_item *item = &glob[i];
|
||||
for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
|
||||
struct drm_global_item *item = &glob[i];
|
||||
mutex_init(&item->mutex);
|
||||
item->object = NULL;
|
||||
item->refcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ttm_global_release(void)
|
||||
void drm_global_release(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TTM_GLOBAL_NUM; ++i) {
|
||||
struct ttm_global_item *item = &glob[i];
|
||||
for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
|
||||
struct drm_global_item *item = &glob[i];
|
||||
BUG_ON(item->object != NULL);
|
||||
BUG_ON(item->refcount != 0);
|
||||
}
|
||||
}
|
||||
|
||||
int ttm_global_item_ref(struct ttm_global_reference *ref)
|
||||
int drm_global_item_ref(struct drm_global_reference *ref)
|
||||
{
|
||||
int ret;
|
||||
struct ttm_global_item *item = &glob[ref->global_type];
|
||||
struct drm_global_item *item = &glob[ref->global_type];
|
||||
void *object;
|
||||
|
||||
mutex_lock(&item->mutex);
|
||||
@ -93,11 +93,11 @@ out_err:
|
||||
item->object = NULL;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_global_item_ref);
|
||||
EXPORT_SYMBOL(drm_global_item_ref);
|
||||
|
||||
void ttm_global_item_unref(struct ttm_global_reference *ref)
|
||||
void drm_global_item_unref(struct drm_global_reference *ref)
|
||||
{
|
||||
struct ttm_global_item *item = &glob[ref->global_type];
|
||||
struct drm_global_item *item = &glob[ref->global_type];
|
||||
|
||||
mutex_lock(&item->mutex);
|
||||
BUG_ON(item->refcount == 0);
|
||||
@ -108,5 +108,5 @@ void ttm_global_item_unref(struct ttm_global_reference *ref)
|
||||
}
|
||||
mutex_unlock(&item->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(ttm_global_item_unref);
|
||||
EXPORT_SYMBOL(drm_global_item_unref);
|
||||
|
@ -51,13 +51,24 @@ int drm_name_info(struct seq_file *m, void *data)
|
||||
if (!master)
|
||||
return 0;
|
||||
|
||||
if (master->unique) {
|
||||
seq_printf(m, "%s %s %s\n",
|
||||
dev->driver->pci_driver.name,
|
||||
pci_name(dev->pdev), master->unique);
|
||||
if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
|
||||
if (master->unique) {
|
||||
seq_printf(m, "%s %s %s\n",
|
||||
dev->driver->platform_device->name,
|
||||
dev_name(dev->dev), master->unique);
|
||||
} else {
|
||||
seq_printf(m, "%s\n",
|
||||
dev->driver->platform_device->name);
|
||||
}
|
||||
} else {
|
||||
seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
|
||||
pci_name(dev->pdev));
|
||||
if (master->unique) {
|
||||
seq_printf(m, "%s %s %s\n",
|
||||
dev->driver->pci_driver.name,
|
||||
dev_name(dev->dev), master->unique);
|
||||
} else {
|
||||
seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
|
||||
dev_name(dev->dev));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -64,6 +64,19 @@ int drm_getunique(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_unset_busid(struct drm_device *dev,
|
||||
struct drm_master *master)
|
||||
{
|
||||
kfree(dev->devname);
|
||||
dev->devname = NULL;
|
||||
|
||||
kfree(master->unique);
|
||||
master->unique = NULL;
|
||||
master->unique_len = 0;
|
||||
master->unique_size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bus id.
|
||||
*
|
||||
@ -94,17 +107,24 @@ int drm_setunique(struct drm_device *dev, void *data,
|
||||
master->unique_len = u->unique_len;
|
||||
master->unique_size = u->unique_len + 1;
|
||||
master->unique = kmalloc(master->unique_size, GFP_KERNEL);
|
||||
if (!master->unique)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(master->unique, u->unique, master->unique_len))
|
||||
return -EFAULT;
|
||||
if (!master->unique) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (copy_from_user(master->unique, u->unique, master->unique_len)) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
master->unique[master->unique_len] = '\0';
|
||||
|
||||
dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
|
||||
strlen(master->unique) + 2, GFP_KERNEL);
|
||||
if (!dev->devname)
|
||||
return -ENOMEM;
|
||||
if (!dev->devname) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
master->unique);
|
||||
@ -113,53 +133,103 @@ int drm_setunique(struct drm_device *dev, void *data,
|
||||
* busid.
|
||||
*/
|
||||
ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
|
||||
if (ret != 3)
|
||||
return -EINVAL;
|
||||
if (ret != 3) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
domain = bus >> 8;
|
||||
bus &= 0xff;
|
||||
|
||||
if ((domain != drm_get_pci_domain(dev)) ||
|
||||
(bus != dev->pdev->bus->number) ||
|
||||
(slot != PCI_SLOT(dev->pdev->devfn)) ||
|
||||
(func != PCI_FUNC(dev->pdev->devfn)))
|
||||
return -EINVAL;
|
||||
(func != PCI_FUNC(dev->pdev->devfn))) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
drm_unset_busid(dev, master);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_master *master = file_priv->master;
|
||||
int len;
|
||||
int len, ret;
|
||||
|
||||
if (master->unique != NULL)
|
||||
return -EBUSY;
|
||||
drm_unset_busid(dev, master);
|
||||
|
||||
master->unique_len = 40;
|
||||
master->unique_size = master->unique_len;
|
||||
master->unique = kmalloc(master->unique_size, GFP_KERNEL);
|
||||
if (master->unique == NULL)
|
||||
return -ENOMEM;
|
||||
if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
|
||||
master->unique_len = 10 + strlen(dev->platformdev->name);
|
||||
master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
|
||||
|
||||
len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d",
|
||||
drm_get_pci_domain(dev),
|
||||
dev->pdev->bus->number,
|
||||
PCI_SLOT(dev->pdev->devfn),
|
||||
PCI_FUNC(dev->pdev->devfn));
|
||||
if (len >= master->unique_len)
|
||||
DRM_ERROR("buffer overflow");
|
||||
else
|
||||
master->unique_len = len;
|
||||
if (master->unique == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
|
||||
master->unique_len + 2, GFP_KERNEL);
|
||||
if (dev->devname == NULL)
|
||||
return -ENOMEM;
|
||||
len = snprintf(master->unique, master->unique_len,
|
||||
"platform:%s", dev->platformdev->name);
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
master->unique);
|
||||
if (len > master->unique_len) {
|
||||
DRM_ERROR("Unique buffer overflowed\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dev->devname =
|
||||
kmalloc(strlen(dev->platformdev->name) +
|
||||
master->unique_len + 2, GFP_KERNEL);
|
||||
|
||||
if (dev->devname == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->platformdev->name,
|
||||
master->unique);
|
||||
|
||||
} else {
|
||||
master->unique_len = 40;
|
||||
master->unique_size = master->unique_len;
|
||||
master->unique = kmalloc(master->unique_size, GFP_KERNEL);
|
||||
if (master->unique == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
len = snprintf(master->unique, master->unique_len,
|
||||
"pci:%04x:%02x:%02x.%d",
|
||||
drm_get_pci_domain(dev),
|
||||
dev->pdev->bus->number,
|
||||
PCI_SLOT(dev->pdev->devfn),
|
||||
PCI_FUNC(dev->pdev->devfn));
|
||||
if (len >= master->unique_len) {
|
||||
DRM_ERROR("buffer overflow");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
} else
|
||||
master->unique_len = len;
|
||||
|
||||
dev->devname =
|
||||
kmalloc(strlen(dev->driver->pci_driver.name) +
|
||||
master->unique_len + 2, GFP_KERNEL);
|
||||
|
||||
if (dev->devname == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
|
||||
master->unique);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
drm_unset_busid(dev, master);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,7 +393,9 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri
|
||||
/*
|
||||
* Version 1.1 includes tying of DRM to specific device
|
||||
*/
|
||||
drm_set_busid(dev, file_priv);
|
||||
retcode = drm_set_busid(dev, file_priv);
|
||||
if (retcode)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm_trace.h"
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/slab.h>
|
||||
@ -57,6 +58,9 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct drm_irq_busid *p = data;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
|
||||
return -EINVAL;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return -EINVAL;
|
||||
|
||||
@ -211,7 +215,7 @@ int drm_irq_install(struct drm_device *dev)
|
||||
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
|
||||
return -EINVAL;
|
||||
|
||||
if (dev->pdev->irq == 0)
|
||||
if (drm_dev_to_irq(dev) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
@ -229,7 +233,7 @@ int drm_irq_install(struct drm_device *dev)
|
||||
dev->irq_enabled = 1;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("irq=%d\n", dev->pdev->irq);
|
||||
DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
|
||||
|
||||
/* Before installing handler */
|
||||
dev->driver->irq_preinstall(dev);
|
||||
@ -302,14 +306,14 @@ int drm_irq_uninstall(struct drm_device * dev)
|
||||
if (!irq_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("irq=%d\n", dev->pdev->irq);
|
||||
DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
|
||||
|
||||
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);
|
||||
free_irq(drm_dev_to_irq(dev), dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -341,7 +345,7 @@ int drm_control(struct drm_device *dev, void *data,
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return 0;
|
||||
if (dev->if_version < DRM_IF_VERSION(1, 2) &&
|
||||
ctl->irq != dev->pdev->irq)
|
||||
ctl->irq != drm_dev_to_irq(dev))
|
||||
return -EINVAL;
|
||||
return drm_irq_install(dev);
|
||||
case DRM_UNINST_HANDLER:
|
||||
@ -587,6 +591,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
|
||||
return -ENOMEM;
|
||||
|
||||
e->pipe = pipe;
|
||||
e->base.pid = current->pid;
|
||||
e->event.base.type = DRM_EVENT_VBLANK;
|
||||
e->event.base.length = sizeof e->event;
|
||||
e->event.user_data = vblwait->request.signal;
|
||||
@ -614,6 +619,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
|
||||
DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
|
||||
vblwait->request.sequence, seq, pipe);
|
||||
|
||||
trace_drm_vblank_event_queued(current->pid, pipe,
|
||||
vblwait->request.sequence);
|
||||
|
||||
e->event.sequence = vblwait->request.sequence;
|
||||
if ((seq - vblwait->request.sequence) <= (1 << 23)) {
|
||||
e->event.tv_sec = now.tv_sec;
|
||||
@ -621,6 +629,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
|
||||
drm_vblank_put(dev, e->pipe);
|
||||
list_add_tail(&e->base.link, &e->base.file_priv->event_list);
|
||||
wake_up_interruptible(&e->base.file_priv->event_wait);
|
||||
trace_drm_vblank_event_delivered(current->pid, pipe,
|
||||
vblwait->request.sequence);
|
||||
} else {
|
||||
list_add_tail(&e->base.link, &dev->vblank_event_list);
|
||||
}
|
||||
@ -651,7 +661,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
int ret = 0;
|
||||
unsigned int flags, seq, crtc;
|
||||
|
||||
if ((!dev->pdev->irq) || (!dev->irq_enabled))
|
||||
if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled))
|
||||
return -EINVAL;
|
||||
|
||||
if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
|
||||
@ -751,9 +761,13 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
|
||||
drm_vblank_put(dev, e->pipe);
|
||||
list_move_tail(&e->base.link, &e->base.file_priv->event_list);
|
||||
wake_up_interruptible(&e->base.file_priv->event_wait);
|
||||
trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
|
||||
e->event.sequence);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
|
||||
trace_drm_vblank_event(crtc, seq);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,44 +48,14 @@
|
||||
|
||||
#define MM_UNUSED_TARGET 4
|
||||
|
||||
unsigned long drm_mm_tail_space(struct drm_mm *mm)
|
||||
{
|
||||
struct list_head *tail_node;
|
||||
struct drm_mm_node *entry;
|
||||
|
||||
tail_node = mm->ml_entry.prev;
|
||||
entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
|
||||
if (!entry->free)
|
||||
return 0;
|
||||
|
||||
return entry->size;
|
||||
}
|
||||
|
||||
int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
|
||||
{
|
||||
struct list_head *tail_node;
|
||||
struct drm_mm_node *entry;
|
||||
|
||||
tail_node = mm->ml_entry.prev;
|
||||
entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
|
||||
if (!entry->free)
|
||||
return -ENOMEM;
|
||||
|
||||
if (entry->size <= size)
|
||||
return -ENOMEM;
|
||||
|
||||
entry->size -= size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
|
||||
{
|
||||
struct drm_mm_node *child;
|
||||
|
||||
if (atomic)
|
||||
child = kmalloc(sizeof(*child), GFP_ATOMIC);
|
||||
child = kzalloc(sizeof(*child), GFP_ATOMIC);
|
||||
else
|
||||
child = kmalloc(sizeof(*child), GFP_KERNEL);
|
||||
child = kzalloc(sizeof(*child), GFP_KERNEL);
|
||||
|
||||
if (unlikely(child == NULL)) {
|
||||
spin_lock(&mm->unused_lock);
|
||||
@ -94,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
|
||||
else {
|
||||
child =
|
||||
list_entry(mm->unused_nodes.next,
|
||||
struct drm_mm_node, fl_entry);
|
||||
list_del(&child->fl_entry);
|
||||
struct drm_mm_node, free_stack);
|
||||
list_del(&child->free_stack);
|
||||
--mm->num_unused;
|
||||
}
|
||||
spin_unlock(&mm->unused_lock);
|
||||
@ -115,7 +85,7 @@ int drm_mm_pre_get(struct drm_mm *mm)
|
||||
spin_lock(&mm->unused_lock);
|
||||
while (mm->num_unused < MM_UNUSED_TARGET) {
|
||||
spin_unlock(&mm->unused_lock);
|
||||
node = kmalloc(sizeof(*node), GFP_KERNEL);
|
||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||
spin_lock(&mm->unused_lock);
|
||||
|
||||
if (unlikely(node == NULL)) {
|
||||
@ -124,7 +94,7 @@ int drm_mm_pre_get(struct drm_mm *mm)
|
||||
return ret;
|
||||
}
|
||||
++mm->num_unused;
|
||||
list_add_tail(&node->fl_entry, &mm->unused_nodes);
|
||||
list_add_tail(&node->free_stack, &mm->unused_nodes);
|
||||
}
|
||||
spin_unlock(&mm->unused_lock);
|
||||
return 0;
|
||||
@ -146,27 +116,12 @@ static int drm_mm_create_tail_node(struct drm_mm *mm,
|
||||
child->start = start;
|
||||
child->mm = mm;
|
||||
|
||||
list_add_tail(&child->ml_entry, &mm->ml_entry);
|
||||
list_add_tail(&child->fl_entry, &mm->fl_entry);
|
||||
list_add_tail(&child->node_list, &mm->node_list);
|
||||
list_add_tail(&child->free_stack, &mm->free_stack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size, int atomic)
|
||||
{
|
||||
struct list_head *tail_node;
|
||||
struct drm_mm_node *entry;
|
||||
|
||||
tail_node = mm->ml_entry.prev;
|
||||
entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
|
||||
if (!entry->free) {
|
||||
return drm_mm_create_tail_node(mm, entry->start + entry->size,
|
||||
size, atomic);
|
||||
}
|
||||
entry->size += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
|
||||
unsigned long size,
|
||||
int atomic)
|
||||
@ -177,15 +132,14 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
|
||||
if (unlikely(child == NULL))
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&child->fl_entry);
|
||||
INIT_LIST_HEAD(&child->free_stack);
|
||||
|
||||
child->free = 0;
|
||||
child->size = size;
|
||||
child->start = parent->start;
|
||||
child->mm = parent->mm;
|
||||
|
||||
list_add_tail(&child->ml_entry, &parent->ml_entry);
|
||||
INIT_LIST_HEAD(&child->fl_entry);
|
||||
list_add_tail(&child->node_list, &parent->node_list);
|
||||
INIT_LIST_HEAD(&child->free_stack);
|
||||
|
||||
parent->size -= size;
|
||||
parent->start += size;
|
||||
@ -213,7 +167,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
|
||||
}
|
||||
|
||||
if (node->size == size) {
|
||||
list_del_init(&node->fl_entry);
|
||||
list_del_init(&node->free_stack);
|
||||
node->free = 0;
|
||||
} else {
|
||||
node = drm_mm_split_at_start(node, size, atomic);
|
||||
@ -251,7 +205,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
|
||||
}
|
||||
|
||||
if (node->size == size) {
|
||||
list_del_init(&node->fl_entry);
|
||||
list_del_init(&node->free_stack);
|
||||
node->free = 0;
|
||||
} else {
|
||||
node = drm_mm_split_at_start(node, size, atomic);
|
||||
@ -273,16 +227,19 @@ void drm_mm_put_block(struct drm_mm_node *cur)
|
||||
{
|
||||
|
||||
struct drm_mm *mm = cur->mm;
|
||||
struct list_head *cur_head = &cur->ml_entry;
|
||||
struct list_head *root_head = &mm->ml_entry;
|
||||
struct list_head *cur_head = &cur->node_list;
|
||||
struct list_head *root_head = &mm->node_list;
|
||||
struct drm_mm_node *prev_node = NULL;
|
||||
struct drm_mm_node *next_node;
|
||||
|
||||
int merged = 0;
|
||||
|
||||
BUG_ON(cur->scanned_block || cur->scanned_prev_free
|
||||
|| cur->scanned_next_free);
|
||||
|
||||
if (cur_head->prev != root_head) {
|
||||
prev_node =
|
||||
list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
|
||||
list_entry(cur_head->prev, struct drm_mm_node, node_list);
|
||||
if (prev_node->free) {
|
||||
prev_node->size += cur->size;
|
||||
merged = 1;
|
||||
@ -290,15 +247,15 @@ void drm_mm_put_block(struct drm_mm_node *cur)
|
||||
}
|
||||
if (cur_head->next != root_head) {
|
||||
next_node =
|
||||
list_entry(cur_head->next, struct drm_mm_node, ml_entry);
|
||||
list_entry(cur_head->next, struct drm_mm_node, node_list);
|
||||
if (next_node->free) {
|
||||
if (merged) {
|
||||
prev_node->size += next_node->size;
|
||||
list_del(&next_node->ml_entry);
|
||||
list_del(&next_node->fl_entry);
|
||||
list_del(&next_node->node_list);
|
||||
list_del(&next_node->free_stack);
|
||||
spin_lock(&mm->unused_lock);
|
||||
if (mm->num_unused < MM_UNUSED_TARGET) {
|
||||
list_add(&next_node->fl_entry,
|
||||
list_add(&next_node->free_stack,
|
||||
&mm->unused_nodes);
|
||||
++mm->num_unused;
|
||||
} else
|
||||
@ -313,12 +270,12 @@ void drm_mm_put_block(struct drm_mm_node *cur)
|
||||
}
|
||||
if (!merged) {
|
||||
cur->free = 1;
|
||||
list_add(&cur->fl_entry, &mm->fl_entry);
|
||||
list_add(&cur->free_stack, &mm->free_stack);
|
||||
} else {
|
||||
list_del(&cur->ml_entry);
|
||||
list_del(&cur->node_list);
|
||||
spin_lock(&mm->unused_lock);
|
||||
if (mm->num_unused < MM_UNUSED_TARGET) {
|
||||
list_add(&cur->fl_entry, &mm->unused_nodes);
|
||||
list_add(&cur->free_stack, &mm->unused_nodes);
|
||||
++mm->num_unused;
|
||||
} else
|
||||
kfree(cur);
|
||||
@ -328,40 +285,50 @@ void drm_mm_put_block(struct drm_mm_node *cur)
|
||||
|
||||
EXPORT_SYMBOL(drm_mm_put_block);
|
||||
|
||||
static int check_free_mm_node(struct drm_mm_node *entry, unsigned long size,
|
||||
unsigned alignment)
|
||||
{
|
||||
unsigned wasted = 0;
|
||||
|
||||
if (entry->size < size)
|
||||
return 0;
|
||||
|
||||
if (alignment) {
|
||||
register unsigned tmp = entry->start % alignment;
|
||||
if (tmp)
|
||||
wasted = alignment - tmp;
|
||||
}
|
||||
|
||||
if (entry->size >= size + wasted) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
|
||||
unsigned long size,
|
||||
unsigned alignment, int best_match)
|
||||
{
|
||||
struct list_head *list;
|
||||
const struct list_head *free_stack = &mm->fl_entry;
|
||||
struct drm_mm_node *entry;
|
||||
struct drm_mm_node *best;
|
||||
unsigned long best_size;
|
||||
unsigned wasted;
|
||||
|
||||
BUG_ON(mm->scanned_blocks);
|
||||
|
||||
best = NULL;
|
||||
best_size = ~0UL;
|
||||
|
||||
list_for_each(list, free_stack) {
|
||||
entry = list_entry(list, struct drm_mm_node, fl_entry);
|
||||
wasted = 0;
|
||||
|
||||
if (entry->size < size)
|
||||
list_for_each_entry(entry, &mm->free_stack, free_stack) {
|
||||
if (!check_free_mm_node(entry, size, alignment))
|
||||
continue;
|
||||
|
||||
if (alignment) {
|
||||
register unsigned tmp = entry->start % alignment;
|
||||
if (tmp)
|
||||
wasted += alignment - tmp;
|
||||
}
|
||||
if (!best_match)
|
||||
return entry;
|
||||
|
||||
if (entry->size >= size + wasted) {
|
||||
if (!best_match)
|
||||
return entry;
|
||||
if (entry->size < best_size) {
|
||||
best = entry;
|
||||
best_size = entry->size;
|
||||
}
|
||||
if (entry->size < best_size) {
|
||||
best = entry;
|
||||
best_size = entry->size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,43 +343,28 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
|
||||
unsigned long end,
|
||||
int best_match)
|
||||
{
|
||||
struct list_head *list;
|
||||
const struct list_head *free_stack = &mm->fl_entry;
|
||||
struct drm_mm_node *entry;
|
||||
struct drm_mm_node *best;
|
||||
unsigned long best_size;
|
||||
unsigned wasted;
|
||||
|
||||
BUG_ON(mm->scanned_blocks);
|
||||
|
||||
best = NULL;
|
||||
best_size = ~0UL;
|
||||
|
||||
list_for_each(list, free_stack) {
|
||||
entry = list_entry(list, struct drm_mm_node, fl_entry);
|
||||
wasted = 0;
|
||||
|
||||
if (entry->size < size)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(entry, &mm->free_stack, free_stack) {
|
||||
if (entry->start > end || (entry->start+entry->size) < start)
|
||||
continue;
|
||||
|
||||
if (entry->start < start)
|
||||
wasted += start - entry->start;
|
||||
if (!check_free_mm_node(entry, size, alignment))
|
||||
continue;
|
||||
|
||||
if (alignment) {
|
||||
register unsigned tmp = (entry->start + wasted) % alignment;
|
||||
if (tmp)
|
||||
wasted += alignment - tmp;
|
||||
}
|
||||
if (!best_match)
|
||||
return entry;
|
||||
|
||||
if (entry->size >= size + wasted &&
|
||||
(entry->start + wasted + size) <= end) {
|
||||
if (!best_match)
|
||||
return entry;
|
||||
if (entry->size < best_size) {
|
||||
best = entry;
|
||||
best_size = entry->size;
|
||||
}
|
||||
if (entry->size < best_size) {
|
||||
best = entry;
|
||||
best_size = entry->size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,9 +372,161 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_search_free_in_range);
|
||||
|
||||
/**
|
||||
* Initializa lru scanning.
|
||||
*
|
||||
* This simply sets up the scanning routines with the parameters for the desired
|
||||
* hole.
|
||||
*
|
||||
* Warning: As long as the scan list is non-empty, no other operations than
|
||||
* adding/removing nodes to/from the scan list are allowed.
|
||||
*/
|
||||
void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
|
||||
unsigned alignment)
|
||||
{
|
||||
mm->scan_alignment = alignment;
|
||||
mm->scan_size = size;
|
||||
mm->scanned_blocks = 0;
|
||||
mm->scan_hit_start = 0;
|
||||
mm->scan_hit_size = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_init_scan);
|
||||
|
||||
/**
|
||||
* Add a node to the scan list that might be freed to make space for the desired
|
||||
* hole.
|
||||
*
|
||||
* Returns non-zero, if a hole has been found, zero otherwise.
|
||||
*/
|
||||
int drm_mm_scan_add_block(struct drm_mm_node *node)
|
||||
{
|
||||
struct drm_mm *mm = node->mm;
|
||||
struct list_head *prev_free, *next_free;
|
||||
struct drm_mm_node *prev_node, *next_node;
|
||||
|
||||
mm->scanned_blocks++;
|
||||
|
||||
prev_free = next_free = NULL;
|
||||
|
||||
BUG_ON(node->free);
|
||||
node->scanned_block = 1;
|
||||
node->free = 1;
|
||||
|
||||
if (node->node_list.prev != &mm->node_list) {
|
||||
prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
|
||||
node_list);
|
||||
|
||||
if (prev_node->free) {
|
||||
list_del(&prev_node->node_list);
|
||||
|
||||
node->start = prev_node->start;
|
||||
node->size += prev_node->size;
|
||||
|
||||
prev_node->scanned_prev_free = 1;
|
||||
|
||||
prev_free = &prev_node->free_stack;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->node_list.next != &mm->node_list) {
|
||||
next_node = list_entry(node->node_list.next, struct drm_mm_node,
|
||||
node_list);
|
||||
|
||||
if (next_node->free) {
|
||||
list_del(&next_node->node_list);
|
||||
|
||||
node->size += next_node->size;
|
||||
|
||||
next_node->scanned_next_free = 1;
|
||||
|
||||
next_free = &next_node->free_stack;
|
||||
}
|
||||
}
|
||||
|
||||
/* The free_stack list is not used for allocated objects, so these two
|
||||
* pointers can be abused (as long as no allocations in this memory
|
||||
* manager happens). */
|
||||
node->free_stack.prev = prev_free;
|
||||
node->free_stack.next = next_free;
|
||||
|
||||
if (check_free_mm_node(node, mm->scan_size, mm->scan_alignment)) {
|
||||
mm->scan_hit_start = node->start;
|
||||
mm->scan_hit_size = node->size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_scan_add_block);
|
||||
|
||||
/**
|
||||
* Remove a node from the scan list.
|
||||
*
|
||||
* Nodes _must_ be removed in the exact same order from the scan list as they
|
||||
* have been added, otherwise the internal state of the memory manager will be
|
||||
* corrupted.
|
||||
*
|
||||
* When the scan list is empty, the selected memory nodes can be freed. An
|
||||
* immediatly following drm_mm_search_free with best_match = 0 will then return
|
||||
* the just freed block (because its at the top of the free_stack list).
|
||||
*
|
||||
* Returns one if this block should be evicted, zero otherwise. Will always
|
||||
* return zero when no hole has been found.
|
||||
*/
|
||||
int drm_mm_scan_remove_block(struct drm_mm_node *node)
|
||||
{
|
||||
struct drm_mm *mm = node->mm;
|
||||
struct drm_mm_node *prev_node, *next_node;
|
||||
|
||||
mm->scanned_blocks--;
|
||||
|
||||
BUG_ON(!node->scanned_block);
|
||||
node->scanned_block = 0;
|
||||
node->free = 0;
|
||||
|
||||
prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
|
||||
free_stack);
|
||||
next_node = list_entry(node->free_stack.next, struct drm_mm_node,
|
||||
free_stack);
|
||||
|
||||
if (prev_node) {
|
||||
BUG_ON(!prev_node->scanned_prev_free);
|
||||
prev_node->scanned_prev_free = 0;
|
||||
|
||||
list_add_tail(&prev_node->node_list, &node->node_list);
|
||||
|
||||
node->start = prev_node->start + prev_node->size;
|
||||
node->size -= prev_node->size;
|
||||
}
|
||||
|
||||
if (next_node) {
|
||||
BUG_ON(!next_node->scanned_next_free);
|
||||
next_node->scanned_next_free = 0;
|
||||
|
||||
list_add(&next_node->node_list, &node->node_list);
|
||||
|
||||
node->size -= next_node->size;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&node->free_stack);
|
||||
|
||||
/* Only need to check for containement because start&size for the
|
||||
* complete resulting free block (not just the desired part) is
|
||||
* stored. */
|
||||
if (node->start >= mm->scan_hit_start &&
|
||||
node->start + node->size
|
||||
<= mm->scan_hit_start + mm->scan_hit_size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_scan_remove_block);
|
||||
|
||||
int drm_mm_clean(struct drm_mm * mm)
|
||||
{
|
||||
struct list_head *head = &mm->ml_entry;
|
||||
struct list_head *head = &mm->node_list;
|
||||
|
||||
return (head->next->next == head);
|
||||
}
|
||||
@ -430,10 +534,11 @@ EXPORT_SYMBOL(drm_mm_clean);
|
||||
|
||||
int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
|
||||
{
|
||||
INIT_LIST_HEAD(&mm->ml_entry);
|
||||
INIT_LIST_HEAD(&mm->fl_entry);
|
||||
INIT_LIST_HEAD(&mm->node_list);
|
||||
INIT_LIST_HEAD(&mm->free_stack);
|
||||
INIT_LIST_HEAD(&mm->unused_nodes);
|
||||
mm->num_unused = 0;
|
||||
mm->scanned_blocks = 0;
|
||||
spin_lock_init(&mm->unused_lock);
|
||||
|
||||
return drm_mm_create_tail_node(mm, start, size, 0);
|
||||
@ -442,25 +547,25 @@ EXPORT_SYMBOL(drm_mm_init);
|
||||
|
||||
void drm_mm_takedown(struct drm_mm * mm)
|
||||
{
|
||||
struct list_head *bnode = mm->fl_entry.next;
|
||||
struct list_head *bnode = mm->free_stack.next;
|
||||
struct drm_mm_node *entry;
|
||||
struct drm_mm_node *next;
|
||||
|
||||
entry = list_entry(bnode, struct drm_mm_node, fl_entry);
|
||||
entry = list_entry(bnode, struct drm_mm_node, free_stack);
|
||||
|
||||
if (entry->ml_entry.next != &mm->ml_entry ||
|
||||
entry->fl_entry.next != &mm->fl_entry) {
|
||||
if (entry->node_list.next != &mm->node_list ||
|
||||
entry->free_stack.next != &mm->free_stack) {
|
||||
DRM_ERROR("Memory manager not clean. Delaying takedown\n");
|
||||
return;
|
||||
}
|
||||
|
||||
list_del(&entry->fl_entry);
|
||||
list_del(&entry->ml_entry);
|
||||
list_del(&entry->free_stack);
|
||||
list_del(&entry->node_list);
|
||||
kfree(entry);
|
||||
|
||||
spin_lock(&mm->unused_lock);
|
||||
list_for_each_entry_safe(entry, next, &mm->unused_nodes, fl_entry) {
|
||||
list_del(&entry->fl_entry);
|
||||
list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
|
||||
list_del(&entry->free_stack);
|
||||
kfree(entry);
|
||||
--mm->num_unused;
|
||||
}
|
||||
@ -475,7 +580,7 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
|
||||
struct drm_mm_node *entry;
|
||||
int total_used = 0, total_free = 0, total = 0;
|
||||
|
||||
list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
|
||||
list_for_each_entry(entry, &mm->node_list, node_list) {
|
||||
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
|
||||
prefix, entry->start, entry->start + entry->size,
|
||||
entry->size, entry->free ? "free" : "used");
|
||||
@ -496,7 +601,7 @@ 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) {
|
||||
list_for_each_entry(entry, &mm->node_list, node_list) {
|
||||
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)
|
||||
|
@ -124,4 +124,147 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
|
||||
|
||||
EXPORT_SYMBOL(drm_pci_free);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* \param pdev - PCI device structure
|
||||
* \param ent entry from the PCI ID table with device type flags
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Attempt to gets inter module "drm" information. If we are first
|
||||
* then register the character device and inter module information.
|
||||
* Try and register, if we fail to register, backout previous work.
|
||||
*/
|
||||
int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto err_g1;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
dev->pdev = pdev;
|
||||
dev->dev = &pdev->dev;
|
||||
|
||||
dev->pci_device = pdev->device;
|
||||
dev->pci_vendor = pdev->vendor;
|
||||
|
||||
#ifdef __alpha__
|
||||
dev->hose = pdev->sysdata;
|
||||
#endif
|
||||
|
||||
if ((ret = drm_fill_in_dev(dev, ent, driver))) {
|
||||
printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
|
||||
goto err_g2;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
pci_set_drvdata(pdev, dev);
|
||||
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
||||
if (ret)
|
||||
goto err_g2;
|
||||
}
|
||||
|
||||
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
|
||||
goto err_g3;
|
||||
|
||||
if (dev->driver->load) {
|
||||
ret = dev->driver->load(dev, ent->driver_data);
|
||||
if (ret)
|
||||
goto err_g4;
|
||||
}
|
||||
|
||||
/* setup the grouping for the legacy output */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = drm_mode_group_init_legacy_group(dev,
|
||||
&dev->primary->mode_group);
|
||||
if (ret)
|
||||
goto err_g4;
|
||||
}
|
||||
|
||||
list_add_tail(&dev->driver_item, &driver->device_list);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
|
||||
driver->name, driver->major, driver->minor, driver->patchlevel,
|
||||
driver->date, pci_name(pdev), dev->primary->index);
|
||||
|
||||
return 0;
|
||||
|
||||
err_g4:
|
||||
drm_put_minor(&dev->primary);
|
||||
err_g3:
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(&dev->control);
|
||||
err_g2:
|
||||
pci_disable_device(pdev);
|
||||
err_g1:
|
||||
kfree(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_pci_dev);
|
||||
|
||||
/**
|
||||
* PCI device initialization. Called via drm_init at module load time,
|
||||
*
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Initializes a drm_device structures,registering the
|
||||
* stubs and initializing the AGP device.
|
||||
*
|
||||
* Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
|
||||
* after the initialization for driver customization.
|
||||
*/
|
||||
int drm_pci_init(struct drm_driver *driver)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
const struct pci_device_id *pid;
|
||||
int i;
|
||||
|
||||
if (driver->driver_features & DRIVER_MODESET)
|
||||
return pci_register_driver(&driver->pci_driver);
|
||||
|
||||
/* If not using KMS, fall back to stealth mode manual scanning. */
|
||||
for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
|
||||
pid = &driver->pci_driver.id_table[i];
|
||||
|
||||
/* Loop around setting up a DRM device for each PCI device
|
||||
* matching our ID and device class. If we had the internal
|
||||
* function that pci_get_subsys and pci_get_class used, we'd
|
||||
* be able to just pass pid in instead of doing a two-stage
|
||||
* thing.
|
||||
*/
|
||||
pdev = NULL;
|
||||
while ((pdev =
|
||||
pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
|
||||
pid->subdevice, pdev)) != NULL) {
|
||||
if ((pdev->class & pid->class_mask) != pid->class)
|
||||
continue;
|
||||
|
||||
/* stealth mode requires a manual probe */
|
||||
pci_dev_get(pdev);
|
||||
drm_get_pci_dev(pdev, pid, driver);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int drm_pci_init(struct drm_driver *driver)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*@}*/
|
||||
|
122
drivers/gpu/drm/drm_platform.c
Normal file
122
drivers/gpu/drm/drm_platform.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Derived from drm_pci.c
|
||||
*
|
||||
* Copyright 2003 José Fonseca.
|
||||
* Copyright 2003 Leif Delgass.
|
||||
* Copyright (c) 2009, Code Aurora Forum.
|
||||
* 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
|
||||
* AUTHORS 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 "drmP.h"
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* \param platdev - Platform device struture
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Attempt to gets inter module "drm" information. If we are first
|
||||
* then register the character device and inter module information.
|
||||
* Try and register, if we fail to register, backout previous work.
|
||||
*/
|
||||
|
||||
int drm_get_platform_dev(struct platform_device *platdev,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->platformdev = platdev;
|
||||
dev->dev = &platdev->dev;
|
||||
|
||||
ret = drm_fill_in_dev(dev, NULL, driver);
|
||||
|
||||
if (ret) {
|
||||
printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
|
||||
goto err_g1;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
dev_set_drvdata(&platdev->dev, dev);
|
||||
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
||||
if (ret)
|
||||
goto err_g1;
|
||||
}
|
||||
|
||||
ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
|
||||
if (ret)
|
||||
goto err_g2;
|
||||
|
||||
if (dev->driver->load) {
|
||||
ret = dev->driver->load(dev, 0);
|
||||
if (ret)
|
||||
goto err_g3;
|
||||
}
|
||||
|
||||
/* setup the grouping for the legacy output */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = drm_mode_group_init_legacy_group(dev,
|
||||
&dev->primary->mode_group);
|
||||
if (ret)
|
||||
goto err_g3;
|
||||
}
|
||||
|
||||
list_add_tail(&dev->driver_item, &driver->device_list);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
|
||||
driver->name, driver->major, driver->minor, driver->patchlevel,
|
||||
driver->date, dev->primary->index);
|
||||
|
||||
return 0;
|
||||
|
||||
err_g3:
|
||||
drm_put_minor(&dev->primary);
|
||||
err_g2:
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(&dev->control);
|
||||
err_g1:
|
||||
kfree(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_platform_dev);
|
||||
|
||||
/**
|
||||
* Platform device initialization. Called via drm_init at module load time,
|
||||
*
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Initializes a drm_device structures,registering the
|
||||
* stubs
|
||||
*
|
||||
* Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
|
||||
* after the initialization for driver customization.
|
||||
*/
|
||||
|
||||
int drm_platform_init(struct drm_driver *driver)
|
||||
{
|
||||
return drm_get_platform_dev(driver->platform_device, driver);
|
||||
}
|
@ -156,6 +156,9 @@ static void drm_master_destroy(struct kref *kref)
|
||||
master->unique_len = 0;
|
||||
}
|
||||
|
||||
kfree(dev->devname);
|
||||
dev->devname = NULL;
|
||||
|
||||
list_for_each_entry_safe(pt, next, &master->magicfree, head) {
|
||||
list_del(&pt->head);
|
||||
drm_ht_remove_item(&master->magiclist, &pt->hash_item);
|
||||
@ -224,7 +227,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
||||
int drm_fill_in_dev(struct drm_device *dev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
@ -245,14 +248,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
||||
|
||||
idr_init(&dev->drw_idr);
|
||||
|
||||
dev->pdev = pdev;
|
||||
dev->pci_device = pdev->device;
|
||||
dev->pci_vendor = pdev->vendor;
|
||||
|
||||
#ifdef __alpha__
|
||||
dev->hose = pdev->sysdata;
|
||||
#endif
|
||||
|
||||
if (drm_ht_create(&dev->map_hash, 12)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -321,7 +316,7 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
|
||||
* create the proc init entry via proc_init(). This routines assigns
|
||||
* minor numbers to secondary heads of multi-headed cards
|
||||
*/
|
||||
static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
|
||||
int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
|
||||
{
|
||||
struct drm_minor *new_minor;
|
||||
int ret;
|
||||
@ -387,83 +382,6 @@ err_idr:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register.
|
||||
*
|
||||
* \param pdev - PCI device structure
|
||||
* \param ent entry from the PCI ID table with device type flags
|
||||
* \return zero on success or a negative number on failure.
|
||||
*
|
||||
* Attempt to gets inter module "drm" information. If we are first
|
||||
* then register the character device and inter module information.
|
||||
* Try and register, if we fail to register, backout previous work.
|
||||
*/
|
||||
int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
|
||||
struct drm_driver *driver)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto err_g1;
|
||||
|
||||
pci_set_master(pdev);
|
||||
if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
|
||||
printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
|
||||
goto err_g2;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
pci_set_drvdata(pdev, dev);
|
||||
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
|
||||
if (ret)
|
||||
goto err_g2;
|
||||
}
|
||||
|
||||
if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
|
||||
goto err_g3;
|
||||
|
||||
if (dev->driver->load) {
|
||||
ret = dev->driver->load(dev, ent->driver_data);
|
||||
if (ret)
|
||||
goto err_g4;
|
||||
}
|
||||
|
||||
/* setup the grouping for the legacy output */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
|
||||
if (ret)
|
||||
goto err_g4;
|
||||
}
|
||||
|
||||
list_add_tail(&dev->driver_item, &driver->device_list);
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
|
||||
driver->name, driver->major, driver->minor, driver->patchlevel,
|
||||
driver->date, pci_name(pdev), dev->primary->index);
|
||||
|
||||
return 0;
|
||||
|
||||
err_g4:
|
||||
drm_put_minor(&dev->primary);
|
||||
err_g3:
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_put_minor(&dev->control);
|
||||
err_g2:
|
||||
pci_disable_device(pdev);
|
||||
err_g1:
|
||||
kfree(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_dev);
|
||||
|
||||
/**
|
||||
* Put a secondary minor number.
|
||||
*
|
||||
|
@ -489,7 +489,8 @@ int drm_sysfs_device_add(struct drm_minor *minor)
|
||||
int err;
|
||||
char *minor_str;
|
||||
|
||||
minor->kdev.parent = &minor->dev->pdev->dev;
|
||||
minor->kdev.parent = minor->dev->dev;
|
||||
|
||||
minor->kdev.class = drm_class;
|
||||
minor->kdev.release = drm_sysfs_device_release;
|
||||
minor->kdev.devt = minor->device;
|
||||
|
66
drivers/gpu/drm/drm_trace.h
Normal file
66
drivers/gpu/drm/drm_trace.h
Normal file
@ -0,0 +1,66 @@
|
||||
#if !defined(_DRM_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _DRM_TRACE_H_
|
||||
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM drm
|
||||
#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
|
||||
#define TRACE_INCLUDE_FILE drm_trace
|
||||
|
||||
TRACE_EVENT(drm_vblank_event,
|
||||
TP_PROTO(int crtc, unsigned int seq),
|
||||
TP_ARGS(crtc, seq),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, crtc)
|
||||
__field(unsigned int, seq)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->crtc = crtc;
|
||||
__entry->seq = seq;
|
||||
),
|
||||
TP_printk("crtc=%d, seq=%d", __entry->crtc, __entry->seq)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drm_vblank_event_queued,
|
||||
TP_PROTO(pid_t pid, int crtc, unsigned int seq),
|
||||
TP_ARGS(pid, crtc, seq),
|
||||
TP_STRUCT__entry(
|
||||
__field(pid_t, pid)
|
||||
__field(int, crtc)
|
||||
__field(unsigned int, seq)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->pid = pid;
|
||||
__entry->crtc = crtc;
|
||||
__entry->seq = seq;
|
||||
),
|
||||
TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
|
||||
__entry->seq)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drm_vblank_event_delivered,
|
||||
TP_PROTO(pid_t pid, int crtc, unsigned int seq),
|
||||
TP_ARGS(pid, crtc, seq),
|
||||
TP_STRUCT__entry(
|
||||
__field(pid_t, pid)
|
||||
__field(int, crtc)
|
||||
__field(unsigned int, seq)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->pid = pid;
|
||||
__entry->crtc = crtc;
|
||||
__entry->seq = seq;
|
||||
),
|
||||
TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
|
||||
__entry->seq)
|
||||
);
|
||||
|
||||
#endif /* _DRM_TRACE_H_ */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#include <trace/define_trace.h>
|
4
drivers/gpu/drm/drm_trace_points.c
Normal file
4
drivers/gpu/drm/drm_trace_points.c
Normal file
@ -0,0 +1,4 @@
|
||||
#include "drmP.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "drm_trace.h"
|
@ -61,7 +61,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
|
||||
tmp = pgprot_writecombine(tmp);
|
||||
else
|
||||
tmp = pgprot_noncached(tmp);
|
||||
#elif defined(__sparc__)
|
||||
#elif defined(__sparc__) || defined(__arm__)
|
||||
tmp = pgprot_noncached(tmp);
|
||||
#endif
|
||||
return tmp;
|
||||
@ -601,6 +601,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
|
||||
}
|
||||
|
||||
switch (map->type) {
|
||||
#if !defined(__arm__)
|
||||
case _DRM_AGP:
|
||||
if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
|
||||
/*
|
||||
@ -615,20 +616,31 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
|
||||
break;
|
||||
}
|
||||
/* fall through to _DRM_FRAME_BUFFER... */
|
||||
#endif
|
||||
case _DRM_FRAME_BUFFER:
|
||||
case _DRM_REGISTERS:
|
||||
offset = dev->driver->get_reg_ofs(dev);
|
||||
vma->vm_flags |= VM_IO; /* not in core dump */
|
||||
vma->vm_page_prot = drm_io_prot(map->type, vma);
|
||||
#if !defined(__arm__)
|
||||
if (io_remap_pfn_range(vma, vma->vm_start,
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
#else
|
||||
if (remap_pfn_range(vma, vma->vm_start,
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot))
|
||||
return -EAGAIN;
|
||||
#endif
|
||||
|
||||
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
|
||||
" offset = 0x%llx\n",
|
||||
map->type,
|
||||
vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
|
||||
|
||||
vma->vm_ops = &drm_vm_ops;
|
||||
break;
|
||||
case _DRM_CONSISTENT:
|
||||
|
@ -2,3 +2,6 @@ ccflags-y := -Iinclude/drm
|
||||
|
||||
ch7006-y := ch7006_drv.o ch7006_mode.o
|
||||
obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
|
||||
|
||||
sil164-y := sil164_drv.o
|
||||
obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
|
||||
|
@ -33,7 +33,7 @@ static void ch7006_encoder_set_config(struct drm_encoder *encoder,
|
||||
{
|
||||
struct ch7006_priv *priv = to_ch7006_priv(encoder);
|
||||
|
||||
priv->params = params;
|
||||
priv->params = *(struct ch7006_encoder_params *)params;
|
||||
}
|
||||
|
||||
static void ch7006_encoder_destroy(struct drm_encoder *encoder)
|
||||
@ -114,7 +114,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
|
||||
{
|
||||
struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
|
||||
struct ch7006_priv *priv = to_ch7006_priv(encoder);
|
||||
struct ch7006_encoder_params *params = priv->params;
|
||||
struct ch7006_encoder_params *params = &priv->params;
|
||||
struct ch7006_state *state = &priv->state;
|
||||
uint8_t *regs = state->regs;
|
||||
struct ch7006_mode *mode = priv->mode;
|
||||
@ -428,6 +428,22 @@ static int ch7006_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ch7006_suspend(struct i2c_client *client, pm_message_t mesg)
|
||||
{
|
||||
ch7006_dbg(client, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ch7006_resume(struct i2c_client *client)
|
||||
{
|
||||
ch7006_dbg(client, "\n");
|
||||
|
||||
ch7006_write(client, 0x3d, 0x0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ch7006_encoder_init(struct i2c_client *client,
|
||||
struct drm_device *dev,
|
||||
struct drm_encoder_slave *encoder)
|
||||
@ -487,6 +503,8 @@ static struct drm_i2c_encoder_driver ch7006_driver = {
|
||||
.i2c_driver = {
|
||||
.probe = ch7006_probe,
|
||||
.remove = ch7006_remove,
|
||||
.suspend = ch7006_suspend,
|
||||
.resume = ch7006_resume,
|
||||
|
||||
.driver = {
|
||||
.name = "ch7006",
|
||||
|
@ -77,7 +77,7 @@ struct ch7006_state {
|
||||
};
|
||||
|
||||
struct ch7006_priv {
|
||||
struct ch7006_encoder_params *params;
|
||||
struct ch7006_encoder_params params;
|
||||
struct ch7006_mode *mode;
|
||||
|
||||
struct ch7006_state state;
|
||||
|
462
drivers/gpu/drm/i2c/sil164_drv.c
Normal file
462
drivers/gpu/drm/i2c/sil164_drv.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 "drmP.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "drm_encoder_slave.h"
|
||||
#include "i2c/sil164.h"
|
||||
|
||||
struct sil164_priv {
|
||||
struct sil164_encoder_params config;
|
||||
struct i2c_client *duallink_slave;
|
||||
|
||||
uint8_t saved_state[0x10];
|
||||
uint8_t saved_slave_state[0x10];
|
||||
};
|
||||
|
||||
#define to_sil164_priv(x) \
|
||||
((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
|
||||
|
||||
#define sil164_dbg(client, format, ...) do { \
|
||||
if (drm_debug & DRM_UT_KMS) \
|
||||
dev_printk(KERN_DEBUG, &client->dev, \
|
||||
"%s: " format, __func__, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define sil164_info(client, format, ...) \
|
||||
dev_info(&client->dev, format, __VA_ARGS__)
|
||||
#define sil164_err(client, format, ...) \
|
||||
dev_err(&client->dev, format, __VA_ARGS__)
|
||||
|
||||
#define SIL164_I2C_ADDR_MASTER 0x38
|
||||
#define SIL164_I2C_ADDR_SLAVE 0x39
|
||||
|
||||
/* HW register definitions */
|
||||
|
||||
#define SIL164_VENDOR_LO 0x0
|
||||
#define SIL164_VENDOR_HI 0x1
|
||||
#define SIL164_DEVICE_LO 0x2
|
||||
#define SIL164_DEVICE_HI 0x3
|
||||
#define SIL164_REVISION 0x4
|
||||
#define SIL164_FREQ_MIN 0x6
|
||||
#define SIL164_FREQ_MAX 0x7
|
||||
#define SIL164_CONTROL0 0x8
|
||||
# define SIL164_CONTROL0_POWER_ON 0x01
|
||||
# define SIL164_CONTROL0_EDGE_RISING 0x02
|
||||
# define SIL164_CONTROL0_INPUT_24BIT 0x04
|
||||
# define SIL164_CONTROL0_DUAL_EDGE 0x08
|
||||
# define SIL164_CONTROL0_HSYNC_ON 0x10
|
||||
# define SIL164_CONTROL0_VSYNC_ON 0x20
|
||||
#define SIL164_DETECT 0x9
|
||||
# define SIL164_DETECT_INTR_STAT 0x01
|
||||
# define SIL164_DETECT_HOTPLUG_STAT 0x02
|
||||
# define SIL164_DETECT_RECEIVER_STAT 0x04
|
||||
# define SIL164_DETECT_INTR_MODE_RECEIVER 0x00
|
||||
# define SIL164_DETECT_INTR_MODE_HOTPLUG 0x08
|
||||
# define SIL164_DETECT_OUT_MODE_HIGH 0x00
|
||||
# define SIL164_DETECT_OUT_MODE_INTR 0x10
|
||||
# define SIL164_DETECT_OUT_MODE_RECEIVER 0x20
|
||||
# define SIL164_DETECT_OUT_MODE_HOTPLUG 0x30
|
||||
# define SIL164_DETECT_VSWING_STAT 0x80
|
||||
#define SIL164_CONTROL1 0xa
|
||||
# define SIL164_CONTROL1_DESKEW_ENABLE 0x10
|
||||
# define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5
|
||||
#define SIL164_GPIO 0xb
|
||||
#define SIL164_CONTROL2 0xc
|
||||
# define SIL164_CONTROL2_FILTER_ENABLE 0x01
|
||||
# define SIL164_CONTROL2_FILTER_SETTING_SHIFT 1
|
||||
# define SIL164_CONTROL2_DUALLINK_MASTER 0x40
|
||||
# define SIL164_CONTROL2_SYNC_CONT 0x80
|
||||
#define SIL164_DUALLINK 0xd
|
||||
# define SIL164_DUALLINK_ENABLE 0x10
|
||||
# define SIL164_DUALLINK_SKEW_SHIFT 5
|
||||
#define SIL164_PLLZONE 0xe
|
||||
# define SIL164_PLLZONE_STAT 0x08
|
||||
# define SIL164_PLLZONE_FORCE_ON 0x10
|
||||
# define SIL164_PLLZONE_FORCE_HIGH 0x20
|
||||
|
||||
/* HW access functions */
|
||||
|
||||
static void
|
||||
sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val)
|
||||
{
|
||||
uint8_t buf[] = {addr, val};
|
||||
int ret;
|
||||
|
||||
ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
|
||||
if (ret < 0)
|
||||
sil164_err(client, "Error %d writing to subaddress 0x%x\n",
|
||||
ret, addr);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
sil164_read(struct i2c_client *client, uint8_t addr)
|
||||
{
|
||||
uint8_t val;
|
||||
int ret;
|
||||
|
||||
ret = i2c_master_send(client, &addr, sizeof(addr));
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = i2c_master_recv(client, &val, sizeof(val));
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
return val;
|
||||
|
||||
fail:
|
||||
sil164_err(client, "Error %d reading from subaddress 0x%x\n",
|
||||
ret, addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_save_state(struct i2c_client *client, uint8_t *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0x8; i <= 0xe; i++)
|
||||
state[i] = sil164_read(client, i);
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_restore_state(struct i2c_client *client, uint8_t *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0x8; i <= 0xe; i++)
|
||||
sil164_write(client, i, state[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_set_power_state(struct i2c_client *client, bool on)
|
||||
{
|
||||
uint8_t control0 = sil164_read(client, SIL164_CONTROL0);
|
||||
|
||||
if (on)
|
||||
control0 |= SIL164_CONTROL0_POWER_ON;
|
||||
else
|
||||
control0 &= ~SIL164_CONTROL0_POWER_ON;
|
||||
|
||||
sil164_write(client, SIL164_CONTROL0, control0);
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_init_state(struct i2c_client *client,
|
||||
struct sil164_encoder_params *config,
|
||||
bool duallink)
|
||||
{
|
||||
sil164_write(client, SIL164_CONTROL0,
|
||||
SIL164_CONTROL0_HSYNC_ON |
|
||||
SIL164_CONTROL0_VSYNC_ON |
|
||||
(config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) |
|
||||
(config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) |
|
||||
(config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0));
|
||||
|
||||
sil164_write(client, SIL164_DETECT,
|
||||
SIL164_DETECT_INTR_STAT |
|
||||
SIL164_DETECT_OUT_MODE_RECEIVER);
|
||||
|
||||
sil164_write(client, SIL164_CONTROL1,
|
||||
(config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) |
|
||||
(((config->input_skew + 4) & 0x7)
|
||||
<< SIL164_CONTROL1_DESKEW_INCR_SHIFT));
|
||||
|
||||
sil164_write(client, SIL164_CONTROL2,
|
||||
SIL164_CONTROL2_SYNC_CONT |
|
||||
(config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) |
|
||||
(4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT));
|
||||
|
||||
sil164_write(client, SIL164_PLLZONE, 0);
|
||||
|
||||
if (duallink)
|
||||
sil164_write(client, SIL164_DUALLINK,
|
||||
SIL164_DUALLINK_ENABLE |
|
||||
(((config->duallink_skew + 4) & 0x7)
|
||||
<< SIL164_DUALLINK_SKEW_SHIFT));
|
||||
else
|
||||
sil164_write(client, SIL164_DUALLINK, 0);
|
||||
}
|
||||
|
||||
/* DRM encoder functions */
|
||||
|
||||
static void
|
||||
sil164_encoder_set_config(struct drm_encoder *encoder, void *params)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
|
||||
priv->config = *(struct sil164_encoder_params *)params;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
bool on = (mode == DRM_MODE_DPMS_ON);
|
||||
bool duallink = (on && encoder->crtc->mode.clock > 165000);
|
||||
|
||||
sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
|
||||
|
||||
if (priv->duallink_slave)
|
||||
sil164_set_power_state(priv->duallink_slave, duallink);
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_encoder_save(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
|
||||
sil164_save_state(drm_i2c_encoder_get_client(encoder),
|
||||
priv->saved_state);
|
||||
|
||||
if (priv->duallink_slave)
|
||||
sil164_save_state(priv->duallink_slave,
|
||||
priv->saved_slave_state);
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_encoder_restore(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
|
||||
sil164_restore_state(drm_i2c_encoder_get_client(encoder),
|
||||
priv->saved_state);
|
||||
|
||||
if (priv->duallink_slave)
|
||||
sil164_restore_state(priv->duallink_slave,
|
||||
priv->saved_slave_state);
|
||||
}
|
||||
|
||||
static bool
|
||||
sil164_encoder_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
sil164_encoder_mode_valid(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
|
||||
if (mode->clock < 32000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (mode->clock > 330000 ||
|
||||
(mode->clock > 165000 && !priv->duallink_slave))
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
bool duallink = adjusted_mode->clock > 165000;
|
||||
|
||||
sil164_init_state(drm_i2c_encoder_get_client(encoder),
|
||||
&priv->config, duallink);
|
||||
|
||||
if (priv->duallink_slave)
|
||||
sil164_init_state(priv->duallink_slave,
|
||||
&priv->config, duallink);
|
||||
|
||||
sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
sil164_encoder_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
|
||||
|
||||
if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT)
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static int
|
||||
sil164_encoder_get_modes(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sil164_encoder_create_resources(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sil164_encoder_set_property(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sil164_encoder_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct sil164_priv *priv = to_sil164_priv(encoder);
|
||||
|
||||
if (priv->duallink_slave)
|
||||
i2c_unregister_device(priv->duallink_slave);
|
||||
|
||||
kfree(priv);
|
||||
drm_i2c_encoder_destroy(encoder);
|
||||
}
|
||||
|
||||
static struct drm_encoder_slave_funcs sil164_encoder_funcs = {
|
||||
.set_config = sil164_encoder_set_config,
|
||||
.destroy = sil164_encoder_destroy,
|
||||
.dpms = sil164_encoder_dpms,
|
||||
.save = sil164_encoder_save,
|
||||
.restore = sil164_encoder_restore,
|
||||
.mode_fixup = sil164_encoder_mode_fixup,
|
||||
.mode_valid = sil164_encoder_mode_valid,
|
||||
.mode_set = sil164_encoder_mode_set,
|
||||
.detect = sil164_encoder_detect,
|
||||
.get_modes = sil164_encoder_get_modes,
|
||||
.create_resources = sil164_encoder_create_resources,
|
||||
.set_property = sil164_encoder_set_property,
|
||||
};
|
||||
|
||||
/* I2C driver functions */
|
||||
|
||||
static int
|
||||
sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
|
||||
sil164_read(client, SIL164_VENDOR_LO);
|
||||
int device = sil164_read(client, SIL164_DEVICE_HI) << 8 |
|
||||
sil164_read(client, SIL164_DEVICE_LO);
|
||||
int rev = sil164_read(client, SIL164_REVISION);
|
||||
|
||||
if (vendor != 0x1 || device != 0x6) {
|
||||
sil164_dbg(client, "Unknown device %x:%x.%x\n",
|
||||
vendor, device, rev);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sil164_info(client, "Detected device %x:%x.%x\n",
|
||||
vendor, device, rev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sil164_remove(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_client *
|
||||
sil164_detect_slave(struct i2c_client *client)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct i2c_msg msg = {
|
||||
.addr = SIL164_I2C_ADDR_SLAVE,
|
||||
.len = 0,
|
||||
};
|
||||
const struct i2c_board_info info = {
|
||||
I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE)
|
||||
};
|
||||
|
||||
if (i2c_transfer(adap, &msg, 1) != 1) {
|
||||
sil164_dbg(adap, "No dual-link slave found.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return i2c_new_device(adap, &info);
|
||||
}
|
||||
|
||||
static int
|
||||
sil164_encoder_init(struct i2c_client *client,
|
||||
struct drm_device *dev,
|
||||
struct drm_encoder_slave *encoder)
|
||||
{
|
||||
struct sil164_priv *priv;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
encoder->slave_priv = priv;
|
||||
encoder->slave_funcs = &sil164_encoder_funcs;
|
||||
|
||||
priv->duallink_slave = sil164_detect_slave(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id sil164_ids[] = {
|
||||
{ "sil164", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sil164_ids);
|
||||
|
||||
static struct drm_i2c_encoder_driver sil164_driver = {
|
||||
.i2c_driver = {
|
||||
.probe = sil164_probe,
|
||||
.remove = sil164_remove,
|
||||
.driver = {
|
||||
.name = "sil164",
|
||||
},
|
||||
.id_table = sil164_ids,
|
||||
},
|
||||
.encoder_init = sil164_encoder_init,
|
||||
};
|
||||
|
||||
/* Module initialization */
|
||||
|
||||
static int __init
|
||||
sil164_init(void)
|
||||
{
|
||||
return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
sil164_exit(void)
|
||||
{
|
||||
drm_i2c_encoder_unregister(&sil164_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
|
||||
MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
||||
module_init(sil164_init);
|
||||
module_exit(sil164_exit);
|
@ -37,6 +37,7 @@
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
#define I810_BUF_FREE 2
|
||||
@ -60,9 +61,8 @@ static struct drm_buf *i810_freelist_get(struct drm_device * dev)
|
||||
/* In use is already a pointer */
|
||||
used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
|
||||
I810_BUF_CLIENT);
|
||||
if (used == I810_BUF_FREE) {
|
||||
if (used == I810_BUF_FREE)
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -71,7 +71,7 @@ static struct drm_buf *i810_freelist_get(struct drm_device * dev)
|
||||
* yet, the hardware updates in use for us once its on the ring buffer.
|
||||
*/
|
||||
|
||||
static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
|
||||
static int i810_freelist_put(struct drm_device *dev, struct drm_buf *buf)
|
||||
{
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int used;
|
||||
@ -121,7 +121,7 @@ static const struct file_operations i810_buffer_fops = {
|
||||
.fasync = drm_fasync,
|
||||
};
|
||||
|
||||
static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
|
||||
static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
@ -152,7 +152,7 @@ static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_unmap_buffer(struct drm_buf * buf)
|
||||
static int i810_unmap_buffer(struct drm_buf *buf)
|
||||
{
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int retcode = 0;
|
||||
@ -172,7 +172,7 @@ static int i810_unmap_buffer(struct drm_buf * buf)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
|
||||
static int i810_dma_get_buffer(struct drm_device *dev, drm_i810_dma_t *d,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_buf *buf;
|
||||
@ -202,7 +202,7 @@ static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_dma_cleanup(struct drm_device * dev)
|
||||
static int i810_dma_cleanup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
|
||||
@ -218,9 +218,8 @@ static int i810_dma_cleanup(struct drm_device * dev)
|
||||
drm_i810_private_t *dev_priv =
|
||||
(drm_i810_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start) {
|
||||
if (dev_priv->ring.virtual_start)
|
||||
drm_core_ioremapfree(&dev_priv->ring.map, dev);
|
||||
}
|
||||
if (dev_priv->hw_status_page) {
|
||||
pci_free_consistent(dev->pdev, PAGE_SIZE,
|
||||
dev_priv->hw_status_page,
|
||||
@ -242,7 +241,7 @@ static int i810_dma_cleanup(struct drm_device * dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i810_wait_ring(struct drm_device * dev, int n)
|
||||
static int i810_wait_ring(struct drm_device *dev, int n)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
@ -271,11 +270,11 @@ static int i810_wait_ring(struct drm_device * dev, int n)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
out_wait_ring:
|
||||
out_wait_ring:
|
||||
return iters;
|
||||
}
|
||||
|
||||
static void i810_kernel_lost_context(struct drm_device * dev)
|
||||
static void i810_kernel_lost_context(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
@ -287,7 +286,7 @@ static void i810_kernel_lost_context(struct drm_device * dev)
|
||||
ring->space += ring->Size;
|
||||
}
|
||||
|
||||
static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
|
||||
static int i810_freelist_init(struct drm_device *dev, drm_i810_private_t *dev_priv)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
int my_idx = 24;
|
||||
@ -322,9 +321,9 @@ static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i810_dma_initialize(struct drm_device * dev,
|
||||
drm_i810_private_t * dev_priv,
|
||||
drm_i810_init_t * init)
|
||||
static int i810_dma_initialize(struct drm_device *dev,
|
||||
drm_i810_private_t *dev_priv,
|
||||
drm_i810_init_t *init)
|
||||
{
|
||||
struct drm_map_list *r_list;
|
||||
memset(dev_priv, 0, sizeof(drm_i810_private_t));
|
||||
@ -462,7 +461,7 @@ static int i810_dma_init(struct drm_device *dev, void *data,
|
||||
* Use 'volatile' & local var tmp to force the emitted values to be
|
||||
* identical to the verified ones.
|
||||
*/
|
||||
static void i810EmitContextVerified(struct drm_device * dev,
|
||||
static void i810EmitContextVerified(struct drm_device *dev,
|
||||
volatile unsigned int *code)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
@ -495,7 +494,7 @@ static void i810EmitContextVerified(struct drm_device * dev,
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
|
||||
static void i810EmitTexVerified(struct drm_device *dev, volatile unsigned int *code)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
int i, j = 0;
|
||||
@ -528,7 +527,7 @@ static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *
|
||||
|
||||
/* Need to do some additional checking when setting the dest buffer.
|
||||
*/
|
||||
static void i810EmitDestVerified(struct drm_device * dev,
|
||||
static void i810EmitDestVerified(struct drm_device *dev,
|
||||
volatile unsigned int *code)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
@ -563,7 +562,7 @@ static void i810EmitDestVerified(struct drm_device * dev,
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i810EmitState(struct drm_device * dev)
|
||||
static void i810EmitState(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -594,7 +593,7 @@ static void i810EmitState(struct drm_device * dev)
|
||||
|
||||
/* need to verify
|
||||
*/
|
||||
static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
|
||||
static void i810_dma_dispatch_clear(struct drm_device *dev, int flags,
|
||||
unsigned int clear_color,
|
||||
unsigned int clear_zval)
|
||||
{
|
||||
@ -669,7 +668,7 @@ static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
static void i810_dma_dispatch_swap(struct drm_device * dev)
|
||||
static void i810_dma_dispatch_swap(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -715,8 +714,8 @@ static void i810_dma_dispatch_swap(struct drm_device * dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void i810_dma_dispatch_vertex(struct drm_device * dev,
|
||||
struct drm_buf * buf, int discard, int used)
|
||||
static void i810_dma_dispatch_vertex(struct drm_device *dev,
|
||||
struct drm_buf *buf, int discard, int used)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
@ -795,7 +794,7 @@ static void i810_dma_dispatch_vertex(struct drm_device * dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void i810_dma_dispatch_flip(struct drm_device * dev)
|
||||
static void i810_dma_dispatch_flip(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
int pitch = dev_priv->pitch;
|
||||
@ -841,7 +840,7 @@ static void i810_dma_dispatch_flip(struct drm_device * dev)
|
||||
|
||||
}
|
||||
|
||||
static void i810_dma_quiescent(struct drm_device * dev)
|
||||
static void i810_dma_quiescent(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
@ -858,7 +857,7 @@ static void i810_dma_quiescent(struct drm_device * dev)
|
||||
i810_wait_ring(dev, dev_priv->ring.Size - 8);
|
||||
}
|
||||
|
||||
static int i810_flush_queue(struct drm_device * dev)
|
||||
static int i810_flush_queue(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
@ -891,7 +890,7 @@ static int i810_flush_queue(struct drm_device * dev)
|
||||
}
|
||||
|
||||
/* Must be called with the lock held */
|
||||
static void i810_reclaim_buffers(struct drm_device * dev,
|
||||
static void i810_reclaim_buffers(struct drm_device *dev,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
@ -969,9 +968,8 @@ static int i810_clear_bufs(struct drm_device *dev, void *data,
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
/* GH: Someone's doing nasty things... */
|
||||
if (!dev->dev_private) {
|
||||
if (!dev->dev_private)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i810_dma_dispatch_clear(dev, clear->flags,
|
||||
clear->clear_color, clear->clear_depth);
|
||||
@ -1039,7 +1037,7 @@ static int i810_docopy(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
|
||||
static void i810_dma_dispatch_mc(struct drm_device *dev, struct drm_buf *buf, int used,
|
||||
unsigned int last_render)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
@ -1053,9 +1051,8 @@ static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf,
|
||||
i810_kernel_lost_context(dev);
|
||||
|
||||
u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
|
||||
if (u != I810_BUF_CLIENT) {
|
||||
if (u != I810_BUF_CLIENT)
|
||||
DRM_DEBUG("MC found buffer that isn't mine!\n");
|
||||
}
|
||||
|
||||
if (used > 4 * 1024)
|
||||
used = 0;
|
||||
@ -1160,7 +1157,7 @@ static int i810_ov0_flip(struct drm_device *dev, void *data,
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
//Tell the overlay to update
|
||||
/* Tell the overlay to update */
|
||||
I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
|
||||
|
||||
return 0;
|
||||
@ -1168,7 +1165,7 @@ static int i810_ov0_flip(struct drm_device *dev, void *data,
|
||||
|
||||
/* Not sure why this isn't set all the time:
|
||||
*/
|
||||
static void i810_do_init_pageflip(struct drm_device * dev)
|
||||
static void i810_do_init_pageflip(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
@ -1178,7 +1175,7 @@ static void i810_do_init_pageflip(struct drm_device * dev)
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
}
|
||||
|
||||
static int i810_do_cleanup_pageflip(struct drm_device * dev)
|
||||
static int i810_do_cleanup_pageflip(struct drm_device *dev)
|
||||
{
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
@ -1218,49 +1215,61 @@ int i810_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i810_driver_lastclose(struct drm_device * dev)
|
||||
void i810_driver_lastclose(struct drm_device *dev)
|
||||
{
|
||||
i810_dma_cleanup(dev);
|
||||
}
|
||||
|
||||
void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
|
||||
void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_i810_private_t *dev_priv = dev->dev_private;
|
||||
if (dev_priv->page_flipping) {
|
||||
if (dev_priv->page_flipping)
|
||||
i810_do_cleanup_pageflip(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
|
||||
void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
i810_reclaim_buffers(dev, file_priv);
|
||||
}
|
||||
|
||||
int i810_driver_dma_quiescent(struct drm_device * dev)
|
||||
int i810_driver_dma_quiescent(struct drm_device *dev)
|
||||
{
|
||||
i810_dma_quiescent(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* call the drm_ioctl under the big kernel lock because
|
||||
* to lock against the i810_mmap_buffers function.
|
||||
*/
|
||||
long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
lock_kernel();
|
||||
ret = drm_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_ioctl_desc i810_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH)
|
||||
DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
|
||||
};
|
||||
|
||||
int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
|
||||
@ -1276,7 +1285,7 @@ int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
|
||||
* \returns
|
||||
* A value of 1 is always retured to indictate every i810 is AGP.
|
||||
*/
|
||||
int i810_driver_device_is_agp(struct drm_device * dev)
|
||||
int i810_driver_device_is_agp(struct drm_device *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ static struct drm_driver driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
.unlocked_ioctl = i810_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
|
@ -115,56 +115,59 @@ typedef struct drm_i810_private {
|
||||
} drm_i810_private_t;
|
||||
|
||||
/* i810_dma.c */
|
||||
extern int i810_driver_dma_quiescent(struct drm_device * dev);
|
||||
extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
|
||||
extern int i810_driver_dma_quiescent(struct drm_device *dev);
|
||||
extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
extern int i810_driver_load(struct drm_device *, unsigned long flags);
|
||||
extern void i810_driver_lastclose(struct drm_device * dev);
|
||||
extern void i810_driver_preclose(struct drm_device * dev,
|
||||
extern void i810_driver_lastclose(struct drm_device *dev);
|
||||
extern void i810_driver_preclose(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
|
||||
extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
extern int i810_driver_device_is_agp(struct drm_device * dev);
|
||||
extern int i810_driver_device_is_agp(struct drm_device *dev);
|
||||
|
||||
extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||
extern struct drm_ioctl_desc i810_ioctls[];
|
||||
extern int i810_max_ioctl;
|
||||
|
||||
#define I810_BASE(reg) ((unsigned long) \
|
||||
dev_priv->mmio_map->handle)
|
||||
#define I810_ADDR(reg) (I810_BASE(reg) + reg)
|
||||
#define I810_DEREF(reg) *(__volatile__ int *)I810_ADDR(reg)
|
||||
#define I810_DEREF(reg) (*(__volatile__ int *)I810_ADDR(reg))
|
||||
#define I810_READ(reg) I810_DEREF(reg)
|
||||
#define I810_WRITE(reg,val) do { I810_DEREF(reg) = val; } while (0)
|
||||
#define I810_DEREF16(reg) *(__volatile__ u16 *)I810_ADDR(reg)
|
||||
#define I810_WRITE(reg, val) do { I810_DEREF(reg) = val; } while (0)
|
||||
#define I810_DEREF16(reg) (*(__volatile__ u16 *)I810_ADDR(reg))
|
||||
#define I810_READ16(reg) I810_DEREF16(reg)
|
||||
#define I810_WRITE16(reg,val) do { I810_DEREF16(reg) = val; } while (0)
|
||||
#define I810_WRITE16(reg, val) do { I810_DEREF16(reg) = val; } while (0)
|
||||
|
||||
#define I810_VERBOSE 0
|
||||
#define RING_LOCALS unsigned int outring, ringmask; \
|
||||
volatile char *virt;
|
||||
volatile char *virt;
|
||||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I810_VERBOSE) \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d)\n", n); \
|
||||
if (dev_priv->ring.space < n*4) \
|
||||
i810_wait_ring(dev, n*4); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start; \
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I810_VERBOSE) \
|
||||
DRM_DEBUG("BEGIN_LP_RING(%d)\n", n); \
|
||||
if (dev_priv->ring.space < n*4) \
|
||||
i810_wait_ring(dev, n*4); \
|
||||
dev_priv->ring.space -= n*4; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
virt = dev_priv->ring.virtual_start; \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n"); \
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I810_VERBOSE) \
|
||||
DRM_DEBUG("ADVANCE_LP_RING\n"); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
I810_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while(0)
|
||||
I810_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while (0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
if (I810_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
#define OUT_RING(n) do { \
|
||||
if (I810_VERBOSE) \
|
||||
DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
} while (0)
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "i830_drm.h"
|
||||
#include "i830_drv.h"
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
@ -62,9 +63,8 @@ static struct drm_buf *i830_freelist_get(struct drm_device * dev)
|
||||
/* In use is already a pointer */
|
||||
used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
|
||||
I830_BUF_CLIENT);
|
||||
if (used == I830_BUF_FREE) {
|
||||
if (used == I830_BUF_FREE)
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -73,7 +73,7 @@ static struct drm_buf *i830_freelist_get(struct drm_device * dev)
|
||||
* yet, the hardware updates in use for us once its on the ring buffer.
|
||||
*/
|
||||
|
||||
static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf)
|
||||
static int i830_freelist_put(struct drm_device *dev, struct drm_buf *buf)
|
||||
{
|
||||
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int used;
|
||||
@ -123,7 +123,7 @@ static const struct file_operations i830_buffer_fops = {
|
||||
.fasync = drm_fasync,
|
||||
};
|
||||
|
||||
static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
|
||||
static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
|
||||
@ -156,7 +156,7 @@ static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i830_unmap_buffer(struct drm_buf * buf)
|
||||
static int i830_unmap_buffer(struct drm_buf *buf)
|
||||
{
|
||||
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int retcode = 0;
|
||||
@ -176,7 +176,7 @@ static int i830_unmap_buffer(struct drm_buf * buf)
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
|
||||
static int i830_dma_get_buffer(struct drm_device *dev, drm_i830_dma_t *d,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_buf *buf;
|
||||
@ -206,7 +206,7 @@ static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i830_dma_cleanup(struct drm_device * dev)
|
||||
static int i830_dma_cleanup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
|
||||
@ -222,9 +222,8 @@ static int i830_dma_cleanup(struct drm_device * dev)
|
||||
drm_i830_private_t *dev_priv =
|
||||
(drm_i830_private_t *) dev->dev_private;
|
||||
|
||||
if (dev_priv->ring.virtual_start) {
|
||||
if (dev_priv->ring.virtual_start)
|
||||
drm_core_ioremapfree(&dev_priv->ring.map, dev);
|
||||
}
|
||||
if (dev_priv->hw_status_page) {
|
||||
pci_free_consistent(dev->pdev, PAGE_SIZE,
|
||||
dev_priv->hw_status_page,
|
||||
@ -246,7 +245,7 @@ static int i830_dma_cleanup(struct drm_device * dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
int i830_wait_ring(struct drm_device *dev, int n, const char *caller)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
@ -276,11 +275,11 @@ int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
|
||||
}
|
||||
|
||||
out_wait_ring:
|
||||
out_wait_ring:
|
||||
return iters;
|
||||
}
|
||||
|
||||
static void i830_kernel_lost_context(struct drm_device * dev)
|
||||
static void i830_kernel_lost_context(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
@ -295,7 +294,7 @@ static void i830_kernel_lost_context(struct drm_device * dev)
|
||||
dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
|
||||
}
|
||||
|
||||
static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv)
|
||||
static int i830_freelist_init(struct drm_device *dev, drm_i830_private_t *dev_priv)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
int my_idx = 36;
|
||||
@ -329,9 +328,9 @@ static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i830_dma_initialize(struct drm_device * dev,
|
||||
drm_i830_private_t * dev_priv,
|
||||
drm_i830_init_t * init)
|
||||
static int i830_dma_initialize(struct drm_device *dev,
|
||||
drm_i830_private_t *dev_priv,
|
||||
drm_i830_init_t *init)
|
||||
{
|
||||
struct drm_map_list *r_list;
|
||||
|
||||
@ -482,7 +481,7 @@ static int i830_dma_init(struct drm_device *dev, void *data,
|
||||
/* Most efficient way to verify state for the i830 is as it is
|
||||
* emitted. Non-conformant state is silently dropped.
|
||||
*/
|
||||
static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
|
||||
static void i830EmitContextVerified(struct drm_device *dev, unsigned int *code)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
int i, j = 0;
|
||||
@ -527,7 +526,7 @@ static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
|
||||
static void i830EmitTexVerified(struct drm_device *dev, unsigned int *code)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
int i, j = 0;
|
||||
@ -561,7 +560,7 @@ static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
|
||||
printk("rejected packet %x\n", code[0]);
|
||||
}
|
||||
|
||||
static void i830EmitTexBlendVerified(struct drm_device * dev,
|
||||
static void i830EmitTexBlendVerified(struct drm_device *dev,
|
||||
unsigned int *code, unsigned int num)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
@ -586,7 +585,7 @@ static void i830EmitTexBlendVerified(struct drm_device * dev,
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i830EmitTexPalette(struct drm_device * dev,
|
||||
static void i830EmitTexPalette(struct drm_device *dev,
|
||||
unsigned int *palette, int number, int is_shared)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
@ -603,9 +602,8 @@ static void i830EmitTexPalette(struct drm_device * dev,
|
||||
} else {
|
||||
OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
for (i = 0; i < 256; i++)
|
||||
OUT_RING(palette[i]);
|
||||
}
|
||||
OUT_RING(0);
|
||||
/* KW: WHERE IS THE ADVANCE_LP_RING? This is effectively a noop!
|
||||
*/
|
||||
@ -613,7 +611,7 @@ static void i830EmitTexPalette(struct drm_device * dev,
|
||||
|
||||
/* Need to do some additional checking when setting the dest buffer.
|
||||
*/
|
||||
static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
|
||||
static void i830EmitDestVerified(struct drm_device *dev, unsigned int *code)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
unsigned int tmp;
|
||||
@ -674,7 +672,7 @@ static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
|
||||
static void i830EmitStippleVerified(struct drm_device *dev, unsigned int *code)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
@ -685,7 +683,7 @@ static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i830EmitState(struct drm_device * dev)
|
||||
static void i830EmitState(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -788,7 +786,7 @@ static void i830EmitState(struct drm_device * dev)
|
||||
* Performance monitoring functions
|
||||
*/
|
||||
|
||||
static void i830_fill_box(struct drm_device * dev,
|
||||
static void i830_fill_box(struct drm_device *dev,
|
||||
int x, int y, int w, int h, int r, int g, int b)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
@ -816,17 +814,16 @@ static void i830_fill_box(struct drm_device * dev,
|
||||
OUT_RING((y << 16) | x);
|
||||
OUT_RING(((y + h) << 16) | (x + w));
|
||||
|
||||
if (dev_priv->current_page == 1) {
|
||||
if (dev_priv->current_page == 1)
|
||||
OUT_RING(dev_priv->front_offset);
|
||||
} else {
|
||||
else
|
||||
OUT_RING(dev_priv->back_offset);
|
||||
}
|
||||
|
||||
OUT_RING(color);
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
static void i830_cp_performance_boxes(struct drm_device * dev)
|
||||
static void i830_cp_performance_boxes(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
@ -871,7 +868,7 @@ static void i830_cp_performance_boxes(struct drm_device * dev)
|
||||
dev_priv->sarea_priv->perf_boxes = 0;
|
||||
}
|
||||
|
||||
static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
|
||||
static void i830_dma_dispatch_clear(struct drm_device *dev, int flags,
|
||||
unsigned int clear_color,
|
||||
unsigned int clear_zval,
|
||||
unsigned int clear_depthmask)
|
||||
@ -966,7 +963,7 @@ static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
|
||||
}
|
||||
}
|
||||
|
||||
static void i830_dma_dispatch_swap(struct drm_device * dev)
|
||||
static void i830_dma_dispatch_swap(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -1036,7 +1033,7 @@ static void i830_dma_dispatch_swap(struct drm_device * dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void i830_dma_dispatch_flip(struct drm_device * dev)
|
||||
static void i830_dma_dispatch_flip(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
@ -1079,8 +1076,8 @@ static void i830_dma_dispatch_flip(struct drm_device * dev)
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
}
|
||||
|
||||
static void i830_dma_dispatch_vertex(struct drm_device * dev,
|
||||
struct drm_buf * buf, int discard, int used)
|
||||
static void i830_dma_dispatch_vertex(struct drm_device *dev,
|
||||
struct drm_buf *buf, int discard, int used)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
|
||||
@ -1100,9 +1097,8 @@ static void i830_dma_dispatch_vertex(struct drm_device * dev,
|
||||
if (discard) {
|
||||
u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
|
||||
I830_BUF_HARDWARE);
|
||||
if (u != I830_BUF_CLIENT) {
|
||||
if (u != I830_BUF_CLIENT)
|
||||
DRM_DEBUG("xxxx 2\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (used > 4 * 1023)
|
||||
@ -1191,7 +1187,7 @@ static void i830_dma_dispatch_vertex(struct drm_device * dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void i830_dma_quiescent(struct drm_device * dev)
|
||||
static void i830_dma_quiescent(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
@ -1208,7 +1204,7 @@ static void i830_dma_quiescent(struct drm_device * dev)
|
||||
i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
|
||||
}
|
||||
|
||||
static int i830_flush_queue(struct drm_device * dev)
|
||||
static int i830_flush_queue(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
@ -1241,7 +1237,7 @@ static int i830_flush_queue(struct drm_device * dev)
|
||||
}
|
||||
|
||||
/* Must be called with the lock held */
|
||||
static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_priv)
|
||||
static void i830_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
int i;
|
||||
@ -1316,9 +1312,8 @@ static int i830_clear_bufs(struct drm_device *dev, void *data,
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
/* GH: Someone's doing nasty things... */
|
||||
if (!dev->dev_private) {
|
||||
if (!dev->dev_private)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i830_dma_dispatch_clear(dev, clear->flags,
|
||||
clear->clear_color,
|
||||
@ -1339,7 +1334,7 @@ static int i830_swap_bufs(struct drm_device *dev, void *data,
|
||||
|
||||
/* Not sure why this isn't set all the time:
|
||||
*/
|
||||
static void i830_do_init_pageflip(struct drm_device * dev)
|
||||
static void i830_do_init_pageflip(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
@ -1349,7 +1344,7 @@ static void i830_do_init_pageflip(struct drm_device * dev)
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
}
|
||||
|
||||
static int i830_do_cleanup_pageflip(struct drm_device * dev)
|
||||
static int i830_do_cleanup_pageflip(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
@ -1490,47 +1485,59 @@ int i830_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i830_driver_lastclose(struct drm_device * dev)
|
||||
void i830_driver_lastclose(struct drm_device *dev)
|
||||
{
|
||||
i830_dma_cleanup(dev);
|
||||
}
|
||||
|
||||
void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
|
||||
void i830_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
if (dev->dev_private) {
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
if (dev_priv->page_flipping) {
|
||||
if (dev_priv->page_flipping)
|
||||
i830_do_cleanup_pageflip(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv)
|
||||
void i830_driver_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv)
|
||||
{
|
||||
i830_reclaim_buffers(dev, file_priv);
|
||||
}
|
||||
|
||||
int i830_driver_dma_quiescent(struct drm_device * dev)
|
||||
int i830_driver_dma_quiescent(struct drm_device *dev)
|
||||
{
|
||||
i830_dma_quiescent(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* call the drm_ioctl under the big kernel lock because
|
||||
* to lock against the i830_mmap_buffers function.
|
||||
*/
|
||||
long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
lock_kernel();
|
||||
ret = drm_ioctl(file, cmd, arg);
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_ioctl_desc i830_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH)
|
||||
DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED),
|
||||
};
|
||||
|
||||
int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
|
||||
@ -1546,7 +1553,7 @@ int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
|
||||
* \returns
|
||||
* A value of 1 is always retured to indictate every i8xx is AGP.
|
||||
*/
|
||||
int i830_driver_device_is_agp(struct drm_device * dev)
|
||||
int i830_driver_device_is_agp(struct drm_device *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ static struct drm_driver driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
.unlocked_ioctl = i830_ioctl,
|
||||
.mmap = drm_mmap,
|
||||
.poll = drm_poll,
|
||||
.fasync = drm_fasync,
|
||||
|
@ -122,6 +122,7 @@ typedef struct drm_i830_private {
|
||||
|
||||
} drm_i830_private_t;
|
||||
|
||||
long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||
extern struct drm_ioctl_desc i830_ioctls[];
|
||||
extern int i830_max_ioctl;
|
||||
|
||||
@ -132,33 +133,33 @@ extern int i830_irq_wait(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void i830_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void i830_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void i830_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern void i830_driver_irq_preinstall(struct drm_device *dev);
|
||||
extern void i830_driver_irq_postinstall(struct drm_device *dev);
|
||||
extern void i830_driver_irq_uninstall(struct drm_device *dev);
|
||||
extern int i830_driver_load(struct drm_device *, unsigned long flags);
|
||||
extern void i830_driver_preclose(struct drm_device * dev,
|
||||
extern void i830_driver_preclose(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
extern void i830_driver_lastclose(struct drm_device * dev);
|
||||
extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
|
||||
extern void i830_driver_lastclose(struct drm_device *dev);
|
||||
extern void i830_driver_reclaim_buffers_locked(struct drm_device *dev,
|
||||
struct drm_file *file_priv);
|
||||
extern int i830_driver_dma_quiescent(struct drm_device * dev);
|
||||
extern int i830_driver_device_is_agp(struct drm_device * dev);
|
||||
extern int i830_driver_dma_quiescent(struct drm_device *dev);
|
||||
extern int i830_driver_device_is_agp(struct drm_device *dev);
|
||||
|
||||
#define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
|
||||
#define I830_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
|
||||
#define I830_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
|
||||
#define I830_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
|
||||
#define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
|
||||
#define I830_WRITE(reg, val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
|
||||
#define I830_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
|
||||
#define I830_WRITE16(reg, val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
|
||||
|
||||
#define I830_VERBOSE 0
|
||||
|
||||
#define RING_LOCALS unsigned int outring, ringmask, outcount; \
|
||||
volatile char *virt;
|
||||
volatile char *virt;
|
||||
|
||||
#define BEGIN_LP_RING(n) do { \
|
||||
if (I830_VERBOSE) \
|
||||
printk("BEGIN_LP_RING(%d)\n", (n)); \
|
||||
if (dev_priv->ring.space < n*4) \
|
||||
i830_wait_ring(dev, n*4, __func__); \
|
||||
i830_wait_ring(dev, n*4, __func__); \
|
||||
outcount = 0; \
|
||||
outring = dev_priv->ring.tail; \
|
||||
ringmask = dev_priv->ring.tail_mask; \
|
||||
@ -166,21 +167,23 @@ extern int i830_driver_device_is_agp(struct drm_device * dev);
|
||||
} while (0)
|
||||
|
||||
#define OUT_RING(n) do { \
|
||||
if (I830_VERBOSE) printk(" OUT_RING %x\n", (int)(n)); \
|
||||
if (I830_VERBOSE) \
|
||||
printk(" OUT_RING %x\n", (int)(n)); \
|
||||
*(volatile unsigned int *)(virt + outring) = n; \
|
||||
outcount++; \
|
||||
outcount++; \
|
||||
outring += 4; \
|
||||
outring &= ringmask; \
|
||||
} while (0)
|
||||
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
dev_priv->ring.space -= outcount * 4; \
|
||||
I830_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while(0)
|
||||
#define ADVANCE_LP_RING() do { \
|
||||
if (I830_VERBOSE) \
|
||||
printk("ADVANCE_LP_RING %x\n", outring); \
|
||||
dev_priv->ring.tail = outring; \
|
||||
dev_priv->ring.space -= outcount * 4; \
|
||||
I830_WRITE(LP_RING + RING_TAIL, outring); \
|
||||
} while (0)
|
||||
|
||||
extern int i830_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
extern int i830_wait_ring(struct drm_device *dev, int n, const char *caller);
|
||||
|
||||
#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23))
|
||||
#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23))
|
||||
|
@ -53,7 +53,7 @@ irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int i830_emit_irq(struct drm_device * dev)
|
||||
static int i830_emit_irq(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
@ -70,7 +70,7 @@ static int i830_emit_irq(struct drm_device * dev)
|
||||
return atomic_read(&dev_priv->irq_emitted);
|
||||
}
|
||||
|
||||
static int i830_wait_irq(struct drm_device * dev, int irq_nr)
|
||||
static int i830_wait_irq(struct drm_device *dev, int irq_nr)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
@ -156,7 +156,7 @@ int i830_irq_wait(struct drm_device *dev, void *data,
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void i830_driver_irq_preinstall(struct drm_device * dev)
|
||||
void i830_driver_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
|
||||
@ -168,14 +168,14 @@ void i830_driver_irq_preinstall(struct drm_device * dev)
|
||||
init_waitqueue_head(&dev_priv->irq_queue);
|
||||
}
|
||||
|
||||
void i830_driver_irq_postinstall(struct drm_device * dev)
|
||||
void i830_driver_irq_postinstall(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
|
||||
I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
|
||||
}
|
||||
|
||||
void i830_driver_irq_uninstall(struct drm_device * dev)
|
||||
void i830_driver_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
|
@ -34,12 +34,15 @@
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_trace.h"
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
extern int intel_max_stolen; /* from AGP driver */
|
||||
|
||||
/**
|
||||
* Sets up the hardware status page for devices that need a physical address
|
||||
* in the register.
|
||||
@ -1256,7 +1259,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
||||
drm_mm_put_block(compressed_fb);
|
||||
}
|
||||
|
||||
if (!IS_GM45(dev)) {
|
||||
if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
|
||||
compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
|
||||
4096, 0);
|
||||
if (!compressed_llb) {
|
||||
@ -1282,8 +1285,9 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
||||
|
||||
intel_disable_fbc(dev);
|
||||
dev_priv->compressed_fb = compressed_fb;
|
||||
|
||||
if (IS_GM45(dev)) {
|
||||
if (IS_IRONLAKE_M(dev))
|
||||
I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
|
||||
else if (IS_GM45(dev)) {
|
||||
I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
|
||||
} else {
|
||||
I915_WRITE(FBC_CFB_BASE, cfb_base);
|
||||
@ -1291,7 +1295,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
||||
dev_priv->compressed_llb = compressed_llb;
|
||||
}
|
||||
|
||||
DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
|
||||
DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
|
||||
ll_base, size >> 20);
|
||||
}
|
||||
|
||||
@ -1354,7 +1358,7 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
||||
int fb_bar = IS_I9XX(dev) ? 2 : 0;
|
||||
int ret = 0;
|
||||
|
||||
dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
|
||||
dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) &
|
||||
0xff000000;
|
||||
|
||||
/* Basic memrange allocator for stolen space (aka vram) */
|
||||
@ -2063,8 +2067,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
|
||||
/* Add register map (needed for suspend/resume) */
|
||||
mmio_bar = IS_I9XX(dev) ? 0 : 1;
|
||||
base = drm_get_resource_start(dev, mmio_bar);
|
||||
size = drm_get_resource_len(dev, mmio_bar);
|
||||
base = pci_resource_start(dev->pdev, mmio_bar);
|
||||
size = pci_resource_len(dev->pdev, mmio_bar);
|
||||
|
||||
if (i915_get_bridge_dev(dev)) {
|
||||
ret = -EIO;
|
||||
@ -2104,6 +2108,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
if (ret)
|
||||
goto out_iomapfree;
|
||||
|
||||
if (prealloc_size > intel_max_stolen) {
|
||||
DRM_INFO("detected %dM stolen memory, trimming to %dM\n",
|
||||
prealloc_size >> 20, intel_max_stolen >> 20);
|
||||
prealloc_size = intel_max_stolen;
|
||||
}
|
||||
|
||||
dev_priv->wq = create_singlethread_workqueue("i915");
|
||||
if (dev_priv->wq == NULL) {
|
||||
DRM_ERROR("Failed to create our workqueue.\n");
|
||||
|
@ -93,11 +93,11 @@ static const struct intel_device_info intel_i945gm_info = {
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i965g_info = {
|
||||
.is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
|
||||
.is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_i965gm_info = {
|
||||
.is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
|
||||
.is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1,
|
||||
.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
|
||||
.has_hotplug = 1,
|
||||
};
|
||||
@ -114,7 +114,7 @@ static const struct intel_device_info intel_g45_info = {
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_gm45_info = {
|
||||
.is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
|
||||
.is_i965g = 1, .is_g4x = 1, .is_i9xx = 1,
|
||||
.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
|
||||
.has_pipe_cxsr = 1,
|
||||
.has_hotplug = 1,
|
||||
@ -134,7 +134,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
|
||||
|
||||
static const struct intel_device_info intel_ironlake_m_info = {
|
||||
.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
|
||||
.need_gfx_hws = 1, .has_rc6 = 1,
|
||||
.need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
|
||||
.has_hotplug = 1,
|
||||
};
|
||||
|
||||
@ -148,33 +148,33 @@ static const struct intel_device_info intel_sandybridge_m_info = {
|
||||
.has_hotplug = 1, .is_gen6 = 1,
|
||||
};
|
||||
|
||||
static const struct pci_device_id pciidlist[] = {
|
||||
INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
|
||||
INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
|
||||
INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
|
||||
static const struct pci_device_id pciidlist[] = { /* aka */
|
||||
INTEL_VGA_DEVICE(0x3577, &intel_i830_info), /* I830_M */
|
||||
INTEL_VGA_DEVICE(0x2562, &intel_845g_info), /* 845_G */
|
||||
INTEL_VGA_DEVICE(0x3582, &intel_i85x_info), /* I855_GM */
|
||||
INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
|
||||
INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
|
||||
INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
|
||||
INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
|
||||
INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
|
||||
INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
|
||||
INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
|
||||
INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
|
||||
INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
|
||||
INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
|
||||
INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
|
||||
INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
|
||||
INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
|
||||
INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
|
||||
INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
|
||||
INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
|
||||
INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
|
||||
INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
|
||||
INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
|
||||
INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
|
||||
INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
|
||||
INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
|
||||
INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
|
||||
INTEL_VGA_DEVICE(0x2572, &intel_i865g_info), /* I865_G */
|
||||
INTEL_VGA_DEVICE(0x2582, &intel_i915g_info), /* I915_G */
|
||||
INTEL_VGA_DEVICE(0x258a, &intel_i915g_info), /* E7221_G */
|
||||
INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info), /* I915_GM */
|
||||
INTEL_VGA_DEVICE(0x2772, &intel_i945g_info), /* I945_G */
|
||||
INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info), /* I945_GM */
|
||||
INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info), /* I945_GME */
|
||||
INTEL_VGA_DEVICE(0x2972, &intel_i965g_info), /* I946_GZ */
|
||||
INTEL_VGA_DEVICE(0x2982, &intel_i965g_info), /* G35_G */
|
||||
INTEL_VGA_DEVICE(0x2992, &intel_i965g_info), /* I965_Q */
|
||||
INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info), /* I965_G */
|
||||
INTEL_VGA_DEVICE(0x29b2, &intel_g33_info), /* Q35_G */
|
||||
INTEL_VGA_DEVICE(0x29c2, &intel_g33_info), /* G33_G */
|
||||
INTEL_VGA_DEVICE(0x29d2, &intel_g33_info), /* Q33_G */
|
||||
INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info), /* I965_GM */
|
||||
INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info), /* I965_GME */
|
||||
INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info), /* GM45_G */
|
||||
INTEL_VGA_DEVICE(0x2e02, &intel_g45_info), /* IGD_E_G */
|
||||
INTEL_VGA_DEVICE(0x2e12, &intel_g45_info), /* Q45_G */
|
||||
INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), /* G45_G */
|
||||
INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), /* G41_G */
|
||||
INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), /* B43_G */
|
||||
INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
|
||||
INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
|
||||
INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
|
||||
@ -340,7 +340,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
|
||||
/*
|
||||
* Clear request list
|
||||
*/
|
||||
i915_gem_retire_requests(dev, &dev_priv->render_ring);
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
if (need_display)
|
||||
i915_save_display(dev);
|
||||
@ -413,7 +413,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
|
||||
static int __devinit
|
||||
i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
return drm_get_dev(pdev, ent, &driver);
|
||||
return drm_get_pci_dev(pdev, ent, &driver);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -482,7 +482,7 @@ static int i915_pm_poweroff(struct device *dev)
|
||||
return i915_drm_freeze(drm_dev);
|
||||
}
|
||||
|
||||
const struct dev_pm_ops i915_pm_ops = {
|
||||
static const struct dev_pm_ops i915_pm_ops = {
|
||||
.suspend = i915_pm_suspend,
|
||||
.resume = i915_pm_resume,
|
||||
.freeze = i915_pm_freeze,
|
||||
|
@ -176,7 +176,8 @@ struct drm_i915_display_funcs {
|
||||
int (*get_display_clock_speed)(struct drm_device *dev);
|
||||
int (*get_fifo_size)(struct drm_device *dev, int plane);
|
||||
void (*update_wm)(struct drm_device *dev, int planea_clock,
|
||||
int planeb_clock, int sr_hdisplay, int pixel_size);
|
||||
int planeb_clock, int sr_hdisplay, int sr_htotal,
|
||||
int pixel_size);
|
||||
/* clock updates for mode set */
|
||||
/* cursor updates */
|
||||
/* render clock increase/decrease */
|
||||
@ -200,6 +201,8 @@ struct intel_device_info {
|
||||
u8 need_gfx_hws : 1;
|
||||
u8 is_g4x : 1;
|
||||
u8 is_pineview : 1;
|
||||
u8 is_broadwater : 1;
|
||||
u8 is_crestline : 1;
|
||||
u8 is_ironlake : 1;
|
||||
u8 is_gen6 : 1;
|
||||
u8 has_fbc : 1;
|
||||
@ -288,6 +291,8 @@ typedef struct drm_i915_private {
|
||||
struct timer_list hangcheck_timer;
|
||||
int hangcheck_count;
|
||||
uint32_t last_acthd;
|
||||
uint32_t last_instdone;
|
||||
uint32_t last_instdone1;
|
||||
|
||||
struct drm_mm vram;
|
||||
|
||||
@ -546,6 +551,14 @@ typedef struct drm_i915_private {
|
||||
/** LRU list of objects with fence regs on them. */
|
||||
struct list_head fence_list;
|
||||
|
||||
/**
|
||||
* List of objects currently pending being freed.
|
||||
*
|
||||
* These objects are no longer in use, but due to a signal
|
||||
* we were prevented from freeing them at the appointed time.
|
||||
*/
|
||||
struct list_head deferred_free_list;
|
||||
|
||||
/**
|
||||
* We leave the user IRQ off as much as possible,
|
||||
* but this means that requests will finish and never
|
||||
@ -677,7 +690,7 @@ struct drm_i915_gem_object {
|
||||
*
|
||||
* Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
|
||||
*/
|
||||
int fence_reg : 5;
|
||||
signed int fence_reg : 5;
|
||||
|
||||
/**
|
||||
* Used for checking the object doesn't appear more than once
|
||||
@ -713,7 +726,7 @@ struct drm_i915_gem_object {
|
||||
*
|
||||
* In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
|
||||
* bits with absolutely no headroom. So use 4 bits. */
|
||||
int pin_count : 4;
|
||||
unsigned int pin_count : 4;
|
||||
#define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
|
||||
|
||||
/** AGP memory structure for our GTT binding. */
|
||||
@ -743,7 +756,7 @@ struct drm_i915_gem_object {
|
||||
uint32_t stride;
|
||||
|
||||
/** Record of address bit 17 of each page at last unbind. */
|
||||
long *bit_17;
|
||||
unsigned long *bit_17;
|
||||
|
||||
/** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */
|
||||
uint32_t agp_type;
|
||||
@ -955,8 +968,7 @@ uint32_t i915_get_gem_seqno(struct drm_device *dev,
|
||||
bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
|
||||
int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
|
||||
int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
|
||||
void i915_gem_retire_requests(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring);
|
||||
void i915_gem_retire_requests(struct drm_device *dev);
|
||||
void i915_gem_retire_work_handler(struct work_struct *work);
|
||||
void i915_gem_clflush_object(struct drm_gem_object *obj);
|
||||
int i915_gem_object_set_domain(struct drm_gem_object *obj,
|
||||
@ -986,7 +998,7 @@ void i915_gem_free_all_phys_object(struct drm_device *dev);
|
||||
int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
|
||||
void i915_gem_object_put_pages(struct drm_gem_object *obj);
|
||||
void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
|
||||
void i915_gem_object_flush_write_domain(struct drm_gem_object *obj);
|
||||
int i915_gem_object_flush_write_domain(struct drm_gem_object *obj);
|
||||
|
||||
void i915_gem_shrinker_init(void);
|
||||
void i915_gem_shrinker_exit(void);
|
||||
@ -1046,6 +1058,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
|
||||
extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
|
||||
extern void i8xx_disable_fbc(struct drm_device *dev);
|
||||
extern void g4x_disable_fbc(struct drm_device *dev);
|
||||
extern void ironlake_disable_fbc(struct drm_device *dev);
|
||||
extern void intel_disable_fbc(struct drm_device *dev);
|
||||
extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
|
||||
extern bool intel_fbc_enabled(struct drm_device *dev);
|
||||
@ -1135,6 +1148,8 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
|
||||
#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm)
|
||||
#define IS_I965G(dev) (INTEL_INFO(dev)->is_i965g)
|
||||
#define IS_I965GM(dev) (INTEL_INFO(dev)->is_i965gm)
|
||||
#define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater)
|
||||
#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline)
|
||||
#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
|
||||
#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x)
|
||||
#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001)
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <linux/swap.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
|
||||
static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
|
||||
static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
|
||||
static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
|
||||
static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
|
||||
@ -53,6 +53,7 @@ static int i915_gem_evict_from_inactive_list(struct drm_device *dev);
|
||||
static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
||||
struct drm_i915_gem_pwrite *args,
|
||||
struct drm_file *file_priv);
|
||||
static void i915_gem_free_object_tail(struct drm_gem_object *obj);
|
||||
|
||||
static LIST_HEAD(shrink_list);
|
||||
static DEFINE_SPINLOCK(shrink_list_lock);
|
||||
@ -127,8 +128,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_gem_handle_create(file_priv, obj, &handle);
|
||||
drm_gem_object_handle_unreference_unlocked(obj);
|
||||
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -496,10 +496,10 @@ fast_user_write(struct io_mapping *mapping,
|
||||
char *vaddr_atomic;
|
||||
unsigned long unwritten;
|
||||
|
||||
vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
|
||||
vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base, KM_USER0);
|
||||
unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
|
||||
user_data, length);
|
||||
io_mapping_unmap_atomic(vaddr_atomic);
|
||||
io_mapping_unmap_atomic(vaddr_atomic, KM_USER0);
|
||||
if (unwritten)
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
@ -1709,9 +1709,9 @@ i915_get_gem_seqno(struct drm_device *dev,
|
||||
/**
|
||||
* This function clears the request list as sequence numbers are passed.
|
||||
*/
|
||||
void
|
||||
i915_gem_retire_requests(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
static void
|
||||
i915_gem_retire_requests_ring(struct drm_device *dev,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t seqno;
|
||||
@ -1750,6 +1750,30 @@ i915_gem_retire_requests(struct drm_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
i915_gem_retire_requests(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (!list_empty(&dev_priv->mm.deferred_free_list)) {
|
||||
struct drm_i915_gem_object *obj_priv, *tmp;
|
||||
|
||||
/* We must be careful that during unbind() we do not
|
||||
* accidentally infinitely recurse into retire requests.
|
||||
* Currently:
|
||||
* retire -> free -> unbind -> wait -> retire_ring
|
||||
*/
|
||||
list_for_each_entry_safe(obj_priv, tmp,
|
||||
&dev_priv->mm.deferred_free_list,
|
||||
list)
|
||||
i915_gem_free_object_tail(&obj_priv->base);
|
||||
}
|
||||
|
||||
i915_gem_retire_requests_ring(dev, &dev_priv->render_ring);
|
||||
if (HAS_BSD(dev))
|
||||
i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring);
|
||||
}
|
||||
|
||||
void
|
||||
i915_gem_retire_work_handler(struct work_struct *work)
|
||||
{
|
||||
@ -1761,10 +1785,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
|
||||
dev = dev_priv->dev;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_retire_requests(dev, &dev_priv->render_ring);
|
||||
|
||||
if (HAS_BSD(dev))
|
||||
i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
if (!dev_priv->mm.suspended &&
|
||||
(!list_empty(&dev_priv->render_ring.request_list) ||
|
||||
@ -1832,7 +1853,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
|
||||
* a separate wait queue to handle that.
|
||||
*/
|
||||
if (ret == 0)
|
||||
i915_gem_retire_requests(dev, ring);
|
||||
i915_gem_retire_requests_ring(dev, ring);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1945,11 +1966,12 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
|
||||
* before we unbind.
|
||||
*/
|
||||
ret = i915_gem_object_set_to_cpu_domain(obj, 1);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS)
|
||||
DRM_ERROR("set_domain failed: %d\n", ret);
|
||||
if (ret == -ERESTARTSYS)
|
||||
return ret;
|
||||
}
|
||||
/* Continue on if we fail due to EIO, the GPU is hung so we
|
||||
* should be safe and we need to cleanup or else we might
|
||||
* cause memory corruption through use-after-free.
|
||||
*/
|
||||
|
||||
BUG_ON(obj_priv->active);
|
||||
|
||||
@ -1985,7 +2007,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
|
||||
|
||||
trace_i915_gem_object_unbind(obj);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_gem_object *
|
||||
@ -2107,10 +2129,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
|
||||
struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
|
||||
struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
|
||||
for (;;) {
|
||||
i915_gem_retire_requests(dev, render_ring);
|
||||
|
||||
if (HAS_BSD(dev))
|
||||
i915_gem_retire_requests(dev, bsd_ring);
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
/* If there's an inactive buffer available now, grab it
|
||||
* and be done.
|
||||
@ -2583,7 +2602,10 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
|
||||
if (!IS_I965G(dev)) {
|
||||
int ret;
|
||||
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = i915_gem_object_wait_rendering(obj);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@ -2634,10 +2656,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
|
||||
if (free_space != NULL) {
|
||||
obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
|
||||
alignment);
|
||||
if (obj_priv->gtt_space != NULL) {
|
||||
obj_priv->gtt_space->private = obj;
|
||||
if (obj_priv->gtt_space != NULL)
|
||||
obj_priv->gtt_offset = obj_priv->gtt_space->start;
|
||||
}
|
||||
}
|
||||
if (obj_priv->gtt_space == NULL) {
|
||||
/* If the gtt is empty and we're still having trouble
|
||||
@ -2733,7 +2753,7 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
|
||||
}
|
||||
|
||||
/** Flushes any GPU write domain for the object if it's dirty. */
|
||||
static void
|
||||
static int
|
||||
i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
@ -2741,17 +2761,18 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
||||
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
||||
|
||||
if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* Queue the GPU write cache flushing we need. */
|
||||
old_write_domain = obj->write_domain;
|
||||
i915_gem_flush(dev, 0, obj->write_domain);
|
||||
(void) i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring);
|
||||
BUG_ON(obj->write_domain);
|
||||
if (i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring) == 0)
|
||||
return -ENOMEM;
|
||||
|
||||
trace_i915_gem_object_change_domain(obj,
|
||||
obj->read_domains,
|
||||
old_write_domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Flushes the GTT write domain for the object if it's dirty. */
|
||||
@ -2795,9 +2816,11 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
|
||||
old_write_domain);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (obj->write_domain) {
|
||||
case I915_GEM_DOMAIN_GTT:
|
||||
i915_gem_object_flush_gtt_write_domain(obj);
|
||||
@ -2806,9 +2829,11 @@ i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
|
||||
i915_gem_object_flush_cpu_write_domain(obj);
|
||||
break;
|
||||
default:
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2828,7 +2853,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
|
||||
if (obj_priv->gtt_space == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* Wait on any GPU rendering and flushing to occur. */
|
||||
ret = i915_gem_object_wait_rendering(obj);
|
||||
if (ret != 0)
|
||||
@ -2878,7 +2906,9 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
|
||||
if (obj_priv->gtt_space == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Wait on any GPU rendering and flushing to occur. */
|
||||
if (obj_priv->active) {
|
||||
@ -2926,7 +2956,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
|
||||
uint32_t old_write_domain, old_read_domains;
|
||||
int ret;
|
||||
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Wait on any GPU rendering and flushing to occur. */
|
||||
ret = i915_gem_object_wait_rendering(obj);
|
||||
if (ret != 0)
|
||||
@ -3216,7 +3249,10 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
|
||||
if (offset == 0 && size == obj->size)
|
||||
return i915_gem_object_set_to_cpu_domain(obj, 0);
|
||||
|
||||
i915_gem_object_flush_gpu_write_domain(obj);
|
||||
ret = i915_gem_object_flush_gpu_write_domain(obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Wait on any GPU rendering and flushing to occur. */
|
||||
ret = i915_gem_object_wait_rendering(obj);
|
||||
if (ret != 0)
|
||||
@ -3451,7 +3487,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
||||
reloc_offset = obj_priv->gtt_offset + reloc->offset;
|
||||
reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
|
||||
(reloc_offset &
|
||||
~(PAGE_SIZE - 1)));
|
||||
~(PAGE_SIZE - 1)),
|
||||
KM_USER0);
|
||||
reloc_entry = (uint32_t __iomem *)(reloc_page +
|
||||
(reloc_offset & (PAGE_SIZE - 1)));
|
||||
reloc_val = target_obj_priv->gtt_offset + reloc->delta;
|
||||
@ -3462,7 +3499,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
||||
readl(reloc_entry), reloc_val);
|
||||
#endif
|
||||
writel(reloc_val, reloc_entry);
|
||||
io_mapping_unmap_atomic(reloc_page);
|
||||
io_mapping_unmap_atomic(reloc_page, KM_USER0);
|
||||
|
||||
/* The updated presumed offset for this entry will be
|
||||
* copied back out to the user.
|
||||
@ -4313,7 +4350,6 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_i915_gem_busy *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_i915_gem_object *obj_priv;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
||||
if (obj == NULL) {
|
||||
@ -4328,10 +4364,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
|
||||
* actually unmasked, and our working set ends up being larger than
|
||||
* required.
|
||||
*/
|
||||
i915_gem_retire_requests(dev, &dev_priv->render_ring);
|
||||
|
||||
if (HAS_BSD(dev))
|
||||
i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
obj_priv = to_intel_bo(obj);
|
||||
/* Don't count being on the flushing list against the object being
|
||||
@ -4441,6 +4474,30 @@ int i915_gem_init_object(struct drm_gem_object *obj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i915_gem_free_object_tail(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
||||
int ret;
|
||||
|
||||
ret = i915_gem_object_unbind(obj);
|
||||
if (ret == -ERESTARTSYS) {
|
||||
list_move(&obj_priv->list,
|
||||
&dev_priv->mm.deferred_free_list);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj_priv->mmap_offset)
|
||||
i915_gem_free_mmap_offset(obj);
|
||||
|
||||
drm_gem_object_release(obj);
|
||||
|
||||
kfree(obj_priv->page_cpu_valid);
|
||||
kfree(obj_priv->bit_17);
|
||||
kfree(obj_priv);
|
||||
}
|
||||
|
||||
void i915_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
@ -4454,16 +4511,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
|
||||
if (obj_priv->phys_obj)
|
||||
i915_gem_detach_phys_object(dev, obj);
|
||||
|
||||
i915_gem_object_unbind(obj);
|
||||
|
||||
if (obj_priv->mmap_offset)
|
||||
i915_gem_free_mmap_offset(obj);
|
||||
|
||||
drm_gem_object_release(obj);
|
||||
|
||||
kfree(obj_priv->page_cpu_valid);
|
||||
kfree(obj_priv->bit_17);
|
||||
kfree(obj_priv);
|
||||
i915_gem_free_object_tail(obj);
|
||||
}
|
||||
|
||||
/** Unbinds all inactive objects. */
|
||||
@ -4689,9 +4737,19 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
|
||||
BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
drm_irq_install(dev);
|
||||
ret = drm_irq_install(dev);
|
||||
if (ret)
|
||||
goto cleanup_ringbuffer;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_ringbuffer:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_cleanup_ringbuffer(dev);
|
||||
dev_priv->mm.suspended = 1;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
@ -4729,6 +4787,7 @@ i915_gem_load(struct drm_device *dev)
|
||||
INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
|
||||
INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
|
||||
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
|
||||
INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list);
|
||||
INIT_LIST_HEAD(&dev_priv->render_ring.active_list);
|
||||
INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
|
||||
if (HAS_BSD(dev)) {
|
||||
@ -5027,10 +5086,7 @@ rescan:
|
||||
continue;
|
||||
|
||||
spin_unlock(&shrink_list_lock);
|
||||
i915_gem_retire_requests(dev, &dev_priv->render_ring);
|
||||
|
||||
if (HAS_BSD(dev))
|
||||
i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
|
||||
i915_gem_retire_requests(dev);
|
||||
|
||||
list_for_each_entry_safe(obj_priv, next_obj,
|
||||
&dev_priv->mm.inactive_list,
|
||||
|
@ -333,8 +333,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
||||
i915_gem_release_mmap(obj);
|
||||
|
||||
if (ret != 0) {
|
||||
WARN(ret != -ERESTARTSYS,
|
||||
"failed to reset object for tiling switch");
|
||||
args->tiling_mode = obj_priv->tiling_mode;
|
||||
args->stride = obj_priv->stride;
|
||||
goto err;
|
||||
|
@ -171,10 +171,10 @@ void intel_enable_asle (struct drm_device *dev)
|
||||
ironlake_enable_display_irq(dev_priv, DE_GSE);
|
||||
else {
|
||||
i915_enable_pipestat(dev_priv, 1,
|
||||
I915_LEGACY_BLC_EVENT_ENABLE);
|
||||
PIPE_LEGACY_BLC_EVENT_ENABLE);
|
||||
if (IS_I965G(dev))
|
||||
i915_enable_pipestat(dev_priv, 0,
|
||||
I915_LEGACY_BLC_EVENT_ENABLE);
|
||||
PIPE_LEGACY_BLC_EVENT_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -842,7 +842,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
u32 iir, new_iir;
|
||||
u32 pipea_stats, pipeb_stats;
|
||||
u32 vblank_status;
|
||||
u32 vblank_enable;
|
||||
int vblank = 0;
|
||||
unsigned long irqflags;
|
||||
int irq_received;
|
||||
@ -856,13 +855,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
|
||||
iir = I915_READ(IIR);
|
||||
|
||||
if (IS_I965G(dev)) {
|
||||
vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
|
||||
vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
|
||||
} else {
|
||||
vblank_status = I915_VBLANK_INTERRUPT_STATUS;
|
||||
vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
|
||||
}
|
||||
if (IS_I965G(dev))
|
||||
vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
|
||||
else
|
||||
vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
|
||||
|
||||
for (;;) {
|
||||
irq_received = iir != 0;
|
||||
@ -966,8 +962,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
intel_finish_page_flip(dev, 1);
|
||||
}
|
||||
|
||||
if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
|
||||
(pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
|
||||
if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
|
||||
(pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
|
||||
(iir & I915_ASLE_INTERRUPT))
|
||||
opregion_asle_intr(dev);
|
||||
|
||||
@ -1233,16 +1229,21 @@ void i915_hangcheck_elapsed(unsigned long data)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *)data;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t acthd;
|
||||
uint32_t acthd, instdone, instdone1;
|
||||
|
||||
/* No reset support on this chip yet. */
|
||||
if (IS_GEN6(dev))
|
||||
return;
|
||||
|
||||
if (!IS_I965G(dev))
|
||||
if (!IS_I965G(dev)) {
|
||||
acthd = I915_READ(ACTHD);
|
||||
else
|
||||
instdone = I915_READ(INSTDONE);
|
||||
instdone1 = 0;
|
||||
} else {
|
||||
acthd = I915_READ(ACTHD_I965);
|
||||
instdone = I915_READ(INSTDONE_I965);
|
||||
instdone1 = I915_READ(INSTDONE1);
|
||||
}
|
||||
|
||||
/* If all work is done then ACTHD clearly hasn't advanced. */
|
||||
if (list_empty(&dev_priv->render_ring.request_list) ||
|
||||
@ -1253,21 +1254,24 @@ void i915_hangcheck_elapsed(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) {
|
||||
DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
|
||||
i915_handle_error(dev, true);
|
||||
return;
|
||||
}
|
||||
if (dev_priv->last_acthd == acthd &&
|
||||
dev_priv->last_instdone == instdone &&
|
||||
dev_priv->last_instdone1 == instdone1) {
|
||||
if (dev_priv->hangcheck_count++ > 1) {
|
||||
DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
|
||||
i915_handle_error(dev, true);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
dev_priv->hangcheck_count = 0;
|
||||
|
||||
dev_priv->last_acthd = acthd;
|
||||
dev_priv->last_instdone = instdone;
|
||||
dev_priv->last_instdone1 = instdone1;
|
||||
}
|
||||
|
||||
/* Reset timer case chip hangs without another request being added */
|
||||
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
|
||||
|
||||
if (acthd != dev_priv->last_acthd)
|
||||
dev_priv->hangcheck_count = 0;
|
||||
else
|
||||
dev_priv->hangcheck_count++;
|
||||
|
||||
dev_priv->last_acthd = acthd;
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
|
@ -442,7 +442,7 @@
|
||||
#define GEN6_RENDER_IMR 0x20a8
|
||||
#define GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT (1 << 8)
|
||||
#define GEN6_RENDER_PPGTT_PAGE_FAULT (1 << 7)
|
||||
#define GEN6_RENDER TIMEOUT_COUNTER_EXPIRED (1 << 6)
|
||||
#define GEN6_RENDER_TIMEOUT_COUNTER_EXPIRED (1 << 6)
|
||||
#define GEN6_RENDER_L3_PARITY_ERROR (1 << 5)
|
||||
#define GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT (1 << 4)
|
||||
#define GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR (1 << 3)
|
||||
@ -530,6 +530,21 @@
|
||||
#define DPFC_CHICKEN 0x3224
|
||||
#define DPFC_HT_MODIFY (1<<31)
|
||||
|
||||
/* Framebuffer compression for Ironlake */
|
||||
#define ILK_DPFC_CB_BASE 0x43200
|
||||
#define ILK_DPFC_CONTROL 0x43208
|
||||
/* The bit 28-8 is reserved */
|
||||
#define DPFC_RESERVED (0x1FFFFF00)
|
||||
#define ILK_DPFC_RECOMP_CTL 0x4320c
|
||||
#define ILK_DPFC_STATUS 0x43210
|
||||
#define ILK_DPFC_FENCE_YOFF 0x43218
|
||||
#define ILK_DPFC_CHICKEN 0x43224
|
||||
#define ILK_FBC_RT_BASE 0x2128
|
||||
#define ILK_FBC_RT_VALID (1<<0)
|
||||
|
||||
#define ILK_DISPLAY_CHICKEN1 0x42000
|
||||
#define ILK_FBCQ_DIS (1<<22)
|
||||
|
||||
/*
|
||||
* GPIO regs
|
||||
*/
|
||||
@ -595,32 +610,6 @@
|
||||
#define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
|
||||
#define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */
|
||||
|
||||
#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
|
||||
#define I915_CRC_ERROR_ENABLE (1UL<<29)
|
||||
#define I915_CRC_DONE_ENABLE (1UL<<28)
|
||||
#define I915_GMBUS_EVENT_ENABLE (1UL<<27)
|
||||
#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25)
|
||||
#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
|
||||
#define I915_DPST_EVENT_ENABLE (1UL<<23)
|
||||
#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
|
||||
#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
|
||||
#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
|
||||
#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
|
||||
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
|
||||
#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16)
|
||||
#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
|
||||
#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
|
||||
#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11)
|
||||
#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9)
|
||||
#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
|
||||
#define I915_DPST_EVENT_STATUS (1UL<<7)
|
||||
#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6)
|
||||
#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
|
||||
#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
|
||||
#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
|
||||
#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1)
|
||||
#define I915_OVERLAY_UPDATED_STATUS (1UL<<0)
|
||||
|
||||
#define SRX_INDEX 0x3c4
|
||||
#define SRX_DATA 0x3c5
|
||||
#define SR01 1
|
||||
@ -2166,7 +2155,8 @@
|
||||
#define I830_FIFO_LINE_SIZE 32
|
||||
|
||||
#define G4X_FIFO_SIZE 127
|
||||
#define I945_FIFO_SIZE 127 /* 945 & 965 */
|
||||
#define I965_FIFO_SIZE 512
|
||||
#define I945_FIFO_SIZE 127
|
||||
#define I915_FIFO_SIZE 95
|
||||
#define I855GM_FIFO_SIZE 127 /* In cachelines */
|
||||
#define I830_FIFO_SIZE 95
|
||||
@ -2185,6 +2175,9 @@
|
||||
#define PINEVIEW_CURSOR_DFT_WM 0
|
||||
#define PINEVIEW_CURSOR_GUARD_WM 5
|
||||
|
||||
#define I965_CURSOR_FIFO 64
|
||||
#define I965_CURSOR_MAX_WM 32
|
||||
#define I965_CURSOR_DFT_WM 8
|
||||
|
||||
/* define the Watermark register on Ironlake */
|
||||
#define WM0_PIPEA_ILK 0x45100
|
||||
@ -2212,6 +2205,9 @@
|
||||
#define ILK_DISPLAY_FIFO 128
|
||||
#define ILK_DISPLAY_MAXWM 64
|
||||
#define ILK_DISPLAY_DFTWM 8
|
||||
#define ILK_CURSOR_FIFO 32
|
||||
#define ILK_CURSOR_MAXWM 16
|
||||
#define ILK_CURSOR_DFTWM 8
|
||||
|
||||
#define ILK_DISPLAY_SR_FIFO 512
|
||||
#define ILK_DISPLAY_MAX_SRWM 0x1ff
|
||||
@ -2510,6 +2506,10 @@
|
||||
#define ILK_VSDPFD_FULL (1<<21)
|
||||
#define ILK_DSPCLK_GATE 0x42020
|
||||
#define ILK_DPARB_CLK_GATE (1<<5)
|
||||
/* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
|
||||
#define ILK_CLK_FBC (1<<7)
|
||||
#define ILK_DPFC_DIS1 (1<<8)
|
||||
#define ILK_DPFC_DIS2 (1<<9)
|
||||
|
||||
#define DISP_ARB_CTL 0x45000
|
||||
#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
|
||||
|
@ -602,7 +602,9 @@ void i915_save_display(struct drm_device *dev)
|
||||
|
||||
/* Only save FBC state on the platform that supports FBC */
|
||||
if (I915_HAS_FBC(dev)) {
|
||||
if (IS_GM45(dev)) {
|
||||
if (IS_IRONLAKE_M(dev)) {
|
||||
dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
|
||||
} else if (IS_GM45(dev)) {
|
||||
dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
|
||||
} else {
|
||||
dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
|
||||
@ -706,7 +708,10 @@ void i915_restore_display(struct drm_device *dev)
|
||||
|
||||
/* only restore FBC info on the platform that supports FBC*/
|
||||
if (I915_HAS_FBC(dev)) {
|
||||
if (IS_GM45(dev)) {
|
||||
if (IS_IRONLAKE_M(dev)) {
|
||||
ironlake_disable_fbc(dev);
|
||||
I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
|
||||
} else if (IS_GM45(dev)) {
|
||||
g4x_disable_fbc(dev);
|
||||
I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
|
||||
} else {
|
||||
|
@ -262,6 +262,42 @@ DEFINE_EVENT(i915_ring, i915_ring_wait_end,
|
||||
TP_ARGS(dev)
|
||||
);
|
||||
|
||||
TRACE_EVENT(i915_flip_request,
|
||||
TP_PROTO(int plane, struct drm_gem_object *obj),
|
||||
|
||||
TP_ARGS(plane, obj),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, plane)
|
||||
__field(struct drm_gem_object *, obj)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->plane = plane;
|
||||
__entry->obj = obj;
|
||||
),
|
||||
|
||||
TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
|
||||
);
|
||||
|
||||
TRACE_EVENT(i915_flip_complete,
|
||||
TP_PROTO(int plane, struct drm_gem_object *obj),
|
||||
|
||||
TP_ARGS(plane, obj),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(int, plane)
|
||||
__field(struct drm_gem_object *, obj)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->plane = plane;
|
||||
__entry->obj = obj;
|
||||
),
|
||||
|
||||
TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
|
||||
);
|
||||
|
||||
#endif /* _I915_TRACE_H_ */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,6 +43,7 @@
|
||||
#define DP_LINK_CONFIGURATION_SIZE 9
|
||||
|
||||
#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
|
||||
#define IS_PCH_eDP(dp_priv) ((dp_priv)->is_pch_edp)
|
||||
|
||||
struct intel_dp_priv {
|
||||
uint32_t output_reg;
|
||||
@ -56,6 +57,7 @@ struct intel_dp_priv {
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct i2c_adapter adapter;
|
||||
struct i2c_algo_dp_aux_data algo;
|
||||
bool is_pch_edp;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -128,8 +130,9 @@ intel_dp_link_required(struct drm_device *dev,
|
||||
struct intel_encoder *intel_encoder, int pixel_clock)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
if (IS_eDP(intel_encoder))
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
|
||||
return (pixel_clock * dev_priv->edp_bpp) / 8;
|
||||
else
|
||||
return pixel_clock * 3;
|
||||
@ -147,9 +150,21 @@ intel_dp_mode_valid(struct drm_connector *connector,
|
||||
{
|
||||
struct drm_encoder *encoder = intel_attached_encoder(connector);
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
|
||||
int max_lanes = intel_dp_max_lane_count(intel_encoder);
|
||||
|
||||
if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
|
||||
dev_priv->panel_fixed_mode) {
|
||||
if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
|
||||
if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
}
|
||||
|
||||
/* only refuse the mode on non eDP since we have seen some wierd eDP panels
|
||||
which are outside spec tolerances but somehow work by magic */
|
||||
if (!IS_eDP(intel_encoder) &&
|
||||
@ -508,11 +523,37 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
{
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int lane_count, clock;
|
||||
int max_lane_count = intel_dp_max_lane_count(intel_encoder);
|
||||
int max_clock = intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
|
||||
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
|
||||
|
||||
if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
|
||||
dev_priv->panel_fixed_mode) {
|
||||
struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
|
||||
|
||||
adjusted_mode->hdisplay = fixed_mode->hdisplay;
|
||||
adjusted_mode->hsync_start = fixed_mode->hsync_start;
|
||||
adjusted_mode->hsync_end = fixed_mode->hsync_end;
|
||||
adjusted_mode->htotal = fixed_mode->htotal;
|
||||
|
||||
adjusted_mode->vdisplay = fixed_mode->vdisplay;
|
||||
adjusted_mode->vsync_start = fixed_mode->vsync_start;
|
||||
adjusted_mode->vsync_end = fixed_mode->vsync_end;
|
||||
adjusted_mode->vtotal = fixed_mode->vtotal;
|
||||
|
||||
adjusted_mode->clock = fixed_mode->clock;
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
/*
|
||||
* the mode->clock is used to calculate the Data&Link M/N
|
||||
* of the pipe. For the eDP the fixed clock should be used.
|
||||
*/
|
||||
mode->clock = dev_priv->panel_fixed_mode->clock;
|
||||
}
|
||||
|
||||
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
|
||||
for (clock = 0; clock <= max_clock; clock++) {
|
||||
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
|
||||
@ -531,7 +572,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
/* okay we failed just pick the highest */
|
||||
dp_priv->lane_count = max_lane_count;
|
||||
dp_priv->link_bw = bws[max_clock];
|
||||
@ -563,14 +604,14 @@ intel_reduce_ratio(uint32_t *num, uint32_t *den)
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_compute_m_n(int bytes_per_pixel,
|
||||
intel_dp_compute_m_n(int bpp,
|
||||
int nlanes,
|
||||
int pixel_clock,
|
||||
int link_clock,
|
||||
struct intel_dp_m_n *m_n)
|
||||
{
|
||||
m_n->tu = 64;
|
||||
m_n->gmch_m = pixel_clock * bytes_per_pixel;
|
||||
m_n->gmch_m = (pixel_clock * bpp) >> 3;
|
||||
m_n->gmch_n = link_clock * nlanes;
|
||||
intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
|
||||
m_n->link_m = pixel_clock;
|
||||
@ -578,6 +619,28 @@ intel_dp_compute_m_n(int bytes_per_pixel,
|
||||
intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
|
||||
}
|
||||
|
||||
bool intel_pch_has_edp(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_dp_priv *dp_priv;
|
||||
|
||||
if (!encoder || encoder->crtc != crtc)
|
||||
continue;
|
||||
|
||||
intel_encoder = enc_to_intel_encoder(encoder);
|
||||
dp_priv = intel_encoder->dev_priv;
|
||||
|
||||
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT)
|
||||
return dp_priv->is_pch_edp;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
@ -587,7 +650,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int lane_count = 4;
|
||||
int lane_count = 4, bpp = 24;
|
||||
struct intel_dp_m_n m_n;
|
||||
|
||||
/*
|
||||
@ -605,6 +668,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
|
||||
if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
||||
lane_count = dp_priv->lane_count;
|
||||
if (IS_PCH_eDP(dp_priv))
|
||||
bpp = dev_priv->edp_bpp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -614,7 +679,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
* the number of bytes_per_pixel post-LUT, which we always
|
||||
* set up for 8-bits of R/G/B, or 3 bytes total.
|
||||
*/
|
||||
intel_dp_compute_m_n(3, lane_count,
|
||||
intel_dp_compute_m_n(bpp, lane_count,
|
||||
mode->clock, adjusted_mode->clock, &m_n);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
@ -796,7 +861,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
||||
if (mode != DRM_MODE_DPMS_ON) {
|
||||
if (dp_reg & DP_PORT_EN) {
|
||||
intel_dp_link_down(intel_encoder, dp_priv->DP);
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
ironlake_edp_backlight_off(dev);
|
||||
ironlake_edp_panel_off(dev);
|
||||
}
|
||||
@ -804,7 +869,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
||||
} else {
|
||||
if (!(dp_reg & DP_PORT_EN)) {
|
||||
intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
ironlake_edp_panel_on(dev);
|
||||
ironlake_edp_backlight_on(dev);
|
||||
}
|
||||
@ -1340,17 +1405,32 @@ static int intel_dp_get_modes(struct drm_connector *connector)
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct drm_device *dev = intel_encoder->enc.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
||||
int ret;
|
||||
|
||||
/* We should parse the EDID data and find out if it has an audio sink
|
||||
*/
|
||||
|
||||
ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
|
||||
!dev_priv->panel_fixed_mode) {
|
||||
struct drm_display_mode *newmode;
|
||||
list_for_each_entry(newmode, &connector->probed_modes,
|
||||
head) {
|
||||
if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
drm_mode_duplicate(dev, newmode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* if eDP has no EDID, try to use fixed panel mode from VBT */
|
||||
if (IS_eDP(intel_encoder)) {
|
||||
if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode;
|
||||
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
@ -1435,6 +1515,26 @@ intel_trans_dp_port_sel (struct drm_crtc *crtc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check the VBT to see whether the eDP is on DP-D port */
|
||||
bool intel_dpd_is_edp(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct child_device_config *p_child;
|
||||
int i;
|
||||
|
||||
if (!dev_priv->child_dev_num)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < dev_priv->child_dev_num; i++) {
|
||||
p_child = dev_priv->child_dev + i;
|
||||
|
||||
if (p_child->dvo_port == PORT_IDPD &&
|
||||
p_child->device_type == DEVICE_TYPE_eDP)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
{
|
||||
@ -1444,6 +1544,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_dp_priv *dp_priv;
|
||||
const char *name = NULL;
|
||||
int type;
|
||||
|
||||
intel_encoder = kcalloc(sizeof(struct intel_encoder) +
|
||||
sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
|
||||
@ -1458,18 +1559,24 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
|
||||
dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D))
|
||||
if (intel_dpd_is_edp(dev))
|
||||
dp_priv->is_pch_edp = true;
|
||||
|
||||
if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
|
||||
type = DRM_MODE_CONNECTOR_eDP;
|
||||
intel_encoder->type = INTEL_OUTPUT_EDP;
|
||||
} else {
|
||||
type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
|
||||
}
|
||||
|
||||
connector = &intel_connector->base;
|
||||
drm_connector_init(dev, connector, &intel_dp_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort);
|
||||
drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
|
||||
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
if (output_reg == DP_A)
|
||||
intel_encoder->type = INTEL_OUTPUT_EDP;
|
||||
else
|
||||
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
|
||||
|
||||
if (output_reg == DP_B || output_reg == PCH_DP_B)
|
||||
intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
|
||||
else if (output_reg == DP_C || output_reg == PCH_DP_C)
|
||||
@ -1528,7 +1635,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
||||
intel_encoder->ddc_bus = &dp_priv->adapter;
|
||||
intel_encoder->hot_plug = intel_dp_hot_plug;
|
||||
|
||||
if (output_reg == DP_A) {
|
||||
if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
|
||||
/* initialize panel mode from VBT if available for eDP */
|
||||
if (dev_priv->lfp_lvds_vbt_mode) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
|
@ -143,8 +143,6 @@ struct intel_crtc {
|
||||
struct drm_crtc base;
|
||||
enum pipe pipe;
|
||||
enum plane plane;
|
||||
struct drm_gem_object *cursor_bo;
|
||||
uint32_t cursor_addr;
|
||||
u8 lut_r[256], lut_g[256], lut_b[256];
|
||||
int dpms_mode;
|
||||
bool busy; /* is scanout buffer being updated frequently? */
|
||||
@ -153,6 +151,12 @@ struct intel_crtc {
|
||||
struct intel_overlay *overlay;
|
||||
struct intel_unpin_work *unpin_work;
|
||||
int fdi_lanes;
|
||||
|
||||
struct drm_gem_object *cursor_bo;
|
||||
uint32_t cursor_addr;
|
||||
int16_t cursor_x, cursor_y;
|
||||
int16_t cursor_width, cursor_height;
|
||||
bool cursor_visble;
|
||||
};
|
||||
|
||||
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
|
||||
@ -179,6 +183,8 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg);
|
||||
void
|
||||
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
extern bool intel_pch_has_edp(struct drm_crtc *crtc);
|
||||
extern bool intel_dpd_is_edp(struct drm_device *dev);
|
||||
extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
|
||||
|
||||
|
||||
|
@ -54,10 +54,11 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
|
||||
struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
|
||||
u32 sdvox;
|
||||
|
||||
sdvox = SDVO_ENCODING_HDMI |
|
||||
SDVO_BORDER_ENABLE |
|
||||
SDVO_VSYNC_ACTIVE_HIGH |
|
||||
SDVO_HSYNC_ACTIVE_HIGH;
|
||||
sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (hdmi_priv->has_hdmi_sink) {
|
||||
sdvox |= SDVO_AUDIO_ENABLE;
|
||||
|
@ -156,31 +156,73 @@ static int intel_lvds_mode_valid(struct drm_connector *connector,
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
centre_horizontally(struct drm_display_mode *mode,
|
||||
int width)
|
||||
{
|
||||
u32 border, sync_pos, blank_width, sync_width;
|
||||
|
||||
/* keep the hsync and hblank widths constant */
|
||||
sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
|
||||
blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
|
||||
sync_pos = (blank_width - sync_width + 1) / 2;
|
||||
|
||||
border = (mode->hdisplay - width + 1) / 2;
|
||||
border += border & 1; /* make the border even */
|
||||
|
||||
mode->crtc_hdisplay = width;
|
||||
mode->crtc_hblank_start = width + border;
|
||||
mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
|
||||
|
||||
mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
|
||||
mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
|
||||
}
|
||||
|
||||
static void
|
||||
centre_vertically(struct drm_display_mode *mode,
|
||||
int height)
|
||||
{
|
||||
u32 border, sync_pos, blank_width, sync_width;
|
||||
|
||||
/* keep the vsync and vblank widths constant */
|
||||
sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
|
||||
blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
|
||||
sync_pos = (blank_width - sync_width + 1) / 2;
|
||||
|
||||
border = (mode->vdisplay - height + 1) / 2;
|
||||
|
||||
mode->crtc_vdisplay = height;
|
||||
mode->crtc_vblank_start = height + border;
|
||||
mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
|
||||
|
||||
mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
|
||||
mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
|
||||
}
|
||||
|
||||
static inline u32 panel_fitter_scaling(u32 source, u32 target)
|
||||
{
|
||||
/*
|
||||
* Floating point operation is not supported. So the FACTOR
|
||||
* is defined, which can avoid the floating point computation
|
||||
* when calculating the panel ratio.
|
||||
*/
|
||||
#define ACCURACY 12
|
||||
#define FACTOR (1 << ACCURACY)
|
||||
u32 ratio = source * FACTOR / target;
|
||||
return (FACTOR * ratio + FACTOR/2) / FACTOR;
|
||||
}
|
||||
|
||||
static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/*
|
||||
* float point operation is not supported . So the PANEL_RATIO_FACTOR
|
||||
* is defined, which can avoid the float point computation when
|
||||
* calculating the panel ratio.
|
||||
*/
|
||||
#define PANEL_RATIO_FACTOR 8192
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||
struct drm_encoder *tmp_encoder;
|
||||
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
||||
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
|
||||
u32 pfit_control = 0, pfit_pgm_ratios = 0;
|
||||
int left_border = 0, right_border = 0, top_border = 0;
|
||||
int bottom_border = 0;
|
||||
bool border = 0;
|
||||
int panel_ratio, desired_ratio, vert_scale, horiz_scale;
|
||||
int horiz_ratio, vert_ratio;
|
||||
u32 hsync_width, vsync_width;
|
||||
u32 hblank_width, vblank_width;
|
||||
u32 hsync_pos, vsync_pos;
|
||||
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
|
||||
|
||||
/* Should never happen!! */
|
||||
if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
|
||||
@ -200,27 +242,25 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
if (dev_priv->panel_fixed_mode == NULL)
|
||||
return true;
|
||||
/*
|
||||
* If we have timings from the BIOS for the panel, put them in
|
||||
* We have timings from the BIOS for the panel, put them in
|
||||
* to the adjusted mode. The CRTC will be set up for this mode,
|
||||
* with the panel scaling set up to source from the H/VDisplay
|
||||
* of the original mode.
|
||||
*/
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
|
||||
adjusted_mode->hsync_start =
|
||||
dev_priv->panel_fixed_mode->hsync_start;
|
||||
adjusted_mode->hsync_end =
|
||||
dev_priv->panel_fixed_mode->hsync_end;
|
||||
adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
|
||||
adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
|
||||
adjusted_mode->vsync_start =
|
||||
dev_priv->panel_fixed_mode->vsync_start;
|
||||
adjusted_mode->vsync_end =
|
||||
dev_priv->panel_fixed_mode->vsync_end;
|
||||
adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
|
||||
adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
}
|
||||
adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
|
||||
adjusted_mode->hsync_start =
|
||||
dev_priv->panel_fixed_mode->hsync_start;
|
||||
adjusted_mode->hsync_end =
|
||||
dev_priv->panel_fixed_mode->hsync_end;
|
||||
adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
|
||||
adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
|
||||
adjusted_mode->vsync_start =
|
||||
dev_priv->panel_fixed_mode->vsync_start;
|
||||
adjusted_mode->vsync_end =
|
||||
dev_priv->panel_fixed_mode->vsync_end;
|
||||
adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
|
||||
adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
/* Make sure pre-965s set dither correctly */
|
||||
if (!IS_I965G(dev)) {
|
||||
@ -230,11 +270,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
|
||||
/* Native modes don't need fitting */
|
||||
if (adjusted_mode->hdisplay == mode->hdisplay &&
|
||||
adjusted_mode->vdisplay == mode->vdisplay) {
|
||||
pfit_pgm_ratios = 0;
|
||||
border = 0;
|
||||
adjusted_mode->vdisplay == mode->vdisplay)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* full screen scale for now */
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
@ -242,25 +279,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
|
||||
/* 965+ wants fuzzy fitting */
|
||||
if (IS_I965G(dev))
|
||||
pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
|
||||
PFIT_FILTER_FUZZY;
|
||||
pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
|
||||
PFIT_FILTER_FUZZY);
|
||||
|
||||
hsync_width = adjusted_mode->crtc_hsync_end -
|
||||
adjusted_mode->crtc_hsync_start;
|
||||
vsync_width = adjusted_mode->crtc_vsync_end -
|
||||
adjusted_mode->crtc_vsync_start;
|
||||
hblank_width = adjusted_mode->crtc_hblank_end -
|
||||
adjusted_mode->crtc_hblank_start;
|
||||
vblank_width = adjusted_mode->crtc_vblank_end -
|
||||
adjusted_mode->crtc_vblank_start;
|
||||
/*
|
||||
* Deal with panel fitting options. Figure out how to stretch the
|
||||
* image based on its aspect ratio & the current panel fitting mode.
|
||||
*/
|
||||
panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR /
|
||||
adjusted_mode->vdisplay;
|
||||
desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR /
|
||||
mode->vdisplay;
|
||||
/*
|
||||
* Enable automatic panel scaling for non-native modes so that they fill
|
||||
* the screen. Should be enabled before the pipe is enabled, according
|
||||
@ -278,170 +299,63 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
* For centered modes, we have to calculate border widths &
|
||||
* heights and modify the values programmed into the CRTC.
|
||||
*/
|
||||
left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2;
|
||||
right_border = left_border;
|
||||
if (mode->hdisplay & 1)
|
||||
right_border++;
|
||||
top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2;
|
||||
bottom_border = top_border;
|
||||
if (mode->vdisplay & 1)
|
||||
bottom_border++;
|
||||
/* Set active & border values */
|
||||
adjusted_mode->crtc_hdisplay = mode->hdisplay;
|
||||
/* Keep the boder be even */
|
||||
if (right_border & 1)
|
||||
right_border++;
|
||||
/* use the border directly instead of border minuse one */
|
||||
adjusted_mode->crtc_hblank_start = mode->hdisplay +
|
||||
right_border;
|
||||
/* keep the blank width constant */
|
||||
adjusted_mode->crtc_hblank_end =
|
||||
adjusted_mode->crtc_hblank_start + hblank_width;
|
||||
/* get the hsync pos relative to hblank start */
|
||||
hsync_pos = (hblank_width - hsync_width) / 2;
|
||||
/* keep the hsync pos be even */
|
||||
if (hsync_pos & 1)
|
||||
hsync_pos++;
|
||||
adjusted_mode->crtc_hsync_start =
|
||||
adjusted_mode->crtc_hblank_start + hsync_pos;
|
||||
/* keep the hsync width constant */
|
||||
adjusted_mode->crtc_hsync_end =
|
||||
adjusted_mode->crtc_hsync_start + hsync_width;
|
||||
adjusted_mode->crtc_vdisplay = mode->vdisplay;
|
||||
/* use the border instead of border minus one */
|
||||
adjusted_mode->crtc_vblank_start = mode->vdisplay +
|
||||
bottom_border;
|
||||
/* keep the vblank width constant */
|
||||
adjusted_mode->crtc_vblank_end =
|
||||
adjusted_mode->crtc_vblank_start + vblank_width;
|
||||
/* get the vsync start postion relative to vblank start */
|
||||
vsync_pos = (vblank_width - vsync_width) / 2;
|
||||
adjusted_mode->crtc_vsync_start =
|
||||
adjusted_mode->crtc_vblank_start + vsync_pos;
|
||||
/* keep the vsync width constant */
|
||||
adjusted_mode->crtc_vsync_end =
|
||||
adjusted_mode->crtc_vsync_start + vsync_width;
|
||||
border = 1;
|
||||
centre_horizontally(adjusted_mode, mode->hdisplay);
|
||||
centre_vertically(adjusted_mode, mode->vdisplay);
|
||||
border = LVDS_BORDER_ENABLE;
|
||||
break;
|
||||
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
/* Scale but preserve the spect ratio */
|
||||
pfit_control |= PFIT_ENABLE;
|
||||
/* Scale but preserve the aspect ratio */
|
||||
if (IS_I965G(dev)) {
|
||||
u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
|
||||
u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
|
||||
|
||||
pfit_control |= PFIT_ENABLE;
|
||||
/* 965+ is easy, it does everything in hw */
|
||||
if (panel_ratio > desired_ratio)
|
||||
if (scaled_width > scaled_height)
|
||||
pfit_control |= PFIT_SCALING_PILLAR;
|
||||
else if (panel_ratio < desired_ratio)
|
||||
else if (scaled_width < scaled_height)
|
||||
pfit_control |= PFIT_SCALING_LETTER;
|
||||
else
|
||||
pfit_control |= PFIT_SCALING_AUTO;
|
||||
} else {
|
||||
u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
|
||||
u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
|
||||
/*
|
||||
* For earlier chips we have to calculate the scaling
|
||||
* ratio by hand and program it into the
|
||||
* PFIT_PGM_RATIO register
|
||||
*/
|
||||
u32 horiz_bits, vert_bits, bits = 12;
|
||||
horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/
|
||||
adjusted_mode->hdisplay;
|
||||
vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/
|
||||
adjusted_mode->vdisplay;
|
||||
horiz_scale = adjusted_mode->hdisplay *
|
||||
PANEL_RATIO_FACTOR / mode->hdisplay;
|
||||
vert_scale = adjusted_mode->vdisplay *
|
||||
PANEL_RATIO_FACTOR / mode->vdisplay;
|
||||
if (scaled_width > scaled_height) { /* pillar */
|
||||
centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay);
|
||||
|
||||
/* retain aspect ratio */
|
||||
if (panel_ratio > desired_ratio) { /* Pillar */
|
||||
u32 scaled_width;
|
||||
scaled_width = mode->hdisplay * vert_scale /
|
||||
PANEL_RATIO_FACTOR;
|
||||
horiz_ratio = vert_ratio;
|
||||
pfit_control |= (VERT_AUTO_SCALE |
|
||||
border = LVDS_BORDER_ENABLE;
|
||||
if (mode->vdisplay != adjusted_mode->vdisplay) {
|
||||
u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
|
||||
pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
|
||||
bits << PFIT_VERT_SCALE_SHIFT);
|
||||
pfit_control |= (PFIT_ENABLE |
|
||||
VERT_INTERP_BILINEAR |
|
||||
HORIZ_INTERP_BILINEAR);
|
||||
}
|
||||
} else if (scaled_width < scaled_height) { /* letter */
|
||||
centre_vertically(adjusted_mode, scaled_width / mode->hdisplay);
|
||||
|
||||
border = LVDS_BORDER_ENABLE;
|
||||
if (mode->hdisplay != adjusted_mode->hdisplay) {
|
||||
u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
|
||||
pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
|
||||
bits << PFIT_VERT_SCALE_SHIFT);
|
||||
pfit_control |= (PFIT_ENABLE |
|
||||
VERT_INTERP_BILINEAR |
|
||||
HORIZ_INTERP_BILINEAR);
|
||||
}
|
||||
} else
|
||||
/* Aspects match, Let hw scale both directions */
|
||||
pfit_control |= (PFIT_ENABLE |
|
||||
VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
|
||||
VERT_INTERP_BILINEAR |
|
||||
HORIZ_INTERP_BILINEAR);
|
||||
/* Pillar will have left/right borders */
|
||||
left_border = (adjusted_mode->hdisplay -
|
||||
scaled_width) / 2;
|
||||
right_border = left_border;
|
||||
if (mode->hdisplay & 1) /* odd resolutions */
|
||||
right_border++;
|
||||
/* keep the border be even */
|
||||
if (right_border & 1)
|
||||
right_border++;
|
||||
adjusted_mode->crtc_hdisplay = scaled_width;
|
||||
/* use border instead of border minus one */
|
||||
adjusted_mode->crtc_hblank_start =
|
||||
scaled_width + right_border;
|
||||
/* keep the hblank width constant */
|
||||
adjusted_mode->crtc_hblank_end =
|
||||
adjusted_mode->crtc_hblank_start +
|
||||
hblank_width;
|
||||
/*
|
||||
* get the hsync start pos relative to
|
||||
* hblank start
|
||||
*/
|
||||
hsync_pos = (hblank_width - hsync_width) / 2;
|
||||
/* keep the hsync_pos be even */
|
||||
if (hsync_pos & 1)
|
||||
hsync_pos++;
|
||||
adjusted_mode->crtc_hsync_start =
|
||||
adjusted_mode->crtc_hblank_start +
|
||||
hsync_pos;
|
||||
/* keept hsync width constant */
|
||||
adjusted_mode->crtc_hsync_end =
|
||||
adjusted_mode->crtc_hsync_start +
|
||||
hsync_width;
|
||||
border = 1;
|
||||
} else if (panel_ratio < desired_ratio) { /* letter */
|
||||
u32 scaled_height = mode->vdisplay *
|
||||
horiz_scale / PANEL_RATIO_FACTOR;
|
||||
vert_ratio = horiz_ratio;
|
||||
pfit_control |= (HORIZ_AUTO_SCALE |
|
||||
VERT_INTERP_BILINEAR |
|
||||
HORIZ_INTERP_BILINEAR);
|
||||
/* Letterbox will have top/bottom border */
|
||||
top_border = (adjusted_mode->vdisplay -
|
||||
scaled_height) / 2;
|
||||
bottom_border = top_border;
|
||||
if (mode->vdisplay & 1)
|
||||
bottom_border++;
|
||||
adjusted_mode->crtc_vdisplay = scaled_height;
|
||||
/* use border instead of border minus one */
|
||||
adjusted_mode->crtc_vblank_start =
|
||||
scaled_height + bottom_border;
|
||||
/* keep the vblank width constant */
|
||||
adjusted_mode->crtc_vblank_end =
|
||||
adjusted_mode->crtc_vblank_start +
|
||||
vblank_width;
|
||||
/*
|
||||
* get the vsync start pos relative to
|
||||
* vblank start
|
||||
*/
|
||||
vsync_pos = (vblank_width - vsync_width) / 2;
|
||||
adjusted_mode->crtc_vsync_start =
|
||||
adjusted_mode->crtc_vblank_start +
|
||||
vsync_pos;
|
||||
/* keep the vsync width constant */
|
||||
adjusted_mode->crtc_vsync_end =
|
||||
adjusted_mode->crtc_vsync_start +
|
||||
vsync_width;
|
||||
border = 1;
|
||||
} else {
|
||||
/* Aspects match, Let hw scale both directions */
|
||||
pfit_control |= (VERT_AUTO_SCALE |
|
||||
HORIZ_AUTO_SCALE |
|
||||
VERT_INTERP_BILINEAR |
|
||||
HORIZ_INTERP_BILINEAR);
|
||||
}
|
||||
horiz_bits = (1 << bits) * horiz_ratio /
|
||||
PANEL_RATIO_FACTOR;
|
||||
vert_bits = (1 << bits) * vert_ratio /
|
||||
PANEL_RATIO_FACTOR;
|
||||
pfit_pgm_ratios =
|
||||
((vert_bits << PFIT_VERT_SCALE_SHIFT) &
|
||||
PFIT_VERT_SCALE_MASK) |
|
||||
((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) &
|
||||
PFIT_HORIZ_SCALE_MASK);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -458,6 +372,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
VERT_INTERP_BILINEAR |
|
||||
HORIZ_INTERP_BILINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -465,14 +380,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
out:
|
||||
lvds_priv->pfit_control = pfit_control;
|
||||
lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
|
||||
/*
|
||||
* When there exists the border, it means that the LVDS_BORDR
|
||||
* should be enabled.
|
||||
*/
|
||||
if (border)
|
||||
dev_priv->lvds_border_bits |= LVDS_BORDER_ENABLE;
|
||||
else
|
||||
dev_priv->lvds_border_bits &= ~(LVDS_BORDER_ENABLE);
|
||||
dev_priv->lvds_border_bits = border;
|
||||
|
||||
/*
|
||||
* XXX: It would be nice to support lower refresh rates on the
|
||||
* panels to reduce power consumption, and perhaps match the
|
||||
|
@ -65,7 +65,7 @@
|
||||
#define OCMD_YUV_410_PLANAR (0xe<<10) /* also 411 */
|
||||
#define OCMD_TVSYNCFLIP_PARITY (0x1<<9)
|
||||
#define OCMD_TVSYNCFLIP_ENABLE (0x1<<7)
|
||||
#define OCMD_BUF_TYPE_MASK (Ox1<<5)
|
||||
#define OCMD_BUF_TYPE_MASK (0x1<<5)
|
||||
#define OCMD_BUF_TYPE_FRAME (0x0<<5)
|
||||
#define OCMD_BUF_TYPE_FIELD (0x1<<5)
|
||||
#define OCMD_TEST_MODE (0x1<<4)
|
||||
@ -185,7 +185,8 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
|
||||
|
||||
if (OVERLAY_NONPHYSICAL(overlay->dev)) {
|
||||
regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
|
||||
overlay->reg_bo->gtt_offset);
|
||||
overlay->reg_bo->gtt_offset,
|
||||
KM_USER0);
|
||||
|
||||
if (!regs) {
|
||||
DRM_ERROR("failed to map overlay regs in GTT\n");
|
||||
@ -200,7 +201,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
|
||||
static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
|
||||
{
|
||||
if (OVERLAY_NONPHYSICAL(overlay->dev))
|
||||
io_mapping_unmap_atomic(overlay->virt_addr);
|
||||
io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0);
|
||||
|
||||
overlay->virt_addr = NULL;
|
||||
|
||||
@ -958,7 +959,7 @@ static int check_overlay_src(struct drm_device *dev,
|
||||
|| rec->src_width < N_HORIZ_Y_TAPS*4)
|
||||
return -EINVAL;
|
||||
|
||||
/* check alingment constrains */
|
||||
/* check alignment constraints */
|
||||
switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
|
||||
case I915_OVERLAY_RGB:
|
||||
/* not implemented */
|
||||
@ -990,7 +991,10 @@ static int check_overlay_src(struct drm_device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
/* stride checking */
|
||||
stride_mask = 63;
|
||||
if (IS_I830(dev) || IS_845G(dev))
|
||||
stride_mask = 255;
|
||||
else
|
||||
stride_mask = 63;
|
||||
|
||||
if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
|
||||
return -EINVAL;
|
||||
|
@ -1237,9 +1237,11 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
||||
|
||||
/* Set the SDVO control regs. */
|
||||
if (IS_I965G(dev)) {
|
||||
sdvox |= SDVO_BORDER_ENABLE |
|
||||
SDVO_VSYNC_ACTIVE_HIGH |
|
||||
SDVO_HSYNC_ACTIVE_HIGH;
|
||||
sdvox |= SDVO_BORDER_ENABLE;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
|
||||
} else {
|
||||
sdvox |= I915_READ(sdvo_priv->sdvo_reg);
|
||||
switch (sdvo_priv->sdvo_reg) {
|
||||
|
@ -476,7 +476,7 @@ static const struct tv_mode tv_modes[] = {
|
||||
.vi_end_f1 = 20, .vi_end_f2 = 21,
|
||||
.nbr_end = 240,
|
||||
|
||||
.burst_ena = 8,
|
||||
.burst_ena = true,
|
||||
.hburst_start = 72, .hburst_len = 34,
|
||||
.vburst_start_f1 = 9, .vburst_end_f1 = 240,
|
||||
.vburst_start_f2 = 10, .vburst_end_f2 = 240,
|
||||
@ -896,8 +896,6 @@ static const struct tv_mode tv_modes[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#define NUM_TV_MODES sizeof(tv_modes) / sizeof (tv_modes[0])
|
||||
|
||||
static void
|
||||
intel_tv_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
@ -1512,7 +1510,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
|
||||
tv_priv->margin[TV_MARGIN_BOTTOM] = val;
|
||||
changed = true;
|
||||
} else if (property == dev->mode_config.tv_mode_property) {
|
||||
if (val >= NUM_TV_MODES) {
|
||||
if (val >= ARRAY_SIZE(tv_modes)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1693,13 +1691,13 @@ intel_tv_init(struct drm_device *dev)
|
||||
connector->doublescan_allowed = false;
|
||||
|
||||
/* Create TV properties then attach current values */
|
||||
tv_format_names = kmalloc(sizeof(char *) * NUM_TV_MODES,
|
||||
tv_format_names = kmalloc(sizeof(char *) * ARRAY_SIZE(tv_modes),
|
||||
GFP_KERNEL);
|
||||
if (!tv_format_names)
|
||||
goto out;
|
||||
for (i = 0; i < NUM_TV_MODES; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
|
||||
tv_format_names[i] = tv_modes[i].name;
|
||||
drm_mode_create_tv_properties(dev, NUM_TV_MODES, tv_format_names);
|
||||
drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names);
|
||||
|
||||
drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
|
||||
initial_mode);
|
||||
|
@ -52,7 +52,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
|
||||
* Engine control
|
||||
*/
|
||||
|
||||
int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
|
||||
int mga_do_wait_for_idle(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
u32 status = 0;
|
||||
int i;
|
||||
@ -74,7 +74,7 @@ int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
|
||||
static int mga_do_dma_reset(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
|
||||
@ -102,7 +102,7 @@ static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
|
||||
* Primary DMA stream
|
||||
*/
|
||||
|
||||
void mga_do_dma_flush(drm_mga_private_t * dev_priv)
|
||||
void mga_do_dma_flush(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
|
||||
u32 head, tail;
|
||||
@ -142,11 +142,10 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv)
|
||||
|
||||
head = MGA_READ(MGA_PRIMADDRESS);
|
||||
|
||||
if (head <= tail) {
|
||||
if (head <= tail)
|
||||
primary->space = primary->size - primary->tail;
|
||||
} else {
|
||||
else
|
||||
primary->space = head - tail;
|
||||
}
|
||||
|
||||
DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
|
||||
DRM_DEBUG(" tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset));
|
||||
@ -158,7 +157,7 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv)
|
||||
DRM_DEBUG("done.\n");
|
||||
}
|
||||
|
||||
void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
|
||||
void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
|
||||
u32 head, tail;
|
||||
@ -181,11 +180,10 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
|
||||
|
||||
head = MGA_READ(MGA_PRIMADDRESS);
|
||||
|
||||
if (head == dev_priv->primary->offset) {
|
||||
if (head == dev_priv->primary->offset)
|
||||
primary->space = primary->size;
|
||||
} else {
|
||||
else
|
||||
primary->space = head - dev_priv->primary->offset;
|
||||
}
|
||||
|
||||
DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
|
||||
DRM_DEBUG(" tail = 0x%06x\n", primary->tail);
|
||||
@ -199,7 +197,7 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
|
||||
DRM_DEBUG("done.\n");
|
||||
}
|
||||
|
||||
void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
|
||||
void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -220,11 +218,11 @@ void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
|
||||
* Freelist management
|
||||
*/
|
||||
|
||||
#define MGA_BUFFER_USED ~0
|
||||
#define MGA_BUFFER_USED (~0)
|
||||
#define MGA_BUFFER_FREE 0
|
||||
|
||||
#if MGA_FREELIST_DEBUG
|
||||
static void mga_freelist_print(struct drm_device * dev)
|
||||
static void mga_freelist_print(struct drm_device *dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_freelist_t *entry;
|
||||
@ -245,7 +243,7 @@ static void mga_freelist_print(struct drm_device * dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
|
||||
static int mga_freelist_init(struct drm_device *dev, drm_mga_private_t *dev_priv)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf;
|
||||
@ -288,7 +286,7 @@ static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_pr
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mga_freelist_cleanup(struct drm_device * dev)
|
||||
static void mga_freelist_cleanup(struct drm_device *dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_freelist_t *entry;
|
||||
@ -308,7 +306,7 @@ static void mga_freelist_cleanup(struct drm_device * dev)
|
||||
#if 0
|
||||
/* FIXME: Still needed?
|
||||
*/
|
||||
static void mga_freelist_reset(struct drm_device * dev)
|
||||
static void mga_freelist_reset(struct drm_device *dev)
|
||||
{
|
||||
struct drm_device_dma *dma = dev->dma;
|
||||
struct drm_buf *buf;
|
||||
@ -356,7 +354,7 @@ static struct drm_buf *mga_freelist_get(struct drm_device * dev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
|
||||
int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
|
||||
@ -391,7 +389,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
|
||||
* DMA initialization, cleanup
|
||||
*/
|
||||
|
||||
int mga_driver_load(struct drm_device * dev, unsigned long flags)
|
||||
int mga_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
{
|
||||
drm_mga_private_t *dev_priv;
|
||||
int ret;
|
||||
@ -405,8 +403,8 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
|
||||
dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
|
||||
dev_priv->chipset = flags;
|
||||
|
||||
dev_priv->mmio_base = drm_get_resource_start(dev, 1);
|
||||
dev_priv->mmio_size = drm_get_resource_len(dev, 1);
|
||||
dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
|
||||
dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
|
||||
|
||||
dev->counters += 3;
|
||||
dev->types[6] = _DRM_STAT_IRQ;
|
||||
@ -439,8 +437,8 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
|
||||
*
|
||||
* \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
|
||||
*/
|
||||
static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
|
||||
drm_mga_dma_bootstrap_t * dma_bs)
|
||||
static int mga_do_agp_dma_bootstrap(struct drm_device *dev,
|
||||
drm_mga_dma_bootstrap_t *dma_bs)
|
||||
{
|
||||
drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
@ -481,11 +479,10 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
|
||||
*/
|
||||
|
||||
if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
|
||||
if (mode.mode & 0x02) {
|
||||
if (mode.mode & 0x02)
|
||||
MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
|
||||
} else {
|
||||
else
|
||||
MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate and bind AGP memory. */
|
||||
@ -593,8 +590,8 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
|
||||
drm_mga_dma_bootstrap_t * dma_bs)
|
||||
static int mga_do_agp_dma_bootstrap(struct drm_device *dev,
|
||||
drm_mga_dma_bootstrap_t *dma_bs)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -614,8 +611,8 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
|
||||
*
|
||||
* \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
|
||||
*/
|
||||
static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
|
||||
drm_mga_dma_bootstrap_t * dma_bs)
|
||||
static int mga_do_pci_dma_bootstrap(struct drm_device *dev,
|
||||
drm_mga_dma_bootstrap_t *dma_bs)
|
||||
{
|
||||
drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
@ -678,9 +675,8 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
|
||||
req.size = dma_bs->secondary_bin_size;
|
||||
|
||||
err = drm_addbufs_pci(dev, &req);
|
||||
if (!err) {
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bin_count == 0) {
|
||||
@ -704,8 +700,8 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_do_dma_bootstrap(struct drm_device * dev,
|
||||
drm_mga_dma_bootstrap_t * dma_bs)
|
||||
static int mga_do_dma_bootstrap(struct drm_device *dev,
|
||||
drm_mga_dma_bootstrap_t *dma_bs)
|
||||
{
|
||||
const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
|
||||
int err;
|
||||
@ -737,17 +733,15 @@ static int mga_do_dma_bootstrap(struct drm_device * dev,
|
||||
* carve off portions of it for internal uses. The remaining memory
|
||||
* is returned to user-mode to be used for AGP textures.
|
||||
*/
|
||||
if (is_agp) {
|
||||
if (is_agp)
|
||||
err = mga_do_agp_dma_bootstrap(dev, dma_bs);
|
||||
}
|
||||
|
||||
/* If we attempted to initialize the card for AGP DMA but failed,
|
||||
* clean-up any mess that may have been created.
|
||||
*/
|
||||
|
||||
if (err) {
|
||||
if (err)
|
||||
mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
|
||||
}
|
||||
|
||||
/* Not only do we want to try and initialized PCI cards for PCI DMA,
|
||||
* but we also try to initialized AGP cards that could not be
|
||||
@ -757,9 +751,8 @@ static int mga_do_dma_bootstrap(struct drm_device * dev,
|
||||
* AGP memory, etc.
|
||||
*/
|
||||
|
||||
if (!is_agp || err) {
|
||||
if (!is_agp || err)
|
||||
err = mga_do_pci_dma_bootstrap(dev, dma_bs);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -792,7 +785,7 @@ int mga_dma_bootstrap(struct drm_device *dev, void *data,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
|
||||
static int mga_do_init_dma(struct drm_device *dev, drm_mga_init_t *init)
|
||||
{
|
||||
drm_mga_private_t *dev_priv;
|
||||
int ret;
|
||||
@ -800,11 +793,10 @@ static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
|
||||
|
||||
dev_priv = dev->dev_private;
|
||||
|
||||
if (init->sgram) {
|
||||
if (init->sgram)
|
||||
dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
|
||||
} else {
|
||||
else
|
||||
dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
|
||||
}
|
||||
dev_priv->maccess = init->maccess;
|
||||
|
||||
dev_priv->fb_cpp = init->fb_cpp;
|
||||
@ -975,9 +967,8 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
|
||||
dev_priv->agp_handle = 0;
|
||||
}
|
||||
|
||||
if ((dev->agp != NULL) && dev->agp->acquired) {
|
||||
if ((dev->agp != NULL) && dev->agp->acquired)
|
||||
err = drm_agp_release(dev);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -998,9 +989,8 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
|
||||
memset(dev_priv->warp_pipe_phys, 0,
|
||||
sizeof(dev_priv->warp_pipe_phys));
|
||||
|
||||
if (dev_priv->head != NULL) {
|
||||
if (dev_priv->head != NULL)
|
||||
mga_freelist_cleanup(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
@ -1017,9 +1007,8 @@ int mga_dma_init(struct drm_device *dev, void *data,
|
||||
switch (init->func) {
|
||||
case MGA_INIT_DMA:
|
||||
err = mga_do_init_dma(dev, init);
|
||||
if (err) {
|
||||
if (err)
|
||||
(void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
|
||||
}
|
||||
return err;
|
||||
case MGA_CLEANUP_DMA:
|
||||
return mga_do_cleanup_dma(dev, FULL_CLEANUP);
|
||||
@ -1047,9 +1036,8 @@ int mga_dma_flush(struct drm_device *dev, void *data,
|
||||
|
||||
WRAP_WAIT_WITH_RETURN(dev_priv);
|
||||
|
||||
if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
|
||||
if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL))
|
||||
mga_do_dma_flush(dev_priv);
|
||||
}
|
||||
|
||||
if (lock->flags & _DRM_LOCK_QUIESCENT) {
|
||||
#if MGA_DMA_DEBUG
|
||||
@ -1079,8 +1067,8 @@ int mga_dma_reset(struct drm_device *dev, void *data,
|
||||
* DMA buffer management
|
||||
*/
|
||||
|
||||
static int mga_dma_get_buffers(struct drm_device * dev,
|
||||
struct drm_file *file_priv, struct drm_dma * d)
|
||||
static int mga_dma_get_buffers(struct drm_device *dev,
|
||||
struct drm_file *file_priv, struct drm_dma *d)
|
||||
{
|
||||
struct drm_buf *buf;
|
||||
int i;
|
||||
@ -1134,9 +1122,8 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
|
||||
|
||||
d->granted_count = 0;
|
||||
|
||||
if (d->request_count) {
|
||||
if (d->request_count)
|
||||
ret = mga_dma_get_buffers(dev, file_priv, d);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1144,7 +1131,7 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
|
||||
/**
|
||||
* Called just before the module is unloaded.
|
||||
*/
|
||||
int mga_driver_unload(struct drm_device * dev)
|
||||
int mga_driver_unload(struct drm_device *dev)
|
||||
{
|
||||
kfree(dev->dev_private);
|
||||
dev->dev_private = NULL;
|
||||
@ -1155,12 +1142,12 @@ int mga_driver_unload(struct drm_device * dev)
|
||||
/**
|
||||
* Called when the last opener of the device is closed.
|
||||
*/
|
||||
void mga_driver_lastclose(struct drm_device * dev)
|
||||
void mga_driver_lastclose(struct drm_device *dev)
|
||||
{
|
||||
mga_do_cleanup_dma(dev, FULL_CLEANUP);
|
||||
}
|
||||
|
||||
int mga_driver_dma_quiescent(struct drm_device * dev)
|
||||
int mga_driver_dma_quiescent(struct drm_device *dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
return mga_do_wait_for_idle(dev_priv);
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#include "drm_pciids.h"
|
||||
|
||||
static int mga_driver_device_is_agp(struct drm_device * dev);
|
||||
static int mga_driver_device_is_agp(struct drm_device *dev);
|
||||
|
||||
static struct pci_device_id pciidlist[] = {
|
||||
mga_PCI_IDS
|
||||
@ -119,7 +119,7 @@ MODULE_LICENSE("GPL and additional rights");
|
||||
* \returns
|
||||
* If the device is a PCI G450, zero is returned. Otherwise 2 is returned.
|
||||
*/
|
||||
static int mga_driver_device_is_agp(struct drm_device * dev)
|
||||
static int mga_driver_device_is_agp(struct drm_device *dev)
|
||||
{
|
||||
const struct pci_dev *const pdev = dev->pdev;
|
||||
|
||||
|
@ -164,59 +164,59 @@ extern int mga_dma_reset(struct drm_device *dev, void *data,
|
||||
extern int mga_dma_buffers(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
|
||||
extern int mga_driver_unload(struct drm_device * dev);
|
||||
extern void mga_driver_lastclose(struct drm_device * dev);
|
||||
extern int mga_driver_dma_quiescent(struct drm_device * dev);
|
||||
extern int mga_driver_unload(struct drm_device *dev);
|
||||
extern void mga_driver_lastclose(struct drm_device *dev);
|
||||
extern int mga_driver_dma_quiescent(struct drm_device *dev);
|
||||
|
||||
extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
|
||||
extern int mga_do_wait_for_idle(drm_mga_private_t *dev_priv);
|
||||
|
||||
extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
|
||||
extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
|
||||
extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
|
||||
extern void mga_do_dma_flush(drm_mga_private_t *dev_priv);
|
||||
extern void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv);
|
||||
extern void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv);
|
||||
|
||||
extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
|
||||
extern int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf);
|
||||
|
||||
/* mga_warp.c */
|
||||
extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_init(drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_install_microcode(drm_mga_private_t *dev_priv);
|
||||
extern int mga_warp_init(drm_mga_private_t *dev_priv);
|
||||
|
||||
/* mga_irq.c */
|
||||
extern int mga_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void mga_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
|
||||
extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
|
||||
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void mga_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern void mga_driver_irq_preinstall(struct drm_device *dev);
|
||||
extern int mga_driver_irq_postinstall(struct drm_device *dev);
|
||||
extern void mga_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern void mga_driver_irq_uninstall(struct drm_device *dev);
|
||||
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER()
|
||||
|
||||
#if defined(__linux__) && defined(__alpha__)
|
||||
#define MGA_BASE( reg ) ((unsigned long)(dev_priv->mmio->handle))
|
||||
#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg)
|
||||
#define MGA_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
|
||||
#define MGA_ADDR(reg) (MGA_BASE(reg) + reg)
|
||||
|
||||
#define MGA_DEREF( reg ) *(volatile u32 *)MGA_ADDR( reg )
|
||||
#define MGA_DEREF8( reg ) *(volatile u8 *)MGA_ADDR( reg )
|
||||
#define MGA_DEREF(reg) (*(volatile u32 *)MGA_ADDR(reg))
|
||||
#define MGA_DEREF8(reg) (*(volatile u8 *)MGA_ADDR(reg))
|
||||
|
||||
#define MGA_READ( reg ) (_MGA_READ((u32 *)MGA_ADDR(reg)))
|
||||
#define MGA_READ8( reg ) (_MGA_READ((u8 *)MGA_ADDR(reg)))
|
||||
#define MGA_WRITE( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
|
||||
#define MGA_WRITE8( reg, val ) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
|
||||
#define MGA_READ(reg) (_MGA_READ((u32 *)MGA_ADDR(reg)))
|
||||
#define MGA_READ8(reg) (_MGA_READ((u8 *)MGA_ADDR(reg)))
|
||||
#define MGA_WRITE(reg, val) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF(reg) = val; } while (0)
|
||||
#define MGA_WRITE8(reg, val) do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8(reg) = val; } while (0)
|
||||
|
||||
static inline u32 _MGA_READ(u32 * addr)
|
||||
static inline u32 _MGA_READ(u32 *addr)
|
||||
{
|
||||
DRM_MEMORYBARRIER();
|
||||
return *(volatile u32 *)addr;
|
||||
}
|
||||
#else
|
||||
#define MGA_READ8( reg ) DRM_READ8(dev_priv->mmio, (reg))
|
||||
#define MGA_READ( reg ) DRM_READ32(dev_priv->mmio, (reg))
|
||||
#define MGA_WRITE8( reg, val ) DRM_WRITE8(dev_priv->mmio, (reg), (val))
|
||||
#define MGA_WRITE( reg, val ) DRM_WRITE32(dev_priv->mmio, (reg), (val))
|
||||
#define MGA_READ8(reg) DRM_READ8(dev_priv->mmio, (reg))
|
||||
#define MGA_READ(reg) DRM_READ32(dev_priv->mmio, (reg))
|
||||
#define MGA_WRITE8(reg, val) DRM_WRITE8(dev_priv->mmio, (reg), (val))
|
||||
#define MGA_WRITE(reg, val) DRM_WRITE32(dev_priv->mmio, (reg), (val))
|
||||
#endif
|
||||
|
||||
#define DWGREG0 0x1c00
|
||||
@ -233,40 +233,39 @@ static inline u32 _MGA_READ(u32 * addr)
|
||||
* Helper macross...
|
||||
*/
|
||||
|
||||
#define MGA_EMIT_STATE( dev_priv, dirty ) \
|
||||
#define MGA_EMIT_STATE(dev_priv, dirty) \
|
||||
do { \
|
||||
if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) { \
|
||||
if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) { \
|
||||
mga_g400_emit_state( dev_priv ); \
|
||||
} else { \
|
||||
mga_g200_emit_state( dev_priv ); \
|
||||
if ((dirty) & ~MGA_UPLOAD_CLIPRECTS) { \
|
||||
if (dev_priv->chipset >= MGA_CARD_TYPE_G400) \
|
||||
mga_g400_emit_state(dev_priv); \
|
||||
else \
|
||||
mga_g200_emit_state(dev_priv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRAP_TEST_WITH_RETURN(dev_priv) \
|
||||
do { \
|
||||
if (test_bit(0, &dev_priv->prim.wrapped)) { \
|
||||
if (mga_is_idle(dev_priv)) { \
|
||||
mga_do_dma_wrap_end(dev_priv); \
|
||||
} else if (dev_priv->prim.space < \
|
||||
dev_priv->prim.high_mark) { \
|
||||
if (MGA_DMA_DEBUG) \
|
||||
DRM_INFO("wrap...\n"); \
|
||||
return -EBUSY; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRAP_TEST_WITH_RETURN( dev_priv ) \
|
||||
#define WRAP_WAIT_WITH_RETURN(dev_priv) \
|
||||
do { \
|
||||
if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( mga_is_idle( dev_priv ) ) { \
|
||||
mga_do_dma_wrap_end( dev_priv ); \
|
||||
} else if ( dev_priv->prim.space < \
|
||||
dev_priv->prim.high_mark ) { \
|
||||
if ( MGA_DMA_DEBUG ) \
|
||||
DRM_INFO( "wrap...\n"); \
|
||||
return -EBUSY; \
|
||||
if (test_bit(0, &dev_priv->prim.wrapped)) { \
|
||||
if (mga_do_wait_for_idle(dev_priv) < 0) { \
|
||||
if (MGA_DMA_DEBUG) \
|
||||
DRM_INFO("wrap...\n"); \
|
||||
return -EBUSY; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRAP_WAIT_WITH_RETURN( dev_priv ) \
|
||||
do { \
|
||||
if ( test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \
|
||||
if ( MGA_DMA_DEBUG ) \
|
||||
DRM_INFO( "wrap...\n"); \
|
||||
return -EBUSY; \
|
||||
} \
|
||||
mga_do_dma_wrap_end( dev_priv ); \
|
||||
mga_do_dma_wrap_end(dev_priv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -280,12 +279,12 @@ do { \
|
||||
|
||||
#define DMA_BLOCK_SIZE (5 * sizeof(u32))
|
||||
|
||||
#define BEGIN_DMA( n ) \
|
||||
#define BEGIN_DMA(n) \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_DMA( %d )\n", (n) ); \
|
||||
DRM_INFO( " space=0x%x req=0x%Zx\n", \
|
||||
dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
|
||||
if (MGA_VERBOSE) { \
|
||||
DRM_INFO("BEGIN_DMA(%d)\n", (n)); \
|
||||
DRM_INFO(" space=0x%x req=0x%Zx\n", \
|
||||
dev_priv->prim.space, (n) * DMA_BLOCK_SIZE); \
|
||||
} \
|
||||
prim = dev_priv->prim.start; \
|
||||
write = dev_priv->prim.tail; \
|
||||
@ -293,9 +292,9 @@ do { \
|
||||
|
||||
#define BEGIN_DMA_WRAP() \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "BEGIN_DMA()\n" ); \
|
||||
DRM_INFO( " space=0x%x\n", dev_priv->prim.space ); \
|
||||
if (MGA_VERBOSE) { \
|
||||
DRM_INFO("BEGIN_DMA()\n"); \
|
||||
DRM_INFO(" space=0x%x\n", dev_priv->prim.space); \
|
||||
} \
|
||||
prim = dev_priv->prim.start; \
|
||||
write = dev_priv->prim.tail; \
|
||||
@ -304,72 +303,68 @@ do { \
|
||||
#define ADVANCE_DMA() \
|
||||
do { \
|
||||
dev_priv->prim.tail = write; \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \
|
||||
write, dev_priv->prim.space ); \
|
||||
} \
|
||||
if (MGA_VERBOSE) \
|
||||
DRM_INFO("ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \
|
||||
write, dev_priv->prim.space); \
|
||||
} while (0)
|
||||
|
||||
#define FLUSH_DMA() \
|
||||
do { \
|
||||
if ( 0 ) { \
|
||||
DRM_INFO( "\n" ); \
|
||||
DRM_INFO( " tail=0x%06x head=0x%06lx\n", \
|
||||
dev_priv->prim.tail, \
|
||||
(unsigned long)(MGA_READ(MGA_PRIMADDRESS) - \
|
||||
dev_priv->primary->offset)); \
|
||||
if (0) { \
|
||||
DRM_INFO("\n"); \
|
||||
DRM_INFO(" tail=0x%06x head=0x%06lx\n", \
|
||||
dev_priv->prim.tail, \
|
||||
(unsigned long)(MGA_READ(MGA_PRIMADDRESS) - \
|
||||
dev_priv->primary->offset)); \
|
||||
} \
|
||||
if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \
|
||||
if ( dev_priv->prim.space < \
|
||||
dev_priv->prim.high_mark ) { \
|
||||
mga_do_dma_wrap_start( dev_priv ); \
|
||||
} else { \
|
||||
mga_do_dma_flush( dev_priv ); \
|
||||
} \
|
||||
if (!test_bit(0, &dev_priv->prim.wrapped)) { \
|
||||
if (dev_priv->prim.space < dev_priv->prim.high_mark) \
|
||||
mga_do_dma_wrap_start(dev_priv); \
|
||||
else \
|
||||
mga_do_dma_flush(dev_priv); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
|
||||
*/
|
||||
#define DMA_WRITE( offset, val ) \
|
||||
#define DMA_WRITE(offset, val) \
|
||||
do { \
|
||||
if ( MGA_VERBOSE ) { \
|
||||
DRM_INFO( " DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \
|
||||
(u32)(val), write + (offset) * sizeof(u32) ); \
|
||||
} \
|
||||
if (MGA_VERBOSE) \
|
||||
DRM_INFO(" DMA_WRITE( 0x%08x ) at 0x%04Zx\n", \
|
||||
(u32)(val), write + (offset) * sizeof(u32)); \
|
||||
*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \
|
||||
} while (0)
|
||||
|
||||
#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 ) \
|
||||
#define DMA_BLOCK(reg0, val0, reg1, val1, reg2, val2, reg3, val3) \
|
||||
do { \
|
||||
DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) | \
|
||||
(DMAREG( reg1 ) << 8) | \
|
||||
(DMAREG( reg2 ) << 16) | \
|
||||
(DMAREG( reg3 ) << 24)) ); \
|
||||
DMA_WRITE( 1, val0 ); \
|
||||
DMA_WRITE( 2, val1 ); \
|
||||
DMA_WRITE( 3, val2 ); \
|
||||
DMA_WRITE( 4, val3 ); \
|
||||
DMA_WRITE(0, ((DMAREG(reg0) << 0) | \
|
||||
(DMAREG(reg1) << 8) | \
|
||||
(DMAREG(reg2) << 16) | \
|
||||
(DMAREG(reg3) << 24))); \
|
||||
DMA_WRITE(1, val0); \
|
||||
DMA_WRITE(2, val1); \
|
||||
DMA_WRITE(3, val2); \
|
||||
DMA_WRITE(4, val3); \
|
||||
write += DMA_BLOCK_SIZE; \
|
||||
} while (0)
|
||||
|
||||
/* Buffer aging via primary DMA stream head pointer.
|
||||
*/
|
||||
|
||||
#define SET_AGE( age, h, w ) \
|
||||
#define SET_AGE(age, h, w) \
|
||||
do { \
|
||||
(age)->head = h; \
|
||||
(age)->wrap = w; \
|
||||
} while (0)
|
||||
|
||||
#define TEST_AGE( age, h, w ) ( (age)->wrap < w || \
|
||||
( (age)->wrap == w && \
|
||||
(age)->head < h ) )
|
||||
#define TEST_AGE(age, h, w) ((age)->wrap < w || \
|
||||
((age)->wrap == w && \
|
||||
(age)->head < h))
|
||||
|
||||
#define AGE_BUFFER( buf_priv ) \
|
||||
#define AGE_BUFFER(buf_priv) \
|
||||
do { \
|
||||
drm_mga_freelist_t *entry = (buf_priv)->list_entry; \
|
||||
if ( (buf_priv)->dispatched ) { \
|
||||
if ((buf_priv)->dispatched) { \
|
||||
entry->age.head = (dev_priv->prim.tail + \
|
||||
dev_priv->primary->offset); \
|
||||
entry->age.wrap = dev_priv->sarea_priv->last_wrap; \
|
||||
@ -681,7 +676,7 @@ do { \
|
||||
|
||||
/* Simple idle test.
|
||||
*/
|
||||
static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
|
||||
static __inline__ int mga_is_idle(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
|
||||
return (status == MGA_ENDPRDMASTS);
|
||||
|
@ -76,9 +76,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
/* In addition to clearing the interrupt-pending bit, we
|
||||
* have to write to MGA_PRIMEND to re-start the DMA operation.
|
||||
*/
|
||||
if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
|
||||
if ((prim_start & ~0x03) != (prim_end & ~0x03))
|
||||
MGA_WRITE(MGA_PRIMEND, prim_end);
|
||||
}
|
||||
|
||||
atomic_inc(&dev_priv->last_fence_retired);
|
||||
DRM_WAKEUP(&dev_priv->fence_queue);
|
||||
@ -120,7 +119,7 @@ void mga_disable_vblank(struct drm_device *dev, int crtc)
|
||||
/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
|
||||
}
|
||||
|
||||
int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
unsigned int cur_fence;
|
||||
@ -139,7 +138,7 @@ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mga_driver_irq_preinstall(struct drm_device * dev)
|
||||
void mga_driver_irq_preinstall(struct drm_device *dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
@ -162,7 +161,7 @@ int mga_driver_irq_postinstall(struct drm_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mga_driver_irq_uninstall(struct drm_device * dev)
|
||||
void mga_driver_irq_uninstall(struct drm_device *dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
if (!dev_priv)
|
||||
|
@ -41,8 +41,8 @@
|
||||
* DMA hardware state programming functions
|
||||
*/
|
||||
|
||||
static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
|
||||
struct drm_clip_rect * box)
|
||||
static void mga_emit_clip_rect(drm_mga_private_t *dev_priv,
|
||||
struct drm_clip_rect *box)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
@ -66,7 +66,7 @@ static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
@ -89,7 +89,7 @@ static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
@ -116,7 +116,7 @@ static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
|
||||
@ -144,7 +144,7 @@ static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
|
||||
@ -184,7 +184,7 @@ static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
|
||||
@ -223,7 +223,7 @@ static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int pipe = sarea_priv->warp_pipe;
|
||||
@ -250,7 +250,7 @@ static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
|
||||
static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int pipe = sarea_priv->warp_pipe;
|
||||
@ -327,7 +327,7 @@ static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
|
||||
ADVANCE_DMA();
|
||||
}
|
||||
|
||||
static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
|
||||
static void mga_g200_emit_state(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
@ -348,7 +348,7 @@ static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
|
||||
static void mga_g400_emit_state(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
@ -381,7 +381,7 @@ static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
|
||||
|
||||
/* Disallow all write destinations except the front and backbuffer.
|
||||
*/
|
||||
static int mga_verify_context(drm_mga_private_t * dev_priv)
|
||||
static int mga_verify_context(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
|
||||
@ -400,7 +400,7 @@ static int mga_verify_context(drm_mga_private_t * dev_priv)
|
||||
|
||||
/* Disallow texture reads from PCI space.
|
||||
*/
|
||||
static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
|
||||
static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
|
||||
@ -417,7 +417,7 @@ static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_verify_state(drm_mga_private_t * dev_priv)
|
||||
static int mga_verify_state(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
unsigned int dirty = sarea_priv->dirty;
|
||||
@ -446,7 +446,7 @@ static int mga_verify_state(drm_mga_private_t * dev_priv)
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
static int mga_verify_iload(drm_mga_private_t * dev_priv,
|
||||
static int mga_verify_iload(drm_mga_private_t *dev_priv,
|
||||
unsigned int dstorg, unsigned int length)
|
||||
{
|
||||
if (dstorg < dev_priv->texture_offset ||
|
||||
@ -465,7 +465,7 @@ static int mga_verify_iload(drm_mga_private_t * dev_priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mga_verify_blit(drm_mga_private_t * dev_priv,
|
||||
static int mga_verify_blit(drm_mga_private_t *dev_priv,
|
||||
unsigned int srcorg, unsigned int dstorg)
|
||||
{
|
||||
if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
|
||||
@ -480,7 +480,7 @@ static int mga_verify_blit(drm_mga_private_t * dev_priv,
|
||||
*
|
||||
*/
|
||||
|
||||
static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
|
||||
static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -568,7 +568,7 @@ static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * cl
|
||||
FLUSH_DMA();
|
||||
}
|
||||
|
||||
static void mga_dma_dispatch_swap(struct drm_device * dev)
|
||||
static void mga_dma_dispatch_swap(struct drm_device *dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -622,7 +622,7 @@ static void mga_dma_dispatch_swap(struct drm_device * dev)
|
||||
DRM_DEBUG("... done.\n");
|
||||
}
|
||||
|
||||
static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
|
||||
static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_buf_priv_t *buf_priv = buf->dev_private;
|
||||
@ -669,7 +669,7 @@ static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * bu
|
||||
FLUSH_DMA();
|
||||
}
|
||||
|
||||
static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
|
||||
static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf,
|
||||
unsigned int start, unsigned int end)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
@ -718,7 +718,7 @@ static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * b
|
||||
/* This copies a 64 byte aligned agp region to the frambuffer with a
|
||||
* standard blit, the ioctl needs to do checking.
|
||||
*/
|
||||
static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
|
||||
static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf,
|
||||
unsigned int dstorg, unsigned int length)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
@ -766,7 +766,7 @@ static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf
|
||||
FLUSH_DMA();
|
||||
}
|
||||
|
||||
static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
|
||||
static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = dev->dev_private;
|
||||
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
@ -801,9 +801,8 @@ static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit
|
||||
int w = pbox[i].x2 - pbox[i].x1 - 1;
|
||||
int start;
|
||||
|
||||
if (blit->ydir == -1) {
|
||||
if (blit->ydir == -1)
|
||||
srcy = blit->height - srcy - 1;
|
||||
}
|
||||
|
||||
start = srcy * blit->src_pitch + srcx;
|
||||
|
||||
|
@ -46,7 +46,7 @@ MODULE_FIRMWARE(FIRMWARE_G400);
|
||||
|
||||
#define WARP_UCODE_SIZE(size) ALIGN(size, MGA_WARP_CODE_ALIGN)
|
||||
|
||||
int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
|
||||
int mga_warp_install_microcode(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
unsigned char *vcbase = dev_priv->warp->handle;
|
||||
unsigned long pcbase = dev_priv->warp->offset;
|
||||
@ -133,7 +133,7 @@ out:
|
||||
|
||||
#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
|
||||
|
||||
int mga_warp_init(drm_mga_private_t * dev_priv)
|
||||
int mga_warp_init(drm_mga_private_t *dev_priv)
|
||||
{
|
||||
u32 wmisc;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
config DRM_NOUVEAU
|
||||
tristate "Nouveau (nVidia) cards"
|
||||
depends on DRM
|
||||
depends on DRM && PCI
|
||||
select FW_LOADER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_TTM
|
||||
@ -41,4 +41,13 @@ config DRM_I2C_CH7006
|
||||
|
||||
This driver is currently only useful if you're also using
|
||||
the nouveau driver.
|
||||
|
||||
config DRM_I2C_SIL164
|
||||
tristate "Silicon Image sil164 TMDS transmitter"
|
||||
default m if DRM_NOUVEAU
|
||||
help
|
||||
Support for sil164 and similar single-link (or dual-link
|
||||
when used in pairs) TMDS transmitters, used in some nVidia
|
||||
video cards.
|
||||
|
||||
endmenu
|
||||
|
@ -9,10 +9,10 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
|
||||
nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
|
||||
nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
|
||||
nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
|
||||
nouveau_dp.o nouveau_grctx.o \
|
||||
nouveau_dp.o \
|
||||
nv04_timer.o \
|
||||
nv04_mc.o nv40_mc.o nv50_mc.o \
|
||||
nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \
|
||||
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \
|
||||
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
|
||||
nv04_graph.o nv10_graph.o nv20_graph.o \
|
||||
nv40_graph.o nv50_graph.o \
|
||||
@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
|
||||
nv50_cursor.o nv50_display.o nv50_fbcon.o \
|
||||
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
|
||||
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
|
||||
nv17_gpio.o nv50_gpio.o \
|
||||
nv10_gpio.o nv50_gpio.o \
|
||||
nv50_calc.o
|
||||
|
||||
nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/video.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
@ -11,6 +12,7 @@
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_drm.h"
|
||||
#include "nv50_display.h"
|
||||
#include "nouveau_connector.h"
|
||||
|
||||
#include <linux/vga_switcheroo.h>
|
||||
|
||||
@ -42,7 +44,7 @@ static const char nouveau_dsm_muid[] = {
|
||||
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
|
||||
};
|
||||
|
||||
static int nouveau_dsm(acpi_handle handle, int func, int arg, int *result)
|
||||
static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
|
||||
{
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_object_list input;
|
||||
@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
|
||||
{
|
||||
return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct acpi_device *acpidev;
|
||||
acpi_handle handle;
|
||||
int type, ret;
|
||||
void *edid;
|
||||
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
type = ACPI_VIDEO_DISPLAY_LCD;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
|
||||
if (!handle)
|
||||
return -ENODEV;
|
||||
|
||||
ret = acpi_bus_get_device(handle, &acpidev);
|
||||
if (ret)
|
||||
return -ENODEV;
|
||||
|
||||
ret = acpi_video_get_edid(acpidev, type, -1, &edid);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
nv_connector->edid = edid;
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -81,6 +81,7 @@ struct dcb_connector_table_entry {
|
||||
enum dcb_connector_type type;
|
||||
uint8_t index2;
|
||||
uint8_t gpio_tag;
|
||||
void *drm;
|
||||
};
|
||||
|
||||
struct dcb_connector_table {
|
||||
@ -117,6 +118,7 @@ struct dcb_entry {
|
||||
struct {
|
||||
struct sor_conf sor;
|
||||
bool use_straps_for_mode;
|
||||
bool use_acpi_for_edid;
|
||||
bool use_power_scripts;
|
||||
} lvdsconf;
|
||||
struct {
|
||||
@ -249,8 +251,6 @@ struct nvbios {
|
||||
|
||||
struct {
|
||||
int crtchead;
|
||||
/* these need remembering across suspend */
|
||||
uint32_t saved_nv_pfb_cfg0;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
|
@ -461,9 +461,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
|
||||
return ret;
|
||||
|
||||
ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
|
||||
evict, no_wait_reserve, no_wait_gpu, new_mem);
|
||||
if (nvbo->channel && nvbo->channel != chan)
|
||||
ret = nouveau_fence_wait(fence, NULL, false, false);
|
||||
evict || (nvbo->channel &&
|
||||
nvbo->channel != chan),
|
||||
no_wait_reserve, no_wait_gpu, new_mem);
|
||||
nouveau_fence_unref((void *)&fence);
|
||||
return ret;
|
||||
}
|
||||
@ -711,8 +711,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
|
||||
return ret;
|
||||
|
||||
/* Software copy if the card isn't up and running yet. */
|
||||
if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
|
||||
!dev_priv->channel) {
|
||||
if (!dev_priv->channel) {
|
||||
ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
|
||||
goto out;
|
||||
}
|
||||
@ -783,7 +782,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
|
||||
break;
|
||||
case TTM_PL_VRAM:
|
||||
mem->bus.offset = mem->mm_node->start << PAGE_SHIFT;
|
||||
mem->bus.base = drm_get_resource_start(dev, 1);
|
||||
mem->bus.base = pci_resource_start(dev->pdev, 1);
|
||||
mem->bus.is_iomem = true;
|
||||
break;
|
||||
default:
|
||||
|
@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
|
||||
struct nv_sim_state sim_data;
|
||||
int MClk = nouveau_hw_get_clock(dev, MPLL);
|
||||
int NVClk = nouveau_hw_get_clock(dev, NVPLL);
|
||||
uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1);
|
||||
uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1);
|
||||
|
||||
sim_data.pclk_khz = VClk;
|
||||
sim_data.mclk_khz = MClk;
|
||||
@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
|
||||
sim_data.mem_latency = 3;
|
||||
sim_data.mem_page_miss = 10;
|
||||
} else {
|
||||
sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1;
|
||||
sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1;
|
||||
sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
|
||||
sim_data.mem_latency = cfg1 & 0xf;
|
||||
sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
|
||||
|
@ -62,7 +62,8 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
|
||||
* VRAM.
|
||||
*/
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
|
||||
drm_get_resource_start(dev, 1),
|
||||
pci_resource_start(dev->pdev,
|
||||
1),
|
||||
dev_priv->fb_available_size,
|
||||
NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_PCI, &pushbuf);
|
||||
@ -257,9 +258,7 @@ nouveau_channel_free(struct nouveau_channel *chan)
|
||||
nouveau_debugfs_channel_fini(chan);
|
||||
|
||||
/* Give outstanding push buffers a chance to complete */
|
||||
spin_lock_irqsave(&chan->fence.lock, flags);
|
||||
nouveau_fence_update(chan);
|
||||
spin_unlock_irqrestore(&chan->fence.lock, flags);
|
||||
if (chan->fence.sequence != chan->fence.sequence_ack) {
|
||||
struct nouveau_fence *fence = NULL;
|
||||
|
||||
@ -368,8 +367,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
if (dev_priv->engine.graph.accel_blocked)
|
||||
return -ENODEV;
|
||||
|
||||
@ -418,7 +415,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
|
||||
struct drm_nouveau_channel_free *cfree = data;
|
||||
struct nouveau_channel *chan;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
|
||||
|
||||
nouveau_channel_free(chan);
|
||||
|
@ -102,63 +102,15 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
|
||||
kfree(drm_connector);
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
|
||||
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
return;
|
||||
|
||||
*flags = 0;
|
||||
if (NVLockVgaCrtcs(dev_priv->dev, false))
|
||||
*flags |= 1;
|
||||
if (nv_heads_tied(dev_priv->dev))
|
||||
*flags |= 2;
|
||||
|
||||
if (*flags & 2)
|
||||
NVSetOwner(dev_priv->dev, 0); /* necessary? */
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_connector_ddc_finish(struct drm_connector *connector, int flags)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
|
||||
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
return;
|
||||
|
||||
if (flags & 2)
|
||||
NVSetOwner(dev_priv->dev, 4);
|
||||
if (flags & 1)
|
||||
NVLockVgaCrtcs(dev_priv->dev, true);
|
||||
}
|
||||
|
||||
static struct nouveau_i2c_chan *
|
||||
nouveau_connector_ddc_detect(struct drm_connector *connector,
|
||||
struct nouveau_encoder **pnv_encoder)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
uint8_t out_buf[] = { 0x0, 0x0}, buf[2];
|
||||
int ret, flags, i;
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = 0x50,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = 0x50,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
struct nouveau_i2c_chan *i2c = NULL;
|
||||
struct nouveau_i2c_chan *i2c;
|
||||
struct nouveau_encoder *nv_encoder;
|
||||
struct drm_mode_object *obj;
|
||||
int id;
|
||||
@ -171,17 +123,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
|
||||
if (!obj)
|
||||
continue;
|
||||
nv_encoder = nouveau_encoder(obj_to_encoder(obj));
|
||||
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
|
||||
|
||||
if (nv_encoder->dcb->i2c_index < 0xf)
|
||||
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
|
||||
if (!i2c)
|
||||
continue;
|
||||
|
||||
nouveau_connector_ddc_prepare(connector, &flags);
|
||||
ret = i2c_transfer(&i2c->adapter, msgs, 2);
|
||||
nouveau_connector_ddc_finish(connector, flags);
|
||||
|
||||
if (ret == 2) {
|
||||
if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
|
||||
*pnv_encoder = nv_encoder;
|
||||
return i2c;
|
||||
}
|
||||
@ -234,21 +178,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_encoder *nv_encoder = NULL;
|
||||
struct nouveau_i2c_chan *i2c;
|
||||
int type, flags;
|
||||
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS)
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
|
||||
if (nv_encoder && nv_connector->native_mode) {
|
||||
unsigned status = connector_status_connected;
|
||||
|
||||
#if defined(CONFIG_ACPI_BUTTON) || \
|
||||
(defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
|
||||
if (!nouveau_ignorelid && !acpi_lid_open())
|
||||
status = connector_status_unknown;
|
||||
#endif
|
||||
nouveau_connector_set_encoder(connector, nv_encoder);
|
||||
return status;
|
||||
}
|
||||
int type;
|
||||
|
||||
/* Cleanup the previous EDID block. */
|
||||
if (nv_connector->edid) {
|
||||
@ -259,9 +189,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
||||
|
||||
i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
|
||||
if (i2c) {
|
||||
nouveau_connector_ddc_prepare(connector, &flags);
|
||||
nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
|
||||
nouveau_connector_ddc_finish(connector, flags);
|
||||
drm_mode_connector_update_edid_property(connector,
|
||||
nv_connector->edid);
|
||||
if (!nv_connector->edid) {
|
||||
@ -321,6 +249,85 @@ detect_analog:
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
nouveau_connector_detect_lvds(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_encoder *nv_encoder = NULL;
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
|
||||
/* Cleanup the previous EDID block. */
|
||||
if (nv_connector->edid) {
|
||||
drm_mode_connector_update_edid_property(connector, NULL);
|
||||
kfree(nv_connector->edid);
|
||||
nv_connector->edid = NULL;
|
||||
}
|
||||
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
|
||||
if (!nv_encoder)
|
||||
return connector_status_disconnected;
|
||||
|
||||
/* Try retrieving EDID via DDC */
|
||||
if (!dev_priv->vbios.fp_no_ddc) {
|
||||
status = nouveau_connector_detect(connector);
|
||||
if (status == connector_status_connected)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* On some laptops (Sony, i'm looking at you) there appears to
|
||||
* be no direct way of accessing the panel's EDID. The only
|
||||
* option available to us appears to be to ask ACPI for help..
|
||||
*
|
||||
* It's important this check's before trying straps, one of the
|
||||
* said manufacturer's laptops are configured in such a way
|
||||
* the nouveau decides an entry in the VBIOS FP mode table is
|
||||
* valid - it's not (rh#613284)
|
||||
*/
|
||||
if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
|
||||
if (!nouveau_acpi_edid(dev, connector)) {
|
||||
status = connector_status_connected;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no EDID found above, and the VBIOS indicates a hardcoded
|
||||
* modeline is avalilable for the panel, set it as the panel's
|
||||
* native mode and exit.
|
||||
*/
|
||||
if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc ||
|
||||
nv_encoder->dcb->lvdsconf.use_straps_for_mode)) {
|
||||
status = connector_status_connected;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Still nothing, some VBIOS images have a hardcoded EDID block
|
||||
* stored for the panel stored in them.
|
||||
*/
|
||||
if (!dev_priv->vbios.fp_no_ddc) {
|
||||
struct edid *edid =
|
||||
(struct edid *)nouveau_bios_embedded_edid(dev);
|
||||
if (edid) {
|
||||
nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
*(nv_connector->edid) = *edid;
|
||||
status = connector_status_connected;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
#if defined(CONFIG_ACPI_BUTTON) || \
|
||||
(defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
|
||||
if (status == connector_status_connected &&
|
||||
!nouveau_ignorelid && !acpi_lid_open())
|
||||
status = connector_status_unknown;
|
||||
#endif
|
||||
|
||||
drm_mode_connector_update_edid_property(connector, nv_connector->edid);
|
||||
nouveau_connector_set_encoder(connector, nv_encoder);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_connector_force(struct drm_connector *connector)
|
||||
{
|
||||
@ -441,7 +448,8 @@ nouveau_connector_native_mode(struct drm_connector *connector)
|
||||
int high_w = 0, high_h = 0, high_v = 0;
|
||||
|
||||
list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
|
||||
if (helper->mode_valid(connector, mode) != MODE_OK)
|
||||
if (helper->mode_valid(connector, mode) != MODE_OK ||
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE))
|
||||
continue;
|
||||
|
||||
/* Use preferred mode if there is one.. */
|
||||
@ -534,21 +542,27 @@ static int
|
||||
nouveau_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
|
||||
int ret = 0;
|
||||
|
||||
/* If we're not LVDS, destroy the previous native mode, the attached
|
||||
* monitor could have changed.
|
||||
/* destroy the native mode, the attached monitor could have changed.
|
||||
*/
|
||||
if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS &&
|
||||
nv_connector->native_mode) {
|
||||
if (nv_connector->native_mode) {
|
||||
drm_mode_destroy(dev, nv_connector->native_mode);
|
||||
nv_connector->native_mode = NULL;
|
||||
}
|
||||
|
||||
if (nv_connector->edid)
|
||||
ret = drm_add_edid_modes(connector, nv_connector->edid);
|
||||
else
|
||||
if (nv_encoder->dcb->type == OUTPUT_LVDS &&
|
||||
(nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
|
||||
dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
|
||||
nv_connector->native_mode = drm_mode_create(dev);
|
||||
nouveau_bios_fp_mode(dev, nv_connector->native_mode);
|
||||
}
|
||||
|
||||
/* Find the native mode if this is a digital panel, if we didn't
|
||||
* find any modes through DDC previously add the native mode to
|
||||
@ -569,7 +583,8 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
||||
ret = get_slave_funcs(nv_encoder)->
|
||||
get_modes(to_drm_encoder(nv_encoder), connector);
|
||||
|
||||
if (nv_encoder->dcb->type == OUTPUT_LVDS)
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS ||
|
||||
nv_connector->dcb->type == DCB_CONNECTOR_eDP)
|
||||
ret += nouveau_connector_scaler_modes_add(connector);
|
||||
|
||||
return ret;
|
||||
@ -643,6 +658,44 @@ nouveau_connector_best_encoder(struct drm_connector *connector)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_connector_set_polling(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
bool spare_crtc = false;
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
spare_crtc |= !crtc->enabled;
|
||||
|
||||
connector->polled = 0;
|
||||
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_VGA:
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
if (dev_priv->card_type >= NV_50 ||
|
||||
(nv_gf4_disp_arch(dev) && spare_crtc))
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
break;
|
||||
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
|
||||
spare_crtc)
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs
|
||||
nouveau_connector_helper_funcs = {
|
||||
.get_modes = nouveau_connector_get_modes,
|
||||
@ -662,148 +715,74 @@ nouveau_connector_funcs = {
|
||||
.force = nouveau_connector_force
|
||||
};
|
||||
|
||||
static int
|
||||
nouveau_connector_create_lvds(struct drm_device *dev,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_i2c_chan *i2c = NULL;
|
||||
struct nouveau_encoder *nv_encoder;
|
||||
struct drm_display_mode native, *mode, *temp;
|
||||
bool dummy, if_is_24bit = false;
|
||||
int ret, flags;
|
||||
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
|
||||
if (!nv_encoder)
|
||||
return -ENODEV;
|
||||
|
||||
ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n");
|
||||
return ret;
|
||||
}
|
||||
nv_connector->use_dithering = !if_is_24bit;
|
||||
|
||||
/* Firstly try getting EDID over DDC, if allowed and I2C channel
|
||||
* is available.
|
||||
*/
|
||||
if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
|
||||
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
|
||||
|
||||
if (i2c) {
|
||||
nouveau_connector_ddc_prepare(connector, &flags);
|
||||
nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
|
||||
nouveau_connector_ddc_finish(connector, flags);
|
||||
}
|
||||
|
||||
/* If no EDID found above, and the VBIOS indicates a hardcoded
|
||||
* modeline is avalilable for the panel, set it as the panel's
|
||||
* native mode and exit.
|
||||
*/
|
||||
if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
|
||||
(nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
|
||||
dev_priv->vbios.fp_no_ddc)) {
|
||||
nv_connector->native_mode = drm_mode_duplicate(dev, &native);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Still nothing, some VBIOS images have a hardcoded EDID block
|
||||
* stored for the panel stored in them.
|
||||
*/
|
||||
if (!nv_connector->edid && !nv_connector->native_mode &&
|
||||
!dev_priv->vbios.fp_no_ddc) {
|
||||
struct edid *edid =
|
||||
(struct edid *)nouveau_bios_embedded_edid(dev);
|
||||
if (edid) {
|
||||
nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
*(nv_connector->edid) = *edid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nv_connector->edid)
|
||||
goto out;
|
||||
|
||||
/* We didn't find/use a panel mode from the VBIOS, so parse the EDID
|
||||
* block and look for the preferred mode there.
|
||||
*/
|
||||
ret = drm_add_edid_modes(connector, nv_connector->edid);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
nv_connector->detected_encoder = nv_encoder;
|
||||
nv_connector->native_mode = nouveau_connector_native_mode(connector);
|
||||
list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
|
||||
drm_mode_remove(connector, mode);
|
||||
|
||||
out:
|
||||
if (!nv_connector->native_mode) {
|
||||
NV_ERROR(dev, "LVDS present in DCB table, but couldn't "
|
||||
"determine its native mode. Disabling.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
drm_mode_connector_update_edid_property(connector, nv_connector->edid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_connector_create(struct drm_device *dev,
|
||||
struct dcb_connector_table_entry *dcb)
|
||||
static const struct drm_connector_funcs
|
||||
nouveau_connector_funcs_lvds = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.save = NULL,
|
||||
.restore = NULL,
|
||||
.detect = nouveau_connector_detect_lvds,
|
||||
.destroy = nouveau_connector_destroy,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = nouveau_connector_set_property,
|
||||
.force = nouveau_connector_force
|
||||
};
|
||||
|
||||
struct drm_connector *
|
||||
nouveau_connector_create(struct drm_device *dev, int index)
|
||||
{
|
||||
const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_connector *nv_connector = NULL;
|
||||
struct dcb_connector_table_entry *dcb = NULL;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
int ret, type;
|
||||
int type, ret = 0;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
if (index >= dev_priv->vbios.dcb.connector.entries)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
dcb = &dev_priv->vbios.dcb.connector.entry[index];
|
||||
if (dcb->drm)
|
||||
return dcb->drm;
|
||||
|
||||
switch (dcb->type) {
|
||||
case DCB_CONNECTOR_NONE:
|
||||
return 0;
|
||||
case DCB_CONNECTOR_VGA:
|
||||
NV_INFO(dev, "Detected a VGA connector\n");
|
||||
type = DRM_MODE_CONNECTOR_VGA;
|
||||
break;
|
||||
case DCB_CONNECTOR_TV_0:
|
||||
case DCB_CONNECTOR_TV_1:
|
||||
case DCB_CONNECTOR_TV_3:
|
||||
NV_INFO(dev, "Detected a TV connector\n");
|
||||
type = DRM_MODE_CONNECTOR_TV;
|
||||
break;
|
||||
case DCB_CONNECTOR_DVI_I:
|
||||
NV_INFO(dev, "Detected a DVI-I connector\n");
|
||||
type = DRM_MODE_CONNECTOR_DVII;
|
||||
break;
|
||||
case DCB_CONNECTOR_DVI_D:
|
||||
NV_INFO(dev, "Detected a DVI-D connector\n");
|
||||
type = DRM_MODE_CONNECTOR_DVID;
|
||||
break;
|
||||
case DCB_CONNECTOR_HDMI_0:
|
||||
case DCB_CONNECTOR_HDMI_1:
|
||||
NV_INFO(dev, "Detected a HDMI connector\n");
|
||||
type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
break;
|
||||
case DCB_CONNECTOR_LVDS:
|
||||
NV_INFO(dev, "Detected a LVDS connector\n");
|
||||
type = DRM_MODE_CONNECTOR_LVDS;
|
||||
funcs = &nouveau_connector_funcs_lvds;
|
||||
break;
|
||||
case DCB_CONNECTOR_DP:
|
||||
NV_INFO(dev, "Detected a DisplayPort connector\n");
|
||||
type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
break;
|
||||
case DCB_CONNECTOR_eDP:
|
||||
NV_INFO(dev, "Detected an eDP connector\n");
|
||||
type = DRM_MODE_CONNECTOR_eDP;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
|
||||
if (!nv_connector)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
nv_connector->dcb = dcb;
|
||||
connector = &nv_connector->base;
|
||||
|
||||
@ -811,27 +790,21 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
connector->interlace_allowed = false;
|
||||
connector->doublescan_allowed = false;
|
||||
|
||||
drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
|
||||
drm_connector_init(dev, connector, funcs, type);
|
||||
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
|
||||
|
||||
/* attach encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
/* Check if we need dithering enabled */
|
||||
if (dcb->type == DCB_CONNECTOR_LVDS) {
|
||||
bool dummy, is_24bit = false;
|
||||
|
||||
if (nv_encoder->dcb->connector != dcb->index)
|
||||
continue;
|
||||
ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "Error parsing LVDS table, disabling "
|
||||
"LVDS\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (get_slave_funcs(nv_encoder))
|
||||
get_slave_funcs(nv_encoder)->create_resources(encoder, connector);
|
||||
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
}
|
||||
|
||||
if (!connector->encoder_ids[0]) {
|
||||
NV_WARN(dev, " no encoders, ignoring\n");
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
return 0;
|
||||
nv_connector->use_dithering = !is_24bit;
|
||||
}
|
||||
|
||||
/* Init DVI-I specific properties */
|
||||
@ -841,12 +814,8 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
|
||||
}
|
||||
|
||||
if (dcb->type != DCB_CONNECTOR_LVDS)
|
||||
nv_connector->use_dithering = false;
|
||||
|
||||
switch (dcb->type) {
|
||||
case DCB_CONNECTOR_VGA:
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
@ -858,17 +827,6 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
case DCB_CONNECTOR_TV_3:
|
||||
nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
|
||||
break;
|
||||
case DCB_CONNECTOR_DP:
|
||||
case DCB_CONNECTOR_eDP:
|
||||
case DCB_CONNECTOR_HDMI_0:
|
||||
case DCB_CONNECTOR_HDMI_1:
|
||||
case DCB_CONNECTOR_DVI_I:
|
||||
case DCB_CONNECTOR_DVI_D:
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
/* fall-through */
|
||||
default:
|
||||
nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
|
||||
|
||||
@ -882,15 +840,15 @@ nouveau_connector_create(struct drm_device *dev,
|
||||
break;
|
||||
}
|
||||
|
||||
nouveau_connector_set_polling(connector);
|
||||
|
||||
drm_sysfs_connector_add(connector);
|
||||
dcb->drm = connector;
|
||||
return dcb->drm;
|
||||
|
||||
if (dcb->type == DCB_CONNECTOR_LVDS) {
|
||||
ret = nouveau_connector_create_lvds(dev, connector);
|
||||
if (ret) {
|
||||
connector->funcs->destroy(connector);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
fail:
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,7 +49,10 @@ static inline struct nouveau_connector *nouveau_connector(
|
||||
return container_of(con, struct nouveau_connector, base);
|
||||
}
|
||||
|
||||
int nouveau_connector_create(struct drm_device *,
|
||||
struct dcb_connector_table_entry *);
|
||||
struct drm_connector *
|
||||
nouveau_connector_create(struct drm_device *, int index);
|
||||
|
||||
void
|
||||
nouveau_connector_set_polling(struct drm_connector *);
|
||||
|
||||
#endif /* __NOUVEAU_CONNECTOR_H__ */
|
||||
|
@ -92,11 +92,9 @@ nouveau_dma_init(struct nouveau_channel *chan)
|
||||
return ret;
|
||||
|
||||
/* Map M2MF notifier object - fbcon. */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = nouveau_bo_map(chan->notifier_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = nouveau_bo_map(chan->notifier_bo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Insert NOPS for NOUVEAU_DMA_SKIPS */
|
||||
ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
|
||||
|
@ -23,8 +23,10 @@
|
||||
*/
|
||||
|
||||
#include "drmP.h"
|
||||
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_i2c.h"
|
||||
#include "nouveau_connector.h"
|
||||
#include "nouveau_encoder.h"
|
||||
|
||||
static int
|
||||
@ -270,13 +272,39 @@ bool
|
||||
nouveau_dp_link_train(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
uint8_t config[4];
|
||||
uint8_t status[3];
|
||||
struct nouveau_connector *nv_connector;
|
||||
struct bit_displayport_encoder_table *dpe;
|
||||
int dpe_headerlen;
|
||||
uint8_t config[4], status[3];
|
||||
bool cr_done, cr_max_vs, eq_done;
|
||||
int ret = 0, i, tries, voltage;
|
||||
|
||||
NV_DEBUG_KMS(dev, "link training!!\n");
|
||||
|
||||
nv_connector = nouveau_encoder_connector_get(nv_encoder);
|
||||
if (!nv_connector)
|
||||
return false;
|
||||
|
||||
dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
|
||||
if (!dpe) {
|
||||
NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* disable hotplug detect, this flips around on some panels during
|
||||
* link training.
|
||||
*/
|
||||
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
|
||||
|
||||
if (dpe->script0) {
|
||||
NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
|
||||
nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
|
||||
nv_encoder->dcb);
|
||||
}
|
||||
|
||||
train:
|
||||
cr_done = eq_done = false;
|
||||
|
||||
@ -403,6 +431,15 @@ stop:
|
||||
}
|
||||
}
|
||||
|
||||
if (dpe->script1) {
|
||||
NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
|
||||
nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
|
||||
nv_encoder->dcb);
|
||||
}
|
||||
|
||||
/* re-enable hotplug detect */
|
||||
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
|
||||
|
||||
return eq_done;
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,6 @@
|
||||
|
||||
#include "drm_pciids.h"
|
||||
|
||||
MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)");
|
||||
int nouveau_ctxfw = 0;
|
||||
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(noagp, "Disable AGP");
|
||||
int nouveau_noagp;
|
||||
module_param_named(noagp, nouveau_noagp, int, 0400);
|
||||
@ -56,7 +52,7 @@ int nouveau_vram_pushbuf;
|
||||
module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
|
||||
int nouveau_vram_notify = 1;
|
||||
int nouveau_vram_notify = 0;
|
||||
module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
|
||||
@ -132,7 +128,7 @@ static struct drm_driver driver;
|
||||
static int __devinit
|
||||
nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
return drm_get_dev(pdev, ent, &driver);
|
||||
return drm_get_pci_dev(pdev, ent, &driver);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
|
||||
struct drm_crtc *crtc;
|
||||
int ret, i;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -ENODEV;
|
||||
|
||||
if (pm_state.event == PM_EVENT_PRETHAW)
|
||||
return 0;
|
||||
|
||||
@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
||||
struct drm_crtc *crtc;
|
||||
int ret, i;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -ENODEV;
|
||||
|
||||
nouveau_fbcon_save_disable_accel(dev);
|
||||
|
||||
NV_INFO(dev, "We're back, enabling device...\n");
|
||||
@ -269,6 +259,13 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
||||
return -1;
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
/* Make sure the AGP controller is in a consistent state */
|
||||
if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
|
||||
nouveau_mem_reset_agp(dev);
|
||||
|
||||
/* Make the CRTCs accessible */
|
||||
engine->display.early_init(dev);
|
||||
|
||||
NV_INFO(dev, "POSTing device...\n");
|
||||
ret = nouveau_run_vbios_init(dev);
|
||||
if (ret)
|
||||
@ -323,7 +320,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
int ret;
|
||||
|
||||
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
|
||||
if (!ret)
|
||||
@ -332,11 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
||||
NV_ERROR(dev, "Could not pin/map cursor.\n");
|
||||
}
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
nv04_display_restore(dev);
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
} else
|
||||
nv50_display_init(dev);
|
||||
engine->display.init(dev);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
@ -371,7 +363,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
|
||||
DRIVER_MODESET,
|
||||
.load = nouveau_load,
|
||||
.firstopen = nouveau_firstopen,
|
||||
.lastclose = nouveau_lastclose,
|
||||
@ -438,16 +431,18 @@ static int __init nouveau_init(void)
|
||||
nouveau_modeset = 1;
|
||||
}
|
||||
|
||||
if (nouveau_modeset == 1) {
|
||||
driver.driver_features |= DRIVER_MODESET;
|
||||
nouveau_register_dsm_handler();
|
||||
}
|
||||
if (!nouveau_modeset)
|
||||
return 0;
|
||||
|
||||
nouveau_register_dsm_handler();
|
||||
return drm_init(&driver);
|
||||
}
|
||||
|
||||
static void __exit nouveau_exit(void)
|
||||
{
|
||||
if (!nouveau_modeset)
|
||||
return;
|
||||
|
||||
drm_exit(&driver);
|
||||
nouveau_unregister_dsm_handler();
|
||||
}
|
||||
|
@ -123,14 +123,6 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo)
|
||||
return ioptr;
|
||||
}
|
||||
|
||||
struct mem_block {
|
||||
struct mem_block *next;
|
||||
struct mem_block *prev;
|
||||
uint64_t start;
|
||||
uint64_t size;
|
||||
struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
|
||||
};
|
||||
|
||||
enum nouveau_flags {
|
||||
NV_NFORCE = 0x10000000,
|
||||
NV_NFORCE2 = 0x20000000
|
||||
@ -149,7 +141,7 @@ struct nouveau_gpuobj {
|
||||
struct list_head list;
|
||||
|
||||
struct nouveau_channel *im_channel;
|
||||
struct mem_block *im_pramin;
|
||||
struct drm_mm_node *im_pramin;
|
||||
struct nouveau_bo *im_backing;
|
||||
uint32_t im_backing_start;
|
||||
uint32_t *im_backing_suspend;
|
||||
@ -196,7 +188,7 @@ struct nouveau_channel {
|
||||
struct list_head pending;
|
||||
uint32_t sequence;
|
||||
uint32_t sequence_ack;
|
||||
uint32_t last_sequence_irq;
|
||||
atomic_t last_sequence_irq;
|
||||
} fence;
|
||||
|
||||
/* DMA push buffer */
|
||||
@ -206,7 +198,7 @@ struct nouveau_channel {
|
||||
|
||||
/* Notifier memory */
|
||||
struct nouveau_bo *notifier_bo;
|
||||
struct mem_block *notifier_heap;
|
||||
struct drm_mm notifier_heap;
|
||||
|
||||
/* PFIFO context */
|
||||
struct nouveau_gpuobj_ref *ramfc;
|
||||
@ -224,7 +216,7 @@ struct nouveau_channel {
|
||||
|
||||
/* Objects */
|
||||
struct nouveau_gpuobj_ref *ramin; /* Private instmem */
|
||||
struct mem_block *ramin_heap; /* Private PRAMIN heap */
|
||||
struct drm_mm ramin_heap; /* Private PRAMIN heap */
|
||||
struct nouveau_gpuobj_ref *ramht; /* Hash table */
|
||||
struct list_head ramht_refs; /* Objects referenced by RAMHT */
|
||||
|
||||
@ -277,8 +269,7 @@ struct nouveau_instmem_engine {
|
||||
void (*clear)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
int (*bind)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
int (*unbind)(struct drm_device *, struct nouveau_gpuobj *);
|
||||
void (*prepare_access)(struct drm_device *, bool write);
|
||||
void (*finish_access)(struct drm_device *);
|
||||
void (*flush)(struct drm_device *);
|
||||
};
|
||||
|
||||
struct nouveau_mc_engine {
|
||||
@ -303,10 +294,11 @@ struct nouveau_fb_engine {
|
||||
};
|
||||
|
||||
struct nouveau_fifo_engine {
|
||||
void *priv;
|
||||
|
||||
int channels;
|
||||
|
||||
struct nouveau_gpuobj_ref *playlist[2];
|
||||
int cur_playlist;
|
||||
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
|
||||
@ -339,10 +331,11 @@ struct nouveau_pgraph_object_class {
|
||||
struct nouveau_pgraph_engine {
|
||||
struct nouveau_pgraph_object_class *grclass;
|
||||
bool accel_blocked;
|
||||
void *ctxprog;
|
||||
void *ctxvals;
|
||||
int grctx_size;
|
||||
|
||||
/* NV2x/NV3x context table (0x400780) */
|
||||
struct nouveau_gpuobj_ref *ctx_table;
|
||||
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
|
||||
@ -358,6 +351,24 @@ struct nouveau_pgraph_engine {
|
||||
uint32_t size, uint32_t pitch);
|
||||
};
|
||||
|
||||
struct nouveau_display_engine {
|
||||
int (*early_init)(struct drm_device *);
|
||||
void (*late_takedown)(struct drm_device *);
|
||||
int (*create)(struct drm_device *);
|
||||
int (*init)(struct drm_device *);
|
||||
void (*destroy)(struct drm_device *);
|
||||
};
|
||||
|
||||
struct nouveau_gpio_engine {
|
||||
int (*init)(struct drm_device *);
|
||||
void (*takedown)(struct drm_device *);
|
||||
|
||||
int (*get)(struct drm_device *, enum dcb_gpio_tag);
|
||||
int (*set)(struct drm_device *, enum dcb_gpio_tag, int state);
|
||||
|
||||
void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on);
|
||||
};
|
||||
|
||||
struct nouveau_engine {
|
||||
struct nouveau_instmem_engine instmem;
|
||||
struct nouveau_mc_engine mc;
|
||||
@ -365,6 +376,8 @@ struct nouveau_engine {
|
||||
struct nouveau_fb_engine fb;
|
||||
struct nouveau_pgraph_engine graph;
|
||||
struct nouveau_fifo_engine fifo;
|
||||
struct nouveau_display_engine display;
|
||||
struct nouveau_gpio_engine gpio;
|
||||
};
|
||||
|
||||
struct nouveau_pll_vals {
|
||||
@ -500,11 +513,6 @@ enum nouveau_card_type {
|
||||
|
||||
struct drm_nouveau_private {
|
||||
struct drm_device *dev;
|
||||
enum {
|
||||
NOUVEAU_CARD_INIT_DOWN,
|
||||
NOUVEAU_CARD_INIT_DONE,
|
||||
NOUVEAU_CARD_INIT_FAILED
|
||||
} init_state;
|
||||
|
||||
/* the card type, takes NV_* as values */
|
||||
enum nouveau_card_type card_type;
|
||||
@ -525,7 +533,7 @@ struct drm_nouveau_private {
|
||||
struct list_head vbl_waiting;
|
||||
|
||||
struct {
|
||||
struct ttm_global_reference mem_global_ref;
|
||||
struct drm_global_reference mem_global_ref;
|
||||
struct ttm_bo_global_ref bo_global_ref;
|
||||
struct ttm_bo_device bdev;
|
||||
spinlock_t bo_list_lock;
|
||||
@ -533,8 +541,6 @@ struct drm_nouveau_private {
|
||||
atomic_t validate_sequence;
|
||||
} ttm;
|
||||
|
||||
struct fb_info *fbdev_info;
|
||||
|
||||
int fifo_alloc_count;
|
||||
struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
|
||||
|
||||
@ -595,11 +601,7 @@ struct drm_nouveau_private {
|
||||
struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
|
||||
int vm_vram_pt_nr;
|
||||
|
||||
struct mem_block *ramin_heap;
|
||||
|
||||
/* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */
|
||||
uint32_t ctx_table_size;
|
||||
struct nouveau_gpuobj_ref *ctx_table;
|
||||
struct drm_mm ramin_heap;
|
||||
|
||||
struct list_head gpuobj_list;
|
||||
|
||||
@ -618,6 +620,11 @@ struct drm_nouveau_private {
|
||||
struct backlight_device *backlight;
|
||||
|
||||
struct nouveau_channel *evo;
|
||||
struct {
|
||||
struct dcb_entry *dcb;
|
||||
u16 script;
|
||||
u32 pclk;
|
||||
} evo_irq;
|
||||
|
||||
struct {
|
||||
struct dentry *channel_root;
|
||||
@ -652,14 +659,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \
|
||||
struct drm_nouveau_private *nv = dev->dev_private; \
|
||||
if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \
|
||||
NV_ERROR(dev, "called without init\n"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \
|
||||
struct drm_nouveau_private *nv = dev->dev_private; \
|
||||
if (!nouveau_channel_owner(dev, (cl), (id))) { \
|
||||
@ -682,7 +681,6 @@ extern int nouveau_tv_disable;
|
||||
extern char *nouveau_tv_norm;
|
||||
extern int nouveau_reg_debug;
|
||||
extern char *nouveau_vbios;
|
||||
extern int nouveau_ctxfw;
|
||||
extern int nouveau_ignorelid;
|
||||
extern int nouveau_nofbaccel;
|
||||
extern int nouveau_noaccel;
|
||||
@ -707,17 +705,10 @@ extern bool nouveau_wait_for_idle(struct drm_device *);
|
||||
extern int nouveau_card_init(struct drm_device *);
|
||||
|
||||
/* nouveau_mem.c */
|
||||
extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start,
|
||||
uint64_t size);
|
||||
extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,
|
||||
uint64_t size, int align2,
|
||||
struct drm_file *, int tail);
|
||||
extern void nouveau_mem_takedown(struct mem_block **heap);
|
||||
extern void nouveau_mem_free_block(struct mem_block *);
|
||||
extern int nouveau_mem_detect(struct drm_device *dev);
|
||||
extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
|
||||
extern int nouveau_mem_init(struct drm_device *);
|
||||
extern int nouveau_mem_init_agp(struct drm_device *);
|
||||
extern int nouveau_mem_reset_agp(struct drm_device *);
|
||||
extern void nouveau_mem_close(struct drm_device *);
|
||||
extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
|
||||
uint32_t addr,
|
||||
@ -857,11 +848,13 @@ void nouveau_register_dsm_handler(void);
|
||||
void nouveau_unregister_dsm_handler(void);
|
||||
int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
|
||||
bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
|
||||
int nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
|
||||
#else
|
||||
static inline void nouveau_register_dsm_handler(void) {}
|
||||
static inline void nouveau_unregister_dsm_handler(void) {}
|
||||
static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
|
||||
static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
|
||||
static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; }
|
||||
#endif
|
||||
|
||||
/* nouveau_backlight.c */
|
||||
@ -924,6 +917,10 @@ extern void nv10_fb_takedown(struct drm_device *);
|
||||
extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
|
||||
uint32_t, uint32_t);
|
||||
|
||||
/* nv30_fb.c */
|
||||
extern int nv30_fb_init(struct drm_device *);
|
||||
extern void nv30_fb_takedown(struct drm_device *);
|
||||
|
||||
/* nv40_fb.c */
|
||||
extern int nv40_fb_init(struct drm_device *);
|
||||
extern void nv40_fb_takedown(struct drm_device *);
|
||||
@ -1035,12 +1032,6 @@ extern int nv50_graph_unload_context(struct drm_device *);
|
||||
extern void nv50_graph_context_switch(struct drm_device *);
|
||||
extern int nv50_grctx_init(struct nouveau_grctx *);
|
||||
|
||||
/* nouveau_grctx.c */
|
||||
extern int nouveau_grctx_prog_load(struct drm_device *);
|
||||
extern void nouveau_grctx_vals_load(struct drm_device *,
|
||||
struct nouveau_gpuobj *);
|
||||
extern void nouveau_grctx_fini(struct drm_device *);
|
||||
|
||||
/* nv04_instmem.c */
|
||||
extern int nv04_instmem_init(struct drm_device *);
|
||||
extern void nv04_instmem_takedown(struct drm_device *);
|
||||
@ -1051,8 +1042,7 @@ extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
|
||||
extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern void nv04_instmem_prepare_access(struct drm_device *, bool write);
|
||||
extern void nv04_instmem_finish_access(struct drm_device *);
|
||||
extern void nv04_instmem_flush(struct drm_device *);
|
||||
|
||||
/* nv50_instmem.c */
|
||||
extern int nv50_instmem_init(struct drm_device *);
|
||||
@ -1064,8 +1054,9 @@ extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
|
||||
extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
|
||||
extern void nv50_instmem_prepare_access(struct drm_device *, bool write);
|
||||
extern void nv50_instmem_finish_access(struct drm_device *);
|
||||
extern void nv50_instmem_flush(struct drm_device *);
|
||||
extern void nv84_instmem_flush(struct drm_device *);
|
||||
extern void nv50_vm_flush(struct drm_device *, int engine);
|
||||
|
||||
/* nv04_mc.c */
|
||||
extern int nv04_mc_init(struct drm_device *);
|
||||
@ -1088,13 +1079,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/* nv04_dac.c */
|
||||
extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
|
||||
extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
|
||||
extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
|
||||
extern int nv04_dac_output_offset(struct drm_encoder *encoder);
|
||||
extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
|
||||
extern bool nv04_dac_in_use(struct drm_encoder *encoder);
|
||||
|
||||
/* nv04_dfp.c */
|
||||
extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry);
|
||||
extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
|
||||
extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
|
||||
extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
|
||||
int head, bool dl);
|
||||
@ -1103,15 +1095,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);
|
||||
|
||||
/* nv04_tv.c */
|
||||
extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
|
||||
extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
|
||||
extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *);
|
||||
|
||||
/* nv17_tv.c */
|
||||
extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
|
||||
extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *);
|
||||
|
||||
/* nv04_display.c */
|
||||
extern int nv04_display_early_init(struct drm_device *);
|
||||
extern void nv04_display_late_takedown(struct drm_device *);
|
||||
extern int nv04_display_create(struct drm_device *);
|
||||
extern int nv04_display_init(struct drm_device *);
|
||||
extern void nv04_display_destroy(struct drm_device *);
|
||||
extern void nv04_display_restore(struct drm_device *);
|
||||
|
||||
/* nv04_crtc.c */
|
||||
extern int nv04_crtc_create(struct drm_device *, int index);
|
||||
@ -1147,7 +1141,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
|
||||
extern int nouveau_fence_flush(void *obj, void *arg);
|
||||
extern void nouveau_fence_unref(void **obj);
|
||||
extern void *nouveau_fence_ref(void *obj);
|
||||
extern void nouveau_fence_handler(struct drm_device *dev, int channel);
|
||||
|
||||
/* nouveau_gem.c */
|
||||
extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
|
||||
@ -1167,13 +1160,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
|
||||
extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
|
||||
/* nv17_gpio.c */
|
||||
int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
|
||||
int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
|
||||
/* nv10_gpio.c */
|
||||
int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
|
||||
int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
|
||||
|
||||
/* nv50_gpio.c */
|
||||
int nv50_gpio_init(struct drm_device *dev);
|
||||
int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
|
||||
int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
|
||||
void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
|
||||
|
||||
/* nv50_calc. */
|
||||
int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
|
||||
@ -1220,6 +1215,14 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
|
||||
iowrite32_native(val, dev_priv->mmio + reg);
|
||||
}
|
||||
|
||||
static inline void nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val)
|
||||
{
|
||||
u32 tmp = nv_rd32(dev, reg);
|
||||
tmp &= ~mask;
|
||||
tmp |= val;
|
||||
nv_wr32(dev, reg, tmp);
|
||||
}
|
||||
|
||||
static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
@ -38,13 +38,15 @@ struct nouveau_encoder {
|
||||
struct dcb_entry *dcb;
|
||||
int or;
|
||||
|
||||
/* different to drm_encoder.crtc, this reflects what's
|
||||
* actually programmed on the hw, not the proposed crtc */
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
struct drm_display_mode mode;
|
||||
int last_dpms;
|
||||
|
||||
struct nv04_output_reg restore;
|
||||
|
||||
void (*disconnect)(struct nouveau_encoder *encoder);
|
||||
|
||||
union {
|
||||
struct {
|
||||
int mc_unknown;
|
||||
@ -71,8 +73,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
|
||||
|
||||
struct nouveau_connector *
|
||||
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
|
||||
int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry);
|
||||
int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry);
|
||||
int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
|
||||
int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
|
||||
|
||||
struct bit_displayport_encoder_table {
|
||||
uint32_t match;
|
||||
|
@ -333,7 +333,7 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev)
|
||||
drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
|
||||
{
|
||||
struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb;
|
||||
|
@ -67,12 +67,13 @@ nouveau_fence_update(struct nouveau_channel *chan)
|
||||
if (USE_REFCNT)
|
||||
sequence = nvchan_rd32(chan, 0x48);
|
||||
else
|
||||
sequence = chan->fence.last_sequence_irq;
|
||||
sequence = atomic_read(&chan->fence.last_sequence_irq);
|
||||
|
||||
if (chan->fence.sequence_ack == sequence)
|
||||
return;
|
||||
chan->fence.sequence_ack = sequence;
|
||||
|
||||
spin_lock(&chan->fence.lock);
|
||||
list_for_each_safe(entry, tmp, &chan->fence.pending) {
|
||||
fence = list_entry(entry, struct nouveau_fence, entry);
|
||||
|
||||
@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan)
|
||||
if (sequence == chan->fence.sequence_ack)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&chan->fence.lock);
|
||||
}
|
||||
|
||||
int
|
||||
@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private;
|
||||
struct nouveau_channel *chan = fence->channel;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = RING_SPACE(chan, 2);
|
||||
@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
return ret;
|
||||
|
||||
if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) {
|
||||
spin_lock_irqsave(&chan->fence.lock, flags);
|
||||
nouveau_fence_update(chan);
|
||||
spin_unlock_irqrestore(&chan->fence.lock, flags);
|
||||
|
||||
BUG_ON(chan->fence.sequence ==
|
||||
chan->fence.sequence_ack - 1);
|
||||
@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
fence->sequence = ++chan->fence.sequence;
|
||||
|
||||
kref_get(&fence->refcount);
|
||||
spin_lock_irqsave(&chan->fence.lock, flags);
|
||||
spin_lock(&chan->fence.lock);
|
||||
list_add_tail(&fence->entry, &chan->fence.pending);
|
||||
spin_unlock_irqrestore(&chan->fence.lock, flags);
|
||||
spin_unlock(&chan->fence.lock);
|
||||
|
||||
BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
|
||||
OUT_RING(chan, fence->sequence);
|
||||
@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg)
|
||||
{
|
||||
struct nouveau_fence *fence = nouveau_fence(sync_obj);
|
||||
struct nouveau_channel *chan = fence->channel;
|
||||
unsigned long flags;
|
||||
|
||||
if (fence->signalled)
|
||||
return true;
|
||||
|
||||
spin_lock_irqsave(&chan->fence.lock, flags);
|
||||
nouveau_fence_update(chan);
|
||||
spin_unlock_irqrestore(&chan->fence.lock, flags);
|
||||
return fence->signalled;
|
||||
}
|
||||
|
||||
@ -190,8 +186,6 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
|
||||
unsigned long timeout = jiffies + (3 * DRM_HZ);
|
||||
int ret = 0;
|
||||
|
||||
__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
||||
|
||||
while (1) {
|
||||
if (nouveau_fence_signalled(sync_obj, sync_arg))
|
||||
break;
|
||||
@ -201,6 +195,8 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
|
||||
break;
|
||||
}
|
||||
|
||||
__set_current_state(intr ? TASK_INTERRUPTIBLE
|
||||
: TASK_UNINTERRUPTIBLE);
|
||||
if (lazy)
|
||||
schedule_timeout(1);
|
||||
|
||||
@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_fence_handler(struct drm_device *dev, int channel)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_channel *chan = NULL;
|
||||
|
||||
if (channel >= 0 && channel < dev_priv->engine.fifo.channels)
|
||||
chan = dev_priv->fifos[channel];
|
||||
|
||||
if (chan) {
|
||||
spin_lock_irq(&chan->fence.lock);
|
||||
nouveau_fence_update(chan);
|
||||
spin_unlock_irq(&chan->fence.lock);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fence_init(struct nouveau_channel *chan)
|
||||
{
|
||||
INIT_LIST_HEAD(&chan->fence.pending);
|
||||
spin_lock_init(&chan->fence.lock);
|
||||
atomic_set(&chan->fence.last_sequence_irq, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
|
||||
uint32_t flags = 0;
|
||||
int ret = 0;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
|
||||
dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
|
||||
|
||||
@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo;
|
||||
struct nouveau_channel *chan;
|
||||
struct validate_op op;
|
||||
struct nouveau_fence *fence = 0;
|
||||
struct nouveau_fence *fence = NULL;
|
||||
int i, j, ret = 0, do_reloc = 0;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
|
||||
|
||||
req->vram_available = dev_priv->fb_aper_free;
|
||||
@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
|
||||
bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
|
||||
int ret = -EINVAL;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
|
||||
if (!gem)
|
||||
return ret;
|
||||
@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
|
||||
struct nouveau_bo *nvbo;
|
||||
int ret = -EINVAL;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
|
||||
if (!gem)
|
||||
return ret;
|
||||
@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
|
||||
struct drm_gem_object *gem;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
|
||||
if (!gem)
|
||||
return -EINVAL;
|
||||
|
@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Ben Skeggs
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "nouveau_drv.h"
|
||||
|
||||
struct nouveau_ctxprog {
|
||||
uint32_t signature;
|
||||
uint8_t version;
|
||||
uint16_t length;
|
||||
uint32_t data[];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct nouveau_ctxvals {
|
||||
uint32_t signature;
|
||||
uint8_t version;
|
||||
uint32_t length;
|
||||
struct {
|
||||
uint32_t offset;
|
||||
uint32_t value;
|
||||
} data[];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int
|
||||
nouveau_grctx_prog_load(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
|
||||
const int chipset = dev_priv->chipset;
|
||||
const struct firmware *fw;
|
||||
const struct nouveau_ctxprog *cp;
|
||||
const struct nouveau_ctxvals *cv;
|
||||
char name[32];
|
||||
int ret, i;
|
||||
|
||||
if (pgraph->accel_blocked)
|
||||
return -ENODEV;
|
||||
|
||||
if (!pgraph->ctxprog) {
|
||||
sprintf(name, "nouveau/nv%02x.ctxprog", chipset);
|
||||
ret = request_firmware(&fw, name, &dev->pdev->dev);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pgraph->ctxprog = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
||||
if (!pgraph->ctxprog) {
|
||||
NV_ERROR(dev, "OOM copying ctxprog\n");
|
||||
release_firmware(fw);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cp = pgraph->ctxprog;
|
||||
if (le32_to_cpu(cp->signature) != 0x5043564e ||
|
||||
cp->version != 0 ||
|
||||
le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
|
||||
NV_ERROR(dev, "ctxprog invalid\n");
|
||||
release_firmware(fw);
|
||||
nouveau_grctx_fini(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
if (!pgraph->ctxvals) {
|
||||
sprintf(name, "nouveau/nv%02x.ctxvals", chipset);
|
||||
ret = request_firmware(&fw, name, &dev->pdev->dev);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset);
|
||||
nouveau_grctx_fini(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pgraph->ctxvals = kmemdup(fw->data, fw->size, GFP_KERNEL);
|
||||
if (!pgraph->ctxvals) {
|
||||
NV_ERROR(dev, "OOM copying ctxvals\n");
|
||||
release_firmware(fw);
|
||||
nouveau_grctx_fini(dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cv = (void *)pgraph->ctxvals;
|
||||
if (le32_to_cpu(cv->signature) != 0x5643564e ||
|
||||
cv->version != 0 ||
|
||||
le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
|
||||
NV_ERROR(dev, "ctxvals invalid\n");
|
||||
release_firmware(fw);
|
||||
nouveau_grctx_fini(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
cp = pgraph->ctxprog;
|
||||
|
||||
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
|
||||
for (i = 0; i < le16_to_cpu(cp->length); i++)
|
||||
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
|
||||
le32_to_cpu(cp->data[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_grctx_fini(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
|
||||
|
||||
if (pgraph->ctxprog) {
|
||||
kfree(pgraph->ctxprog);
|
||||
pgraph->ctxprog = NULL;
|
||||
}
|
||||
|
||||
if (pgraph->ctxvals) {
|
||||
kfree(pgraph->ctxprog);
|
||||
pgraph->ctxvals = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
|
||||
struct nouveau_ctxvals *cv = pgraph->ctxvals;
|
||||
int i;
|
||||
|
||||
if (!cv)
|
||||
return;
|
||||
|
||||
for (i = 0; i < le32_to_cpu(cv->length); i++)
|
||||
nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
|
||||
le32_to_cpu(cv->data[i].value));
|
||||
}
|
@ -278,3 +278,45 @@ nouveau_i2c_find(struct drm_device *dev, int index)
|
||||
return i2c->chan;
|
||||
}
|
||||
|
||||
bool
|
||||
nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
|
||||
{
|
||||
uint8_t buf[] = { 0 };
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = buf,
|
||||
},
|
||||
{
|
||||
.addr = addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_i2c_identify(struct drm_device *dev, const char *what,
|
||||
struct i2c_board_info *info, int index)
|
||||
{
|
||||
struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
|
||||
int i;
|
||||
|
||||
NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
|
||||
|
||||
for (i = 0; info[i].addr; i++) {
|
||||
if (nouveau_probe_i2c_addr(i2c, info[i].addr)) {
|
||||
NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
NV_DEBUG(dev, "No devices found.\n");
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -45,6 +45,9 @@ struct nouveau_i2c_chan {
|
||||
int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
|
||||
void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
|
||||
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
|
||||
bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
|
||||
int nouveau_i2c_identify(struct drm_device *dev, const char *what,
|
||||
struct i2c_board_info *info, int index);
|
||||
|
||||
int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte,
|
||||
uint8_t *read_byte);
|
||||
|
@ -35,162 +35,6 @@
|
||||
#include "drm_sarea.h"
|
||||
#include "nouveau_drv.h"
|
||||
|
||||
static struct mem_block *
|
||||
split_block(struct mem_block *p, uint64_t start, uint64_t size,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
/* Maybe cut off the start of an existing block */
|
||||
if (start > p->start) {
|
||||
struct mem_block *newblock =
|
||||
kmalloc(sizeof(*newblock), GFP_KERNEL);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start;
|
||||
newblock->size = p->size - (start - p->start);
|
||||
newblock->file_priv = NULL;
|
||||
newblock->next = p->next;
|
||||
newblock->prev = p;
|
||||
p->next->prev = newblock;
|
||||
p->next = newblock;
|
||||
p->size -= newblock->size;
|
||||
p = newblock;
|
||||
}
|
||||
|
||||
/* Maybe cut off the end of an existing block */
|
||||
if (size < p->size) {
|
||||
struct mem_block *newblock =
|
||||
kmalloc(sizeof(*newblock), GFP_KERNEL);
|
||||
if (!newblock)
|
||||
goto out;
|
||||
newblock->start = start + size;
|
||||
newblock->size = p->size - size;
|
||||
newblock->file_priv = NULL;
|
||||
newblock->next = p->next;
|
||||
newblock->prev = p;
|
||||
p->next->prev = newblock;
|
||||
p->next = newblock;
|
||||
p->size = size;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Our block is in the middle */
|
||||
p->file_priv = file_priv;
|
||||
return p;
|
||||
}
|
||||
|
||||
struct mem_block *
|
||||
nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size,
|
||||
int align2, struct drm_file *file_priv, int tail)
|
||||
{
|
||||
struct mem_block *p;
|
||||
uint64_t mask = (1 << align2) - 1;
|
||||
|
||||
if (!heap)
|
||||
return NULL;
|
||||
|
||||
if (tail) {
|
||||
list_for_each_prev(p, heap) {
|
||||
uint64_t start = ((p->start + p->size) - size) & ~mask;
|
||||
|
||||
if (p->file_priv == NULL && start >= p->start &&
|
||||
start + size <= p->start + p->size)
|
||||
return split_block(p, start, size, file_priv);
|
||||
}
|
||||
} else {
|
||||
list_for_each(p, heap) {
|
||||
uint64_t start = (p->start + mask) & ~mask;
|
||||
|
||||
if (p->file_priv == NULL &&
|
||||
start + size <= p->start + p->size)
|
||||
return split_block(p, start, size, file_priv);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nouveau_mem_free_block(struct mem_block *p)
|
||||
{
|
||||
p->file_priv = NULL;
|
||||
|
||||
/* Assumes a single contiguous range. Needs a special file_priv in
|
||||
* 'heap' to stop it being subsumed.
|
||||
*/
|
||||
if (p->next->file_priv == NULL) {
|
||||
struct mem_block *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
p->next->prev = p;
|
||||
kfree(q);
|
||||
}
|
||||
|
||||
if (p->prev->file_priv == NULL) {
|
||||
struct mem_block *q = p->prev;
|
||||
q->size += p->size;
|
||||
q->next = p->next;
|
||||
q->next->prev = q;
|
||||
kfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize. How to check for an uninitialized heap?
|
||||
*/
|
||||
int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start,
|
||||
uint64_t size)
|
||||
{
|
||||
struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
|
||||
|
||||
if (!blocks)
|
||||
return -ENOMEM;
|
||||
|
||||
*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
|
||||
if (!*heap) {
|
||||
kfree(blocks);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
blocks->start = start;
|
||||
blocks->size = size;
|
||||
blocks->file_priv = NULL;
|
||||
blocks->next = blocks->prev = *heap;
|
||||
|
||||
memset(*heap, 0, sizeof(**heap));
|
||||
(*heap)->file_priv = (struct drm_file *) -1;
|
||||
(*heap)->next = (*heap)->prev = blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free all blocks associated with the releasing file_priv
|
||||
*/
|
||||
void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
if (!heap || !heap->next)
|
||||
return;
|
||||
|
||||
list_for_each(p, heap) {
|
||||
if (p->file_priv == file_priv)
|
||||
p->file_priv = NULL;
|
||||
}
|
||||
|
||||
/* Assumes a single contiguous range. Needs a special file_priv in
|
||||
* 'heap' to stop it being subsumed.
|
||||
*/
|
||||
list_for_each(p, heap) {
|
||||
while ((p->file_priv == NULL) &&
|
||||
(p->next->file_priv == NULL) &&
|
||||
(p->next != heap)) {
|
||||
struct mem_block *q = p->next;
|
||||
p->size += q->size;
|
||||
p->next = q->next;
|
||||
p->next->prev = p;
|
||||
kfree(q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NV10-NV40 tiling helpers
|
||||
*/
|
||||
@ -299,7 +143,6 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
|
||||
phys |= 0x30;
|
||||
}
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
while (size) {
|
||||
unsigned offset_h = upper_32_bits(phys);
|
||||
unsigned offset_l = lower_32_bits(phys);
|
||||
@ -331,36 +174,12 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
|
||||
}
|
||||
}
|
||||
}
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00050001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00000001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00040001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00060001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
nv50_vm_flush(dev, 5);
|
||||
nv50_vm_flush(dev, 0);
|
||||
nv50_vm_flush(dev, 4);
|
||||
nv50_vm_flush(dev, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -374,7 +193,6 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
|
||||
virt -= dev_priv->vm_vram_base;
|
||||
pages = (size >> 16) << 1;
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
while (pages) {
|
||||
pgt = dev_priv->vm_vram_pt[virt >> 29];
|
||||
pte = (virt & 0x1ffe0000ULL) >> 15;
|
||||
@ -388,57 +206,19 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
|
||||
while (pte < end)
|
||||
nv_wo32(dev, pgt, pte++, 0);
|
||||
}
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00050001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00000001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00040001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
return;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00060001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
|
||||
}
|
||||
nv50_vm_flush(dev, 5);
|
||||
nv50_vm_flush(dev, 0);
|
||||
nv50_vm_flush(dev, 4);
|
||||
nv50_vm_flush(dev, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup everything
|
||||
*/
|
||||
void nouveau_mem_takedown(struct mem_block **heap)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
if (!*heap)
|
||||
return;
|
||||
|
||||
for (p = (*heap)->next; p != *heap;) {
|
||||
struct mem_block *q = p;
|
||||
p = p->next;
|
||||
kfree(q);
|
||||
}
|
||||
|
||||
kfree(*heap);
|
||||
*heap = NULL;
|
||||
}
|
||||
|
||||
void nouveau_mem_close(struct drm_device *dev)
|
||||
void
|
||||
nouveau_mem_close(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
@ -449,8 +229,7 @@ void nouveau_mem_close(struct drm_device *dev)
|
||||
|
||||
nouveau_ttm_global_release(dev_priv);
|
||||
|
||||
if (drm_core_has_AGP(dev) && dev->agp &&
|
||||
drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
if (drm_core_has_AGP(dev) && dev->agp) {
|
||||
struct drm_agp_mem *entry, *tempe;
|
||||
|
||||
/* Remove AGP resources, but leave dev->agp
|
||||
@ -471,28 +250,29 @@ void nouveau_mem_close(struct drm_device *dev)
|
||||
}
|
||||
|
||||
if (dev_priv->fb_mtrr) {
|
||||
drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),
|
||||
drm_get_resource_len(dev, 1), DRM_MTRR_WC);
|
||||
dev_priv->fb_mtrr = 0;
|
||||
drm_mtrr_del(dev_priv->fb_mtrr,
|
||||
pci_resource_start(dev->pdev, 1),
|
||||
pci_resource_len(dev->pdev, 1), DRM_MTRR_WC);
|
||||
dev_priv->fb_mtrr = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
nouveau_mem_detect_nv04(struct drm_device *dev)
|
||||
{
|
||||
uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0);
|
||||
uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);
|
||||
|
||||
if (boot0 & 0x00000100)
|
||||
return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;
|
||||
|
||||
switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) {
|
||||
case NV04_BOOT_0_RAM_AMOUNT_32MB:
|
||||
switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
|
||||
return 32 * 1024 * 1024;
|
||||
case NV04_BOOT_0_RAM_AMOUNT_16MB:
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
|
||||
return 16 * 1024 * 1024;
|
||||
case NV04_BOOT_0_RAM_AMOUNT_8MB:
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
|
||||
return 8 * 1024 * 1024;
|
||||
case NV04_BOOT_0_RAM_AMOUNT_4MB:
|
||||
case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
|
||||
return 4 * 1024 * 1024;
|
||||
}
|
||||
|
||||
@ -536,12 +316,18 @@ nouveau_mem_detect(struct drm_device *dev)
|
||||
} else
|
||||
if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
|
||||
dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
|
||||
} else
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
|
||||
dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
|
||||
} else {
|
||||
dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA);
|
||||
dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
|
||||
if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
|
||||
dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
|
||||
dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
|
||||
dev_priv->vram_size &= 0xffffffff00ll;
|
||||
if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
|
||||
dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
|
||||
dev_priv->vram_sys_base <<= 12;
|
||||
}
|
||||
}
|
||||
|
||||
NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
|
||||
@ -555,18 +341,36 @@ nouveau_mem_detect(struct drm_device *dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if __OS_HAS_AGP
|
||||
static void nouveau_mem_reset_agp(struct drm_device *dev)
|
||||
int
|
||||
nouveau_mem_reset_agp(struct drm_device *dev)
|
||||
{
|
||||
uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable;
|
||||
#if __OS_HAS_AGP
|
||||
uint32_t saved_pci_nv_1, pmc_enable;
|
||||
int ret;
|
||||
|
||||
/* First of all, disable fast writes, otherwise if it's
|
||||
* already enabled in the AGP bridge and we disable the card's
|
||||
* AGP controller we might be locking ourselves out of it. */
|
||||
if (dev->agp->acquired) {
|
||||
struct drm_agp_info info;
|
||||
struct drm_agp_mode mode;
|
||||
|
||||
ret = drm_agp_info(dev, &info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mode.mode = info.mode & ~0x10;
|
||||
ret = drm_agp_enable(dev, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1);
|
||||
saved_pci_nv_19 = nv_rd32(dev, NV04_PBUS_PCI_NV_19);
|
||||
|
||||
/* clear busmaster bit */
|
||||
nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
|
||||
/* clear SBA and AGP bits */
|
||||
nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
|
||||
/* disable AGP */
|
||||
nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0);
|
||||
|
||||
/* power cycle pgraph, if enabled */
|
||||
pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
|
||||
@ -578,11 +382,12 @@ static void nouveau_mem_reset_agp(struct drm_device *dev)
|
||||
}
|
||||
|
||||
/* and restore (gives effect of resetting AGP) */
|
||||
nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
|
||||
nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_mem_init_agp(struct drm_device *dev)
|
||||
{
|
||||
@ -592,11 +397,6 @@ nouveau_mem_init_agp(struct drm_device *dev)
|
||||
struct drm_agp_mode mode;
|
||||
int ret;
|
||||
|
||||
if (nouveau_noagp)
|
||||
return 0;
|
||||
|
||||
nouveau_mem_reset_agp(dev);
|
||||
|
||||
if (!dev->agp->acquired) {
|
||||
ret = drm_agp_acquire(dev);
|
||||
if (ret) {
|
||||
@ -633,7 +433,7 @@ nouveau_mem_init(struct drm_device *dev)
|
||||
struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
|
||||
int ret, dma_bits = 32;
|
||||
|
||||
dev_priv->fb_phys = drm_get_resource_start(dev, 1);
|
||||
dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
|
||||
dev_priv->gart_info.type = NOUVEAU_GART_NONE;
|
||||
|
||||
if (dev_priv->card_type >= NV_50 &&
|
||||
@ -665,8 +465,9 @@ nouveau_mem_init(struct drm_device *dev)
|
||||
|
||||
dev_priv->fb_available_size = dev_priv->vram_size;
|
||||
dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
|
||||
if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1))
|
||||
dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1);
|
||||
if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
|
||||
dev_priv->fb_mappable_pages =
|
||||
pci_resource_len(dev->pdev, 1);
|
||||
dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
|
||||
|
||||
/* remove reserved space at end of vram from available amount */
|
||||
@ -692,7 +493,8 @@ nouveau_mem_init(struct drm_device *dev)
|
||||
|
||||
/* GART */
|
||||
#if !defined(__powerpc__) && !defined(__ia64__)
|
||||
if (drm_device_is_agp(dev) && dev->agp) {
|
||||
if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) {
|
||||
nouveau_mem_reset_agp(dev);
|
||||
ret = nouveau_mem_init_agp(dev);
|
||||
if (ret)
|
||||
NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
|
||||
@ -718,8 +520,8 @@ nouveau_mem_init(struct drm_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
|
||||
drm_get_resource_len(dev, 1),
|
||||
dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
|
||||
pci_resource_len(dev->pdev, 1),
|
||||
DRM_MTRR_WC);
|
||||
|
||||
return 0;
|
||||
|
@ -55,7 +55,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size);
|
||||
ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
@ -80,7 +80,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
|
||||
nouveau_bo_unpin(chan->notifier_bo);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
|
||||
nouveau_mem_takedown(&chan->notifier_heap);
|
||||
drm_mm_takedown(&chan->notifier_heap);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -90,7 +90,7 @@ nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
|
||||
NV_DEBUG(dev, "\n");
|
||||
|
||||
if (gpuobj->priv)
|
||||
nouveau_mem_free_block(gpuobj->priv);
|
||||
drm_mm_put_block(gpuobj->priv);
|
||||
}
|
||||
|
||||
int
|
||||
@ -100,18 +100,13 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *nobj = NULL;
|
||||
struct mem_block *mem;
|
||||
struct drm_mm_node *mem;
|
||||
uint32_t offset;
|
||||
int target, ret;
|
||||
|
||||
if (!chan->notifier_heap) {
|
||||
NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n",
|
||||
chan->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0,
|
||||
(struct drm_file *)-2, 0);
|
||||
mem = drm_mm_search_free(&chan->notifier_heap, size, 0, 0);
|
||||
if (mem)
|
||||
mem = drm_mm_get_block(mem, size, 0);
|
||||
if (!mem) {
|
||||
NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
|
||||
return -ENOMEM;
|
||||
@ -144,17 +139,17 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
|
||||
mem->size, NV_DMA_ACCESS_RW, target,
|
||||
&nobj);
|
||||
if (ret) {
|
||||
nouveau_mem_free_block(mem);
|
||||
drm_mm_put_block(mem);
|
||||
NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
nobj->dtor = nouveau_notifier_gpuobj_dtor;
|
||||
nobj->priv = mem;
|
||||
nobj->dtor = nouveau_notifier_gpuobj_dtor;
|
||||
nobj->priv = mem;
|
||||
|
||||
ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL);
|
||||
if (ret) {
|
||||
nouveau_gpuobj_del(dev, &nobj);
|
||||
nouveau_mem_free_block(mem);
|
||||
drm_mm_put_block(mem);
|
||||
NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
@ -170,7 +165,7 @@ nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset)
|
||||
return -EINVAL;
|
||||
|
||||
if (poffset) {
|
||||
struct mem_block *mem = nobj->priv;
|
||||
struct drm_mm_node *mem = nobj->priv;
|
||||
|
||||
if (*poffset >= mem->size)
|
||||
return false;
|
||||
@ -189,7 +184,6 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
|
||||
|
||||
ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset);
|
||||
|
@ -132,7 +132,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
}
|
||||
}
|
||||
|
||||
instmem->prepare_access(dev, true);
|
||||
co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
|
||||
do {
|
||||
if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
|
||||
@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
nv_wo32(dev, ramht, (co + 4)/4, ctx);
|
||||
|
||||
list_add_tail(&ref->list, &chan->ramht_refs);
|
||||
instmem->finish_access(dev);
|
||||
instmem->flush(dev);
|
||||
return 0;
|
||||
}
|
||||
NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
|
||||
@ -153,7 +152,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
if (co >= dev_priv->ramht_size)
|
||||
co = 0;
|
||||
} while (co != ho);
|
||||
instmem->finish_access(dev);
|
||||
|
||||
NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
|
||||
return -ENOMEM;
|
||||
@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
return;
|
||||
}
|
||||
|
||||
instmem->prepare_access(dev, true);
|
||||
co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
|
||||
do {
|
||||
if (nouveau_ramht_entry_valid(dev, ramht, co) &&
|
||||
@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
nv_wo32(dev, ramht, (co + 4)/4, 0x00000000);
|
||||
|
||||
list_del(&ref->list);
|
||||
instmem->finish_access(dev);
|
||||
instmem->flush(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
|
||||
co = 0;
|
||||
} while (co != ho);
|
||||
list_del(&ref->list);
|
||||
instmem->finish_access(dev);
|
||||
|
||||
NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
|
||||
chan->id, ref->handle);
|
||||
@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine *engine = &dev_priv->engine;
|
||||
struct nouveau_gpuobj *gpuobj;
|
||||
struct mem_block *pramin = NULL;
|
||||
struct drm_mm *pramin = NULL;
|
||||
int ret;
|
||||
|
||||
NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
|
||||
@ -233,25 +229,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
|
||||
* available.
|
||||
*/
|
||||
if (chan) {
|
||||
if (chan->ramin_heap) {
|
||||
NV_DEBUG(dev, "private heap\n");
|
||||
pramin = chan->ramin_heap;
|
||||
} else
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
NV_DEBUG(dev, "global heap fallback\n");
|
||||
pramin = dev_priv->ramin_heap;
|
||||
}
|
||||
NV_DEBUG(dev, "channel heap\n");
|
||||
pramin = &chan->ramin_heap;
|
||||
} else {
|
||||
NV_DEBUG(dev, "global heap\n");
|
||||
pramin = dev_priv->ramin_heap;
|
||||
}
|
||||
pramin = &dev_priv->ramin_heap;
|
||||
|
||||
if (!pramin) {
|
||||
NV_ERROR(dev, "No PRAMIN heap!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!chan) {
|
||||
ret = engine->instmem.populate(dev, gpuobj, &size);
|
||||
if (ret) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
|
||||
}
|
||||
|
||||
/* Allocate a chunk of the PRAMIN aperture */
|
||||
gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
|
||||
drm_order(align),
|
||||
(struct drm_file *)-2, 0);
|
||||
gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0);
|
||||
if (gpuobj->im_pramin)
|
||||
gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align);
|
||||
|
||||
if (!gpuobj->im_pramin) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
return -ENOMEM;
|
||||
@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
|
||||
if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
|
||||
int i;
|
||||
|
||||
engine->instmem.prepare_access(dev, true);
|
||||
for (i = 0; i < gpuobj->im_pramin->size; i += 4)
|
||||
nv_wo32(dev, gpuobj, i/4, 0);
|
||||
engine->instmem.finish_access(dev);
|
||||
engine->instmem.flush(dev);
|
||||
}
|
||||
|
||||
*gpuobj_ret = gpuobj;
|
||||
@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
||||
}
|
||||
|
||||
if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
|
||||
engine->instmem.prepare_access(dev, true);
|
||||
for (i = 0; i < gpuobj->im_pramin->size; i += 4)
|
||||
nv_wo32(dev, gpuobj, i/4, 0);
|
||||
engine->instmem.finish_access(dev);
|
||||
engine->instmem.flush(dev);
|
||||
}
|
||||
|
||||
if (gpuobj->dtor)
|
||||
@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
|
||||
if (gpuobj->flags & NVOBJ_FLAG_FAKE)
|
||||
kfree(gpuobj->im_pramin);
|
||||
else
|
||||
nouveau_mem_free_block(gpuobj->im_pramin);
|
||||
drm_mm_put_block(gpuobj->im_pramin);
|
||||
}
|
||||
|
||||
list_del(&gpuobj->list);
|
||||
@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
|
||||
list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
|
||||
|
||||
if (p_offset != ~0) {
|
||||
gpuobj->im_pramin = kzalloc(sizeof(struct mem_block),
|
||||
gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node),
|
||||
GFP_KERNEL);
|
||||
if (!gpuobj->im_pramin) {
|
||||
nouveau_gpuobj_del(dev, &gpuobj);
|
||||
@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
|
||||
}
|
||||
|
||||
if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
for (i = 0; i < gpuobj->im_pramin->size; i += 4)
|
||||
nv_wo32(dev, gpuobj, i/4, 0);
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
}
|
||||
|
||||
if (pref) {
|
||||
@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
|
||||
return ret;
|
||||
}
|
||||
|
||||
instmem->prepare_access(dev, true);
|
||||
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
uint32_t frame, adjust, pte_flags = 0;
|
||||
|
||||
@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
|
||||
nv_wo32(dev, *gpuobj, 5, flags5);
|
||||
}
|
||||
|
||||
instmem->finish_access(dev);
|
||||
instmem->flush(dev);
|
||||
|
||||
(*gpuobj)->engine = NVOBJ_ENGINE_SW;
|
||||
(*gpuobj)->class = class;
|
||||
@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
nv_wo32(dev, *gpuobj, 0, class);
|
||||
nv_wo32(dev, *gpuobj, 5, 0x00010000);
|
||||
@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
|
||||
}
|
||||
}
|
||||
}
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
(*gpuobj)->engine = NVOBJ_ENGINE_GR;
|
||||
(*gpuobj)->class = class;
|
||||
@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
|
||||
base = 0;
|
||||
|
||||
/* PGRAPH context */
|
||||
size += dev_priv->engine.graph.grctx_size;
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
/* Various fixed table thingos */
|
||||
@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
|
||||
size += 0x8000;
|
||||
/* RAMFC */
|
||||
size += 0x1000;
|
||||
/* PGRAPH context */
|
||||
size += 0x70000;
|
||||
}
|
||||
|
||||
NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
|
||||
chan->id, size, base);
|
||||
ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
|
||||
&chan->ramin);
|
||||
if (ret) {
|
||||
@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
|
||||
}
|
||||
pramin = chan->ramin->gpuobj;
|
||||
|
||||
ret = nouveau_mem_init_heap(&chan->ramin_heap,
|
||||
pramin->im_pramin->start + base, size);
|
||||
ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin);
|
||||
@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
|
||||
NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
|
||||
|
||||
/* Reserve a block of PRAMIN for the channel
|
||||
*XXX: maybe on <NV50 too at some point
|
||||
*/
|
||||
if (0 || dev_priv->card_type == NV_50) {
|
||||
ret = nouveau_gpuobj_channel_init_pramin(chan);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "init pramin\n");
|
||||
return ret;
|
||||
}
|
||||
/* Allocate a chunk of memory for per-channel object storage */
|
||||
ret = nouveau_gpuobj_channel_init_pramin(chan);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "init pramin\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NV50 VM
|
||||
@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
uint32_t vm_offset, pde;
|
||||
|
||||
instmem->prepare_access(dev, true);
|
||||
|
||||
vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
|
||||
vm_offset += chan->ramin->gpuobj->im_pramin->start;
|
||||
|
||||
ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
|
||||
0, &chan->vm_pd, NULL);
|
||||
if (ret) {
|
||||
instmem->finish_access(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
for (i = 0; i < 0x4000; i += 8) {
|
||||
nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000);
|
||||
nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe);
|
||||
@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
|
||||
dev_priv->gart_info.sg_ctxdma,
|
||||
&chan->vm_gart_pt);
|
||||
if (ret) {
|
||||
instmem->finish_access(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
nv_wo32(dev, chan->vm_pd, pde++,
|
||||
chan->vm_gart_pt->instance | 0x03);
|
||||
nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
|
||||
@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
|
||||
ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
|
||||
dev_priv->vm_vram_pt[i],
|
||||
&chan->vm_vram_pt[i]);
|
||||
if (ret) {
|
||||
instmem->finish_access(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nv_wo32(dev, chan->vm_pd, pde++,
|
||||
chan->vm_vram_pt[i]->instance | 0x61);
|
||||
nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
|
||||
}
|
||||
|
||||
instmem->finish_access(dev);
|
||||
instmem->flush(dev);
|
||||
}
|
||||
|
||||
/* RAMHT */
|
||||
@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
|
||||
for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]);
|
||||
|
||||
if (chan->ramin_heap)
|
||||
nouveau_mem_takedown(&chan->ramin_heap);
|
||||
if (chan->ramin_heap.free_stack.next)
|
||||
drm_mm_takedown(&chan->ramin_heap);
|
||||
if (chan->ramin)
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramin);
|
||||
|
||||
@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, false);
|
||||
for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
|
||||
gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i);
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev)
|
||||
if (!gpuobj->im_backing_suspend)
|
||||
continue;
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
|
||||
nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]);
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
}
|
||||
|
||||
nouveau_gpuobj_suspend_cleanup(dev);
|
||||
@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
|
||||
|
||||
if (init->handle == ~0)
|
||||
@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
|
||||
struct nouveau_channel *chan;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
|
||||
|
||||
ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref);
|
||||
|
@ -1,19 +1,64 @@
|
||||
|
||||
#define NV04_PFB_BOOT_0 0x00100000
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002
|
||||
# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003
|
||||
# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020
|
||||
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028
|
||||
# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100
|
||||
# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000
|
||||
#define NV04_PFB_DEBUG_0 0x00100080
|
||||
# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001
|
||||
# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010
|
||||
# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00
|
||||
# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000
|
||||
# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000
|
||||
# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000
|
||||
# define NV04_PFB_DEBUG_0_CASOE 0x00100000
|
||||
# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000
|
||||
# define NV04_PFB_DEBUG_0_REFINC 0x20000000
|
||||
# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000
|
||||
#define NV04_PFB_CFG0 0x00100200
|
||||
# define NV04_PFB_CFG0_SCRAMBLE 0x20000000
|
||||
#define NV04_PFB_CFG1 0x00100204
|
||||
#define NV04_PFB_FIFO_DATA 0x0010020c
|
||||
# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000
|
||||
# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20
|
||||
#define NV10_PFB_REFCTRL 0x00100210
|
||||
# define NV10_PFB_REFCTRL_VALID_1 (1 << 31)
|
||||
#define NV04_PFB_PAD 0x0010021c
|
||||
# define NV04_PFB_PAD_CKE_NORMAL (1 << 0)
|
||||
#define NV10_PFB_TILE(i) (0x00100240 + (i*16))
|
||||
#define NV10_PFB_TILE__SIZE 8
|
||||
#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16))
|
||||
#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16))
|
||||
#define NV10_PFB_TSTATUS(i) (0x0010024c + (i*16))
|
||||
#define NV04_PFB_REF 0x001002d0
|
||||
# define NV04_PFB_REF_CMD_REFRESH (1 << 0)
|
||||
#define NV04_PFB_PRE 0x001002d4
|
||||
# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0)
|
||||
#define NV10_PFB_CLOSE_PAGE2 0x0010033c
|
||||
#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i))
|
||||
#define NV40_PFB_TILE(i) (0x00100600 + (i*16))
|
||||
#define NV40_PFB_TILE__SIZE_0 12
|
||||
#define NV40_PFB_TILE__SIZE_1 15
|
||||
#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16))
|
||||
#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16))
|
||||
#define NV40_PFB_TSTATUS(i) (0x0010060c + (i*16))
|
||||
#define NV40_PFB_UNK_800 0x00100800
|
||||
|
||||
#define NV03_BOOT_0 0x00100000
|
||||
# define NV03_BOOT_0_RAM_AMOUNT 0x00000003
|
||||
# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000
|
||||
# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001
|
||||
# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002
|
||||
# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003
|
||||
# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000
|
||||
# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001
|
||||
# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002
|
||||
# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003
|
||||
|
||||
#define NV04_FIFO_DATA 0x0010020c
|
||||
# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000
|
||||
# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20
|
||||
#define NV_PEXTDEV_BOOT_0 0x00101000
|
||||
#define NV_PEXTDEV_BOOT_0_RAMCFG 0x0000003c
|
||||
# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12)
|
||||
#define NV_PEXTDEV_BOOT_3 0x0010100c
|
||||
|
||||
#define NV_RAMIN 0x00700000
|
||||
|
||||
@ -131,23 +176,6 @@
|
||||
#define NV04_PTIMER_TIME_1 0x00009410
|
||||
#define NV04_PTIMER_ALARM_0 0x00009420
|
||||
|
||||
#define NV04_PFB_CFG0 0x00100200
|
||||
#define NV04_PFB_CFG1 0x00100204
|
||||
#define NV40_PFB_020C 0x0010020C
|
||||
#define NV10_PFB_TILE(i) (0x00100240 + (i*16))
|
||||
#define NV10_PFB_TILE__SIZE 8
|
||||
#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16))
|
||||
#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16))
|
||||
#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16))
|
||||
#define NV10_PFB_CLOSE_PAGE2 0x0010033C
|
||||
#define NV40_PFB_TILE(i) (0x00100600 + (i*16))
|
||||
#define NV40_PFB_TILE__SIZE_0 12
|
||||
#define NV40_PFB_TILE__SIZE_1 15
|
||||
#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16))
|
||||
#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16))
|
||||
#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16))
|
||||
#define NV40_PFB_UNK_800 0x00100800
|
||||
|
||||
#define NV04_PGRAPH_DEBUG_0 0x00400080
|
||||
#define NV04_PGRAPH_DEBUG_1 0x00400084
|
||||
#define NV04_PGRAPH_DEBUG_2 0x00400088
|
||||
@ -814,6 +842,7 @@
|
||||
#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000
|
||||
#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff
|
||||
#define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80)
|
||||
#define NV50_SOR_DP_CTRL_ENABLED 0x00000001
|
||||
#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000
|
||||
#define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000
|
||||
#define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000
|
||||
|
@ -97,7 +97,6 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
|
||||
|
||||
NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start);
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
|
||||
pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT);
|
||||
nvbe->pte_start = pte;
|
||||
for (i = 0; i < nvbe->nr_pages; i++) {
|
||||
@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
|
||||
dma_offset += NV_CTXDMA_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
dev_priv->engine.instmem.finish_access(nvbe->dev);
|
||||
dev_priv->engine.instmem.flush(nvbe->dev);
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
nv_wr32(dev, 0x100c80, 0x00050001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
|
||||
nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00000001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
|
||||
nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
nv50_vm_flush(dev, 5); /* PGRAPH */
|
||||
nv50_vm_flush(dev, 0); /* PFIFO */
|
||||
}
|
||||
|
||||
nvbe->bound = true;
|
||||
@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
|
||||
if (!nvbe->bound)
|
||||
return 0;
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
|
||||
pte = nvbe->pte_start;
|
||||
for (i = 0; i < nvbe->nr_pages; i++) {
|
||||
dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
|
||||
@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
|
||||
dma_offset += NV_CTXDMA_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
dev_priv->engine.instmem.finish_access(nvbe->dev);
|
||||
dev_priv->engine.instmem.flush(nvbe->dev);
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
nv_wr32(dev, 0x100c80, 0x00050001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
|
||||
nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x100c80, 0x00000001);
|
||||
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
|
||||
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
|
||||
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
|
||||
nv_rd32(dev, 0x100c80));
|
||||
return -EBUSY;
|
||||
}
|
||||
nv50_vm_flush(dev, 5);
|
||||
nv50_vm_flush(dev, 0);
|
||||
}
|
||||
|
||||
nvbe->bound = false;
|
||||
@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev)
|
||||
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
|
||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
|
||||
* confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE
|
||||
@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev)
|
||||
nv_wo32(dev, gpuobj, (i+4)/4, 0);
|
||||
}
|
||||
}
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
dev_priv->engine.instmem.flush(dev);
|
||||
|
||||
dev_priv->gart_info.type = NOUVEAU_GART_SGDMA;
|
||||
dev_priv->gart_info.aper_base = 0;
|
||||
@ -325,14 +296,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
|
||||
struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
|
||||
int pte;
|
||||
|
||||
pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
|
||||
if (dev_priv->card_type < NV_50) {
|
||||
instmem->prepare_access(dev, false);
|
||||
*page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
|
||||
instmem->finish_access(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "nv50_display.h"
|
||||
|
||||
static void nouveau_stub_takedown(struct drm_device *dev) {}
|
||||
static int nouveau_stub_init(struct drm_device *dev) { return 0; }
|
||||
|
||||
static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
{
|
||||
@ -54,8 +55,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.clear = nv04_instmem_clear;
|
||||
engine->instmem.bind = nv04_instmem_bind;
|
||||
engine->instmem.unbind = nv04_instmem_unbind;
|
||||
engine->instmem.prepare_access = nv04_instmem_prepare_access;
|
||||
engine->instmem.finish_access = nv04_instmem_finish_access;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->mc.init = nv04_mc_init;
|
||||
engine->mc.takedown = nv04_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
@ -85,6 +85,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv04_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv04_fifo_load_context;
|
||||
engine->fifo.unload_context = nv04_fifo_unload_context;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
engine->display.init = nv04_display_init;
|
||||
engine->display.destroy = nv04_display_destroy;
|
||||
engine->gpio.init = nouveau_stub_init;
|
||||
engine->gpio.takedown = nouveau_stub_takedown;
|
||||
engine->gpio.get = NULL;
|
||||
engine->gpio.set = NULL;
|
||||
engine->gpio.irq_enable = NULL;
|
||||
break;
|
||||
case 0x10:
|
||||
engine->instmem.init = nv04_instmem_init;
|
||||
@ -95,8 +105,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.clear = nv04_instmem_clear;
|
||||
engine->instmem.bind = nv04_instmem_bind;
|
||||
engine->instmem.unbind = nv04_instmem_unbind;
|
||||
engine->instmem.prepare_access = nv04_instmem_prepare_access;
|
||||
engine->instmem.finish_access = nv04_instmem_finish_access;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->mc.init = nv04_mc_init;
|
||||
engine->mc.takedown = nv04_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
@ -128,6 +137,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv10_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv10_fifo_load_context;
|
||||
engine->fifo.unload_context = nv10_fifo_unload_context;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
engine->display.init = nv04_display_init;
|
||||
engine->display.destroy = nv04_display_destroy;
|
||||
engine->gpio.init = nouveau_stub_init;
|
||||
engine->gpio.takedown = nouveau_stub_takedown;
|
||||
engine->gpio.get = nv10_gpio_get;
|
||||
engine->gpio.set = nv10_gpio_set;
|
||||
engine->gpio.irq_enable = NULL;
|
||||
break;
|
||||
case 0x20:
|
||||
engine->instmem.init = nv04_instmem_init;
|
||||
@ -138,8 +157,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.clear = nv04_instmem_clear;
|
||||
engine->instmem.bind = nv04_instmem_bind;
|
||||
engine->instmem.unbind = nv04_instmem_unbind;
|
||||
engine->instmem.prepare_access = nv04_instmem_prepare_access;
|
||||
engine->instmem.finish_access = nv04_instmem_finish_access;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->mc.init = nv04_mc_init;
|
||||
engine->mc.takedown = nv04_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
@ -171,6 +189,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv10_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv10_fifo_load_context;
|
||||
engine->fifo.unload_context = nv10_fifo_unload_context;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
engine->display.init = nv04_display_init;
|
||||
engine->display.destroy = nv04_display_destroy;
|
||||
engine->gpio.init = nouveau_stub_init;
|
||||
engine->gpio.takedown = nouveau_stub_takedown;
|
||||
engine->gpio.get = nv10_gpio_get;
|
||||
engine->gpio.set = nv10_gpio_set;
|
||||
engine->gpio.irq_enable = NULL;
|
||||
break;
|
||||
case 0x30:
|
||||
engine->instmem.init = nv04_instmem_init;
|
||||
@ -181,15 +209,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.clear = nv04_instmem_clear;
|
||||
engine->instmem.bind = nv04_instmem_bind;
|
||||
engine->instmem.unbind = nv04_instmem_unbind;
|
||||
engine->instmem.prepare_access = nv04_instmem_prepare_access;
|
||||
engine->instmem.finish_access = nv04_instmem_finish_access;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->mc.init = nv04_mc_init;
|
||||
engine->mc.takedown = nv04_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
engine->timer.read = nv04_timer_read;
|
||||
engine->timer.takedown = nv04_timer_takedown;
|
||||
engine->fb.init = nv10_fb_init;
|
||||
engine->fb.takedown = nv10_fb_takedown;
|
||||
engine->fb.init = nv30_fb_init;
|
||||
engine->fb.takedown = nv30_fb_takedown;
|
||||
engine->fb.set_region_tiling = nv10_fb_set_region_tiling;
|
||||
engine->graph.grclass = nv30_graph_grclass;
|
||||
engine->graph.init = nv30_graph_init;
|
||||
@ -214,6 +241,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv10_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv10_fifo_load_context;
|
||||
engine->fifo.unload_context = nv10_fifo_unload_context;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
engine->display.init = nv04_display_init;
|
||||
engine->display.destroy = nv04_display_destroy;
|
||||
engine->gpio.init = nouveau_stub_init;
|
||||
engine->gpio.takedown = nouveau_stub_takedown;
|
||||
engine->gpio.get = nv10_gpio_get;
|
||||
engine->gpio.set = nv10_gpio_set;
|
||||
engine->gpio.irq_enable = NULL;
|
||||
break;
|
||||
case 0x40:
|
||||
case 0x60:
|
||||
@ -225,8 +262,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.clear = nv04_instmem_clear;
|
||||
engine->instmem.bind = nv04_instmem_bind;
|
||||
engine->instmem.unbind = nv04_instmem_unbind;
|
||||
engine->instmem.prepare_access = nv04_instmem_prepare_access;
|
||||
engine->instmem.finish_access = nv04_instmem_finish_access;
|
||||
engine->instmem.flush = nv04_instmem_flush;
|
||||
engine->mc.init = nv40_mc_init;
|
||||
engine->mc.takedown = nv40_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
@ -258,6 +294,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv40_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv40_fifo_load_context;
|
||||
engine->fifo.unload_context = nv40_fifo_unload_context;
|
||||
engine->display.early_init = nv04_display_early_init;
|
||||
engine->display.late_takedown = nv04_display_late_takedown;
|
||||
engine->display.create = nv04_display_create;
|
||||
engine->display.init = nv04_display_init;
|
||||
engine->display.destroy = nv04_display_destroy;
|
||||
engine->gpio.init = nouveau_stub_init;
|
||||
engine->gpio.takedown = nouveau_stub_takedown;
|
||||
engine->gpio.get = nv10_gpio_get;
|
||||
engine->gpio.set = nv10_gpio_set;
|
||||
engine->gpio.irq_enable = NULL;
|
||||
break;
|
||||
case 0x50:
|
||||
case 0x80: /* gotta love NVIDIA's consistency.. */
|
||||
@ -271,8 +317,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->instmem.clear = nv50_instmem_clear;
|
||||
engine->instmem.bind = nv50_instmem_bind;
|
||||
engine->instmem.unbind = nv50_instmem_unbind;
|
||||
engine->instmem.prepare_access = nv50_instmem_prepare_access;
|
||||
engine->instmem.finish_access = nv50_instmem_finish_access;
|
||||
if (dev_priv->chipset == 0x50)
|
||||
engine->instmem.flush = nv50_instmem_flush;
|
||||
else
|
||||
engine->instmem.flush = nv84_instmem_flush;
|
||||
engine->mc.init = nv50_mc_init;
|
||||
engine->mc.takedown = nv50_mc_takedown;
|
||||
engine->timer.init = nv04_timer_init;
|
||||
@ -300,6 +348,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
engine->fifo.destroy_context = nv50_fifo_destroy_context;
|
||||
engine->fifo.load_context = nv50_fifo_load_context;
|
||||
engine->fifo.unload_context = nv50_fifo_unload_context;
|
||||
engine->display.early_init = nv50_display_early_init;
|
||||
engine->display.late_takedown = nv50_display_late_takedown;
|
||||
engine->display.create = nv50_display_create;
|
||||
engine->display.init = nv50_display_init;
|
||||
engine->display.destroy = nv50_display_destroy;
|
||||
engine->gpio.init = nv50_gpio_init;
|
||||
engine->gpio.takedown = nouveau_stub_takedown;
|
||||
engine->gpio.get = nv50_gpio_get;
|
||||
engine->gpio.set = nv50_gpio_set;
|
||||
engine->gpio.irq_enable = nv50_gpio_irq_enable;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
|
||||
@ -407,11 +465,6 @@ nouveau_card_init(struct drm_device *dev)
|
||||
struct nouveau_engine *engine;
|
||||
int ret;
|
||||
|
||||
NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
|
||||
|
||||
if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
|
||||
return 0;
|
||||
|
||||
vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
|
||||
vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
|
||||
nouveau_switcheroo_can_switch);
|
||||
@ -421,15 +474,17 @@ nouveau_card_init(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto out;
|
||||
engine = &dev_priv->engine;
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
|
||||
spin_lock_init(&dev_priv->context_switch_lock);
|
||||
|
||||
/* Make the CRTCs and I2C buses accessible */
|
||||
ret = engine->display.early_init(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Parse BIOS tables / Run init tables if card not POSTed */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = nouveau_bios_init(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
ret = nouveau_bios_init(dev);
|
||||
if (ret)
|
||||
goto out_display_early;
|
||||
|
||||
ret = nouveau_mem_detect(dev);
|
||||
if (ret)
|
||||
@ -461,10 +516,15 @@ nouveau_card_init(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto out_gpuobj;
|
||||
|
||||
/* PGPIO */
|
||||
ret = engine->gpio.init(dev);
|
||||
if (ret)
|
||||
goto out_mc;
|
||||
|
||||
/* PTIMER */
|
||||
ret = engine->timer.init(dev);
|
||||
if (ret)
|
||||
goto out_mc;
|
||||
goto out_gpio;
|
||||
|
||||
/* PFB */
|
||||
ret = engine->fb.init(dev);
|
||||
@ -485,12 +545,16 @@ nouveau_card_init(struct drm_device *dev)
|
||||
goto out_graph;
|
||||
}
|
||||
|
||||
ret = engine->display.create(dev);
|
||||
if (ret)
|
||||
goto out_fifo;
|
||||
|
||||
/* this call irq_preinstall, register irq handler and
|
||||
* call irq_postinstall
|
||||
*/
|
||||
ret = drm_irq_install(dev);
|
||||
if (ret)
|
||||
goto out_fifo;
|
||||
goto out_display;
|
||||
|
||||
ret = drm_vblank_init(dev, 0);
|
||||
if (ret)
|
||||
@ -504,35 +568,18 @@ nouveau_card_init(struct drm_device *dev)
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
ret = nv50_display_create(dev);
|
||||
else
|
||||
ret = nv04_display_create(dev);
|
||||
if (ret)
|
||||
goto out_channel;
|
||||
}
|
||||
|
||||
ret = nouveau_backlight_init(dev);
|
||||
if (ret)
|
||||
NV_ERROR(dev, "Error %d registering backlight\n", ret);
|
||||
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
nouveau_fbcon_init(dev);
|
||||
drm_kms_helper_poll_init(dev);
|
||||
}
|
||||
|
||||
nouveau_fbcon_init(dev);
|
||||
drm_kms_helper_poll_init(dev);
|
||||
return 0;
|
||||
|
||||
out_channel:
|
||||
if (dev_priv->channel) {
|
||||
nouveau_channel_free(dev_priv->channel);
|
||||
dev_priv->channel = NULL;
|
||||
}
|
||||
out_irq:
|
||||
drm_irq_uninstall(dev);
|
||||
out_display:
|
||||
engine->display.destroy(dev);
|
||||
out_fifo:
|
||||
if (!nouveau_noaccel)
|
||||
engine->fifo.takedown(dev);
|
||||
@ -543,6 +590,8 @@ out_fb:
|
||||
engine->fb.takedown(dev);
|
||||
out_timer:
|
||||
engine->timer.takedown(dev);
|
||||
out_gpio:
|
||||
engine->gpio.takedown(dev);
|
||||
out_mc:
|
||||
engine->mc.takedown(dev);
|
||||
out_gpuobj:
|
||||
@ -556,6 +605,8 @@ out_gpuobj_early:
|
||||
nouveau_gpuobj_late_takedown(dev);
|
||||
out_bios:
|
||||
nouveau_bios_takedown(dev);
|
||||
out_display_early:
|
||||
engine->display.late_takedown(dev);
|
||||
out:
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
return ret;
|
||||
@ -566,45 +617,39 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine *engine = &dev_priv->engine;
|
||||
|
||||
NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
|
||||
nouveau_backlight_exit(dev);
|
||||
|
||||
if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
|
||||
|
||||
nouveau_backlight_exit(dev);
|
||||
|
||||
if (dev_priv->channel) {
|
||||
nouveau_channel_free(dev_priv->channel);
|
||||
dev_priv->channel = NULL;
|
||||
}
|
||||
|
||||
if (!nouveau_noaccel) {
|
||||
engine->fifo.takedown(dev);
|
||||
engine->graph.takedown(dev);
|
||||
}
|
||||
engine->fb.takedown(dev);
|
||||
engine->timer.takedown(dev);
|
||||
engine->mc.takedown(dev);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
nouveau_sgdma_takedown(dev);
|
||||
|
||||
nouveau_gpuobj_takedown(dev);
|
||||
nouveau_mem_close(dev);
|
||||
engine->instmem.takedown(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
nouveau_gpuobj_late_takedown(dev);
|
||||
nouveau_bios_takedown(dev);
|
||||
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
|
||||
if (dev_priv->channel) {
|
||||
nouveau_channel_free(dev_priv->channel);
|
||||
dev_priv->channel = NULL;
|
||||
}
|
||||
|
||||
if (!nouveau_noaccel) {
|
||||
engine->fifo.takedown(dev);
|
||||
engine->graph.takedown(dev);
|
||||
}
|
||||
engine->fb.takedown(dev);
|
||||
engine->timer.takedown(dev);
|
||||
engine->gpio.takedown(dev);
|
||||
engine->mc.takedown(dev);
|
||||
engine->display.late_takedown(dev);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
nouveau_sgdma_takedown(dev);
|
||||
|
||||
nouveau_gpuobj_takedown(dev);
|
||||
nouveau_mem_close(dev);
|
||||
engine->instmem.takedown(dev);
|
||||
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
nouveau_gpuobj_late_takedown(dev);
|
||||
nouveau_bios_takedown(dev);
|
||||
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* here a client dies, release the stuff that was allocated for its
|
||||
@ -691,6 +736,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
||||
struct drm_nouveau_private *dev_priv;
|
||||
uint32_t reg0;
|
||||
resource_size_t mmio_start_offs;
|
||||
int ret;
|
||||
|
||||
dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
|
||||
if (!dev_priv)
|
||||
@ -699,7 +745,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
||||
dev_priv->dev = dev;
|
||||
|
||||
dev_priv->flags = flags & NOUVEAU_FLAGS;
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
|
||||
|
||||
NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
|
||||
dev->pci_vendor, dev->pci_device, dev->pdev->class);
|
||||
@ -773,11 +818,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
||||
NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
|
||||
dev_priv->card_type, reg0);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
int ret = nouveau_remove_conflicting_drivers(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = nouveau_remove_conflicting_drivers(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
|
||||
if (dev_priv->card_type >= NV_40) {
|
||||
@ -812,46 +855,26 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
||||
dev_priv->flags |= NV_NFORCE2;
|
||||
|
||||
/* For kernel modesetting, init card now and bring up fbcon */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
int ret = nouveau_card_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = nouveau_card_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nouveau_close(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* In the case of an error dev_priv may not be allocated yet */
|
||||
if (dev_priv)
|
||||
nouveau_card_takedown(dev);
|
||||
}
|
||||
|
||||
/* KMS: we need mmio at load time, not when the first drm client opens. */
|
||||
void nouveau_lastclose(struct drm_device *dev)
|
||||
{
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return;
|
||||
|
||||
nouveau_close(dev);
|
||||
}
|
||||
|
||||
int nouveau_unload(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_engine *engine = &dev_priv->engine;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
nouveau_fbcon_fini(dev);
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
nv50_display_destroy(dev);
|
||||
else
|
||||
nv04_display_destroy(dev);
|
||||
nouveau_close(dev);
|
||||
}
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
nouveau_fbcon_fini(dev);
|
||||
engine->display.destroy(dev);
|
||||
nouveau_card_takedown(dev);
|
||||
|
||||
iounmap(dev_priv->mmio);
|
||||
iounmap(dev_priv->ramin);
|
||||
@ -867,8 +890,6 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_getparam *getparam = data;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
switch (getparam->param) {
|
||||
case NOUVEAU_GETPARAM_CHIPSET_ID:
|
||||
getparam->value = dev_priv->chipset;
|
||||
@ -937,8 +958,6 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct drm_nouveau_setparam *setparam = data;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
switch (setparam->param) {
|
||||
default:
|
||||
NV_ERROR(dev, "unknown parameter %lld\n", setparam->param);
|
||||
|
@ -42,13 +42,13 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_ttm_mem_global_init(struct ttm_global_reference *ref)
|
||||
nouveau_ttm_mem_global_init(struct drm_global_reference *ref)
|
||||
{
|
||||
return ttm_mem_global_init(ref->object);
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_ttm_mem_global_release(struct ttm_global_reference *ref)
|
||||
nouveau_ttm_mem_global_release(struct drm_global_reference *ref)
|
||||
{
|
||||
ttm_mem_global_release(ref->object);
|
||||
}
|
||||
@ -56,16 +56,16 @@ nouveau_ttm_mem_global_release(struct ttm_global_reference *ref)
|
||||
int
|
||||
nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
|
||||
{
|
||||
struct ttm_global_reference *global_ref;
|
||||
struct drm_global_reference *global_ref;
|
||||
int ret;
|
||||
|
||||
global_ref = &dev_priv->ttm.mem_global_ref;
|
||||
global_ref->global_type = TTM_GLOBAL_TTM_MEM;
|
||||
global_ref->global_type = DRM_GLOBAL_TTM_MEM;
|
||||
global_ref->size = sizeof(struct ttm_mem_global);
|
||||
global_ref->init = &nouveau_ttm_mem_global_init;
|
||||
global_ref->release = &nouveau_ttm_mem_global_release;
|
||||
|
||||
ret = ttm_global_item_ref(global_ref);
|
||||
ret = drm_global_item_ref(global_ref);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed setting up TTM memory accounting\n");
|
||||
dev_priv->ttm.mem_global_ref.release = NULL;
|
||||
@ -74,15 +74,15 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
|
||||
|
||||
dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object;
|
||||
global_ref = &dev_priv->ttm.bo_global_ref.ref;
|
||||
global_ref->global_type = TTM_GLOBAL_TTM_BO;
|
||||
global_ref->global_type = DRM_GLOBAL_TTM_BO;
|
||||
global_ref->size = sizeof(struct ttm_bo_global);
|
||||
global_ref->init = &ttm_bo_global_init;
|
||||
global_ref->release = &ttm_bo_global_release;
|
||||
|
||||
ret = ttm_global_item_ref(global_ref);
|
||||
ret = drm_global_item_ref(global_ref);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed setting up TTM BO subsystem\n");
|
||||
ttm_global_item_unref(&dev_priv->ttm.mem_global_ref);
|
||||
drm_global_item_unref(&dev_priv->ttm.mem_global_ref);
|
||||
dev_priv->ttm.mem_global_ref.release = NULL;
|
||||
return ret;
|
||||
}
|
||||
@ -96,8 +96,8 @@ nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv)
|
||||
if (dev_priv->ttm.mem_global_ref.release == NULL)
|
||||
return;
|
||||
|
||||
ttm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref);
|
||||
ttm_global_item_unref(&dev_priv->ttm.mem_global_ref);
|
||||
drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref);
|
||||
drm_global_item_unref(&dev_priv->ttm.mem_global_ref);
|
||||
dev_priv->ttm.mem_global_ref.release = NULL;
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_connector *connector;
|
||||
unsigned char seq1 = 0, crtc17 = 0;
|
||||
unsigned char crtc1A;
|
||||
|
||||
@ -211,6 +212,10 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
NVVgaSeqReset(dev, nv_crtc->index, false);
|
||||
|
||||
NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
|
||||
|
||||
/* Update connector polling modes */
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
|
||||
nouveau_connector_set_polling(connector);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
|
||||
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
|
||||
uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
|
||||
uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
|
||||
@ -251,22 +252,21 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
|
||||
nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
|
||||
}
|
||||
|
||||
saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
|
||||
saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
|
||||
saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
|
||||
saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
|
||||
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
|
||||
|
||||
msleep(4);
|
||||
|
||||
saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
|
||||
head = (saved_routput & 0x100) >> 8;
|
||||
#if 0
|
||||
/* if there's a spare crtc, using it will minimise flicker for the case
|
||||
* where the in-use crtc is in use by an off-chip tmds encoder */
|
||||
if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled)
|
||||
|
||||
/* if there's a spare crtc, using it will minimise flicker */
|
||||
if (!(NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX) & 0xC0))
|
||||
head ^= 1;
|
||||
#endif
|
||||
|
||||
/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
|
||||
routput = (saved_routput & 0xfffffece) | head << 8;
|
||||
|
||||
@ -304,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
|
||||
nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
|
||||
nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
|
||||
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
|
||||
|
||||
return sample;
|
||||
}
|
||||
@ -315,9 +315,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
|
||||
uint32_t sample = nv17_dac_sample_load(encoder);
|
||||
|
||||
if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
|
||||
if (nv04_dac_in_use(encoder))
|
||||
return connector_status_disconnected;
|
||||
|
||||
if (nv17_dac_sample_load(encoder) &
|
||||
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
|
||||
NV_INFO(dev, "Load detected on output %c\n",
|
||||
'@' + ffs(dcb->or));
|
||||
return connector_status_connected;
|
||||
@ -330,6 +333,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
if (nv04_dac_in_use(encoder))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -428,6 +434,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the DAC corresponding to 'encoder' is being used by
|
||||
* someone else. */
|
||||
bool nv04_dac_in_use(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
|
||||
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
|
||||
|
||||
return nv_gf4_disp_arch(encoder->dev) &&
|
||||
(dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index));
|
||||
}
|
||||
|
||||
static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
@ -501,11 +518,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
|
||||
.destroy = nv04_dac_destroy,
|
||||
};
|
||||
|
||||
int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
int
|
||||
nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
|
||||
{
|
||||
const struct drm_encoder_helper_funcs *helper;
|
||||
struct drm_encoder *encoder;
|
||||
struct nouveau_encoder *nv_encoder = NULL;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
|
||||
if (!nv_encoder)
|
||||
@ -527,5 +546,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
encoder->possible_crtcs = entry->heads;
|
||||
encoder->possible_clones = 0;
|
||||
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
return 0;
|
||||
}
|
||||
|
@ -413,10 +413,6 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
|
||||
struct dcb_entry *dcbe = nv_encoder->dcb;
|
||||
int head = nouveau_crtc(encoder->crtc)->index;
|
||||
|
||||
NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
|
||||
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
|
||||
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
|
||||
|
||||
if (dcbe->type == OUTPUT_TMDS)
|
||||
run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
|
||||
else if (dcbe->type == OUTPUT_LVDS)
|
||||
@ -584,11 +580,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
|
||||
.destroy = nv04_dfp_destroy,
|
||||
};
|
||||
|
||||
int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
int
|
||||
nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry)
|
||||
{
|
||||
const struct drm_encoder_helper_funcs *helper;
|
||||
struct drm_encoder *encoder;
|
||||
struct nouveau_encoder *nv_encoder = NULL;
|
||||
struct drm_encoder *encoder;
|
||||
int type;
|
||||
|
||||
switch (entry->type) {
|
||||
@ -613,11 +610,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
nv_encoder->dcb = entry;
|
||||
nv_encoder->or = ffs(entry->or) - 1;
|
||||
|
||||
drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type);
|
||||
drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type);
|
||||
drm_encoder_helper_add(encoder, helper);
|
||||
|
||||
encoder->possible_crtcs = entry->heads;
|
||||
encoder->possible_clones = 0;
|
||||
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,8 +32,6 @@
|
||||
#include "nouveau_encoder.h"
|
||||
#include "nouveau_connector.h"
|
||||
|
||||
#define MULTIPLE_ENCODERS(e) (e & (e - 1))
|
||||
|
||||
static void
|
||||
nv04_display_store_initial_head_owner(struct drm_device *dev)
|
||||
{
|
||||
@ -41,7 +39,7 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
|
||||
|
||||
if (dev_priv->chipset != 0x11) {
|
||||
dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
|
||||
goto ownerknown;
|
||||
return;
|
||||
}
|
||||
|
||||
/* reading CR44 is broken on nv11, so we attempt to infer it */
|
||||
@ -52,8 +50,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
|
||||
bool tvA = false;
|
||||
bool tvB = false;
|
||||
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
||||
slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
|
||||
0x80;
|
||||
if (slaved_on_B)
|
||||
@ -66,8 +62,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
|
||||
tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
|
||||
MASK(NV_CIO_CRE_LCD_LCD_SELECT));
|
||||
|
||||
NVLockVgaCrtcs(dev, true);
|
||||
|
||||
if (slaved_on_A && !tvA)
|
||||
dev_priv->crtc_owner = 0x0;
|
||||
else if (slaved_on_B && !tvB)
|
||||
@ -79,14 +73,40 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
|
||||
else
|
||||
dev_priv->crtc_owner = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
ownerknown:
|
||||
NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner);
|
||||
int
|
||||
nv04_display_early_init(struct drm_device *dev)
|
||||
{
|
||||
/* Make the I2C buses accessible. */
|
||||
if (!nv_gf4_disp_arch(dev)) {
|
||||
uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
|
||||
|
||||
/* we need to ensure the heads are not tied henceforth, or reading any
|
||||
* 8 bit reg on head B will fail
|
||||
* setting a single arbitrary head solves that */
|
||||
NVSetOwner(dev, 0);
|
||||
if (!(pmc_enable & 1))
|
||||
nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1);
|
||||
}
|
||||
|
||||
/* Unlock the VGA CRTCs. */
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
||||
/* Make sure the CRTCs aren't in slaved mode. */
|
||||
if (nv_two_heads(dev)) {
|
||||
nv04_display_store_initial_head_owner(dev);
|
||||
NVSetOwner(dev, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nv04_display_late_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (nv_two_heads(dev))
|
||||
NVSetOwner(dev, dev_priv->crtc_owner);
|
||||
|
||||
NVLockVgaCrtcs(dev, true);
|
||||
}
|
||||
|
||||
int
|
||||
@ -94,14 +114,13 @@ nv04_display_create(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct dcb_table *dcb = &dev_priv->vbios.dcb;
|
||||
struct drm_connector *connector, *ct;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_crtc *crtc;
|
||||
int i, ret;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
if (nv_two_heads(dev))
|
||||
nv04_display_store_initial_head_owner(dev);
|
||||
nouveau_hw_save_vga_fonts(dev, 1);
|
||||
|
||||
drm_mode_config_init(dev);
|
||||
@ -132,19 +151,23 @@ nv04_display_create(struct drm_device *dev)
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
struct dcb_entry *dcbent = &dcb->entry[i];
|
||||
|
||||
connector = nouveau_connector_create(dev, dcbent->connector);
|
||||
if (IS_ERR(connector))
|
||||
continue;
|
||||
|
||||
switch (dcbent->type) {
|
||||
case OUTPUT_ANALOG:
|
||||
ret = nv04_dac_create(dev, dcbent);
|
||||
ret = nv04_dac_create(connector, dcbent);
|
||||
break;
|
||||
case OUTPUT_LVDS:
|
||||
case OUTPUT_TMDS:
|
||||
ret = nv04_dfp_create(dev, dcbent);
|
||||
ret = nv04_dfp_create(connector, dcbent);
|
||||
break;
|
||||
case OUTPUT_TV:
|
||||
if (dcbent->location == DCB_LOC_ON_CHIP)
|
||||
ret = nv17_tv_create(dev, dcbent);
|
||||
ret = nv17_tv_create(connector, dcbent);
|
||||
else
|
||||
ret = nv04_tv_create(dev, dcbent);
|
||||
ret = nv04_tv_create(connector, dcbent);
|
||||
break;
|
||||
default:
|
||||
NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
|
||||
@ -155,12 +178,16 @@ nv04_display_create(struct drm_device *dev)
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < dcb->connector.entries; i++)
|
||||
nouveau_connector_create(dev, &dcb->connector.entry[i]);
|
||||
list_for_each_entry_safe(connector, ct,
|
||||
&dev->mode_config.connector_list, head) {
|
||||
if (!connector->encoder_ids[0]) {
|
||||
NV_WARN(dev, "%s has no encoders, removing\n",
|
||||
drm_get_connector_name(connector));
|
||||
connector->funcs->destroy(connector);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save previous state */
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
crtc->funcs->save(crtc);
|
||||
|
||||
@ -191,8 +218,6 @@ nv04_display_destroy(struct drm_device *dev)
|
||||
}
|
||||
|
||||
/* Restore state */
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct drm_encoder_helper_funcs *func = encoder->helper_private;
|
||||
|
||||
@ -207,15 +232,12 @@ nv04_display_destroy(struct drm_device *dev)
|
||||
nouveau_hw_save_vga_fonts(dev, 0);
|
||||
}
|
||||
|
||||
void
|
||||
nv04_display_restore(struct drm_device *dev)
|
||||
int
|
||||
nv04_display_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
||||
/* meh.. modeset apparently doesn't setup all the regs and depends
|
||||
* on pre-existing state, for now load the state of the card *before*
|
||||
* nouveau was loaded, and then do a modeset.
|
||||
@ -233,12 +255,6 @@ nv04_display_restore(struct drm_device *dev)
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
crtc->funcs->restore(crtc);
|
||||
|
||||
if (nv_two_heads(dev)) {
|
||||
NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n",
|
||||
dev_priv->crtc_owner);
|
||||
NVSetOwner(dev, dev_priv->crtc_owner);
|
||||
}
|
||||
|
||||
NVLockVgaCrtcs(dev, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,12 @@ nv04_fifo_channel_id(struct drm_device *dev)
|
||||
NV03_PFIFO_CACHE1_PUSH1_CHID_MASK;
|
||||
}
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
#define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN
|
||||
#else
|
||||
#define DMA_FETCH_ENDIANNESS 0
|
||||
#endif
|
||||
|
||||
int
|
||||
nv04_fifo_create_context(struct nouveau_channel *chan)
|
||||
{
|
||||
@ -131,18 +137,13 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
/* Setup initial state */
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
RAMFC_WR(DMA_PUT, chan->pushbuf_base);
|
||||
RAMFC_WR(DMA_GET, chan->pushbuf_base);
|
||||
RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
|
||||
RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
|
||||
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
|
||||
NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
|
||||
#ifdef __BIG_ENDIAN
|
||||
NV_PFIFO_CACHE1_BIG_ENDIAN |
|
||||
#endif
|
||||
0));
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
DMA_FETCH_ENDIANNESS));
|
||||
|
||||
/* enable the fifo dma operation */
|
||||
nv_wr32(dev, NV04_PFIFO_MODE,
|
||||
@ -169,8 +170,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid)
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t fc = NV04_RAMFC(chid), tmp;
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, false);
|
||||
|
||||
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
|
||||
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
|
||||
tmp = nv_ri32(dev, fc + 8);
|
||||
@ -181,8 +180,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid)
|
||||
nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
|
||||
nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
|
||||
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
|
||||
nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
|
||||
}
|
||||
@ -223,7 +220,6 @@ nv04_fifo_unload_context(struct drm_device *dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
|
||||
RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
|
||||
tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
|
||||
@ -233,7 +229,6 @@ nv04_fifo_unload_context(struct drm_device *dev)
|
||||
RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
|
||||
RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
|
||||
RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
nv04_fifo_do_load_context(dev, pfifo->channels - 1);
|
||||
nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
|
||||
@ -297,6 +292,7 @@ nv04_fifo_init(struct drm_device *dev)
|
||||
|
||||
nv04_fifo_init_intr(dev);
|
||||
pfifo->enable(dev);
|
||||
pfifo->reassign(dev, true);
|
||||
|
||||
for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
|
||||
if (dev_priv->fifos[i]) {
|
||||
|
@ -342,7 +342,7 @@ static uint32_t nv04_graph_ctx_regs[] = {
|
||||
};
|
||||
|
||||
struct graph_state {
|
||||
int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
|
||||
uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
|
||||
};
|
||||
|
||||
struct nouveau_channel *
|
||||
@ -527,8 +527,7 @@ static int
|
||||
nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
|
||||
int mthd, uint32_t data)
|
||||
{
|
||||
chan->fence.last_sequence_irq = data;
|
||||
nouveau_fence_handler(chan->dev, chan->id);
|
||||
atomic_set(&chan->fence.last_sequence_irq, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -49,10 +49,8 @@ nv04_instmem_determine_amount(struct drm_device *dev)
|
||||
NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10);
|
||||
|
||||
/* Clear all of it, except the BIOS image that's in the first 64KiB */
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4)
|
||||
nv_wi32(dev, i, 0x00000000);
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -106,7 +104,7 @@ int nv04_instmem_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t offset;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
nv04_instmem_determine_amount(dev);
|
||||
nv04_instmem_configure_fixed_tables(dev);
|
||||
@ -129,14 +127,14 @@ int nv04_instmem_init(struct drm_device *dev)
|
||||
offset = 0x40000;
|
||||
}
|
||||
|
||||
ret = nouveau_mem_init_heap(&dev_priv->ramin_heap,
|
||||
offset, dev_priv->ramin_rsvd_vram - offset);
|
||||
ret = drm_mm_init(&dev_priv->ramin_heap, offset,
|
||||
dev_priv->ramin_rsvd_vram - offset);
|
||||
if (ret) {
|
||||
dev_priv->ramin_heap = NULL;
|
||||
NV_ERROR(dev, "Failed to init RAMIN heap\n");
|
||||
NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
@ -186,12 +184,7 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
|
||||
}
|
||||
|
||||
void
|
||||
nv04_instmem_prepare_access(struct drm_device *dev, bool write)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nv04_instmem_finish_access(struct drm_device *dev)
|
||||
nv04_instmem_flush(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,10 @@ nv04_mc_init(struct drm_device *dev)
|
||||
*/
|
||||
|
||||
nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
|
||||
|
||||
/* Disable PROM access. */
|
||||
nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -34,69 +34,26 @@
|
||||
|
||||
#include "i2c/ch7006.h"
|
||||
|
||||
static struct {
|
||||
struct i2c_board_info board_info;
|
||||
struct drm_encoder_funcs funcs;
|
||||
struct drm_encoder_helper_funcs hfuncs;
|
||||
void *params;
|
||||
|
||||
} nv04_tv_encoder_info[] = {
|
||||
static struct i2c_board_info nv04_tv_encoder_info[] = {
|
||||
{
|
||||
.board_info = { I2C_BOARD_INFO("ch7006", 0x75) },
|
||||
.params = &(struct ch7006_encoder_params) {
|
||||
I2C_BOARD_INFO("ch7006", 0x75),
|
||||
.platform_data = &(struct ch7006_encoder_params) {
|
||||
CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
|
||||
0, 0, 0,
|
||||
CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
|
||||
CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
|
||||
},
|
||||
}
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr)
|
||||
{
|
||||
struct i2c_msg msg = {
|
||||
.addr = addr,
|
||||
.len = 0,
|
||||
};
|
||||
|
||||
return i2c_transfer(adapter, &msg, 1) == 1;
|
||||
}
|
||||
|
||||
int nv04_tv_identify(struct drm_device *dev, int i2c_index)
|
||||
{
|
||||
struct nouveau_i2c_chan *i2c;
|
||||
bool was_locked;
|
||||
int i, ret;
|
||||
|
||||
NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index);
|
||||
|
||||
i2c = nouveau_i2c_find(dev, i2c_index);
|
||||
if (!i2c)
|
||||
return -ENODEV;
|
||||
|
||||
was_locked = NVLockVgaCrtcs(dev, false);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) {
|
||||
if (probe_i2c_addr(&i2c->adapter,
|
||||
nv04_tv_encoder_info[i].board_info.addr)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < ARRAY_SIZE(nv04_tv_encoder_info)) {
|
||||
NV_TRACE(dev, "Detected TV encoder: %s\n",
|
||||
nv04_tv_encoder_info[i].board_info.type);
|
||||
|
||||
} else {
|
||||
NV_TRACE(dev, "No TV encoders found.\n");
|
||||
i = -ENODEV;
|
||||
}
|
||||
|
||||
NVLockVgaCrtcs(dev, was_locked);
|
||||
return i;
|
||||
return nouveau_i2c_identify(dev, "TV encoder",
|
||||
nv04_tv_encoder_info, i2c_index);
|
||||
}
|
||||
|
||||
|
||||
#define PLLSEL_TV_CRTC1_MASK \
|
||||
(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \
|
||||
| NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
|
||||
@ -214,30 +171,32 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
|
||||
|
||||
static void nv04_tv_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
|
||||
to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
|
||||
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
||||
kfree(nv_encoder);
|
||||
kfree(encoder->helper_private);
|
||||
kfree(nouveau_encoder(encoder));
|
||||
}
|
||||
|
||||
int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
static const struct drm_encoder_funcs nv04_tv_funcs = {
|
||||
.destroy = nv04_tv_destroy,
|
||||
};
|
||||
|
||||
int
|
||||
nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
|
||||
{
|
||||
struct nouveau_encoder *nv_encoder;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct i2c_adapter *adap;
|
||||
struct drm_encoder_funcs *funcs = NULL;
|
||||
struct drm_encoder_helper_funcs *hfuncs = NULL;
|
||||
struct drm_encoder_slave_funcs *sfuncs = NULL;
|
||||
int i2c_index = entry->i2c_index;
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_encoder_helper_funcs *hfuncs;
|
||||
struct drm_encoder_slave_funcs *sfuncs;
|
||||
struct nouveau_i2c_chan *i2c =
|
||||
nouveau_i2c_find(dev, entry->i2c_index);
|
||||
int type, ret;
|
||||
bool was_locked;
|
||||
|
||||
/* Ensure that we can talk to this encoder */
|
||||
type = nv04_tv_identify(dev, i2c_index);
|
||||
type = nv04_tv_identify(dev, entry->i2c_index);
|
||||
if (type < 0)
|
||||
return type;
|
||||
|
||||
@ -246,41 +205,32 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
if (!nv_encoder)
|
||||
return -ENOMEM;
|
||||
|
||||
hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
|
||||
if (!hfuncs) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
/* Initialize the common members */
|
||||
encoder = to_drm_encoder(nv_encoder);
|
||||
|
||||
funcs = &nv04_tv_encoder_info[type].funcs;
|
||||
hfuncs = &nv04_tv_encoder_info[type].hfuncs;
|
||||
|
||||
drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC);
|
||||
drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
|
||||
drm_encoder_helper_add(encoder, hfuncs);
|
||||
|
||||
encoder->possible_crtcs = entry->heads;
|
||||
encoder->possible_clones = 0;
|
||||
|
||||
nv_encoder->dcb = entry;
|
||||
nv_encoder->or = ffs(entry->or) - 1;
|
||||
|
||||
/* Run the slave-specific initialization */
|
||||
adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter;
|
||||
|
||||
was_locked = NVLockVgaCrtcs(dev, false);
|
||||
|
||||
ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
|
||||
&nv04_tv_encoder_info[type].board_info);
|
||||
|
||||
NVLockVgaCrtcs(dev, was_locked);
|
||||
|
||||
ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
|
||||
&i2c->adapter, &nv04_tv_encoder_info[type]);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
goto fail_cleanup;
|
||||
|
||||
/* Fill the function pointers */
|
||||
sfuncs = to_encoder_slave(encoder)->slave_funcs;
|
||||
|
||||
*funcs = (struct drm_encoder_funcs) {
|
||||
.destroy = nv04_tv_destroy,
|
||||
};
|
||||
|
||||
*hfuncs = (struct drm_encoder_helper_funcs) {
|
||||
.dpms = nv04_tv_dpms,
|
||||
.save = sfuncs->save,
|
||||
@ -292,14 +242,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
.detect = sfuncs->detect,
|
||||
};
|
||||
|
||||
/* Set the slave encoder configuration */
|
||||
sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
|
||||
/* Attach it to the specified connector. */
|
||||
sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data);
|
||||
sfuncs->create_resources(encoder, connector);
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fail_cleanup:
|
||||
drm_encoder_cleanup(encoder);
|
||||
|
||||
kfree(hfuncs);
|
||||
fail_free:
|
||||
kfree(nv_encoder);
|
||||
return ret;
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
|
||||
/* Fill entries that are seen filled in dumps of nvidia driver just
|
||||
* after channel's is put into DMA mode
|
||||
*/
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
nv_wi32(dev, fc + 0, chan->pushbuf_base);
|
||||
nv_wi32(dev, fc + 4, chan->pushbuf_base);
|
||||
nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4);
|
||||
@ -66,7 +65,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
|
||||
NV_PFIFO_CACHE1_BIG_ENDIAN |
|
||||
#endif
|
||||
0);
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
/* enable the fifo dma operation */
|
||||
nv_wr32(dev, NV04_PFIFO_MODE,
|
||||
@ -91,8 +89,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid)
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t fc = NV10_RAMFC(chid), tmp;
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, false);
|
||||
|
||||
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
|
||||
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
|
||||
nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
|
||||
@ -117,8 +113,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid)
|
||||
nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48));
|
||||
|
||||
out:
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
|
||||
nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
|
||||
}
|
||||
@ -155,8 +149,6 @@ nv10_fifo_unload_context(struct drm_device *dev)
|
||||
return 0;
|
||||
fc = NV10_RAMFC(chid);
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
|
||||
nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
|
||||
nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
|
||||
nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
|
||||
@ -179,8 +171,6 @@ nv10_fifo_unload_context(struct drm_device *dev)
|
||||
nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
|
||||
|
||||
out:
|
||||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
nv10_fifo_do_load_context(dev, pfifo->channels - 1);
|
||||
nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
|
||||
return 0;
|
||||
|
@ -55,7 +55,7 @@ get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
|
||||
}
|
||||
|
||||
int
|
||||
nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
|
||||
nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
|
||||
{
|
||||
struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
|
||||
uint32_t reg, shift, mask, value;
|
||||
@ -72,7 +72,7 @@ nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
|
||||
}
|
||||
|
||||
int
|
||||
nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
|
||||
nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
|
||||
{
|
||||
struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
|
||||
uint32_t reg, shift, mask, value;
|
@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
|
||||
uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
|
||||
uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
|
||||
fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
|
||||
@ -52,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
|
||||
head = (dacclk & 0x100) >> 8;
|
||||
|
||||
/* Save the previous state. */
|
||||
gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
|
||||
gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
|
||||
gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
|
||||
gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
|
||||
fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
|
||||
fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
|
||||
fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
|
||||
@ -64,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
|
||||
ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
|
||||
|
||||
/* Prepare the DAC for load detection. */
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC1, true);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC0, true);
|
||||
|
||||
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
|
||||
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
|
||||
@ -110,12 +111,27 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
|
||||
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
|
||||
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
|
||||
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC1, gpio1);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC0, gpio0);
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
static bool
|
||||
get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
|
||||
{
|
||||
/* Zotac FX5200 */
|
||||
if (dev->pdev->device == 0x0322 &&
|
||||
dev->pdev->subsystem_vendor == 0x19da &&
|
||||
(dev->pdev->subsystem_device == 0x1035 ||
|
||||
dev->pdev->subsystem_device == 0x2035)) {
|
||||
*pin_mask = 0xc;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
{
|
||||
@ -124,12 +140,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
struct drm_mode_config *conf = &dev->mode_config;
|
||||
struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
|
||||
struct dcb_entry *dcb = tv_enc->base.dcb;
|
||||
bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask);
|
||||
|
||||
if (dev_priv->chipset == 0x42 ||
|
||||
dev_priv->chipset == 0x43)
|
||||
tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
|
||||
else
|
||||
tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
|
||||
if (nv04_dac_in_use(encoder))
|
||||
return connector_status_disconnected;
|
||||
|
||||
if (reliable) {
|
||||
if (dev_priv->chipset == 0x42 ||
|
||||
dev_priv->chipset == 0x43)
|
||||
tv_enc->pin_mask =
|
||||
nv42_tv_sample_load(encoder) >> 28 & 0xe;
|
||||
else
|
||||
tv_enc->pin_mask =
|
||||
nv17_dac_sample_load(encoder) >> 28 & 0xe;
|
||||
}
|
||||
|
||||
switch (tv_enc->pin_mask) {
|
||||
case 0x2:
|
||||
@ -154,7 +178,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
conf->tv_subconnector_property,
|
||||
tv_enc->subconnector);
|
||||
|
||||
if (tv_enc->subconnector) {
|
||||
if (!reliable) {
|
||||
return connector_status_unknown;
|
||||
} else if (tv_enc->subconnector) {
|
||||
NV_INFO(dev, "Load detected on output %c\n",
|
||||
'@' + ffs(dcb->or));
|
||||
return connector_status_connected;
|
||||
@ -296,6 +322,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
|
||||
{
|
||||
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
|
||||
|
||||
if (nv04_dac_in_use(encoder))
|
||||
return false;
|
||||
|
||||
if (tv_norm->kind == CTV_ENC_MODE)
|
||||
adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
|
||||
else
|
||||
@ -307,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
|
||||
static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
|
||||
struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
|
||||
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
|
||||
|
||||
@ -331,8 +362,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)
|
||||
|
||||
nv_load_ptv(dev, regs, 200);
|
||||
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
|
||||
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
|
||||
gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
|
||||
|
||||
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
|
||||
}
|
||||
@ -744,8 +775,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
|
||||
.destroy = nv17_tv_destroy,
|
||||
};
|
||||
|
||||
int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
int
|
||||
nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_encoder *encoder;
|
||||
struct nv17_tv_encoder *tv_enc = NULL;
|
||||
|
||||
@ -774,5 +807,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
|
||||
encoder->possible_crtcs = entry->heads;
|
||||
encoder->possible_clones = 0;
|
||||
|
||||
nv17_tv_create_resources(encoder, connector);
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
return 0;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user