forked from Minki/linux
ce806a3047
Linear copy works by adding the offset to the buffer address, which may end up not being 16-byte aligned. Some tests I've written for prime_pcopy show that the engine allows this correctly, so the restriction on lowest 4 bits of address can be lifted safely. The comments added were by envyas, I think because I used a newer version. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com> Cc: stable@vger.kernel.org
873 lines
20 KiB
Plaintext
873 lines
20 KiB
Plaintext
/* fuc microcode for copy engine on nva3- chipsets
|
|
*
|
|
* Copyright 2011 Red Hat Inc.
|
|
*
|
|
* 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs
|
|
*/
|
|
|
|
/* To build for nva3:nvc0
|
|
* m4 -DNVA3 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nva3_copy.fuc.h
|
|
*
|
|
* To build for nvc0-
|
|
* m4 -DNVC0 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_copy.fuc.h
|
|
*/
|
|
|
|
ifdef(`NVA3',
|
|
.section #nva3_pcopy_data
|
|
,
|
|
.section #nvc0_pcopy_data
|
|
)
|
|
|
|
ctx_object: .b32 0
|
|
ifdef(`NVA3',
|
|
ctx_dma:
|
|
ctx_dma_query: .b32 0
|
|
ctx_dma_src: .b32 0
|
|
ctx_dma_dst: .b32 0
|
|
,)
|
|
.equ #ctx_dma_count 3
|
|
ctx_query_address_high: .b32 0
|
|
ctx_query_address_low: .b32 0
|
|
ctx_query_counter: .b32 0
|
|
ctx_src_address_high: .b32 0
|
|
ctx_src_address_low: .b32 0
|
|
ctx_src_pitch: .b32 0
|
|
ctx_src_tile_mode: .b32 0
|
|
ctx_src_xsize: .b32 0
|
|
ctx_src_ysize: .b32 0
|
|
ctx_src_zsize: .b32 0
|
|
ctx_src_zoff: .b32 0
|
|
ctx_src_xoff: .b32 0
|
|
ctx_src_yoff: .b32 0
|
|
ctx_src_cpp: .b32 0
|
|
ctx_dst_address_high: .b32 0
|
|
ctx_dst_address_low: .b32 0
|
|
ctx_dst_pitch: .b32 0
|
|
ctx_dst_tile_mode: .b32 0
|
|
ctx_dst_xsize: .b32 0
|
|
ctx_dst_ysize: .b32 0
|
|
ctx_dst_zsize: .b32 0
|
|
ctx_dst_zoff: .b32 0
|
|
ctx_dst_xoff: .b32 0
|
|
ctx_dst_yoff: .b32 0
|
|
ctx_dst_cpp: .b32 0
|
|
ctx_format: .b32 0
|
|
ctx_swz_const0: .b32 0
|
|
ctx_swz_const1: .b32 0
|
|
ctx_xcnt: .b32 0
|
|
ctx_ycnt: .b32 0
|
|
.align 256
|
|
|
|
dispatch_table:
|
|
// mthd 0x0000, NAME
|
|
.b16 0x000 1
|
|
.b32 #ctx_object ~0xffffffff
|
|
// mthd 0x0100, NOP
|
|
.b16 0x040 1
|
|
.b32 0x00010000 + #cmd_nop ~0xffffffff
|
|
// mthd 0x0140, PM_TRIGGER
|
|
.b16 0x050 1
|
|
.b32 0x00010000 + #cmd_pm_trigger ~0xffffffff
|
|
ifdef(`NVA3', `
|
|
// mthd 0x0180-0x018c, DMA_
|
|
.b16 0x060 #ctx_dma_count
|
|
dispatch_dma:
|
|
.b32 0x00010000 + #cmd_dma ~0xffffffff
|
|
.b32 0x00010000 + #cmd_dma ~0xffffffff
|
|
.b32 0x00010000 + #cmd_dma ~0xffffffff
|
|
',)
|
|
// mthd 0x0200-0x0218, SRC_TILE
|
|
.b16 0x80 7
|
|
.b32 #ctx_src_tile_mode ~0x00000fff
|
|
.b32 #ctx_src_xsize ~0x0007ffff
|
|
.b32 #ctx_src_ysize ~0x00001fff
|
|
.b32 #ctx_src_zsize ~0x000007ff
|
|
.b32 #ctx_src_zoff ~0x00000fff
|
|
.b32 #ctx_src_xoff ~0x0007ffff
|
|
.b32 #ctx_src_yoff ~0x00001fff
|
|
// mthd 0x0220-0x0238, DST_TILE
|
|
.b16 0x88 7
|
|
.b32 #ctx_dst_tile_mode ~0x00000fff
|
|
.b32 #ctx_dst_xsize ~0x0007ffff
|
|
.b32 #ctx_dst_ysize ~0x00001fff
|
|
.b32 #ctx_dst_zsize ~0x000007ff
|
|
.b32 #ctx_dst_zoff ~0x00000fff
|
|
.b32 #ctx_dst_xoff ~0x0007ffff
|
|
.b32 #ctx_dst_yoff ~0x00001fff
|
|
// mthd 0x0300-0x0304, EXEC, WRCACHE_FLUSH
|
|
.b16 0xc0 2
|
|
.b32 0x00010000 + #cmd_exec ~0xffffffff
|
|
.b32 0x00010000 + #cmd_wrcache_flush ~0xffffffff
|
|
// mthd 0x030c-0x0340, various stuff
|
|
.b16 0xc3 14
|
|
.b32 #ctx_src_address_high ~0x000000ff
|
|
.b32 #ctx_src_address_low ~0xffffffff
|
|
.b32 #ctx_dst_address_high ~0x000000ff
|
|
.b32 #ctx_dst_address_low ~0xffffffff
|
|
.b32 #ctx_src_pitch ~0x0007ffff
|
|
.b32 #ctx_dst_pitch ~0x0007ffff
|
|
.b32 #ctx_xcnt ~0x0000ffff
|
|
.b32 #ctx_ycnt ~0x00001fff
|
|
.b32 #ctx_format ~0x0333ffff
|
|
.b32 #ctx_swz_const0 ~0xffffffff
|
|
.b32 #ctx_swz_const1 ~0xffffffff
|
|
.b32 #ctx_query_address_high ~0x000000ff
|
|
.b32 #ctx_query_address_low ~0xffffffff
|
|
.b32 #ctx_query_counter ~0xffffffff
|
|
.b16 0x800 0
|
|
|
|
ifdef(`NVA3',
|
|
.section #nva3_pcopy_code
|
|
,
|
|
.section #nvc0_pcopy_code
|
|
)
|
|
|
|
main:
|
|
clear b32 $r0
|
|
mov $sp $r0
|
|
|
|
// setup i0 handler and route fifo and ctxswitch to it
|
|
mov $r1 #ih
|
|
mov $iv0 $r1
|
|
mov $r1 0x400
|
|
movw $r2 0xfff3
|
|
sethi $r2 0
|
|
iowr I[$r1 + 0x300] $r2
|
|
|
|
// enable interrupts
|
|
or $r2 0xc
|
|
iowr I[$r1] $r2
|
|
bset $flags ie0
|
|
|
|
// enable fifo access and context switching
|
|
mov $r1 0x1200
|
|
mov $r2 3
|
|
iowr I[$r1] $r2
|
|
|
|
// sleep forever, waking for interrupts
|
|
bset $flags $p0
|
|
spin:
|
|
sleep $p0
|
|
bra #spin
|
|
|
|
// i0 handler
|
|
ih:
|
|
iord $r1 I[$r0 + 0x200]
|
|
|
|
and $r2 $r1 0x00000008
|
|
bra e #ih_no_chsw
|
|
call #chsw
|
|
ih_no_chsw:
|
|
and $r2 $r1 0x00000004
|
|
bra e #ih_no_cmd
|
|
call #dispatch
|
|
|
|
ih_no_cmd:
|
|
and $r1 $r1 0x0000000c
|
|
iowr I[$r0 + 0x100] $r1
|
|
iret
|
|
|
|
// $p1 direction (0 = unload, 1 = load)
|
|
// $r3 channel
|
|
swctx:
|
|
mov $r4 0x7700
|
|
mov $xtargets $r4
|
|
ifdef(`NVA3', `
|
|
// target 7 hardcoded to ctx dma object
|
|
mov $xdbase $r0
|
|
', ` // NVC0
|
|
// read SCRATCH3 to decide if we are PCOPY0 or PCOPY1
|
|
mov $r4 0x2100
|
|
iord $r4 I[$r4 + 0]
|
|
and $r4 1
|
|
shl b32 $r4 4
|
|
add b32 $r4 0x30
|
|
|
|
// channel is in vram
|
|
mov $r15 0x61c
|
|
shl b32 $r15 6
|
|
mov $r5 0x114
|
|
iowrs I[$r15] $r5
|
|
|
|
// read 16-byte PCOPYn info, containing context pointer, from channel
|
|
shl b32 $r5 $r3 4
|
|
add b32 $r5 2
|
|
mov $xdbase $r5
|
|
mov $r5 $sp
|
|
// get a chunk of stack space, aligned to 256 byte boundary
|
|
sub b32 $r5 0x100
|
|
mov $r6 0xff
|
|
not b32 $r6
|
|
and $r5 $r6
|
|
sethi $r5 0x00020000
|
|
xdld $r4 $r5
|
|
xdwait
|
|
sethi $r5 0
|
|
|
|
// set context pointer, from within channel VM
|
|
mov $r14 0
|
|
iowrs I[$r15] $r14
|
|
ld b32 $r4 D[$r5 + 0]
|
|
shr b32 $r4 8
|
|
ld b32 $r6 D[$r5 + 4]
|
|
shl b32 $r6 24
|
|
or $r4 $r6
|
|
mov $xdbase $r4
|
|
')
|
|
// 256-byte context, at start of data segment
|
|
mov b32 $r4 $r0
|
|
sethi $r4 0x60000
|
|
|
|
// swap!
|
|
bra $p1 #swctx_load
|
|
xdst $r0 $r4
|
|
bra #swctx_done
|
|
swctx_load:
|
|
xdld $r0 $r4
|
|
swctx_done:
|
|
xdwait
|
|
ret
|
|
|
|
chsw:
|
|
// read current channel
|
|
mov $r2 0x1400
|
|
iord $r3 I[$r2]
|
|
|
|
// if it's active, unload it and return
|
|
xbit $r15 $r3 0x1e
|
|
bra e #chsw_no_unload
|
|
bclr $flags $p1
|
|
call #swctx
|
|
bclr $r3 0x1e
|
|
iowr I[$r2] $r3
|
|
mov $r4 1
|
|
iowr I[$r2 + 0x200] $r4
|
|
ret
|
|
|
|
// read next channel
|
|
chsw_no_unload:
|
|
iord $r3 I[$r2 + 0x100]
|
|
|
|
// is there a channel waiting to be loaded?
|
|
xbit $r13 $r3 0x1e
|
|
bra e #chsw_finish_load
|
|
bset $flags $p1
|
|
call #swctx
|
|
ifdef(`NVA3',
|
|
// load dma objects back into TARGET regs
|
|
mov $r5 #ctx_dma
|
|
mov $r6 #ctx_dma_count
|
|
chsw_load_ctx_dma:
|
|
ld b32 $r7 D[$r5 + $r6 * 4]
|
|
add b32 $r8 $r6 0x180
|
|
shl b32 $r8 8
|
|
iowr I[$r8] $r7
|
|
sub b32 $r6 1
|
|
bra nc #chsw_load_ctx_dma
|
|
,)
|
|
|
|
chsw_finish_load:
|
|
mov $r3 2
|
|
iowr I[$r2 + 0x200] $r3
|
|
ret
|
|
|
|
dispatch:
|
|
// read incoming fifo command
|
|
mov $r3 0x1900
|
|
iord $r2 I[$r3 + 0x100]
|
|
iord $r3 I[$r3 + 0x000]
|
|
and $r4 $r2 0x7ff
|
|
// $r2 will be used to store exception data
|
|
shl b32 $r2 0x10
|
|
|
|
// lookup method in the dispatch table, ILLEGAL_MTHD if not found
|
|
mov $r5 #dispatch_table
|
|
clear b32 $r6
|
|
clear b32 $r7
|
|
dispatch_loop:
|
|
ld b16 $r6 D[$r5 + 0]
|
|
ld b16 $r7 D[$r5 + 2]
|
|
add b32 $r5 4
|
|
cmpu b32 $r4 $r6
|
|
bra c #dispatch_illegal_mthd
|
|
add b32 $r7 $r6
|
|
cmpu b32 $r4 $r7
|
|
bra c #dispatch_valid_mthd
|
|
sub b32 $r7 $r6
|
|
shl b32 $r7 3
|
|
add b32 $r5 $r7
|
|
bra #dispatch_loop
|
|
|
|
// ensure no bits set in reserved fields, INVALID_BITFIELD
|
|
dispatch_valid_mthd:
|
|
sub b32 $r4 $r6
|
|
shl b32 $r4 3
|
|
add b32 $r4 $r5
|
|
ld b32 $r5 D[$r4 + 4]
|
|
and $r5 $r3
|
|
cmpu b32 $r5 0
|
|
bra ne #dispatch_invalid_bitfield
|
|
|
|
// depending on dispatch flags: execute method, or save data as state
|
|
ld b16 $r5 D[$r4 + 0]
|
|
ld b16 $r6 D[$r4 + 2]
|
|
cmpu b32 $r6 0
|
|
bra ne #dispatch_cmd
|
|
st b32 D[$r5] $r3
|
|
bra #dispatch_done
|
|
dispatch_cmd:
|
|
bclr $flags $p1
|
|
call $r5
|
|
bra $p1 #dispatch_error
|
|
bra #dispatch_done
|
|
|
|
dispatch_invalid_bitfield:
|
|
or $r2 2
|
|
dispatch_illegal_mthd:
|
|
or $r2 1
|
|
|
|
// store exception data in SCRATCH0/SCRATCH1, signal hostirq
|
|
dispatch_error:
|
|
mov $r4 0x1000
|
|
iowr I[$r4 + 0x000] $r2
|
|
iowr I[$r4 + 0x100] $r3
|
|
mov $r2 0x40
|
|
iowr I[$r0] $r2
|
|
hostirq_wait:
|
|
iord $r2 I[$r0 + 0x200]
|
|
and $r2 0x40
|
|
cmpu b32 $r2 0
|
|
bra ne #hostirq_wait
|
|
|
|
dispatch_done:
|
|
mov $r2 0x1d00
|
|
mov $r3 1
|
|
iowr I[$r2] $r3
|
|
ret
|
|
|
|
// No-operation
|
|
//
|
|
// Inputs:
|
|
// $r1: irqh state
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
// $r4: dispatch table entry
|
|
// Outputs:
|
|
// $r1: irqh state
|
|
// $p1: set on error
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
cmd_nop:
|
|
ret
|
|
|
|
// PM_TRIGGER
|
|
//
|
|
// Inputs:
|
|
// $r1: irqh state
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
// $r4: dispatch table entry
|
|
// Outputs:
|
|
// $r1: irqh state
|
|
// $p1: set on error
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
cmd_pm_trigger:
|
|
mov $r2 0x2200
|
|
clear b32 $r3
|
|
sethi $r3 0x20000
|
|
iowr I[$r2] $r3
|
|
ret
|
|
|
|
ifdef(`NVA3',
|
|
// SET_DMA_* method handler
|
|
//
|
|
// Inputs:
|
|
// $r1: irqh state
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
// $r4: dispatch table entry
|
|
// Outputs:
|
|
// $r1: irqh state
|
|
// $p1: set on error
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
cmd_dma:
|
|
sub b32 $r4 #dispatch_dma
|
|
shr b32 $r4 1
|
|
bset $r3 0x1e
|
|
st b32 D[$r4 + #ctx_dma] $r3
|
|
add b32 $r4 0x600
|
|
shl b32 $r4 6
|
|
iowr I[$r4] $r3
|
|
ret
|
|
,)
|
|
|
|
// Calculates the hw swizzle mask and adjusts the surface's xcnt to match
|
|
//
|
|
cmd_exec_set_format:
|
|
// zero out a chunk of the stack to store the swizzle into
|
|
add $sp -0x10
|
|
st b32 D[$sp + 0x00] $r0
|
|
st b32 D[$sp + 0x04] $r0
|
|
st b32 D[$sp + 0x08] $r0
|
|
st b32 D[$sp + 0x0c] $r0
|
|
|
|
// extract cpp, src_ncomp and dst_ncomp from FORMAT
|
|
ld b32 $r4 D[$r0 + #ctx_format]
|
|
extr $r5 $r4 16:17
|
|
add b32 $r5 1
|
|
extr $r6 $r4 20:21
|
|
add b32 $r6 1
|
|
extr $r7 $r4 24:25
|
|
add b32 $r7 1
|
|
|
|
// convert FORMAT swizzle mask to hw swizzle mask
|
|
bclr $flags $p2
|
|
clear b32 $r8
|
|
clear b32 $r9
|
|
ncomp_loop:
|
|
and $r10 $r4 0xf
|
|
shr b32 $r4 4
|
|
clear b32 $r11
|
|
bpc_loop:
|
|
cmpu b8 $r10 4
|
|
bra nc #cmp_c0
|
|
mulu $r12 $r10 $r5
|
|
add b32 $r12 $r11
|
|
bset $flags $p2
|
|
bra #bpc_next
|
|
cmp_c0:
|
|
bra ne #cmp_c1
|
|
mov $r12 0x10
|
|
add b32 $r12 $r11
|
|
bra #bpc_next
|
|
cmp_c1:
|
|
cmpu b8 $r10 6
|
|
bra nc #cmp_zero
|
|
mov $r12 0x14
|
|
add b32 $r12 $r11
|
|
bra #bpc_next
|
|
cmp_zero:
|
|
mov $r12 0x80
|
|
bpc_next:
|
|
st b8 D[$sp + $r8] $r12
|
|
add b32 $r8 1
|
|
add b32 $r11 1
|
|
cmpu b32 $r11 $r5
|
|
bra c #bpc_loop
|
|
add b32 $r9 1
|
|
cmpu b32 $r9 $r7
|
|
bra c #ncomp_loop
|
|
|
|
// SRC_XCNT = (xcnt * src_cpp), or 0 if no src ref in swz (hw will hang)
|
|
mulu $r6 $r5
|
|
st b32 D[$r0 + #ctx_src_cpp] $r6
|
|
ld b32 $r8 D[$r0 + #ctx_xcnt]
|
|
mulu $r6 $r8
|
|
bra $p2 #dst_xcnt
|
|
clear b32 $r6
|
|
|
|
dst_xcnt:
|
|
mulu $r7 $r5
|
|
st b32 D[$r0 + #ctx_dst_cpp] $r7
|
|
mulu $r7 $r8
|
|
|
|
mov $r5 0x810
|
|
shl b32 $r5 6
|
|
iowr I[$r5 + 0x000] $r6
|
|
iowr I[$r5 + 0x100] $r7
|
|
add b32 $r5 0x800
|
|
ld b32 $r6 D[$r0 + #ctx_dst_cpp]
|
|
sub b32 $r6 1
|
|
shl b32 $r6 8
|
|
ld b32 $r7 D[$r0 + #ctx_src_cpp]
|
|
sub b32 $r7 1
|
|
or $r6 $r7
|
|
iowr I[$r5 + 0x000] $r6
|
|
add b32 $r5 0x100
|
|
ld b32 $r6 D[$sp + 0x00]
|
|
iowr I[$r5 + 0x000] $r6
|
|
ld b32 $r6 D[$sp + 0x04]
|
|
iowr I[$r5 + 0x100] $r6
|
|
ld b32 $r6 D[$sp + 0x08]
|
|
iowr I[$r5 + 0x200] $r6
|
|
ld b32 $r6 D[$sp + 0x0c]
|
|
iowr I[$r5 + 0x300] $r6
|
|
add b32 $r5 0x400
|
|
ld b32 $r6 D[$r0 + #ctx_swz_const0]
|
|
iowr I[$r5 + 0x000] $r6
|
|
ld b32 $r6 D[$r0 + #ctx_swz_const1]
|
|
iowr I[$r5 + 0x100] $r6
|
|
add $sp 0x10
|
|
ret
|
|
|
|
// Setup to handle a tiled surface
|
|
//
|
|
// Calculates a number of parameters the hardware requires in order
|
|
// to correctly handle tiling.
|
|
//
|
|
// Offset calculation is performed as follows (Tp/Th/Td from TILE_MODE):
|
|
// nTx = round_up(w * cpp, 1 << Tp) >> Tp
|
|
// nTy = round_up(h, 1 << Th) >> Th
|
|
// Txo = (x * cpp) & ((1 << Tp) - 1)
|
|
// Tx = (x * cpp) >> Tp
|
|
// Tyo = y & ((1 << Th) - 1)
|
|
// Ty = y >> Th
|
|
// Tzo = z & ((1 << Td) - 1)
|
|
// Tz = z >> Td
|
|
//
|
|
// off = (Tzo << Tp << Th) + (Tyo << Tp) + Txo
|
|
// off += ((Tz * nTy * nTx)) + (Ty * nTx) + Tx) << Td << Th << Tp;
|
|
//
|
|
// Inputs:
|
|
// $r4: hw command (0x104800)
|
|
// $r5: ctx offset adjustment for src/dst selection
|
|
// $p2: set if dst surface
|
|
//
|
|
cmd_exec_set_surface_tiled:
|
|
// translate TILE_MODE into Tp, Th, Td shift values
|
|
ld b32 $r7 D[$r5 + #ctx_src_tile_mode]
|
|
extr $r9 $r7 8:11
|
|
extr $r8 $r7 4:7
|
|
ifdef(`NVA3',
|
|
add b32 $r8 2
|
|
,
|
|
add b32 $r8 3
|
|
)
|
|
extr $r7 $r7 0:3
|
|
cmp b32 $r7 0xe
|
|
bra ne #xtile64
|
|
mov $r7 4
|
|
bra #xtileok
|
|
xtile64:
|
|
xbit $r7 $flags $p2
|
|
add b32 $r7 17
|
|
bset $r4 $r7
|
|
mov $r7 6
|
|
xtileok:
|
|
|
|
// Op = (x * cpp) & ((1 << Tp) - 1)
|
|
// Tx = (x * cpp) >> Tp
|
|
ld b32 $r10 D[$r5 + #ctx_src_xoff]
|
|
ld b32 $r11 D[$r5 + #ctx_src_cpp]
|
|
mulu $r10 $r11
|
|
mov $r11 1
|
|
shl b32 $r11 $r7
|
|
sub b32 $r11 1
|
|
and $r12 $r10 $r11
|
|
shr b32 $r10 $r7
|
|
|
|
// Tyo = y & ((1 << Th) - 1)
|
|
// Ty = y >> Th
|
|
ld b32 $r13 D[$r5 + #ctx_src_yoff]
|
|
mov $r14 1
|
|
shl b32 $r14 $r8
|
|
sub b32 $r14 1
|
|
and $r11 $r13 $r14
|
|
shr b32 $r13 $r8
|
|
|
|
// YTILE = ((1 << Th) << 12) | ((1 << Th) - Tyo)
|
|
add b32 $r14 1
|
|
shl b32 $r15 $r14 12
|
|
sub b32 $r14 $r11
|
|
or $r15 $r14
|
|
xbit $r6 $flags $p2
|
|
add b32 $r6 0x208
|
|
shl b32 $r6 8
|
|
iowr I[$r6 + 0x000] $r15
|
|
|
|
// Op += Tyo << Tp
|
|
shl b32 $r11 $r7
|
|
add b32 $r12 $r11
|
|
|
|
// nTx = ((w * cpp) + ((1 << Tp) - 1) >> Tp)
|
|
ld b32 $r15 D[$r5 + #ctx_src_xsize]
|
|
ld b32 $r11 D[$r5 + #ctx_src_cpp]
|
|
mulu $r15 $r11
|
|
mov $r11 1
|
|
shl b32 $r11 $r7
|
|
sub b32 $r11 1
|
|
add b32 $r15 $r11
|
|
shr b32 $r15 $r7
|
|
push $r15
|
|
|
|
// nTy = (h + ((1 << Th) - 1)) >> Th
|
|
ld b32 $r15 D[$r5 + #ctx_src_ysize]
|
|
mov $r11 1
|
|
shl b32 $r11 $r8
|
|
sub b32 $r11 1
|
|
add b32 $r15 $r11
|
|
shr b32 $r15 $r8
|
|
push $r15
|
|
|
|
// Tys = Tp + Th
|
|
// CFG_YZ_TILE_SIZE = ((1 << Th) >> 2) << Td
|
|
add b32 $r7 $r8
|
|
sub b32 $r8 2
|
|
mov $r11 1
|
|
shl b32 $r11 $r8
|
|
shl b32 $r11 $r9
|
|
|
|
// Tzo = z & ((1 << Td) - 1)
|
|
// Tz = z >> Td
|
|
// Op += Tzo << Tys
|
|
// Ts = Tys + Td
|
|
ld b32 $r8 D[$r5 + #ctx_src_zoff]
|
|
mov $r14 1
|
|
shl b32 $r14 $r9
|
|
sub b32 $r14 1
|
|
and $r15 $r8 $r14
|
|
shl b32 $r15 $r7
|
|
add b32 $r12 $r15
|
|
add b32 $r7 $r9
|
|
shr b32 $r8 $r9
|
|
|
|
// Ot = ((Tz * nTy * nTx) + (Ty * nTx) + Tx) << Ts
|
|
pop $r15
|
|
pop $r9
|
|
mulu $r13 $r9
|
|
add b32 $r10 $r13
|
|
mulu $r8 $r9
|
|
mulu $r8 $r15
|
|
add b32 $r10 $r8
|
|
shl b32 $r10 $r7
|
|
|
|
// PITCH = (nTx - 1) << Ts
|
|
sub b32 $r9 1
|
|
shl b32 $r9 $r7
|
|
iowr I[$r6 + 0x200] $r9
|
|
|
|
// SRC_ADDRESS_LOW = (Ot + Op) & 0xffffffff
|
|
// CFG_ADDRESS_HIGH |= ((Ot + Op) >> 32) << 16
|
|
ld b32 $r7 D[$r5 + #ctx_src_address_low]
|
|
ld b32 $r8 D[$r5 + #ctx_src_address_high]
|
|
add b32 $r10 $r12
|
|
add b32 $r7 $r10
|
|
adc b32 $r8 0
|
|
shl b32 $r8 16
|
|
or $r8 $r11
|
|
sub b32 $r6 0x600
|
|
iowr I[$r6 + 0x000] $r7
|
|
add b32 $r6 0x400
|
|
iowr I[$r6 + 0x000] $r8
|
|
ret
|
|
|
|
// Setup to handle a linear surface
|
|
//
|
|
// Nothing to see here.. Sets ADDRESS and PITCH, pretty non-exciting
|
|
//
|
|
cmd_exec_set_surface_linear:
|
|
xbit $r6 $flags $p2
|
|
add b32 $r6 0x202
|
|
shl b32 $r6 8
|
|
ld b32 $r7 D[$r5 + #ctx_src_address_low]
|
|
iowr I[$r6 + 0x000] $r7
|
|
add b32 $r6 0x400
|
|
ld b32 $r7 D[$r5 + #ctx_src_address_high]
|
|
shl b32 $r7 16
|
|
iowr I[$r6 + 0x000] $r7
|
|
add b32 $r6 0x400
|
|
ld b32 $r7 D[$r5 + #ctx_src_pitch]
|
|
iowr I[$r6 + 0x000] $r7
|
|
ret
|
|
|
|
// wait for regs to be available for use
|
|
cmd_exec_wait:
|
|
push $r0
|
|
push $r1
|
|
mov $r0 0x800
|
|
shl b32 $r0 6
|
|
loop:
|
|
iord $r1 I[$r0]
|
|
and $r1 1
|
|
bra ne #loop
|
|
pop $r1
|
|
pop $r0
|
|
ret
|
|
|
|
cmd_exec_query:
|
|
// if QUERY_SHORT not set, write out { -, 0, TIME_LO, TIME_HI }
|
|
xbit $r4 $r3 13
|
|
bra ne #query_counter
|
|
call #cmd_exec_wait
|
|
mov $r4 0x80c
|
|
shl b32 $r4 6
|
|
ld b32 $r5 D[$r0 + #ctx_query_address_low]
|
|
add b32 $r5 4
|
|
iowr I[$r4 + 0x000] $r5
|
|
iowr I[$r4 + 0x100] $r0
|
|
mov $r5 0xc
|
|
iowr I[$r4 + 0x200] $r5
|
|
add b32 $r4 0x400
|
|
ld b32 $r5 D[$r0 + #ctx_query_address_high]
|
|
shl b32 $r5 16
|
|
iowr I[$r4 + 0x000] $r5
|
|
add b32 $r4 0x500
|
|
mov $r5 0x00000b00
|
|
sethi $r5 0x00010000
|
|
iowr I[$r4 + 0x000] $r5
|
|
mov $r5 0x00004040
|
|
shl b32 $r5 1
|
|
sethi $r5 0x80800000
|
|
iowr I[$r4 + 0x100] $r5
|
|
mov $r5 0x00001110
|
|
sethi $r5 0x13120000
|
|
iowr I[$r4 + 0x200] $r5
|
|
mov $r5 0x00001514
|
|
sethi $r5 0x17160000
|
|
iowr I[$r4 + 0x300] $r5
|
|
mov $r5 0x00002601
|
|
sethi $r5 0x00010000
|
|
mov $r4 0x800
|
|
shl b32 $r4 6
|
|
iowr I[$r4 + 0x000] $r5
|
|
|
|
// write COUNTER
|
|
query_counter:
|
|
call #cmd_exec_wait
|
|
mov $r4 0x80c
|
|
shl b32 $r4 6
|
|
ld b32 $r5 D[$r0 + #ctx_query_address_low]
|
|
iowr I[$r4 + 0x000] $r5
|
|
iowr I[$r4 + 0x100] $r0
|
|
mov $r5 0x4
|
|
iowr I[$r4 + 0x200] $r5
|
|
add b32 $r4 0x400
|
|
ld b32 $r5 D[$r0 + #ctx_query_address_high]
|
|
shl b32 $r5 16
|
|
iowr I[$r4 + 0x000] $r5
|
|
add b32 $r4 0x500
|
|
mov $r5 0x00000300
|
|
iowr I[$r4 + 0x000] $r5
|
|
mov $r5 0x00001110
|
|
sethi $r5 0x13120000
|
|
iowr I[$r4 + 0x100] $r5
|
|
ld b32 $r5 D[$r0 + #ctx_query_counter]
|
|
add b32 $r4 0x500
|
|
iowr I[$r4 + 0x000] $r5
|
|
mov $r5 0x00002601
|
|
sethi $r5 0x00010000
|
|
mov $r4 0x800
|
|
shl b32 $r4 6
|
|
iowr I[$r4 + 0x000] $r5
|
|
ret
|
|
|
|
// Execute a copy operation
|
|
//
|
|
// Inputs:
|
|
// $r1: irqh state
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
// 000002000 QUERY_SHORT
|
|
// 000001000 QUERY
|
|
// 000000100 DST_LINEAR
|
|
// 000000010 SRC_LINEAR
|
|
// 000000001 FORMAT
|
|
// $r4: dispatch table entry
|
|
// Outputs:
|
|
// $r1: irqh state
|
|
// $p1: set on error
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
cmd_exec:
|
|
call #cmd_exec_wait
|
|
|
|
// if format requested, call function to calculate it, otherwise
|
|
// fill in cpp/xcnt for both surfaces as if (cpp == 1)
|
|
xbit $r15 $r3 0
|
|
bra e #cmd_exec_no_format
|
|
call #cmd_exec_set_format
|
|
mov $r4 0x200
|
|
bra #cmd_exec_init_src_surface
|
|
cmd_exec_no_format:
|
|
mov $r6 0x810
|
|
shl b32 $r6 6
|
|
mov $r7 1
|
|
st b32 D[$r0 + #ctx_src_cpp] $r7
|
|
st b32 D[$r0 + #ctx_dst_cpp] $r7
|
|
ld b32 $r7 D[$r0 + #ctx_xcnt]
|
|
iowr I[$r6 + 0x000] $r7
|
|
iowr I[$r6 + 0x100] $r7
|
|
clear b32 $r4
|
|
|
|
cmd_exec_init_src_surface:
|
|
bclr $flags $p2
|
|
clear b32 $r5
|
|
xbit $r15 $r3 4
|
|
bra e #src_tiled
|
|
call #cmd_exec_set_surface_linear
|
|
bra #cmd_exec_init_dst_surface
|
|
src_tiled:
|
|
call #cmd_exec_set_surface_tiled
|
|
bset $r4 7
|
|
|
|
cmd_exec_init_dst_surface:
|
|
bset $flags $p2
|
|
mov $r5 #ctx_dst_address_high - #ctx_src_address_high
|
|
xbit $r15 $r3 8
|
|
bra e #dst_tiled
|
|
call #cmd_exec_set_surface_linear
|
|
bra #cmd_exec_kick
|
|
dst_tiled:
|
|
call #cmd_exec_set_surface_tiled
|
|
bset $r4 8
|
|
|
|
cmd_exec_kick:
|
|
mov $r5 0x800
|
|
shl b32 $r5 6
|
|
ld b32 $r6 D[$r0 + #ctx_ycnt]
|
|
iowr I[$r5 + 0x100] $r6
|
|
mov $r6 0x0041
|
|
// SRC_TARGET = 1, DST_TARGET = 2
|
|
sethi $r6 0x44000000
|
|
or $r4 $r6
|
|
iowr I[$r5] $r4
|
|
|
|
// if requested, queue up a QUERY write after the copy has completed
|
|
xbit $r15 $r3 12
|
|
bra e #cmd_exec_done
|
|
call #cmd_exec_query
|
|
|
|
cmd_exec_done:
|
|
ret
|
|
|
|
// Flush write cache
|
|
//
|
|
// Inputs:
|
|
// $r1: irqh state
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
// $r4: dispatch table entry
|
|
// Outputs:
|
|
// $r1: irqh state
|
|
// $p1: set on error
|
|
// $r2: hostirq state
|
|
// $r3: data
|
|
cmd_wrcache_flush:
|
|
mov $r2 0x2200
|
|
clear b32 $r3
|
|
sethi $r3 0x10000
|
|
iowr I[$r2] $r3
|
|
ret
|
|
|
|
.align 0x100
|