6ca4cc9e3238acbce8e4eacbc0bebee1b303a395
[mplayer/glamo.git] / drivers / libglamo / dma.c
blob6ca4cc9e3238acbce8e4eacbc0bebee1b303a395
1 /*
2 * Glamo DMA engine.
4 * Copyright (C) 2007 OpenMoko, Inc.
5 * Author: Chia-I Wu <olv@openmoko.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 or
10 * (at your option) version 3 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "dma.h"
27 #include "hw.h"
28 #include "glamo.h"
30 #define DMA_CMDQ_SIZE (1 * 1024)
32 static void dma_cmdq_init(struct glamo_dma_manager *dma)
34 int cmdq_len;
36 cmdq_len = (DMA_CMDQ_SIZE >> 10) - 1;
38 dma->cmdq = (GLAMO_REG_TYPE *) (glamo_fb + GLAMO_VRAM_CMDQ);
39 dma->size = DMA_CMDQ_SIZE;
40 dma->r = 0;
41 dma->w = 0;
43 dma->cmdq[dma->size >> 1] = 0x0;
44 dma->cmdq[(dma->size >> 1) + 1] = 0x0;
46 glamo_hw_engine_enable(GLAMO_ENGINE_CMDQ);
47 glamo_hw_engine_reset(GLAMO_ENGINE_CMDQ);
49 GLAMO_OUT_REG(GLAMO_REG_CMDQ_BASE_ADDRL,
50 GLAMO_VRAM_CMDQ & 0xffff);
51 GLAMO_OUT_REG(GLAMO_REG_CMDQ_BASE_ADDRH,
52 (GLAMO_VRAM_CMDQ >> 16) & 0x7f);
53 GLAMO_OUT_REG(GLAMO_REG_CMDQ_LEN, cmdq_len);
55 GLAMO_OUT_REG(GLAMO_REG_CMDQ_WRITE_ADDRH, 0);
56 GLAMO_OUT_REG(GLAMO_REG_CMDQ_WRITE_ADDRL, 0);
57 GLAMO_OUT_REG(GLAMO_REG_CMDQ_READ_ADDRH, 0);
58 GLAMO_OUT_REG(GLAMO_REG_CMDQ_READ_ADDRL, 0);
59 GLAMO_OUT_REG(GLAMO_REG_CMDQ_CONTROL,
60 1 << 12 | /* turbo flip */
61 0 << 11 | /* no triple buffer */
62 5 << 8 | /* no interrupt */
63 8 << 4 | /* HQ threshold */
64 0 << 2 | /* no auto-correction */
65 0 << 1); /* SQ mode */
68 static void dma_cmdq_flush(struct glamo_dma_manager *dma)
70 GLAMO_REG_TYPE *p = (GLAMO_REG_TYPE *) dma->lbuf;
71 int ring_size = dma->size >> 1;
72 int ring_count = dma->llen >> 1;
74 if (ring_count == 0)
75 return;
77 /* write pointer can be ring_size, but not zero */
78 while (ring_count--)
80 if (dma->w >= ring_size)
81 dma->w = 0;
83 dma->cmdq[dma->w++] = *p++;
85 while (dma->r == dma->w)
87 dma->r = GLAMO_IN_REG(GLAMO_REG_CMDQ_READ_ADDRL);
88 dma->r |= (GLAMO_IN_REG(GLAMO_REG_CMDQ_READ_ADDRH) & 0x7) << 16;
92 GLAMO_OUT_REG(GLAMO_REG_CMDQ_WRITE_ADDRH, (dma->w >> 15) & 0x7);
93 GLAMO_OUT_REG(GLAMO_REG_CMDQ_WRITE_ADDRL, (dma->w << 1) & 0xffff);
95 dma->llen = 0;
98 static void dma_mmio_flush(struct glamo_dma_manager *dma)
100 GLAMO_REG_TYPE *p = (GLAMO_REG_TYPE *) dma->lbuf;
102 while ((unsigned char *) p < dma->lbuf + dma->llen)
104 GLAMO_REG_TYPE reg, val;
106 reg = *p++;
107 val = *p++;
109 if (reg & (1 << 15))
111 int i, n = val;
113 reg &= ~(1 << 15);
115 for (i = 0; i < n; i++, reg += 2)
117 val = *p++;
118 //printf("burst 0x%x to 0x%x\n", val, reg);
119 GLAMO_OUT_REG(reg, val);
122 if (n & 1)
123 p++;
125 else
126 GLAMO_OUT_REG(reg, val);
129 dma->llen = 0;
132 void glamo_dma_wait(struct glamo_dma_manager *dma, enum glamo_dma_wait_type t)
134 int mask, val;
136 switch (dma->mode)
138 case GLAMO_DMA_MODE_CMDQ:
139 switch (t)
141 case GLAMO_DMA_WAIT_CMDQ:
142 mask = 0x3;
143 val = mask;
144 break;
145 case GLAMO_DMA_WAIT_ISP:
146 mask = 0x3 | (1 << 8);
147 val = 0x3;
148 case GLAMO_DMA_WAIT_ALL:
149 mask = 1 << 2;
150 val = mask;
151 break;
152 default:
153 return;
156 while (1)
158 int status;
160 status = GLAMO_IN_REG(GLAMO_REG_CMDQ_STATUS);
161 if ((status & mask) == val)
162 break;
164 break;
165 case GLAMO_DMA_MODE_MMIO:
166 default:
167 break;
171 void glamo_dma_flush(struct glamo_dma_manager *dma)
173 if (dma->llen == 0)
174 return;
176 switch (dma->mode)
178 case GLAMO_DMA_MODE_CMDQ:
179 dma_cmdq_flush(dma);
180 break;
181 case GLAMO_DMA_MODE_MMIO:
182 default:
183 dma_mmio_flush(dma);
184 break;
188 struct glamo_dma_manager *glamo_dma_new(enum glamo_dma_mode mode)
190 struct glamo_dma_manager *dma;
192 dma = malloc(sizeof(*dma));
193 if (!dma)
194 return NULL;
196 dma->mode = mode;
197 dma->lsize = DMA_CMDQ_SIZE;
198 dma->lbuf = malloc(dma->lsize);
199 dma->llen = 0;
201 switch (mode)
203 case GLAMO_DMA_MODE_CMDQ:
204 dma_cmdq_init(dma);
205 break;
206 case GLAMO_DMA_MODE_MMIO:
207 default:
208 break;
211 return dma;
214 void glamo_dma_destroy(struct glamo_dma_manager *dma)
216 switch (dma->mode)
218 case GLAMO_DMA_MODE_CMDQ:
219 glamo_hw_engine_reset(GLAMO_ENGINE_CMDQ);
220 glamo_hw_engine_disable(GLAMO_ENGINE_CMDQ);
221 break;
222 case GLAMO_DMA_MODE_MMIO:
223 default:
224 break;
227 free(dma->lbuf);
228 free(dma);
231 void glamo_dma_dump(struct glamo_dma_manager *dma)
233 int i;
235 switch (dma->mode)
237 case GLAMO_DMA_MODE_CMDQ:
238 glamo_hw_dump(GLAMO_REG_CMDQ_BASE_ADDRL, 10);
239 printf("w 0x%x, r 0x%x\n", dma->w << 1, dma->r << 1);
240 for (i = 0; i < 16; i++)
241 printf("0x%04x%c", dma->cmdq[i], ((i % 16) == 15) ? '\n' : ' ');
242 break;
243 case GLAMO_DMA_MODE_MMIO:
244 default:
245 break;