i915: enable tiled framebuffer

git-svn-id: svn://kolibrios.org@4280 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2013-11-22 14:45:09 +00:00
parent bd92a354fb
commit 304eb30a10
21 changed files with 805 additions and 231 deletions

View File

@ -273,7 +273,6 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);
// drm_gem_remove_prime_handles(obj, filp);
if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, filp);
@ -317,12 +316,6 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
}
*handlep = ret;
// ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
// if (ret) {
// drm_gem_handle_delete(file_priv, *handlep);
// return ret;
// }
if (dev->driver->gem_open_object) {
ret = dev->driver->gem_open_object(obj, file_priv);
if (ret) {

View File

@ -76,6 +76,7 @@ NAME_SRC= main.c \
intel_sprite.c \
intel_uncore.c \
kms_display.c \
kos_gem_fb.c \
utils.c \
../hdmi.c \
Gtt/intel-agp.c \

View File

@ -1156,7 +1156,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret)
DRM_INFO("failed to find VBIOS tables\n");
fb_obj = kos_gem_fb_object_create(dev,0,12*1024*1024);
/* Initialise stolen first so that we may reserve preallocated
* objects for the BIOS to KMS transition.
@ -1524,6 +1524,8 @@ int i915_driver_unload(struct drm_device *dev)
cancel_work_sync(&dev_priv->gpu_error.work);
i915_destroy_error_state(dev);
cancel_delayed_work_sync(&dev_priv->pc8.enable_work);
if (dev->pdev->msi_enabled)
pci_disable_msi(dev->pdev);

View File

@ -62,7 +62,7 @@ MODULE_PARM_DESC(panel_ignore_lid,
"Override lid status (0=autodetect, 1=autodetect disabled [default], "
"-1=force lid closed, -2=force lid open)");
unsigned int i915_powersave __read_mostly = 1;
unsigned int i915_powersave __read_mostly = 0;
module_param_named(powersave, i915_powersave, int, 0600);
MODULE_PARM_DESC(powersave,
"Enable powersavings, fbc, downclocking, etc. (default: true)");
@ -72,7 +72,7 @@ module_param_named(semaphores, i915_semaphores, int, 0600);
MODULE_PARM_DESC(semaphores,
"Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
int i915_enable_rc6 __read_mostly = -1;
int i915_enable_rc6 __read_mostly = 0;
module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400);
MODULE_PARM_DESC(i915_enable_rc6,
"Enable power-saving render C-state 6. "
@ -81,7 +81,7 @@ MODULE_PARM_DESC(i915_enable_rc6,
"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
"default: -1 (use per-chip default)");
int i915_enable_fbc __read_mostly = -1;
int i915_enable_fbc __read_mostly = 0;
module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
MODULE_PARM_DESC(i915_enable_fbc,
"Enable frame buffer compression for power savings "
@ -150,7 +150,7 @@ module_param_named(fastboot, i915_fastboot, bool, 0600);
MODULE_PARM_DESC(fastboot, "Try to skip unnecessary mode sets at boot time "
"(default: false)");
int i915_enable_pc8 __read_mostly = 1;
int i915_enable_pc8 __read_mostly = 0;
module_param_named(enable_pc8, i915_enable_pc8, int, 0600);
MODULE_PARM_DESC(enable_pc8, "Enable support for low power package C states (PC8+) (default: true)");

View File

@ -509,10 +509,12 @@ struct i915_address_space {
/* FIXME: Need a more generic return type */
gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
enum i915_cache_level level);
enum i915_cache_level level,
bool valid); /* Create a valid PTE */
void (*clear_range)(struct i915_address_space *vm,
unsigned int first_entry,
unsigned int num_entries);
unsigned int num_entries,
bool use_scratch);
void (*insert_entries)(struct i915_address_space *vm,
struct sg_table *st,
unsigned int first_entry,
@ -2071,6 +2073,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,
void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
struct drm_i915_gem_object *obj);
void i915_check_and_clear_faults(struct drm_device *dev);
void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
void i915_gem_restore_gtt_mappings(struct drm_device *dev);
int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
@ -2340,6 +2344,12 @@ timespec_to_jiffies_timeout(const struct timespec *value)
return min_t(unsigned long, MAX_JIFFY_OFFSET, j + 1);
}
static inline int mutex_trylock(struct mutex *lock)
{
if (likely(atomic_cmpxchg(&lock->count, 1, 0) == 1))
return 1;
return 0;
}
typedef struct
{
@ -2349,19 +2359,27 @@ typedef struct
int freq;
}videomode_t;
static inline int mutex_trylock(struct mutex *lock)
struct cmdtable
{
if (likely(atomic_cmpxchg(&lock->count, 1, 0) == 1))
return 1;
return 0;
}
char *key;
int size;
int *val;
};
#define CMDENTRY(key, val) {(key), (sizeof(key)-1), &val}
void parse_cmdline(char *cmdline, struct cmdtable *table, char *log, videomode_t *mode);
struct drm_i915_gem_object
*kos_gem_fb_object_create(struct drm_device *dev, u32 gtt_offset, u32 size);
extern struct drm_i915_gem_object *fb_obj;
static struct drm_i915_gem_object *get_fb_obj()
{
return fb_obj;
};
#define ioread32(addr) readl(addr)
#endif

View File

