From patchwork Tue Apr 23 22:46:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 2481431 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 7C8FDDF2E5 for ; Tue, 23 Apr 2013 22:47:17 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 57D10E618C for ; Tue, 23 Apr 2013 15:47:17 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from oproxy6-pub.bluehost.com (oproxy6-pub.bluehost.com [67.222.54.6]) by gabe.freedesktop.org (Postfix) with SMTP id 1D38CE60F2 for ; Tue, 23 Apr 2013 15:46:44 -0700 (PDT) Received: (qmail 8952 invoked by uid 0); 23 Apr 2013 22:46:43 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by cpoproxy3.bluehost.com with SMTP; 23 Apr 2013 22:46:43 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuousgeek.org; s=default; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-Id:Date:Subject:To:From; bh=xw3Q3HR1b7GyqRjfvLCbR06K8zSyl8Ejaqtg135KK88=; b=Wpf5Yxp5ONDIbxJ/Mfk+5433UFsA9q/D4ptaLzP1osiEZwUe6/TSk0mm2QwcumfPD7wfXEMVb7SFTG09QEEx+KL8ExLmYJr60AMAbOskfQ0hroeXeZ5qH+4D+dtzyOHz; Received: from [67.161.37.189] (port=45365 helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:CAMELLIA256-SHA:256) (Exim 4.80) (envelope-from ) id 1UUlz1-0005up-1U for intel-gfx@lists.freedesktop.org; Tue, 23 Apr 2013 16:46:43 -0600 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Tue, 23 Apr 2013 15:46:41 -0700 Message-Id: <1366757201-5838-1-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.161.37.189 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] =?utf-8?q?=5BPATCH=5D_drm/i915=3A_init_hardware_to_a_?= =?utf-8?q?known_state_on_resume_v3?= X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org From: Zou Nanhai 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 Signed-off-by: Jesse Barnes --- 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 + * + */ +#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); +}