Software support for the new TMU
[mw/milkymist.git] / software / libhal / tmu.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009, 2010 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
62         CSR_TMU_VERTICESADR = (unsigned int)td->vertices;
63         CSR_TMU_TEXFBUF = (unsigned int)td->texfbuf;
64         CSR_TMU_TEXHRES = td->texhres;
65         CSR_TMU_TEXVRES = td->texvres;
66         CSR_TMU_TEXHMASK = td->texhmask;
67         CSR_TMU_TEXVMASK = td->texvmask;
68
69         CSR_TMU_DSTFBUF = (unsigned int)td->dstfbuf;
70         CSR_TMU_DSTHRES = td->dsthres;
71         CSR_TMU_DSTVRES = td->dstvres;
72         CSR_TMU_DSTHOFFSET = td->dsthoffset;
73         CSR_TMU_DSTVOFFSET = td->dstvoffset;
74         CSR_TMU_DSTSQUAREW = td->dstsquarew;
75         CSR_TMU_DSTSQUAREH = td->dstsquareh;
76
77         CSR_TMU_CTL = td->flags|TMU_CTL_START;
78 }
79
80 void tmu_isr()
81 {
82         if(queue[consume]->callback)
83                 queue[consume]->callback(queue[consume]);
84         consume = (consume + 1) & TMU_TASKQ_MASK;
85         level--;
86
87         irq_ack(IRQ_TMU);
88
89         if(level > 0)
90                 tmu_start(queue[consume]);
91         else
92                 cts = 1;
93 }
94
95 int tmu_submit_task(struct tmu_td *td)
96 {
97         unsigned int oldmask;
98
99         oldmask = irq_getmask();
100         irq_setmask(oldmask & (~IRQ_TMU));
101
102         if(level >= TMU_TASKQ_SIZE) {
103                 irq_setmask(oldmask);
104                 printf("TMU: taskq overflow\n");
105                 return 0;
106         }
107
108         queue[produce] = td;
109         produce = (produce + 1) & TMU_TASKQ_MASK;
110         level++;
111
112         if(cts) {
113                 cts = 0;
114                 tmu_start(td);
115         }
116
117         irq_setmask(oldmask);
118
119         return 1;
120 }
121