@ -26,6 +26,7 @@
*/
#include <drm/drmP.h>
#include <drm/drm_vma_manager.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
#include "i915_trace.h"
@ -2619,6 +2620,9 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
POSTING_READ(fence_reg + 4);
I915_WRITE(fence_reg + 0, val);
dbgprintf("%s val %x%x\n",__FUNCTION__, (int)(val >> 32), (int)val);
POSTING_READ(fence_reg);
} else {
I915_WRITE(fence_reg + 4, 0);
@ -3668,9 +3672,6 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
return -EBUSY;
// if( obj == get_fb_obj())
// return 0;
WARN_ON(map_and_fenceable && !i915_is_ggtt(vm));
vma = i915_gem_obj_to_vma(obj, vm);

View File

@ -299,11 +299,31 @@ static int context_idr_cleanup(int id, void *p, void *data)
BUG_ON(id == DEFAULT_CONTEXT_ID);
i915_gem_context_unreference(ctx);
return 0;
}
struct i915_ctx_hang_stats *
i915_gem_context_get_hang_stats(struct drm_device *dev,
struct drm_file *file,
u32 id)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_file_private *file_priv = file->driver_priv;
struct i915_hw_context *ctx;
if (id == DEFAULT_CONTEXT_ID)
return &file_priv->hang_stats;
ctx = NULL;
if (!dev_priv->hw_contexts_disabled)
ctx = i915_gem_context_get(file->driver_priv, id);
if (ctx == NULL)
return ERR_PTR(-ENOENT);
return &ctx->hang_stats;
}
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;

View File

@ -65,9 +65,10 @@
#define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6)
static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
enum i915_cache_level level)
enum i915_cache_level level,
bool valid)
{
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) {
@ -86,9 +87,10 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
}
static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
enum i915_cache_level level)
enum i915_cache_level level,
bool valid)
{
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
switch (level) {
@ -112,9 +114,10 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
#define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2)
static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
enum i915_cache_level level)
enum i915_cache_level level,
bool valid)
{
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= GEN6_PTE_ADDR_ENCODE(addr);
/* Mark the page as writeable. Other platforms don't have a
@ -129,9 +132,10 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
}
static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
enum i915_cache_level level)
enum i915_cache_level level,
bool valid)
{
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= HSW_PTE_ADDR_ENCODE(addr);
if (level != I915_CACHE_NONE)
@ -141,9 +145,10 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
}
static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
enum i915_cache_level level)
enum i915_cache_level level,
bool valid)
{
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
pte |= HSW_PTE_ADDR_ENCODE(addr);
switch (level) {
@ -243,7 +248,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
/* PPGTT support for Sandybdrige/Gen6 and later */
static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
unsigned first_entry,
unsigned num_entries)
unsigned num_entries,
bool use_scratch)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
@ -252,7 +258,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
unsigned last_pte, i;
scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
pt_vaddr = AllocKernelSpace(4096);
@ -301,7 +307,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
dma_addr_t page_addr;
page_addr = sg_page_iter_dma_address(&sg_iter);
pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level);
pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true);
if (++act_pte == I915_PPGTT_PT_ENTRIES) {
act_pt++;
MapPage(pt_vaddr,(addr_t)(ppgtt->pt_pages[act_pt]), 3);
@ -380,7 +386,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
}
ppgtt->base.clear_range(&ppgtt->base, 0,
ppgtt->num_pd_entries*I915_PPGTT_PT_ENTRIES);
ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
@ -457,7 +463,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
{
ppgtt->base.clear_range(&ppgtt->base,
i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
obj->base.size >> PAGE_SHIFT);
obj->base.size >> PAGE_SHIFT,
true);
}
extern int intel_iommu_gfx_mapped;
@ -498,15 +505,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
dev_priv->mm.interruptible = interruptible;
}
void i915_check_and_clear_faults(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
int i;
if (INTEL_INFO(dev)->gen < 6)
return;
for_each_ring(ring, dev_priv, i) {
u32 fault_reg;
fault_reg = I915_READ(RING_FAULT_REG(ring));
if (fault_reg & RING_FAULT_VALID) {
DRM_DEBUG_DRIVER("Unexpected fault\n"
"\tAddr: 0x%08lx\\n"
"\tAddress space: %s\n"
"\tSource ID: %d\n"
"\tType: %d\n",
fault_reg & PAGE_MASK,
fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
RING_FAULT_SRCID(fault_reg),
RING_FAULT_FAULT_TYPE(fault_reg));
I915_WRITE(RING_FAULT_REG(ring),
fault_reg & ~RING_FAULT_VALID);
}
}
POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
}
void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
/* Don't bother messing with faults pre GEN6 as we have little
* documentation supporting that it's a good idea.
*/
if (INTEL_INFO(dev)->gen < 6)
return;
i915_check_and_clear_faults(dev);
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
dev_priv->gtt.base.start / PAGE_SIZE,
dev_priv->gtt.base.total / PAGE_SIZE,
false);
}
void i915_gem_restore_gtt_mappings(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
i915_check_and_clear_faults(dev);
/* First fill our portion of the GTT with scratch pages */
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
dev_priv->gtt.base.start / PAGE_SIZE,
dev_priv->gtt.base.total / PAGE_SIZE);
dev_priv->gtt.base.total / PAGE_SIZE,
true);
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
i915_gem_clflush_object(obj, obj->pin_display);
@ -549,7 +606,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
addr = sg_page_iter_dma_address(&sg_iter);
iowrite32(vm->pte_encode(addr, level), &gtt_entries[i]);
iowrite32(vm->pte_encode(addr, level, true), &gtt_entries[i]);
i++;
}
@ -561,7 +618,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
*/
if (i != 0)
WARN_ON(readl(&gtt_entries[i-1]) !=
vm->pte_encode(addr, level));
vm->pte_encode(addr, level, true));
/* This next bit makes the above posting read even more important. We
* want to flush the TLBs only after we're certain all the PTE updates
@ -573,7 +630,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
unsigned int first_entry,
unsigned int num_entries)
unsigned int num_entries,
bool use_scratch)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
@ -586,7 +644,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
first_entry, num_entries, max_entries))
num_entries = max_entries;
scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch);
for (i = 0; i < num_entries; i++)
iowrite32(scratch_pte, &gtt_base[i]);
readl(gtt_base);
@ -607,7 +666,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
static void i915_ggtt_clear_range(struct i915_address_space *vm,
unsigned int first_entry,
unsigned int num_entries)
unsigned int num_entries,
bool unused)
{
intel_gtt_clear_range(first_entry, num_entries);
}
@ -635,7 +695,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)
dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
entry,
obj->base.size >> PAGE_SHIFT);
obj->base.size >> PAGE_SHIFT,
true);
obj->has_global_gtt_mapping = 0;
}
@ -722,11 +783,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
const unsigned long count = (hole_end - hole_start) / PAGE_SIZE;
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
hole_start, hole_end);
ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count);
ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true);
}
/* And finally clear the reserved guard page */
ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1);
ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true);
}
static bool
@ -752,7 +813,6 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
gtt_size = dev_priv->gtt.base.total;
mappable_size = dev_priv->gtt.mappable_end;
#if 0
if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
int ret;
@ -762,7 +822,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
gtt_size -= GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
}
i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size-LFB_SIZE);
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
ret = i915_gem_init_aliasing_ppgtt(dev);
if (!ret)
@ -772,9 +832,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev)
drm_mm_takedown(&dev_priv->gtt.base.mm);
gtt_size += GEN6_PPGTT_PD_ENTRIES * PAGE_SIZE;
}
#endif
i915_gem_setup_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size-LFB_SIZE);
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
}
static int setup_scratch_page(struct drm_device *dev)

