Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/anholt/drm-intel

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel:
  drm/i915: Add support for VGA load detection (pre-945).
  drm/i915: Use an I2C algo to do the flip to SDVO DDC bus.
  drm/i915: Determine type before initialising connector
  drm/i915: Return SDVO LVDS VBT mode if no EDID modes are detected.
  drm/i915: Fetch SDVO LVDS mode lines from VBT, then reserve them
  i915: support 8xx desktop cursors
  drm/i915: allocate large pointer arrays with vmalloc
  • Loading branch information
Linus Torvalds committed May 26, 2009
2 parents 299297c + e4a5d54 commit ebd4c99
Show file tree
Hide file tree
Showing 10 changed files with 432 additions and 89 deletions.
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ typedef struct drm_i915_private {
int backlight_duty_cycle; /* restore backlight to this value */
bool panel_wants_dither;
struct drm_display_mode *panel_fixed_mode;
struct drm_display_mode *vbt_mode; /* if any */
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */

/* Feature bits from the VBIOS */
unsigned int int_tv_support:1;
Expand Down
42 changes: 17 additions & 25 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
num_pages = last_data_page - first_data_page + 1;

user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
user_pages = drm_calloc_large(num_pages, sizeof(struct page *));
if (user_pages == NULL)
return -ENOMEM;

Expand Down Expand Up @@ -429,7 +429,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
SetPageDirty(user_pages[i]);
page_cache_release(user_pages[i]);
}
kfree(user_pages);
drm_free_large(user_pages);

return ret;
}
Expand Down Expand Up @@ -649,7 +649,7 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
num_pages = last_data_page - first_data_page + 1;

user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
user_pages = drm_calloc_large(num_pages, sizeof(struct page *));
if (user_pages == NULL)
return -ENOMEM;

Expand Down Expand Up @@ -719,7 +719,7 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
out_unpin_pages:
for (i = 0; i < pinned_pages; i++)
page_cache_release(user_pages[i]);
kfree(user_pages);
drm_free_large(user_pages);

return ret;
}
Expand Down Expand Up @@ -824,7 +824,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
num_pages = last_data_page - first_data_page + 1;

user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
user_pages = drm_calloc_large(num_pages, sizeof(struct page *));
if (user_pages == NULL)
return -ENOMEM;

Expand Down Expand Up @@ -902,7 +902,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
fail_put_user_pages:
for (i = 0; i < pinned_pages; i++)
page_cache_release(user_pages[i]);
kfree(user_pages);
drm_free_large(user_pages);

return ret;
}
Expand Down Expand Up @@ -1145,7 +1145,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
list_add(&obj_priv->list, &dev_priv->mm.inactive_list);
list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
}

/* Need a new fence register? */
Expand Down Expand Up @@ -1375,7 +1375,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
mutex_unlock(&dev->struct_mutex);
return ret;
}
list_add(&obj_priv->list, &dev_priv->mm.inactive_list);
list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list);
}

drm_gem_object_unreference(obj);
Expand Down Expand Up @@ -1408,9 +1408,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
}
obj_priv->dirty = 0;

drm_free(obj_priv->pages,
page_count * sizeof(struct page *),
DRM_MEM_DRIVER);
drm_free_large(obj_priv->pages);
obj_priv->pages = NULL;
}

Expand Down Expand Up @@ -2024,8 +2022,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj)
*/
page_count = obj->size / PAGE_SIZE;
BUG_ON(obj_priv->pages != NULL);
obj_priv->pages = drm_calloc(page_count, sizeof(struct page *),
DRM_MEM_DRIVER);
obj_priv->pages = drm_calloc_large(page_count, sizeof(struct page *));
if (obj_priv->pages == NULL) {
DRM_ERROR("Faled to allocate page list\n");
obj_priv->pages_refcount--;
Expand Down Expand Up @@ -3111,7 +3108,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
reloc_count += exec_list[i].relocation_count;
}

*relocs = drm_calloc(reloc_count, sizeof(**relocs), DRM_MEM_DRIVER);
*relocs = drm_calloc_large(reloc_count, sizeof(**relocs));
if (*relocs == NULL)
return -ENOMEM;

Expand All @@ -3125,8 +3122,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
exec_list[i].relocation_count *
sizeof(**relocs));
if (ret != 0) {
drm_free(*relocs, reloc_count * sizeof(**relocs),
DRM_MEM_DRIVER);
drm_free_large(*relocs);
*relocs = NULL;
return -EFAULT;
}
Expand Down Expand Up @@ -3165,7 +3161,7 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
}

err:
drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER);
drm_free_large(relocs);

return ret;
}
Expand Down Expand Up @@ -3198,10 +3194,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
/* Copy in the exec list from userland */
exec_list = drm_calloc(sizeof(*exec_list), args->buffer_count,
DRM_MEM_DRIVER);
object_list = drm_calloc(sizeof(*object_list), args->buffer_count,
DRM_MEM_DRIVER);
exec_list = drm_calloc_large(sizeof(*exec_list), args->buffer_count);
object_list = drm_calloc_large(sizeof(*object_list), args->buffer_count);
if (exec_list == NULL || object_list == NULL) {
DRM_ERROR("Failed to allocate exec or object list "
"for %d buffers\n",
Expand Down Expand Up @@ -3462,10 +3456,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
}

pre_mutex_err:
drm_free(object_list, sizeof(*object_list) * args->buffer_count,
DRM_MEM_DRIVER);
drm_free(exec_list, sizeof(*exec_list) * args->buffer_count,
DRM_MEM_DRIVER);
drm_free_large(object_list);
drm_free_large(exec_list);
drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects,
DRM_MEM_DRIVER);

Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1410,16 +1410,33 @@

