[Intel-gfx] [PATCH] drm/i915: init hardware to a known state on resume v3
Jesse Barnes
jbarnes at virtuousgeek.org
Wed Apr 24 00:46:41 CEST 2013
From: Zou Nanhai <nanhai.zou at intel.com>
Needed on SNB to avoid some RC6 related hangs.
v2: remove unneeded defines (Ken)
v3: update to agp-less driver (Jesse)
fixup for new GEM APIs (Jesse)
make debugfs use new locking (Jesse)
Signed-off-by: Zou Nanhai <nanhai.zou at intel.com>
Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
---
drivers/gpu/drm/i915/Makefile | 1 +
drivers/gpu/drm/i915/i915_debugfs.c | 22 +
drivers/gpu/drm/i915/i915_drv.c | 8 +-
drivers/gpu/drm/i915/i915_drv.h | 7 +
drivers/gpu/drm/i915/i965_defines.h | 141 +++++
drivers/gpu/drm/i915/intel_3d.c | 1085 +++++++++++++++++++++++++++++++++++
6 files changed, 1263 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/drm/i915/i965_defines.h
create mode 100644 drivers/gpu/drm/i915/intel_3d.c
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 91f3ac6..6253390 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -32,6 +32,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
intel_fb.o \
intel_tv.o \
intel_dvo.o \
+ intel_3d.o \
intel_ringbuffer.o \
intel_overlay.o \
intel_sprite.o \
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index a55630a..eb93539 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1444,6 +1444,26 @@ out:
return 0;
}
+static int i915_gem_framebuffer_draw_3drect(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_device *dev = node->minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct intel_crtc *crtc;
+ int pipe;
+
+ drm_modeset_lock_all(dev);
+ for_each_pipe(pipe) {
+ crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+ if (!crtc->base.fb)
+ continue;
+ i915_render_rect(dev, to_intel_framebuffer(crtc->base.fb),
+ 100, 100, 100, 100);
+ }
+ drm_modeset_unlock_all(dev);
+ return 0;
+}
+
static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
@@ -2110,6 +2130,8 @@ static struct drm_info_list i915_debugfs_list[] = {
{"i915_fbc_status", i915_fbc_status, 0},
{"i915_sr_status", i915_sr_status, 0},
{"i915_opregion", i915_opregion, 0},
+
+ {"i915_draw_rect",i915_gem_framebuffer_draw_3drect, 0},
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
{"i915_context_status", i915_context_status, 0},
{"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 624cdfc..e31f305 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -512,7 +512,9 @@ static int i915_drm_freeze(struct drm_device *dev)
/* If KMS is active, we do the leavevt stuff here */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- int error = i915_gem_idle(dev);
+ int error;
+ gen6_suspend_workaround(dev);
+ error = i915_gem_idle(dev);
if (error) {
dev_err(&dev->pdev->dev,
"GEM idle failed, resume might fail\n");
@@ -639,6 +641,10 @@ static int __i915_drm_thaw(struct drm_device *dev)
dev_priv->enable_hotplug_processing = true;
/* Config may have changed between suspend and resume */
intel_resume_hotplug(dev);
+
+ mutex_lock(&dev->struct_mutex);
+ gen6_wakeup_workaround(dev);
+ mutex_unlock(&dev->struct_mutex);
}
intel_opregion_init(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a4234a8..4626e79 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1862,6 +1862,13 @@ extern bool i915_semaphore_is_enabled(struct drm_device *dev);
int i915_reg_read_ioctl(struct drm_device *dev, void *data,
struct drm_file *file);
+extern void gen6_wakeup_workaround (struct drm_device *dev);
+extern void gen6_suspend_workaround (struct drm_device *dev);
+
+struct intel_framebuffer;
+extern void i915_render_rect(struct drm_device *dev,
+ struct intel_framebuffer *fb, int x, int y, int w, int h);
+
/* overlay */
#ifdef CONFIG_DEBUG_FS
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i965_defines.h b/drivers/gpu/drm/i915/i965_defines.h
new file mode 100644
index 0000000..02ee524
--- /dev/null
+++ b/drivers/gpu/drm/i915/i965_defines.h
@@ -0,0 +1,141 @@
+#ifndef _I965_DEFINES_H_
+#define _I965_DEFINES_H_
+
+#define CMD(pipeline,op,sub_op) ((3 << 29) | \
+ ((pipeline) << 27) | \
+ ((op) << 24) | \
+ ((sub_op) << 16))
+
+#define CMD_STATE_BASE_ADDRESS CMD(0, 1, 1)
+#define CMD_STATE_SIP CMD(0, 1, 2)
+#define CMD_PIPELINE_SELECT CMD(1, 1, 4)
+
+#define CMD_BINDING_TABLE_POINTERS CMD(3, 0, 1)
+# define GEN6_BINDING_TABLE_MODIFY_PS (1 << 12)/* for GEN6 */
+# define GEN6_BINDING_TABLE_MODIFY_GS (1 << 9) /* for GEN6 */
+# define GEN6_BINDING_TABLE_MODIFY_VS (1 << 8) /* for GEN6 */
+
+#define CMD_VERTEX_BUFFERS CMD(3, 0, 8)
+#define CMD_VERTEX_ELEMENTS CMD(3, 0, 9)
+#define CMD_DRAWING_RECTANGLE CMD(3, 1, 0)
+#define CMD_3DPRIMITIVE CMD(3, 3, 0)
+
+#define CMD_DEPTH_BUFFER CMD(3, 1, 5)
+# define CMD_DEPTH_BUFFER_TYPE_SHIFT 29
+# define CMD_DEPTH_BUFFER_FORMAT_SHIFT 18
+
+#define CMD_CLEAR_PARAMS CMD(3, 1, 0x10)
+/* DW1 */
+# define CMD_CLEAR_PARAMS_DEPTH_CLEAR_VALID (1 << 15)
+
+/* for GEN6+ */
+#define GEN6_3DSTATE_SAMPLER_STATE_POINTERS CMD(3, 0, 0x02)
+
+#define GEN6_3DSTATE_URB CMD(3, 0, 0x05)
+/* DW1 */
+# define GEN6_3DSTATE_URB_VS_SIZE_SHIFT 16
+# define GEN6_3DSTATE_URB_VS_ENTRIES_SHIFT 0
+/* DW2 */
+# define GEN6_3DSTATE_URB_GS_ENTRIES_SHIFT 8
+# define GEN6_3DSTATE_URB_GS_SIZE_SHIFT 0
+
+#define GEN6_3DSTATE_VIEWPORT_STATE_POINTERS CMD(3, 0, 0x0d)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CC (1 << 12)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_SF (1 << 11)
+# define GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CLIP (1 << 10)
+
+#define GEN6_3DSTATE_CC_STATE_POINTERS CMD(3, 0, 0x0e)
+
+#define GEN6_3DSTATE_VS CMD(3, 0, 0x10)
+
+#define GEN6_3DSTATE_GS CMD(3, 0, 0x11)
+
+#define GEN6_3DSTATE_CLIP CMD(3, 0, 0x12)
+
+#define GEN6_3DSTATE_SF CMD(3, 0, 0x13)
+/* DW1 */
+# define GEN6_3DSTATE_SF_NUM_OUTPUTS_SHIFT 22
+# define GEN6_3DSTATE_SF_URB_ENTRY_READ_LENGTH_SHIFT 11
+# define GEN6_3DSTATE_SF_URB_ENTRY_READ_OFFSET_SHIFT 4
+/* DW2 */
+/* DW3 */
+# define GEN6_3DSTATE_SF_CULL_BOTH (0 << 29)
+# define GEN6_3DSTATE_SF_CULL_NONE (1 << 29)
+# define GEN6_3DSTATE_SF_CULL_FRONT (2 << 29)
+# define GEN6_3DSTATE_SF_CULL_BACK (3 << 29)
+/* DW4 */
+# define GEN6_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT 25
+
+
+#define GEN6_3DSTATE_WM CMD(3, 0, 0x14)
+/* DW2 */
+# define GEN6_3DSTATE_WM_SAMPLER_COUNT_SHIFT 27
+# define GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT 18
+/* DW4 */
+# define GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT 16
+/* DW5 */
+# define GEN6_3DSTATE_WM_MAX_THREADS_SHIFT 25
+# define GEN6_3DSTATE_WM_DISPATCH_ENABLE (1 << 19)
+# define GEN6_3DSTATE_WM_16_DISPATCH_ENABLE (1 << 1)
+# define GEN6_3DSTATE_WM_8_DISPATCH_ENABLE (1 << 0)
+/* DW6 */
+# define GEN6_3DSTATE_WM_NUM_SF_OUTPUTS_SHIFT 20
+# define GEN6_3DSTATE_WM_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 10)
+
+
+#define GEN6_3DSTATE_CONSTANT_VS CMD(3, 0, 0x15)
+#define GEN6_3DSTATE_CONSTANT_GS CMD(3, 0, 0x16)
+#define GEN6_3DSTATE_CONSTANT_PS CMD(3, 0, 0x17)
+
+#define GEN6_3DSTATE_SAMPLE_MASK CMD(3, 0, 0x18)
+
+#define I965_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0
+#define I965_SURFACEFORMAT_R32G32_FLOAT 0x085
+
+
+#define GEN6_3DSTATE_MULTISAMPLE CMD(3, 1, 0x0d)
+/* DW1 */
+# define GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_CENTER (0 << 4)
+# define GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_UPPER_LEFT (1 << 4)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_1 (0 << 1)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_4 (2 << 1)
+# define GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_8 (3 << 1)
+
+#define I965_DEPTHFORMAT_D32_FLOAT 1
+
+#define BASE_ADDRESS_MODIFY (1 << 0)
+
+#define PIPELINE_SELECT_3D 0
+#define PIPELINE_SELECT_MEDIA 1
+
+#define I965_SURFACE_2D 1
+#define I965_SURFACE_NULL 7
+
+#define I965_VFCOMPONENT_NOSTORE 0
+#define I965_VFCOMPONENT_STORE_SRC 1
+#define I965_VFCOMPONENT_STORE_1_FLT 3
+
+#define GEN6_VE0_VERTEX_BUFFER_INDEX_SHIFT 26 /* for GEN6 */
+#define GEN6_VE0_VALID (1 << 25) /* for GEN6 */
+#define VE0_FORMAT_SHIFT 16
+#define VE0_OFFSET_SHIFT 0
+#define VE1_VFCOMPONENT_0_SHIFT 28
+#define VE1_VFCOMPONENT_1_SHIFT 24
+#define VE1_VFCOMPONENT_2_SHIFT 20
+#define VE1_VFCOMPONENT_3_SHIFT 16
+
+#define GEN6_VB0_BUFFER_INDEX_SHIFT 26
+#define GEN6_VB0_VERTEXDATA (0 << 20)
+#define GEN6_VB0_INSTANCEDATA (1 << 20)
+#define VB0_BUFFER_PITCH_SHIFT 0
+
+#define _3DPRIMITIVE_VERTEX_SEQUENTIAL (0 << 15)
+#define _3DPRIMITIVE_TOPOLOGY_SHIFT 10
+
+#define _3DPRIM_POINTLIST 0x01
+#define _3DPRIM_RECTLIST 0x0F
+
+#define I965_TILEWALK_XMAJOR 0
+#define I965_TILEWALK_YMAJOR 1
+
+#endif /* _I965_DEFINES_H_ */
diff --git a/drivers/gpu/drm/i915/intel_3d.c b/drivers/gpu/drm/i915/intel_3d.c
new file mode 100644
index 0000000..629a977
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_3d.c
@@ -0,0 +1,1085 @@
+/*
+ * Copyright © 2011 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:
+ * Zou Nan hai <nanhai.zou at intel.com>
+ *
+ */
+#include "intel_drv.h"
+#include "i915_drv.h"
+#include "i915_drm.h"
+#include "i965_defines.h"
+
+#define MAX_SURFACES 17
+
+static const uint32_t ps_kernel[][4] = {
+ { 0x00600001, 0x200003a2, 0x00000000, 0x00000000 },
+ { 0x00600001, 0x202003a2, 0x00000020, 0x00000000 },
+ { 0x00600001, 0x204003fe, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x206003fe, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x208003fe, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x20a003fe, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x20c003fe, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x20e003fe, 0x00000000, 0x3f800000 },
+ { 0x00600001, 0x210003fe, 0x00000000, 0x00000000 },
+ { 0x00600001, 0x212003fe, 0x00000000, 0x00000000 },
+ { 0x05800031, 0x24001cc8, 0x00000040, 0x90019000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000007e, 0x00000000, 0x00000000, 0x00000000 },
+};
+
+struct thread0
+{
+ unsigned int pad0:1;
+ unsigned int grf_reg_count:3;
+ unsigned int pad1:2;
+ unsigned int kernel_start_pointer:26;
+};
+
+struct thread1
+{
+ unsigned int ext_halt_exception_enable:1;
+ unsigned int sw_exception_enable:1;
+ unsigned int mask_stack_exception_enable:1;
+ unsigned int timeout_exception_enable:1;
+ unsigned int illegal_op_exception_enable:1;
+ unsigned int pad0:3;
+ unsigned int depth_coef_urb_read_offset:6; /* WM only */
+ unsigned int pad1:2;
+ unsigned int floating_point_mode:1;
+ unsigned int thread_priority:1;
+ unsigned int binding_table_entry_count:8;
+ unsigned int pad3:5;
+ unsigned int single_program_flow:1;
+};
+
+struct thread2
+{
+ unsigned int per_thread_scratch_space:4;
+ unsigned int pad0:6;
+ unsigned int scratch_space_base_pointer:22;
+};
+
+
+struct thread3
+{
+ unsigned int dispatch_grf_start_reg:4;
+ unsigned int urb_entry_read_offset:6;
+ unsigned int pad0:1;
+ unsigned int urb_entry_read_length:6;
+ unsigned int pad1:1;
+ unsigned int const_urb_entry_read_offset:6;
+ unsigned int pad2:1;
+ unsigned int const_urb_entry_read_length:6;
+ unsigned int pad3:1;
+};
+
+struct gen6_wm_state {
+ struct thread0 thread0;
+ struct thread1 thread1;
+ struct thread2 thread2;
+ struct thread3 thread3;
+
+ struct {
+ unsigned int stats_enable:1;
+ unsigned int pad0:1;
+ unsigned int sampler_count:3;
+ unsigned int sampler_state_pointer:27;
+ } wm4;
+
+ struct {
+ unsigned int enable_8_pix:1;
+ unsigned int enable_16_pix:1;
+ unsigned int enable_32_pix:1;
+ unsigned int pad0:7;
+ unsigned int legacy_global_depth_bias:1;
+ unsigned int line_stipple:1;
+ unsigned int depth_offset:1;
+ unsigned int polygon_stipple:1;
+ unsigned int line_aa_region_width:2;
+ unsigned int line_endcap_aa_region_width:2;
+ unsigned int early_depth_test:1;
+ unsigned int thread_dispatch_enable:1;
+ unsigned int program_uses_depth:1;
+ unsigned int program_computes_depth:1;
+ unsigned int program_uses_killpixel:1;
+ unsigned int legacy_line_rast: 1;
+ unsigned int transposed_urb_read:1;
+ unsigned int max_threads:7;
+ } wm5;
+ float global_depth_offset_constant;
+ float global_depth_offset_scale;
+};
+
+struct gen6_cc_state {
+ struct {
+ unsigned int alpha_test_format:1;
+ unsigned int pad0:14;
+ unsigned int round_disable:1;
+ unsigned int bf_stencil_ref:8;
+ unsigned int stencil_ref:8;
+ } cc0;
+
+ union {
+ float alpha_ref_f;
+ struct {
+ unsigned int ui:8;
+ unsigned int pad0:24;
+ } alpha_ref_fi;
+ } cc1;
+
+ float constant_r;
+ float constant_g;
+ float constant_b;
+ float constant_a;
+};
+
+struct gen6_cc_viewport {
+ float min_depth;
+ float max_depth;
+};
+
+struct gen6_blend_state {
+ struct {
+ unsigned int dest_blend_factor:5;
+ unsigned int source_blend_factor:5;
+ unsigned int pad3:1;
+ unsigned int blend_func:3;
+ unsigned int pad2:1;
+ unsigned int ia_dest_blend_factor:5;
+ unsigned int ia_source_blend_factor:5;
+ unsigned int pad1:1;
+ unsigned int ia_blend_func:3;
+ unsigned int pad0:1;
+ unsigned int ia_blend_enable:1;
+ unsigned int blend_enable:1;
+ } blend0;
+
+ struct {
+ unsigned int post_blend_clamp_enable:1;
+ unsigned int pre_blend_clamp_enable:1;
+ unsigned int clamp_range:2;
+ unsigned int pad0:4;
+ unsigned int x_dither_offset:2;
+ unsigned int y_dither_offset:2;
+ unsigned int dither_enable:1;
+ unsigned int alpha_test_func:3;
+ unsigned int alpha_test_enable:1;
+ unsigned int pad1:1;
+ unsigned int logic_op_func:4;
+ unsigned int logic_op_enable:1;
+ unsigned int pad2:1;
+ unsigned int write_disable_b:1;
+ unsigned int write_disable_g:1;
+ unsigned int write_disable_r:1;
+ unsigned int write_disable_a:1;
+ unsigned int pad3:1;
+ unsigned int alpha_to_coverage_dither:1;
+ unsigned int alpha_to_one:1;
+ unsigned int alpha_to_coverage:1;
+ } blend1;
+};
+struct gen6_depth_stencil_state
+{
+ struct {
+ unsigned int pad0:3;
+ unsigned int bf_stencil_pass_depth_pass_op:3;
+ unsigned int bf_stencil_pass_depth_fail_op:3;
+ unsigned int bf_stencil_fail_op:3;
+ unsigned int bf_stencil_func:3;
+ unsigned int bf_stencil_enable:1;
+ unsigned int pad1:2;
+ unsigned int stencil_write_enable:1;
+ unsigned int stencil_pass_depth_pass_op:3;
+ unsigned int stencil_pass_depth_fail_op:3;
+ unsigned int stencil_fail_op:3;
+ unsigned int stencil_func:3;
+ unsigned int stencil_enable:1;
+ } ds0;
+
+ struct {
+ unsigned int bf_stencil_write_mask:8;
+ unsigned int bf_stencil_test_mask:8;
+ unsigned int stencil_write_mask:8;
+ unsigned int stencil_test_mask:8;
+ } ds1;
+
+ struct {
+ unsigned int pad0:26;
+ unsigned int depth_write_enable:1;
+ unsigned int depth_test_func:3;
+ unsigned int pad1:1;
+ unsigned int depth_test_enable:1;
+ } ds2;
+};
+
+struct gen6_surface_state {
+ struct {
+ unsigned int cube_pos_z:1;
+ unsigned int cube_neg_z:1;
+ unsigned int cube_pos_y:1;
+ unsigned int cube_neg_y:1;
+ unsigned int cube_pos_x:1;
+ unsigned int cube_neg_x:1;
+ unsigned int pad:2;
+ unsigned int render_cache_read_mode:1;
+ unsigned int cube_map_corner_mode:1;
+ unsigned int mipmap_layout_mode:1;
+ unsigned int vert_line_stride_ofs:1;
+ unsigned int vert_line_stride:1;
+ unsigned int color_blend:1;
+ unsigned int writedisable_blue:1;
+ unsigned int writedisable_green:1;
+ unsigned int writedisable_red:1;
+ unsigned int writedisable_alpha:1;
+ unsigned int surface_format:9;
+ unsigned int data_return_format:1;
+ unsigned int pad0:1;
+ unsigned int surface_type:3;
+ } ss0;
+
+ struct {
+ unsigned int base_addr;
+ } ss1;
+
+ struct {
+ unsigned int render_target_rotation:2;
+ unsigned int mip_count:4;
+ unsigned int width:13;
+ unsigned int height:13;
+ } ss2;
+
+ struct {
+ unsigned int tile_walk:1;
+ unsigned int tiled_surface:1;
+ unsigned int pad:1;
+ unsigned int pitch:18;
+ unsigned int depth:11;
+ } ss3;
+
+ struct {
+ unsigned int pad:19;
+ unsigned int min_array_elt:9;
+ unsigned int min_lod:4;
+ } ss4;
+
+ struct {
+ unsigned int pad:20;
+ unsigned int y_offset:4;
+ unsigned int pad2:1;
+ unsigned int x_offset:7;
+ } ss5;
+};
+
+#define SURFACE_STATE_SIZE ALIGN(sizeof(struct gen6_surface_state), 32)
+#define BINDING_TABLE_OFFSET (SURFACE_STATE_SIZE * MAX_SURFACES)
+
+
+struct gen6_render_context {
+ struct drm_i915_gem_object *vb;
+ struct drm_i915_gem_object *vs_state;
+ struct drm_i915_gem_object *sf_state;
+ struct drm_i915_gem_object *surface_state;
+ struct drm_i915_gem_object *wm_state;
+ struct drm_i915_gem_object *cc_state;
+ struct drm_i915_gem_object *cc_viewport;
+ struct drm_i915_gem_object *cc_blend;
+ struct drm_i915_gem_object *depth_stencil;
+ struct drm_i915_gem_object *ps_kernel;
+};
+
+
+static struct gen6_render_context gen6_rc;
+
+static struct drm_i915_gem_object *
+alloc_and_pin(struct drm_device *dev, int size)
+{
+ struct drm_i915_gem_object *obj;
+ obj = i915_gem_alloc_object(dev, size);
+ if (obj == NULL) {
+ DRM_ERROR("fail to allocate obj\n");
+ return NULL;
+ }
+ if (i915_gem_object_pin(obj, 4096, true, false)) {
+ DRM_ERROR("fail to pin obj\n");
+ drm_gem_object_unreference(&obj->base);
+ return NULL;
+ }
+ return obj;
+}
+
+static void
+unpin_and_free(struct drm_i915_gem_object *obj)
+{
+ i915_gem_object_unpin(obj);
+ drm_gem_object_unreference(&obj->base);
+}
+
+static void init_render_context(struct drm_device *dev)
+{
+ gen6_rc.vb = alloc_and_pin(dev, 4096);
+ if (gen6_rc.vb == NULL) {
+ DRM_DEBUG("failed to alloc vexter buffer\n");
+ goto vb_alloc_fail;
+ }
+
+ gen6_rc.surface_state = alloc_and_pin(dev,
+ ALIGN(MAX_SURFACES*(SURFACE_STATE_SIZE+4), 4096));
+ if (gen6_rc.surface_state == NULL) {
+ DRM_DEBUG("failed to alloc surface state\n");
+ goto surface_alloc_fail;
+ }
+
+ gen6_rc.wm_state = alloc_and_pin(dev,
+ ALIGN(sizeof(struct gen6_wm_state), 4096));
+ if (gen6_rc.wm_state == NULL) {
+ DRM_DEBUG("failed to alloc wm state\n");
+ goto wm_alloc_fail;
+ }
+
+ gen6_rc.cc_state = alloc_and_pin(dev,
+ ALIGN(sizeof(struct gen6_cc_state), 4096));
+ if (gen6_rc.cc_state == NULL) {
+ DRM_DEBUG("failed to alloc cc state\n");
+ goto cc_alloc_fail;
+
+ }
+ gen6_rc.cc_viewport = alloc_and_pin(dev,
+ ALIGN(sizeof(struct gen6_cc_viewport), 4096));
+ if (gen6_rc.cc_viewport == NULL) {
+ DRM_DEBUG("failed to alloc cc viewport\n");
+ goto cc_vp_alloc_fail;
+ }
+
+ gen6_rc.cc_blend = alloc_and_pin(dev,
+ ALIGN(sizeof(struct gen6_blend_state), 4096));
+ if (gen6_rc.cc_blend == NULL) {
+ DRM_DEBUG("failed to alloc blend state\n");
+ goto cc_blend_alloc_fail;
+ }
+
+ gen6_rc.depth_stencil = alloc_and_pin(dev,
+ ALIGN(sizeof(struct gen6_depth_stencil_state), 4096));
+ if (gen6_rc.depth_stencil == NULL) {
+ DRM_DEBUG("failed to alloc depth state\n");
+ goto cc_depth_stencil_alloc_fail;
+ }
+
+ gen6_rc.ps_kernel = alloc_and_pin(dev,
+ ALIGN(sizeof(ps_kernel), 4096));
+ if (gen6_rc.ps_kernel == NULL) {
+ DRM_DEBUG("failed to alloc ps kernel\n");
+ goto ps_alloc_fail;
+ }
+ return;
+ps_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.depth_stencil->base);
+cc_depth_stencil_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.cc_blend->base);
+cc_blend_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.cc_viewport->base);
+cc_vp_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.cc_state->base);
+cc_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.wm_state->base);
+wm_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.surface_state->base);
+surface_alloc_fail:
+ drm_gem_object_unreference(&gen6_rc.vb->base);
+vb_alloc_fail:
+ return;
+}
+static void *map_buffer(struct drm_device *dev,
+ struct drm_local_map *map,
+ struct drm_i915_gem_object *obj,
+ int size)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ map->size = size;
+ map->offset = dev_priv->gtt.mappable_base + obj->gtt_offset;
+ map->type = 0;
+ map->flags = 0;
+ map->mtrr = 0;
+ drm_core_ioremap_wc(map, dev);
+ return map->handle;
+}
+
+static void upload_point_vertex(struct drm_device *dev)
+{
+ struct drm_local_map map;
+ unsigned int *vb;
+ vb = map_buffer(dev, &map, gen6_rc.vb, 4096);
+ vb[0] = 0;
+ vb[1] = 0;
+ vb[2] = 0;
+ vb[3] = 0;
+ drm_core_ioremapfree(&map, dev);
+}
+
+static void upload_rect_vertex(struct drm_device *dev)
+{
+ struct drm_local_map map;
+ unsigned int *vb;
+ int i;
+ vb = map_buffer(dev, &map, gen6_rc.vb, 4096);
+ i = 0;
+ vb[i++] = 0;
+ vb[i++] = 0;
+ vb[i++] = 0x43480000; /* 200.0 */
+ vb[i++] = 0x43480000; /* 200.0 */
+
+ vb[i++] = 0;
+ vb[i++] = 0;
+ vb[i++] = 0x42c80000; /* 100.0 */
+ vb[i++] = 0x43480000; /* 100.0 */
+
+ vb[i++] = 0;
+ vb[i++] = 0;
+ vb[i++] = 0x42c80000; /* 100.0 */
+ vb[i++] = 0x42c80000; /* 100.0 */
+ drm_core_ioremapfree(&map, dev);
+}
+
+static void
+setup_render_target_wa(struct drm_device *dev)
+{
+ struct drm_local_map map;
+ struct gen6_surface_state *ss;
+ unsigned int *binding_table;
+ ss = map_buffer(dev, &map, gen6_rc.surface_state, SURFACE_STATE_SIZE);
+ memset(ss, 0, SURFACE_STATE_SIZE);
+ ss->ss0.surface_type = I965_SURFACE_NULL;
+ ss->ss0.surface_format = I965_SURFACEFORMAT_B8G8R8A8_UNORM;
+ ss->ss0.color_blend = 0;
+ ss->ss1.base_addr = 0x10000;
+
+ ss->ss2.width = 127;
+ ss->ss2.height = 127;
+ ss->ss2.mip_count = 0;
+ ss->ss2.render_target_rotation = 0;
+ ss->ss3.pitch = 127;
+ binding_table = (unsigned int *)((unsigned char *)ss + BINDING_TABLE_OFFSET);
+ binding_table[0] = 0;
+ drm_core_ioremapfree(&map, dev);
+}
+
+static void
+setup_depth_stencil_wa(struct drm_device *dev)
+{
+ struct drm_local_map map;
+ struct gen6_depth_stencil_state *depth_stencil;
+ depth_stencil = map_buffer (dev, &map, gen6_rc.depth_stencil,
+ sizeof(*depth_stencil));
+ memset(depth_stencil, 0, sizeof(*depth_stencil));
+ depth_stencil->ds2.depth_test_enable = 1;
+ drm_core_ioremapfree(&map, dev);
+}
+
+static void
+setup_render_target(struct drm_device *dev,
+ struct intel_framebuffer *fb)
+{
+ struct drm_local_map map;
+ struct gen6_surface_state *ss;
+ unsigned int *binding_table;
+ ss = map_buffer(dev, &map, gen6_rc.surface_state, SURFACE_STATE_SIZE);
+ memset(ss, 0, SURFACE_STATE_SIZE);
+ ss->ss0.surface_type = I965_SURFACE_2D;
+ ss->ss0.surface_format = I965_SURFACEFORMAT_B8G8R8A8_UNORM;
+ ss->ss0.color_blend = 0;
+ ss->ss1.base_addr = fb->obj->gtt_offset;
+
+ ss->ss2.width = fb->base.width - 1;
+ ss->ss2.height = fb->base.height - 1;
+ ss->ss2.mip_count = 0;
+ ss->ss2.render_target_rotation = 0;
+ ss->ss3.pitch = fb->base.pitches[0] - 1;
+ switch (fb->obj->tiling_mode) {
+ case I915_TILING_NONE:
+ ss->ss3.tiled_surface = 0;
+ ss->ss3.tile_walk = 0;
+ break;
+ case I915_TILING_X:
+ ss->ss3.tiled_surface = 1;
+ ss->ss3.tile_walk = I965_TILEWALK_XMAJOR;
+ break;
+ case I915_TILING_Y:
+ ss->ss3.tiled_surface = 1;
+ ss->ss3.tile_walk = I965_TILEWALK_YMAJOR;
+ break;
+ }
+ binding_table = (unsigned int *)((unsigned char *)ss + BINDING_TABLE_OFFSET);
+ binding_table[0] = 0;
+ drm_core_ioremapfree(&map, dev);
+}
+
+static void
+setup_depth_stencil(struct drm_device *dev)
+{
+ struct drm_local_map map;
+ struct gen6_depth_stencil_state *depth_stencil;
+ depth_stencil = map_buffer(dev, &map, gen6_rc.depth_stencil,
+ sizeof(*depth_stencil));
+ memset(depth_stencil, 0, sizeof(*depth_stencil));
+ drm_core_ioremapfree(&map, dev);
+}
+
+static void init_render_state(struct drm_device *dev)
+{
+ struct drm_local_map map;
+ {
+
+ struct gen6_cc_viewport *vp;
+ vp = map_buffer(dev, &map, gen6_rc.cc_viewport, sizeof(*vp));
+ memset(vp, 0, sizeof(*vp));
+ *(unsigned int *)&vp->min_depth = 0xf99a130c; /* -1.e35 */;
+ *(unsigned int *)&vp->max_depth = 0x799a130c; /* 1.e35 */;
+ drm_core_ioremapfree(&map, dev);
+ }
+ {
+ struct gen6_cc_state *cc;
+ cc = map_buffer(dev, &map, gen6_rc.cc_state, sizeof(*cc));
+ memset(cc, 0, sizeof(*cc));
+ drm_core_ioremapfree(&map, dev);
+ }
+ {
+ struct gen6_blend_state *blend_state;
+ blend_state = map_buffer (dev, &map, gen6_rc.cc_blend,
+ sizeof(*blend_state));
+ memset(blend_state, 0, sizeof(*blend_state));
+ blend_state->blend1.logic_op_enable = 1;
+ blend_state->blend1.logic_op_func = 0xc;
+ drm_core_ioremapfree(&map, dev);
+ }
+ {
+ unsigned char *kernel;
+ kernel = map_buffer(dev, &map, gen6_rc.ps_kernel,
+ sizeof(ps_kernel));
+ memcpy(kernel, ps_kernel, sizeof(ps_kernel));
+ drm_core_ioremapfree(&map, dev);
+ }
+}
+
+static int
+gen6_emit_state_base_address(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 10)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_STATE_BASE_ADDRESS | (10 - 2));
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* General state base address */
+ intel_ring_emit(ring,
+ gen6_rc.surface_state->gtt_offset| BASE_ADDRESS_MODIFY); /* Surface state base address */
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* Dynamic state base address */
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* Indirect object base address */
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* Instruction base address */
+ intel_ring_emit (ring, BASE_ADDRESS_MODIFY); /* General state upper bound */
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* Dynamic state upper bound */
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* Indirect object upper bound */
+ intel_ring_emit(ring, BASE_ADDRESS_MODIFY); /* Instruction base */
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_invarient_states(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 8)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_PIPELINE_SELECT | PIPELINE_SELECT_3D);
+ intel_ring_emit(ring, GEN6_3DSTATE_MULTISAMPLE | (3 - 2));
+ intel_ring_emit(ring, GEN6_3DSTATE_MULTISAMPLE_PIXEL_LOCATION_CENTER |
+ GEN6_3DSTATE_MULTISAMPLE_NUMSAMPLES_1); /* 1 sample/pixel */
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, GEN6_3DSTATE_SAMPLE_MASK | (2 - 2));
+ intel_ring_emit(ring, 1);
+ intel_ring_emit(ring, CMD_STATE_SIP | 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_viewport_state_pointers(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if (intel_ring_begin(ring, 4))
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_VIEWPORT_STATE_POINTERS |
+ GEN6_3DSTATE_VIEWPORT_STATE_MODIFY_CC |
+ (4 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, gen6_rc.cc_viewport->gtt_offset);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_urb(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 3))!= 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_URB | (3 - 2));
+ intel_ring_emit(ring, ((1 - 1) << GEN6_3DSTATE_URB_VS_SIZE_SHIFT) |
+ (24 << GEN6_3DSTATE_URB_VS_ENTRIES_SHIFT));
+ intel_ring_emit(ring, (0 << GEN6_3DSTATE_URB_GS_SIZE_SHIFT) |
+ (24 << GEN6_3DSTATE_URB_GS_ENTRIES_SHIFT));
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_cc_state_pointers (struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 4)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_CC_STATE_POINTERS | (4 - 2));
+ intel_ring_emit(ring, gen6_rc.cc_blend->gtt_offset|1);
+ intel_ring_emit(ring, gen6_rc.depth_stencil->gtt_offset|1);
+ intel_ring_emit(ring, gen6_rc.cc_state->gtt_offset| 1);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_sampler_state_pointers(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 4)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_SAMPLER_STATE_POINTERS |
+ (4 - 2));
+ intel_ring_emit(ring, 0); /* VS */
+ intel_ring_emit(ring, 0); /* GS */
+ intel_ring_emit(ring, 0); /* WM */
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_vs_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 5)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_CONSTANT_VS | (5 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+
+ if ((intel_ring_begin(ring, 6)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_VS | (6 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, (1<<10));
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_gs_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 12)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_CONSTANT_GS | (5 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+
+ intel_ring_emit(ring, GEN6_3DSTATE_GS | (7 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, (1<<10));
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_clip_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 4)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_CLIP | (4 - 2));
+ intel_ring_emit(ring, 1<<10);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_sf_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 20)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_SF | (20 - 2));
+ intel_ring_emit(ring, (1 << GEN6_3DSTATE_SF_NUM_OUTPUTS_SHIFT) |
+ (1 << GEN6_3DSTATE_SF_URB_ENTRY_READ_LENGTH_SHIFT) |
+ (1 << GEN6_3DSTATE_SF_URB_ENTRY_READ_OFFSET_SHIFT));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, GEN6_3DSTATE_SF_CULL_NONE);
+ intel_ring_emit(ring, 2 << GEN6_3DSTATE_SF_TRIFAN_PROVOKE_SHIFT);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_wm_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 5)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_CONSTANT_PS |
+ (5 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+
+ if ((ret = intel_ring_begin(ring, 9)) != 0)
+ return ret;
+ intel_ring_emit(ring, GEN6_3DSTATE_WM | (9 - 2));
+ intel_ring_emit(ring, gen6_rc.ps_kernel->gtt_offset);
+ intel_ring_emit(ring, (0 << GEN6_3DSTATE_WM_SAMPLER_COUNT_SHIFT) |
+ (5 << GEN6_3DSTATE_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT));
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, (6 << GEN6_3DSTATE_WM_DISPATCH_START_GRF_0_SHIFT));
+ intel_ring_emit(ring, ((60 - 1) << GEN6_3DSTATE_WM_MAX_THREADS_SHIFT) |
+ GEN6_3DSTATE_WM_DISPATCH_ENABLE |
+ GEN6_3DSTATE_WM_16_DISPATCH_ENABLE);
+ intel_ring_emit(ring, (1 << GEN6_3DSTATE_WM_NUM_SF_OUTPUTS_SHIFT) |
+ GEN6_3DSTATE_WM_PERSPECTIVE_PIXEL_BARYCENTRIC);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_binding_table(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 4)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_BINDING_TABLE_POINTERS |
+ GEN6_BINDING_TABLE_MODIFY_PS |
+ (4 - 2));
+ intel_ring_emit(ring, 0); /* vs */
+ intel_ring_emit(ring, 0); /* gs */
+ intel_ring_emit(ring, BINDING_TABLE_OFFSET);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_depth_buffer_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret =intel_ring_begin(ring, 9)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_DEPTH_BUFFER | (7 - 2));
+ intel_ring_emit(ring,
+ (I965_SURFACE_NULL << CMD_DEPTH_BUFFER_TYPE_SHIFT)
+ | (I965_DEPTHFORMAT_D32_FLOAT << CMD_DEPTH_BUFFER_FORMAT_SHIFT));
+ intel_ring_emit(ring, 0x20000);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+ intel_ring_emit(ring, 0);
+
+ intel_ring_emit(ring, CMD_CLEAR_PARAMS | (2 - 2));
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_drawing_rectangle (struct intel_ring_buffer *ring,
+ struct intel_framebuffer *fb)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 4)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_DRAWING_RECTANGLE | 2);
+ intel_ring_emit(ring, 0x00000000);
+ if (fb)
+ intel_ring_emit(ring, (fb->base.width - 1) | (fb->base.height - 1) << 16);
+ else /* workaournd code */
+ intel_ring_emit(ring, 127 | (127 << 16));
+
+ intel_ring_emit(ring, 0x00000000);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_vertex_element_state(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 5)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_VERTEX_ELEMENTS | (5 - 2));
+ intel_ring_emit(ring, (0 << GEN6_VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ GEN6_VE0_VALID |
+ (I965_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (0 << VE0_OFFSET_SHIFT));
+ intel_ring_emit(ring, (I965_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (I965_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (I965_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+ (I965_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT));
+ intel_ring_emit(ring, (0 << GEN6_VE0_VERTEX_BUFFER_INDEX_SHIFT) |
+ GEN6_VE0_VALID |
+ (I965_SURFACEFORMAT_R32G32_FLOAT << VE0_FORMAT_SHIFT) |
+ (8 << VE0_OFFSET_SHIFT));
+ intel_ring_emit(ring, (I965_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_0_SHIFT) |
+ (I965_VFCOMPONENT_STORE_SRC << VE1_VFCOMPONENT_1_SHIFT) |
+ (I965_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_2_SHIFT) |
+ (I965_VFCOMPONENT_STORE_1_FLT << VE1_VFCOMPONENT_3_SHIFT));
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+emit_vertex_buffer(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 5)) != 0)
+ return ret;
+ intel_ring_emit(ring, CMD_VERTEX_BUFFERS | 3);
+ intel_ring_emit(ring,
+ (0 << GEN6_VB0_BUFFER_INDEX_SHIFT) |
+ GEN6_VB0_VERTEXDATA |
+ ((4 * 4) << VB0_BUFFER_PITCH_SHIFT));
+ intel_ring_emit(ring, gen6_rc.vb->gtt_offset);
+ intel_ring_emit(ring, gen6_rc.vb->gtt_offset + 4096);
+ intel_ring_emit(ring, 0);
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_rect_vertex(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 6)) != 0)
+ return ret;
+ intel_ring_emit(ring,
+ CMD_3DPRIMITIVE |
+ _3DPRIMITIVE_VERTEX_SEQUENTIAL |
+ (_3DPRIM_RECTLIST << _3DPRIMITIVE_TOPOLOGY_SHIFT) |
+ (0 << 9) |
+ 4);
+ intel_ring_emit(ring, 3); /* vertex count per instance */
+ intel_ring_emit(ring, 0); /* start vertex offset */
+ intel_ring_emit(ring, 1); /* single instance */
+ intel_ring_emit(ring, 0); /* start instance location */
+ intel_ring_emit(ring, 0); /* index buffer offset, ignored */
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static int
+gen6_emit_point_vertex(struct intel_ring_buffer *ring)
+{
+ int ret;
+ if ((ret = intel_ring_begin(ring, 6)) != 0)
+ return ret;
+ intel_ring_emit(ring,
+ CMD_3DPRIMITIVE |
+ _3DPRIMITIVE_VERTEX_SEQUENTIAL |
+ (_3DPRIM_POINTLIST << _3DPRIMITIVE_TOPOLOGY_SHIFT) |
+ (0 << 9) |
+ 4);
+ intel_ring_emit(ring, 1); /* vertex count per instance */
+ intel_ring_emit(ring, 0); /* start vertex offset */
+ intel_ring_emit(ring, 1); /* single instance */
+ intel_ring_emit(ring, 0); /* start instance location */
+ intel_ring_emit(ring, 0); /* index buffer offset, ignored */
+ intel_ring_advance(ring);
+ return 0;
+}
+
+static void
+gen6_emit_wa(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+
+ upload_point_vertex(dev);
+ setup_render_target_wa(dev);
+ setup_depth_stencil_wa(dev);
+
+ gen6_emit_invarient_states(ring);
+ gen6_emit_state_base_address(ring);
+ gen6_emit_viewport_state_pointers(ring);
+ gen6_emit_urb(ring);
+ gen6_emit_cc_state_pointers(ring);
+ gen6_emit_sampler_state_pointers(ring);
+ gen6_emit_vs_state(ring);
+ gen6_emit_gs_state(ring);
+ gen6_emit_clip_state(ring);
+ gen6_emit_sf_state(ring);
+ gen6_emit_wm_state(ring);
+ gen6_emit_binding_table(ring);
+ gen6_emit_drawing_rectangle(ring, NULL);
+ gen6_emit_vertex_element_state(ring);
+ emit_vertex_buffer(ring);
+ gen6_emit_point_vertex(ring);
+ if (intel_ring_flush_all_caches(ring)) {
+ DRM_ERROR("fail to flush ring \n");
+ return;
+ }
+ if (intel_ring_idle(ring)) {
+ DRM_ERROR("fail to wait ring idle\n");
+ return;
+ }
+}
+
+static void
+gen6_emit_rect(struct drm_device *dev,
+ struct intel_framebuffer *fb,
+ int x, int y, int w, int h)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+ u32 seqno;
+ int ret;
+
+ upload_rect_vertex(dev);
+ setup_render_target(dev, fb);
+ setup_depth_stencil(dev);
+
+ gen6_emit_invarient_states(ring);
+ gen6_emit_state_base_address(ring);
+ gen6_emit_viewport_state_pointers(ring);
+ gen6_emit_urb(ring);
+ gen6_emit_cc_state_pointers(ring);
+ gen6_emit_sampler_state_pointers(ring);
+ gen6_emit_vs_state(ring);
+ gen6_emit_gs_state(ring);
+ gen6_emit_clip_state(ring);
+ gen6_emit_sf_state(ring);
+ gen6_emit_wm_state(ring);
+ gen6_emit_binding_table(ring);
+ gen6_emit_depth_buffer_state(ring);
+ gen6_emit_drawing_rectangle(ring, fb);
+ gen6_emit_vertex_element_state(ring);
+ emit_vertex_buffer(ring);
+ gen6_emit_rect_vertex(ring);
+ ret = i915_add_request(ring, NULL, &seqno);
+ if (ret)
+ return;
+
+ if (intel_ring_flush_all_caches(ring)) {
+ DRM_ERROR("fail to flush ring \n");
+ return;
+ }
+
+ if (i915_wait_seqno(ring, seqno)) {
+ DRM_ERROR("fail to wait request\n");
+ return;
+ }
+}
+
+static void
+release_render_context(struct drm_device *dev)
+{
+ unpin_and_free(gen6_rc.surface_state);
+ unpin_and_free(gen6_rc.wm_state);
+ unpin_and_free(gen6_rc.cc_state);
+ unpin_and_free(gen6_rc.cc_viewport);
+ unpin_and_free(gen6_rc.cc_blend);
+ unpin_and_free(gen6_rc.depth_stencil);
+ unpin_and_free(gen6_rc.ps_kernel);
+}
+
+void i915_render_rect(struct drm_device *dev,
+ struct intel_framebuffer *fb,
+ int x, int y, int w, int h)
+{
+ if (INTEL_INFO(dev)->gen == 6) {
+ mutex_lock(&dev->struct_mutex);
+ init_render_context(dev);
+ init_render_state(dev);
+ gen6_emit_rect(dev, fb, x, y, w, h);
+ release_render_context(dev);
+ mutex_unlock(&dev->struct_mutex);
+ }
+}
+
+void gen6_suspend_workaround(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
+ if (INTEL_INFO(dev)->gen < 6)
+ return;
+ gen6_emit_depth_buffer_state(ring);
+}
+
+void gen6_wakeup_workaround(struct drm_device *dev)
+{
+ if (INTEL_INFO(dev)->gen < 6)
+ return;
+ init_render_context(dev);
+ init_render_state(dev);
+ gen6_emit_wa(dev);
+ release_render_context(dev);
+}
--
1.7.9.5
More information about the Intel-gfx
mailing list