View File

@ -604,6 +604,10 @@
#define ARB_MODE_SWIZZLE_IVB (1<<5)
#define RENDER_HWS_PGA_GEN7 (0x04080)
#define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id)
#define RING_FAULT_GTTSEL_MASK (1<<11)
#define RING_FAULT_SRCID(x) ((x >> 3) & 0xff)
#define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3)
#define RING_FAULT_VALID (1<<0)
#define DONE_REG 0x40b0
#define BSD_HWS_PGA_GEN7 (0x04180)
#define BLT_HWS_PGA_GEN7 (0x04280)
@ -4279,7 +4283,9 @@
#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
#define SOUTH_DSPCLK_GATE_D 0xc2020
#define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30)
#define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
#define PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14)
#define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12)
/* CPU: FDI_TX */

View File

@ -82,8 +82,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
return true;
}
static void intel_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
struct intel_crt *crt = intel_encoder_to_crt(encoder);
@ -101,7 +100,25 @@ static void intel_crt_get_config(struct intel_encoder *encoder,
else
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
return flags;
}
static void intel_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
static void hsw_crt_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
intel_ddi_get_config(encoder, pipe_config);
pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
DRM_MODE_FLAG_NHSYNC |
DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NVSYNC);
pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
}
/* Note: The caller is required to filter out dpms modes not supported by the
@ -776,6 +793,9 @@ void intel_crt_init(struct drm_device *dev)
crt->base.mode_set = intel_crt_mode_set;
crt->base.disable = intel_disable_crt;
crt->base.enable = intel_enable_crt;
if (IS_HASWELL(dev))
crt->base.get_config = hsw_crt_get_config;
else
crt->base.get_config = intel_crt_get_config;
if (I915_HAS_HOTPLUG(dev))
crt->base.hpd_pin = HPD_CRT;

View File

@ -1249,7 +1249,7 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder)
intel_dp_check_link_status(intel_dp);
}
static void intel_ddi_get_config(struct intel_encoder *encoder,
void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config)
{
struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@ -1268,6 +1268,23 @@ static void intel_ddi_get_config(struct intel_encoder *encoder,
flags |= DRM_MODE_FLAG_NVSYNC;
pipe_config->adjusted_mode.flags |= flags;
switch (temp & TRANS_DDI_BPC_MASK) {
case TRANS_DDI_BPC_6:
pipe_config->pipe_bpp = 18;
break;
case TRANS_DDI_BPC_8:
pipe_config->pipe_bpp = 24;
break;
case TRANS_DDI_BPC_10:
pipe_config->pipe_bpp = 30;
break;
case TRANS_DDI_BPC_12:
pipe_config->pipe_bpp = 36;
break;
default:
break;
}
}
static void intel_ddi_destroy(struct drm_encoder *encoder)

View File

@ -1828,6 +1828,8 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
u32 alignment;
int ret;
ENTER();
switch (obj->tiling_mode) {
case I915_TILING_NONE:
if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
@ -1876,6 +1878,9 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
i915_gem_object_pin_fence(obj);
dev_priv->mm.interruptible = true;
LEAVE();
return 0;
err_unpin:
@ -2240,15 +2245,28 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
}
mutex_lock(&dev->struct_mutex);
// ret = intel_pin_and_fence_fb_obj(dev,
// to_intel_framebuffer(fb)->obj,
// NULL);
// if (ret != 0) {
// mutex_unlock(&dev->struct_mutex);
// DRM_ERROR("pin & fence failed\n");
// return ret;
// }
ret = intel_pin_and_fence_fb_obj(dev,
to_intel_framebuffer(fb)->obj,
NULL);
if (ret != 0) {
mutex_unlock(&dev->struct_mutex);
DRM_ERROR("pin & fence failed\n");
return ret;
}
/* Update pipe size and adjust fitter if needed */
if (i915_fastboot) {
I915_WRITE(PIPESRC(intel_crtc->pipe),
((crtc->mode.hdisplay - 1) << 16) |
(crtc->mode.vdisplay - 1));
if (!intel_crtc->config.pch_pfit.enabled &&
(intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
I915_WRITE(PF_CTL(intel_crtc->pipe), 0);
I915_WRITE(PF_WIN_POS(intel_crtc->pipe), 0);
I915_WRITE(PF_WIN_SZ(intel_crtc->pipe), 0);
}
}
ret = dev_priv->display.update_plane(crtc, fb, x, y);
if (ret) {
@ -2317,9 +2335,10 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
FDI_FE_ERRC_ENABLE);
}
static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc)
static bool pipe_has_enabled_pch(struct intel_crtc *crtc)
{
return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder;
return crtc->base.enabled && crtc->active &&
crtc->config.has_pch_encoder;
}
static void ivb_modeset_global_resources(struct drm_device *dev)
@ -2971,6 +2990,48 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
I915_READ(VSYNCSHIFT(cpu_transcoder)));
}
static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t temp;
temp = I915_READ(SOUTH_CHICKEN1);
if (temp & FDI_BC_BIFURCATION_SELECT)
return;
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
temp |= FDI_BC_BIFURCATION_SELECT;
DRM_DEBUG_KMS("enabling fdi C rx\n");
I915_WRITE(SOUTH_CHICKEN1, temp);
POSTING_READ(SOUTH_CHICKEN1);
}
static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
switch (intel_crtc->pipe) {
case PIPE_A:
break;
case PIPE_B:
if (intel_crtc->config.fdi_lanes > 2)
WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
else
cpt_enable_fdi_bc_bifurcation(dev);
break;
case PIPE_C:
cpt_enable_fdi_bc_bifurcation(dev);
break;
default:
BUG();
}
}
/*
* Enable PCH resources required for PCH ports:
* - PCH PLLs
@ -2989,6 +3050,9 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
assert_pch_transcoder_disabled(dev_priv, pipe);
if (IS_IVYBRIDGE(dev))
ivybridge_update_fdi_bc_bifurcation(intel_crtc);
/* Write the TU size bits before fdi link training, so that error
* detection works. */
I915_WRITE(FDI_RX_TUSIZE1(pipe),
@ -3852,12 +3916,12 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
// if (crtc->fb) {
// mutex_lock(&dev->struct_mutex);
// intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
// mutex_unlock(&dev->struct_mutex);
// crtc->fb = NULL;
// }
if (crtc->fb) {
mutex_lock(&dev->struct_mutex);
intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
mutex_unlock(&dev->struct_mutex);
crtc->fb = NULL;
}
/* Update computed state. */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@ -4977,6 +5041,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
return false;
if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
switch (tmp & PIPECONF_BPC_MASK) {
case PIPECONF_6BPC:
pipe_config->pipe_bpp = 18;
break;
case PIPECONF_8BPC:
pipe_config->pipe_bpp = 24;
break;
case PIPECONF_10BPC:
pipe_config->pipe_bpp = 30;
break;
default:
break;
}
}
intel_get_pipe_timings(crtc, pipe_config);
i9xx_get_pfit_config(crtc, pipe_config);
@ -5570,48 +5650,6 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc,
return true;
}
static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t temp;
temp = I915_READ(SOUTH_CHICKEN1);
if (temp & FDI_BC_BIFURCATION_SELECT)
return;
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
temp |= FDI_BC_BIFURCATION_SELECT;
DRM_DEBUG_KMS("enabling fdi C rx\n");
I915_WRITE(SOUTH_CHICKEN1, temp);
POSTING_READ(SOUTH_CHICKEN1);
}
static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
{
struct drm_device *dev = intel_crtc->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
switch (intel_crtc->pipe) {
case PIPE_A:
break;
case PIPE_B:
if (intel_crtc->config.fdi_lanes > 2)
WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
else
cpt_enable_fdi_bc_bifurcation(dev);
break;
case PIPE_C:
cpt_enable_fdi_bc_bifurcation(dev);
break;
default:
BUG();
}
}
int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
{
/*
@ -5805,9 +5843,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
&intel_crtc->config.fdi_m_n);
}
if (IS_IVYBRIDGE(dev))
ivybridge_update_fdi_bc_bifurcation(intel_crtc);
ironlake_set_pipeconf(crtc);
/* Set up the display plane register */
@ -5875,6 +5910,23 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
if (!(tmp & PIPECONF_ENABLE))
return false;
switch (tmp & PIPECONF_BPC_MASK) {
case PIPECONF_6BPC:
pipe_config->pipe_bpp = 18;
break;
case PIPECONF_8BPC:
pipe_config->pipe_bpp = 24;
break;
case PIPECONF_10BPC:
pipe_config->pipe_bpp = 30;
break;
case PIPECONF_12BPC:
pipe_config->pipe_bpp = 36;
break;
default:
break;
}
if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
struct intel_shared_dpll *pll;
@ -7050,22 +7102,22 @@ mode_fits_in_fbdev(struct drm_device *dev,
struct drm_i915_gem_object *obj;
struct drm_framebuffer *fb;
// if (dev_priv->fbdev == NULL)
// return NULL;
// obj = dev_priv->fbdev->ifb.obj;
// if (obj == NULL)
if (dev_priv->fbdev == NULL)
return NULL;
// if (obj->base.size < mode->vdisplay * fb->pitch)
obj = dev_priv->fbdev->ifb.obj;
if (obj == NULL)
return NULL;
fb = &dev_priv->fbdev->ifb.base;
if (fb->pitches[0] < intel_framebuffer_pitch_for_width(mode->hdisplay,
fb->bits_per_pixel))
// return NULL;
return NULL;
if (obj->base.size < mode->vdisplay * fb->pitches[0])
return NULL;
// return fb;
return fb;
}
bool intel_get_load_detect_pipe(struct drm_connector *connector,
@ -8597,6 +8649,9 @@ intel_pipe_config_compare(struct drm_device *dev,
PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
PIPE_CONF_CHECK_I(pipe_bpp);
#undef PIPE_CONF_CHECK_X
#undef PIPE_CONF_CHECK_I
#undef PIPE_CONF_CHECK_FLAGS
@ -9952,10 +10007,6 @@ static void intel_init_quirks(struct drm_device *dev)
q->subsystem_device == PCI_ANY_ID))
q->hook(dev);
}
// for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
// if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
// intel_dmi_quirks[i].hook(dev);
// }
}
/* Disable the VGA plane that we never use */
@ -10471,11 +10522,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
/* flush any delayed tasks or pending work */
flush_scheduled_work();
// cancel_work_sync(&dev_priv->hotplug_work);
// cancel_work_sync(&dev_priv->rps.work);
/* flush any delayed tasks or pending work */
// flush_scheduled_work();
/* destroy backlight, if any, before the connectors */
intel_panel_destroy_backlight(dev);
drm_mode_config_cleanup(dev);
#endif

