c92034e63321146ec36534131869003c6a4478a7
[mw/milkymist.git] / software / libhal / tmu.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <stdio.h>
19 #include <irq.h>
20 #include <board.h>
21 #include <hw/interrupts.h>
22 #include <hw/tmu.h>
23
24 #include <hal/brd.h>
25 #include <hal/tmu.h>
26
27 #define TMU_TASKQ_SIZE 4 /* < must be a power of 2 */
28 #define TMU_TASKQ_MASK (TMU_TASKQ_SIZE-1)
29
30 static struct tmu_td *queue[TMU_TASKQ_SIZE];
31 static unsigned int produce;
32 static unsigned int consume;
33 static unsigned int level;
34 static int cts;
35
36 void tmu_init()
37 {
38         unsigned int mask;
39
40         produce = 0;
41         consume = 0;
42         level = 0;
43         cts = 1;
44
45         CSR_TMU_CTL = 0;
46         irq_ack(IRQ_TMU);
47
48         mask = irq_getmask();
49         mask |= IRQ_TMU;
50         irq_setmask(mask);
51
52         printf("TMU: texture mapping unit initialized\n");
53 }
54
55 static void tmu_start(struct tmu_td *td)
56 {
57         CSR_TMU_HMESHLAST = td->hmeshlast;
58         CSR_TMU_VMESHLAST = td->vmeshlast;
59         CSR_TMU_BRIGHTNESS = td->brightness;
60         CSR_TMU_CHROMAKEY = td->chromakey;
61         CSR_TMU_SRCMESH = (unsigned int)td->srcmesh;
62         CSR_TMU_SRCFBUF = (unsigned int)td->srcfbuf;
63         CSR_TMU_SRCHRES = td->srchres;
64         CSR_TMU_SRCVRES = td->srcvres;
65         CSR_TMU_DSTMESH = (unsigned int)td->dstmesh;
66         CSR_TMU_DSTFBUF = (unsigned int)td->dstfbuf;
67         CSR_TMU_DSTHRES = td->dsthres;
68         CSR_TMU_DSTVRES = td->dstvres;
69
70         CSR_TMU_CTL = td->flags|TMU_CTL_START;
71         //printf("write %d read %d\n", td->flags|TMU_CTL_START, CSR_TMU_CTL);
72 }
73
74 void tmu_isr()
75 {
76         if(queue[consume]->callback)
77                 queue[consume]->callback(queue[consume]);
78         if(queue[consume]->profile) {
79                 int pixels, clocks, misses, hits;
80
81                 printf("TMU: ====================================================\n");
82                 pixels = CSR_TMUP_PIXELS;
83                 clocks = CSR_TMUP_CLOCKS;
84                 printf("TMU: Drawn pixels:                         %d\n", pixels);
85                 printf("TMU: Processing time (clock cycles):       %d\n", clocks);
86                 printf("TMU: Fill rate (Mpixels/s):                %d\n", (brd_desc->clk_frequency/1000000)*pixels/clocks);
87                 printf("TMU: Frames per second:                    %d\n", brd_desc->clk_frequency/clocks);
88                 printf("TMU: Geometry rate (Kvertices/s):          %d\n", (brd_desc->clk_frequency/1000)*((CSR_TMU_HMESHLAST+1)*(CSR_TMU_VMESHLAST+1))/clocks);
89                 printf("TMU: At point 1:\n");
90                 printf("TMU:   - stalled transactions:             %d\n", CSR_TMUP_STALL1);
91                 printf("TMU:   - completed transactions:           %d\n", CSR_TMUP_COMPLETE1);
92                 printf("TMU: At point 2:\n");
93                 printf("TMU:   - stalled transactions:             %d\n", CSR_TMUP_STALL2);
94                 printf("TMU:   - completed transactions:           %d\n", CSR_TMUP_COMPLETE2);
95                 printf("TMU: Texel cache:\n");
96                 misses = CSR_TMUP_MISSES;
97                 hits = pixels-misses;
98                 printf("TMU:   - hits:                             %d\n", hits);
99                 printf("TMU:   - misses:                           %d\n", misses);
100                 printf("TMU:   - hit rate:                         %d%%\n", 100*hits/(hits+misses));
101                 printf("TMU: ====================================================\n");
102         }
103         consume = (consume + 1) & TMU_TASKQ_MASK;
104         level--;
105
106         irq_ack(IRQ_TMU);
107
108         if(level > 0)
109                 tmu_start(queue[consume]);
110         else
111                 cts = 1;
112 }
113
114 int tmu_submit_task(struct tmu_td *td)
115 {
116         unsigned int oldmask;
117
118         oldmask = irq_getmask();
119         irq_setmask(oldmask & (~IRQ_TMU));
120
121         if(level >= TMU_TASKQ_SIZE) {
122                 irq_setmask(oldmask);
123                 printf("TMU: taskq overflow\n");
124                 return 0;
125         }
126
127         queue[produce] = td;
128         produce = (produce + 1) & TMU_TASKQ_MASK;
129         level++;
130
131         if(cts) {
132                 cts = 0;
133                 tmu_start(td);
134         }
135
136         irq_setmask(oldmask);
137
138         return 1;
139 }
140