diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2016-01-21 15:20:25 +0000 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2016-03-07 15:36:56 +0100 |
commit | 8581d8149750e19fc363ad93327f4382b26959f9 (patch) | |
tree | ad2c934857bcb1b46b14f252d7d9e93761a44704 /drivers/gpu/drm/etnaviv/etnaviv_buffer.c | |
parent | f60863116b4026713fba1810927f8639bfd6ae80 (diff) |
drm: etnaviv: flush all GPU caches when stopping GPU
Flush the GPU caches to ensure that any dirty data is pushed out before
stopping the front end.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_buffer.c')
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index 950db38c1324..6ff10d76a601 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -21,6 +21,7 @@ #include "common.xml.h" #include "state.xml.h" +#include "state_3d.xml.h" #include "cmdstream.xml.h" /* @@ -179,12 +180,42 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu) void etnaviv_buffer_end(struct etnaviv_gpu *gpu) { struct etnaviv_cmdbuf *buffer = gpu->buffer; + unsigned int waitlink_offset = buffer->user_size - 16; + u32 link_target, flush = 0; - /* Replace the last WAIT with an END */ - buffer->user_size -= 16; - - CMD_END(buffer); - mb(); + if (gpu->exec_state == ETNA_PIPE_2D) + flush = VIVS_GL_FLUSH_CACHE_PE2D; + else if (gpu->exec_state == ETNA_PIPE_3D) + flush = VIVS_GL_FLUSH_CACHE_DEPTH | + VIVS_GL_FLUSH_CACHE_COLOR | + VIVS_GL_FLUSH_CACHE_TEXTURE | + VIVS_GL_FLUSH_CACHE_TEXTUREVS | + VIVS_GL_FLUSH_CACHE_SHADER_L2; + + if (flush) { + unsigned int dwords = 7; + + link_target = etnaviv_buffer_reserve(gpu, buffer, dwords); + + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush); + if (gpu->exec_state == ETNA_PIPE_3D) + CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, + VIVS_TS_FLUSH_CACHE_FLUSH); + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + CMD_END(buffer); + + etnaviv_buffer_replace_wait(buffer, waitlink_offset, + VIV_FE_LINK_HEADER_OP_LINK | + VIV_FE_LINK_HEADER_PREFETCH(dwords), + link_target); + } else { + /* Replace the last link-wait with an "END" command */ + etnaviv_buffer_replace_wait(buffer, waitlink_offset, + VIV_FE_END_HEADER_OP_END, 0); + } } void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, |