View File

@ -1390,6 +1390,26 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
else
pipe_config->port_clock = 270000;
}
if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp &&
pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
/*
* This is a big fat ugly hack.
*
* Some machines in UEFI boot mode provide us a VBT that has 18
* bpp and 1.62 GHz link bandwidth for eDP, which for reasons
* unknown we fail to light up. Yet the same BIOS boots up with
* 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as
* max, not what it tells us to use.
*
* Note: This will still be broken if the eDP panel is not lit
* up by the BIOS, and thus we can't get the mode at module
* load.
*/
DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
}
}
static bool is_edp_psr(struct intel_dp *intel_dp)

View File

@ -770,6 +770,8 @@ extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder);
extern bool
intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
extern void intel_ddi_get_config(struct intel_encoder *encoder,
struct intel_crtc_config *pipe_config);
extern void intel_display_handle_reset(struct drm_device *dev);
extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,

View File

@ -43,12 +43,7 @@
#include <drm/i915_drm.h>
#include "i915_drv.h"
static struct drm_i915_gem_object *fb_obj;
struct drm_i915_gem_object *get_fb_obj()
{
return fb_obj;
};
struct drm_i915_gem_object *fb_obj;
struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
{
@ -105,6 +100,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
struct device *device = &dev->pdev->dev;
int size, ret;
ENTER();
/* we don't do packed 24bpp */
if (sizes->surface_bpp == 24)
sizes->surface_bpp = 32;
@ -113,49 +110,29 @@ static int intelfb_create(struct drm_fb_helper *helper,
mode_cmd.height = sizes->surface_height;
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) /
8), 64);
8), 512);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
obj = i915_gem_alloc_object(dev, size);
obj = fb_obj;
if (!obj) {
DRM_ERROR("failed to allocate framebuffer\n");
ret = -ENOMEM;
goto out;
}
obj->stride = mode_cmd.pitches[0];
mutex_lock(&dev->struct_mutex);
#if 0
// skip this part and use existing framebiffer
/* Flush everything out, we'll be doing GTT only from now on */
ret = intel_pin_and_fence_fb_obj(dev, obj, false);
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
if (ret) {
DRM_ERROR("failed to pin fb: %d\n", ret);
goto out_unref;
}
#endif
/***********************************************************************/
{
#define LFB_SIZE 0xC00000
static struct drm_mm_node lfb_vm_node;
lfb_vm_node.size = LFB_SIZE;
lfb_vm_node.start = 0;
lfb_vm_node.mm = NULL;
obj->pin_count = 2;
obj->cache_level = I915_CACHE_NONE;
obj->base.write_domain = 0;
obj->base.read_domains = I915_GEM_DOMAIN_GTT;
}
/***********************************************************************/
info = framebuffer_alloc(0, device);
if (!info) {
@ -194,6 +171,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
info->screen_base = (void*) 0xFE000000;
info->screen_size = size;
/* This driver doesn't need a VT switch to restore the mode on resume */
info->skip_vt_switch = true;
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
@ -206,9 +185,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
mutex_unlock(&dev->struct_mutex);
fb_obj = obj;
return 0;
out_unpin:

View File

@ -698,6 +698,22 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Intel D410PT",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
DMI_MATCH(DMI_BOARD_NAME, "D410PT"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Intel D425KT",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),
},
},
{
.callback = intel_no_lvds_dmi_callback,
.ident = "Intel D510MO",

View File

@ -4768,7 +4768,9 @@ static void cpt_init_clock_gating(struct drm_device *dev)
* gating for the panel power sequencer or it will fail to
* start up when no ports are active.
*/
I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
PCH_DPLUNIT_CLOCK_GATE_DISABLE |
PCH_CPUNIT_CLOCK_GATE_DISABLE);
I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
DPLS_EDP_PPS_FIX_DIS);
/* The below fixes the weird display corruption, a few pixels shifted

View File

@ -106,6 +106,7 @@ bool set_mode(struct drm_device *dev, struct drm_connector *connector,
struct drm_framebuffer *fb = NULL;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
struct drm_i915_gem_object *fb_obj;
struct drm_mode_set set;
char *con_name;
char *enc_name;
@ -162,14 +163,16 @@ do_set:
if (crtc->invert_dimensions)
swap(hdisplay, vdisplay);
fb_obj = get_fb_obj();
fb = fb_helper->fb;
fb->width = reqmode->width;
fb->height = reqmode->height;
fb->pitches[0] = ALIGN(reqmode->width * 4, 64);
fb->pitches[1] = ALIGN(reqmode->width * 4, 64);
fb->pitches[2] = ALIGN(reqmode->width * 4, 64);
fb->pitches[3] = ALIGN(reqmode->width * 4, 64);
fb->pitches[0] = fb->pitches[1] = fb->pitches[2] =
fb->pitches[3] = ALIGN(reqmode->width * 4, 512);
fb_obj->stride = fb->pitches[0];
fb->bits_per_pixel = 32;
fb->depth = 24;
@ -178,6 +181,8 @@ do_set:
crtc->enabled = true;
os_display->crtc = crtc;
i915_gem_object_put_fence(fb_obj);
set.crtc = crtc;
set.x = 0;
set.y = 0;
@ -261,7 +266,7 @@ static struct drm_connector* get_def_connector(struct drm_device *dev)
};
int init_display_kms(struct drm_device *dev)
int init_display_kms(struct drm_device *dev, videomode_t *usermode)
{
struct drm_connector *connector;
struct drm_connector_helper_funcs *connector_funcs;
@ -273,6 +278,10 @@ int init_display_kms(struct drm_device *dev)
u32_t ifl;
int err;
ENTER();
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
{
if( connector->status != connector_status_connected)
@ -289,20 +298,22 @@ int init_display_kms(struct drm_device *dev)
connector->encoder = encoder;
crtc = encoder->crtc;
DRM_DEBUG_KMS("CONNECTOR %x ID:%d status:%d ENCODER %x CRTC %x ID:%d\n",
DRM_DEBUG_KMS("CONNECTOR %p ID:%d status:%d ENCODER %x CRTC %p ID:%d\n",
connector, connector->base.id,
connector->status, connector->encoder,
crtc, crtc->base.id );
break;
};
if(connector == NULL)
{
DRM_ERROR("No active connectors!\n");
DRM_DEBUG_KMS("No active connectors!\n");
mutex_unlock(&dev->mode_config.mutex);
return -1;
};
dbgprintf("CRTC %p\n", crtc);
if(crtc == NULL)
{
struct drm_crtc *tmp_crtc;
@ -310,24 +321,28 @@ int init_display_kms(struct drm_device *dev)
list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head)
{
dbgprintf("tmp_crtc %p\n", tmp_crtc);
if (encoder->possible_crtcs & crtc_mask)
{
crtc = tmp_crtc;
encoder->crtc = crtc;
dbgprintf("CRTC %p\n", crtc);
break;
};
crtc_mask <<= 1;
};
};
dbgprintf("CRTC %p\n", crtc);
if(crtc == NULL)
{
DRM_ERROR("No CRTC for encoder %d\n", encoder->base.id);
DRM_DEBUG_KMS("No CRTC for encoder %d\n", encoder->base.id);
mutex_unlock(&dev->mode_config.mutex);
return -1;
};
DRM_DEBUG_KMS("[Select CRTC:%d]\n", crtc->base.id);
DRM_DEBUG_KMS("[Select CRTC: %p ID:%d]\n",crtc, crtc->base.id);
os_display = GetDisplay();
os_display->ddev = dev;
@ -361,10 +376,53 @@ int init_display_kms(struct drm_device *dev)
};
safe_sti(ifl);
if( (usermode->width == 0) ||
(usermode->height == 0))
{
struct drm_display_mode *mode;
// connector->funcs->fill_modes(connector, dev->mode_config.max_width,
// dev->mode_config.max_height);
list_for_each_entry(mode, &connector->modes, head)
{
printf("check mode w:%d h:%d %dHz\n",
drm_mode_width(mode), drm_mode_height(mode),
drm_mode_vrefresh(mode));
if( os_display->width == drm_mode_width(mode) &&
os_display->height == drm_mode_height(mode) &&
drm_mode_vrefresh(mode) == 60)
{
usermode->width = os_display->width;
usermode->height = os_display->height;
usermode->freq = 60;
break;
}
}
if( usermode->width == 0 ||
usermode->height == 0)
{
mode = list_entry(connector->modes.next, typeof(*mode), head);
usermode->width = drm_mode_width(mode);
usermode->height = drm_mode_height(mode);
usermode->freq = drm_mode_vrefresh(mode);
};
};
mutex_unlock(&dev->mode_config.mutex);
set_mode(dev, os_display->connector, usermode, false);
#ifdef __HWA__
err = init_bitmaps();
#endif
LEAVE();
return 0;
};

View File

@ -0,0 +1,199 @@
/*
* Copyright © 2008-2012 Intel Corporation
*
* 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 OR COPYRIGHT HOLDERS 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:
* Eric Anholt <eric@anholt.net>
* Chris Wilson <chris@chris-wilson.co.uk>
*
*/
#include <drm/drmP.h>
#include <drm/i915_drm.h>
#include "i915_drv.h"
static struct sg_table *
i915_pages_create_for_fb(struct drm_device *dev,
u32 offset, u32 size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct sg_table *st;
struct scatterlist *sg;
addr_t fb_pages;
DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
// BUG_ON(offset > dev_priv->gtt.stolen_size - size);
/* We hide that we have no struct page backing our stolen object
* by wrapping the contiguous physical allocation with a fake
* dma mapping in a single scatterlist.
*/
st = kmalloc(sizeof(*st), GFP_KERNEL);
if (st == NULL)
return NULL;
if (sg_alloc_table(st, 1, GFP_KERNEL)) {
kfree(st);
return NULL;
}
fb_pages = AllocPages(size/PAGE_SIZE);
if(fb_pages == 0)
{
kfree(st);
return NULL;
};
sg = st->sgl;
sg->offset = offset;
sg->length = size;
sg_dma_address(sg) = (dma_addr_t)fb_pages;
sg_dma_len(sg) = size;
return st;
}
static int kos_fb_object_get_pages(struct drm_i915_gem_object *obj)
{
BUG();
return -EINVAL;
}
static void kos_fb_object_put_pages(struct drm_i915_gem_object *obj)
{
/* Should only be called during free */
sg_free_table(obj->pages);
kfree(obj->pages);
}
static const struct drm_i915_gem_object_ops kos_fb_object_ops = {
.get_pages = kos_fb_object_get_pages,
.put_pages = kos_fb_object_put_pages,
};
static struct drm_i915_gem_object *
_kos_fb_object_create(struct drm_device *dev,
struct drm_mm_node *fb_node)
{
struct drm_i915_gem_object *obj;
obj = i915_gem_object_alloc(dev);
if (obj == NULL)
return NULL;
drm_gem_private_object_init(dev, &obj->base, fb_node->size);
i915_gem_object_init(obj, &kos_fb_object_ops);
obj->pages = i915_pages_create_for_fb(dev,
fb_node->start, fb_node->size);
if (obj->pages == NULL)
goto cleanup;
obj->has_dma_mapping = true;
i915_gem_object_pin_pages(obj);
obj->stolen = fb_node;
obj->base.read_domains = I915_GEM_DOMAIN_GTT;
obj->cache_level = I915_CACHE_NONE;
obj->tiling_mode = I915_TILING_X;
return obj;
cleanup:
i915_gem_object_free(obj);
return NULL;
}
struct drm_i915_gem_object *
kos_gem_fb_object_create(struct drm_device *dev,
u32 gtt_offset,
u32 size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_address_space *ggtt = &dev_priv->gtt.base;
struct drm_i915_gem_object *obj;
struct drm_mm_node *fb_node;
struct i915_vma *vma;
int ret;
DRM_DEBUG_KMS("creating preallocated framebuffer object: gtt_offset=%x, size=%x\n",
gtt_offset, size);
/* KISS and expect everything to be page-aligned */
BUG_ON(size & 4095);
if (WARN_ON(size == 0))
return NULL;
fb_node = kzalloc(sizeof(*fb_node), GFP_KERNEL);
if (!fb_node)
return NULL;
fb_node->start = gtt_offset;
fb_node->size = size;
obj = _kos_fb_object_create(dev, fb_node);
if (obj == NULL) {
DRM_DEBUG_KMS("failed to preallocate framebuffer object\n");
kfree(fb_node);
return NULL;
}
vma = i915_gem_vma_create(obj, ggtt);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err_out;
}
/* To simplify the initialisation sequence between KMS and GTT,
* we allow construction of the stolen object prior to
* setting up the GTT space. The actual reservation will occur
* later.
*/
vma->node.start = gtt_offset;
vma->node.size = size;
if (drm_mm_initialized(&ggtt->mm)) {
ret = drm_mm_reserve_node(&ggtt->mm, &vma->node);
if (ret) {
DRM_DEBUG_KMS("failed to allocate framebuffer GTT space\n");
goto err_vma;
}
}
obj->has_global_gtt_mapping = 1;
list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
list_add_tail(&vma->mm_list, &ggtt->inactive_list);
return obj;
err_vma:
i915_gem_vma_destroy(vma);
err_out:
kfree(fb_node);
drm_gem_object_unreference(&obj->base);
return NULL;
}