/* Cursor A & B regs */
#define CURACNTR 0x70080
/* Old style CUR*CNTR flags (desktop 8xx) */
#define CURSOR_ENABLE 0x80000000
#define CURSOR_GAMMA_ENABLE 0x40000000
#define CURSOR_STRIDE_MASK 0x30000000
#define CURSOR_FORMAT_SHIFT 24
#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT)
#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT)
#define CURSOR_FORMAT_3C (0x01 << CURSOR_FORMAT_SHIFT)
#define CURSOR_FORMAT_4C (0x02 << CURSOR_FORMAT_SHIFT)
#define CURSOR_FORMAT_ARGB (0x04 << CURSOR_FORMAT_SHIFT)
#define CURSOR_FORMAT_XRGB (0x05 << CURSOR_FORMAT_SHIFT)
/* New style CUR*CNTR flags */
#define CURSOR_MODE 0x27
#define CURSOR_MODE_DISABLE 0x00
#define CURSOR_MODE_64_32B_AX 0x07
#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
#define MCURSOR_PIPE_SELECT (1 << 28)
#define MCURSOR_PIPE_A 0x00
#define MCURSOR_PIPE_B (1 << 28)
#define MCURSOR_GAMMA_ENABLE (1 << 26)
#define CURABASE 0x70084
#define CURAPOS 0x70088
#define CURSOR_POS_MASK 0x007FF
#define CURSOR_POS_SIGN 0x8000
#define CURSOR_X_SHIFT 0
#define CURSOR_Y_SHIFT 16
#define CURSIZE 0x700a0
#define CURBCNTR 0x700c0
#define CURBBASE 0x700c4
#define CURBPOS 0x700c8
Expand Down
102 changes: 72 additions & 30 deletions drivers/gpu/drm/i915/intel_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,43 @@ find_section(struct bdb_header *bdb, int section_id)
return NULL;
}

/* Try to find panel data */
static void
parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
struct lvds_dvo_timing *dvo_timing)
{
panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
dvo_timing->hactive_lo;
panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
dvo_timing->hsync_pulse_width;
panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);

panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
dvo_timing->vactive_lo;
panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
dvo_timing->vsync_off;
panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
dvo_timing->vsync_pulse_width;
panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
panel_fixed_mode->clock = dvo_timing->clock * 10;
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;

/* Some VBTs have bogus h/vtotal values */
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;

drm_mode_set_name(panel_fixed_mode);
}

/* Try to find integrated panel data */
static void
parse_lfp_panel_data(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
struct bdb_lvds_options *lvds_options;
struct bdb_lvds_lfp_data *lvds_lfp_data;
Expand Down Expand Up @@ -91,38 +125,45 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
DRM_MEM_DRIVER);

panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
dvo_timing->hactive_lo;
panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
dvo_timing->hsync_pulse_width;
panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
fill_detail_timing_data(panel_fixed_mode, dvo_timing);

panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
dvo_timing->vactive_lo;
panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
dvo_timing->vsync_off;
panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
dvo_timing->vsync_pulse_width;
panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
panel_fixed_mode->clock = dvo_timing->clock * 10;
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;

/* Some VBTs have bogus h/vtotal values */
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode);

drm_mode_set_name(panel_fixed_mode);
return;
}

/* Try to find sdvo panel data */
static void
parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
struct bdb_header *bdb)
{
struct bdb_sdvo_lvds_options *sdvo_lvds_options;
struct lvds_dvo_timing *dvo_timing;
struct drm_display_mode *panel_fixed_mode;

dev_priv->vbt_mode = panel_fixed_mode;
dev_priv->sdvo_lvds_vbt_mode = NULL;

DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode);
sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
if (!sdvo_lvds_options)
return;

dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
if (!dvo_timing)
return;

panel_fixed_mode = drm_calloc(1, sizeof(*panel_fixed_mode),
DRM_MEM_DRIVER);

if (!panel_fixed_mode)
return;

fill_detail_timing_data(panel_fixed_mode,
dvo_timing + sdvo_lvds_options->panel_type);

dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;

return;
}
Expand Down Expand Up @@ -199,7 +240,8 @@ intel_init_bios(struct drm_device *dev)

/* Grab useful general definitions */
parse_general_features(dev_priv, bdb);
parse_panel_data(dev_priv, bdb);
parse_lfp_panel_data(dev_priv, bdb);
parse_sdvo_panel_data(dev_priv, bdb);

pci_unmap_rom(pdev, bios);

Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/i915/intel_bios.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,23 @@ struct vch_bdb_22 {
struct vch_panel_data panels[16];
} __attribute__((packed));

struct bdb_sdvo_lvds_options {
u8 panel_backlight;
u8 h40_set_panel_type;
u8 panel_type;
u8 ssc_clk_freq;
u16 als_low_trip;
u16 als_high_trip;
u8 sclalarcoeff_tab_row_num;
u8 sclalarcoeff_tab_row_size;
u8 coefficient[8];
u8 panel_misc_bits_1;
u8 panel_misc_bits_2;
u8 panel_misc_bits_3;
u8 panel_misc_bits_4;
} __attribute__((packed));


bool intel_init_bios(struct drm_device *dev);

/*
Expand Down
Loading

0 comments on commit ebd4c99

Please sign in to comment.