View File

@ -28,10 +28,10 @@ struct pci_device {
struct drm_device *main_device;
struct drm_file *drm_file_handlers[256];
videomode_t usermode;
void cpu_detect();
void parse_cmdline(char *cmdline, char *log);
int _stdcall display_handler(ioctl_t *io);
int init_agp(void);
@ -51,6 +51,15 @@ int i915_getparam(struct drm_device *dev, void *data,
int i915_mask_update(struct drm_device *dev, void *data,
struct drm_file *file);
struct cmdtable cmdtable[]= {
CMDENTRY("-pm=", i915_powersave),
CMDENTRY("-rc6=", i915_enable_rc6),
CMDENTRY("-fbc=", i915_enable_fbc),
CMDENTRY("-ppgt=", i915_enable_ppgtt),
CMDENTRY("-pc8=", i915_enable_pc8),
{NULL, 0}
};
static char log[256];
@ -158,8 +167,22 @@ u32_t __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
if( GetService("DISPLAY") != 0 )
return 0;
printf("i915 v3.12\n\nusage: i915 [options]\n"
"-pm=<0,1> Enable powersavings, fbc, downclocking, etc. (default: 0 - false)\n");
printf("-rc6=<-1,0-7> Enable power-saving render C-state 6.\n"
" Different stages can be selected via bitmask values\n"
" (0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6).\n"
" For example, 3 would enable rc6 and deep rc6, and 7 would enable everything.\n"
" default: -1 (use per-chip default)\n");
printf("-fbc=<-1,0,1> Enable frame buffer compression for power savings\n"
" (default: 0 - false)\n");
printf("-ppgt=<0,1> Enable PPGTT (default: 0 - false)\n");
printf("-pc8=<0,1> Enable support for low power package C states (PC8+) (default: 0 - false)\n");
printf("-l<path> path to log file\n");
printf("-m<WxHxHz> set videomode\n");
if( cmdline && *cmdline )
parse_cmdline(cmdline, log);
parse_cmdline(cmdline, cmdtable, log, &usermode);
if(!dbg_open(log))
{
@ -171,7 +194,6 @@ u32_t __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
return 0;
};
}
dbgprintf(" i915 v3.12-6\n cmdline: %s\n", cmdline);
cpu_detect();
// dbgprintf("\ncache line size %d\n", x86_clflush_size);
@ -184,7 +206,8 @@ u32_t __attribute__((externally_visible)) drvEntry(int action, char *cmdline)
dbgprintf("Epic Fail :(\n");
return 0;
};
init_display_kms(main_device);
init_display_kms(main_device, &usermode);
err = RegService("DISPLAY", display_handler);
@ -458,38 +481,6 @@ int pci_scan_filter(u32_t id, u32_t busnr, u32_t devfn)
};
static char* parse_path(char *p, char *log)
{
char c;
while( (c = *p++) == ' ');
p--;
while( (c = *log++ = *p++) && (c != ' '));
*log = 0;
return p;
};
void parse_cmdline(char *cmdline, char *log)
{
char *p = cmdline;
char c = *p++;
while( c )
{
if( c == '-')
{
switch(*p++)
{
case 'l':
p = parse_path(p, log);
break;
};
};
c = *p++;
};
};
static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
@ -571,3 +562,137 @@ void get_pci_info(struct pci_device *dev)
char *strstr(const char *cs, const char *ct);
static int my_atoi(char **cmd)
{
char* p = *cmd;
int val = 0;
int sign = 1;
if(*p == '-')
{
sign = -1;
p++;
};
for (;; *p++) {
switch (*p) {
case '0' ... '9':
val = 10*val+(*p-'0');
break;
default:
*cmd = p;
return val*sign;
}
}
}
char* parse_mode(char *p, videomode_t *mode)
{
char c;
while( (c = *p++) == ' ');
if( c )
{
p--;
mode->width = my_atoi(&p);
if(*p == 'x') p++;
mode->height = my_atoi(&p);
if(*p == 'x') p++;
mode->bpp = 32;
mode->freq = my_atoi(&p);
if( mode->freq == 0 )
mode->freq = 60;
}
return p;
};
static char* parse_path(char *p, char *log)
{
char c;
while( (c = *p++) == ' ');
p--;
while( (c = *log++ = *p++) && (c != ' '));
*log = 0;
return p;
};
void parse_cmdline(char *cmdline, struct cmdtable *table, char *log, videomode_t *mode)
{
char *p = cmdline;
char *p1;
int val;
char c = *p++;
if( table )
{
while(table->key)
{
if(p1 = strstr(cmdline, table->key))
{
p1+= table->size;
*table->val = my_atoi(&p1);
// printf("%s %d\n", table->key, *table->val);
}
table++;
}
}
while( c )
{
if( c == '-')
{
switch(*p++)
{
case 'l':
p = parse_path(p, log);
break;
case 'm':
p = parse_mode(p, mode);
break;
};
};
c = *p++;
};
};
char *strstr(const char *cs, const char *ct)
{
int d0, d1;
register char *__res;
__asm__ __volatile__(
"movl %6,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n"
"1:\tmovl %6,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
"cmpsb\n\t"
"je 2f\n\t" /* also works for empty string, see above */
"xchgl %%eax,%%esi\n\t"
"incl %%esi\n\t"
"cmpb $0,-1(%%eax)\n\t"
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
: "=a" (__res), "=&c" (d0), "=&S" (d1)
: "0" (0), "1" (0xffffffff), "2" (cs), "g" (ct)
: "dx", "di");
return __res;
}

View File

@ -783,18 +783,9 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
return (void __iomem *)(unsigned long)
pci_resource_start(pdev, PCI_ROM_RESOURCE);
} else {
/* assign the ROM an address if it doesn't have one */
// if (res->parent == NULL &&
// pci_assign_resource(pdev,PCI_ROM_RESOURCE))
return NULL;
// start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
// *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
// if (*size == 0)
// return NULL;
start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */
/* Enable ROM space decodes */
// if (pci_enable_rom(pdev))
// return NULL;
}
}