mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-23 23:20:38 +02:00
ubb-vga.c: added (fragile) DMA support (locks up on anything but 800x600)
Note that DMA is very sensitive to the video timing. At the moment, only 800x600 mode works without locking up the DMA controller. - ubb-vga.c (DMA, setup_noirq, cleanup_noirq, line): replaced MMC PIO with DMA - ubb-vga.c (frame): pass physical addresses to "line" - ubb-vga.c (frame): detect if the DMA controller is stuck
This commit is contained in:
parent
64f3047144
commit
a8a0cfa22f
@ -67,6 +67,7 @@ static int bad;
|
|||||||
|
|
||||||
|
|
||||||
#define TIMER 7
|
#define TIMER 7
|
||||||
|
#define DMA 0
|
||||||
|
|
||||||
|
|
||||||
static uint32_t old_icmr;
|
static uint32_t old_icmr;
|
||||||
@ -245,25 +246,35 @@ static void setup(void)
|
|||||||
|
|
||||||
static void setup_noirq(void)
|
static void setup_noirq(void)
|
||||||
{
|
{
|
||||||
|
DMAC = 1;
|
||||||
|
DCS(DMA) = (1 << 3) | (1 << 2);
|
||||||
|
DCS(DMA) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cleanup_noirq(void)
|
static void cleanup_noirq(void)
|
||||||
{
|
{
|
||||||
|
DMAC = 0;
|
||||||
|
DCS(DMA) = (1 << 3) | (1 << 2);
|
||||||
|
DCS(DMA) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void line(const uint32_t *line)
|
static void line(unsigned long line)
|
||||||
{
|
{
|
||||||
const uint32_t *p = line;
|
|
||||||
uint32_t first;
|
|
||||||
|
|
||||||
/* Back porch */
|
/* Back porch */
|
||||||
|
|
||||||
MSC_STRPCL = 1 << 3; /* reset the MSC */
|
MSC_STRPCL = 1 << 3; /* reset the MSC */
|
||||||
// while (MSC_STAT & (1 << 15));
|
|
||||||
|
|
||||||
first = *p++;
|
DCS(DMA) = (1 << 31) | (1 << 3) | (1 << 2);
|
||||||
|
DCS(DMA) = 1 << 31;
|
||||||
|
DSA(DMA) = line;
|
||||||
|
DTA(DMA) = REG_PADDR(MSC_TXFIFO);
|
||||||
|
DTC(DMA) = mode->xres >> 5;
|
||||||
|
DCM(DMA) =
|
||||||
|
(1 << 23) | /* source address increment */
|
||||||
|
(4 << 8); /* transfer size is 32 bytes */
|
||||||
|
DRT(DMA) = 26; /* MSC transmit-fifo-empty transfer request */
|
||||||
|
|
||||||
until(US(0.79));
|
until(US(0.79));
|
||||||
|
|
||||||
@ -275,50 +286,30 @@ static void line(const uint32_t *line)
|
|||||||
|
|
||||||
MSC_CMDAT =
|
MSC_CMDAT =
|
||||||
(2 << 9) | /* 4 bit bus */
|
(2 << 9) | /* 4 bit bus */
|
||||||
|
(1 << 8) | /* DMA */
|
||||||
(1 << 4) | /* write */
|
(1 << 4) | /* write */
|
||||||
(1 << 3) | /* with data transfer */
|
(1 << 3) | /* with data transfer */
|
||||||
1; /* R1 response */
|
1; /* R1 response */
|
||||||
|
|
||||||
MSC_STRPCL = 4; /* START_OP */
|
MSC_STRPCL = 4; /* START_OP */
|
||||||
|
|
||||||
|
DCS(DMA) =
|
||||||
|
(1 << 31) | /* no descriptor */
|
||||||
|
1;
|
||||||
|
|
||||||
until(mode->hsync_end);
|
until(mode->hsync_end);
|
||||||
|
|
||||||
/* Front porch */
|
// MSC_TXFIFO = 0xffffffff;
|
||||||
|
|
||||||
MSC_TXFIFO = first;
|
/* Front porch */
|
||||||
|
|
||||||
PDFUNS = CMD;
|
PDFUNS = CMD;
|
||||||
PDDATS = HSYNC;
|
PDDATS = HSYNC;
|
||||||
PDFUNC = CMD;
|
PDFUNC = CMD;
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't wait for the end of the front porch because the beginning
|
|
||||||
* of pixel data is determined by the MSC. Instead, we make good use
|
|
||||||
* of the delay to shovel bits into the MSC's FIFO.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 1 /* quick load */
|
|
||||||
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
|
||||||
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
|
||||||
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
|
||||||
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
|
||||||
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
|
||||||
#endif
|
|
||||||
while (p != line+mode->line_words) {
|
|
||||||
uint8_t st;
|
|
||||||
do {
|
|
||||||
st = MSC_STAT;
|
|
||||||
if (st & 3) {
|
|
||||||
bad++;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (st & (1 << 7));
|
|
||||||
MSC_TXFIFO = *p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
|
||||||
until(mode->line_cycles);
|
until(mode->line_cycles);
|
||||||
|
if (MSC_STAT & 3)
|
||||||
|
bad++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -334,9 +325,9 @@ static void hdelay(int cycles)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void frame(void *const *f)
|
static void frame(const unsigned long *f)
|
||||||
{
|
{
|
||||||
void *const *p;
|
const unsigned long *p;
|
||||||
|
|
||||||
/* VSYNC */
|
/* VSYNC */
|
||||||
PDDATC = VSYNC;
|
PDDATC = VSYNC;
|
||||||
@ -378,19 +369,27 @@ static void frame(void *const *f)
|
|||||||
|
|
||||||
static void session(void (*gen)(void **fb, int xres, int yres), int frames)
|
static void session(void (*gen)(void **fb, int xres, int yres), int frames)
|
||||||
{
|
{
|
||||||
void **f;
|
void **f_virt;
|
||||||
|
const unsigned long *f_phys;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ccube_init();
|
ccube_init();
|
||||||
f = calloc_phys_vec(mode->yres, mode->xres/2);
|
f_virt = calloc_phys_vec(mode->yres, mode->xres/2);
|
||||||
gen(f, mode->xres, mode->yres);
|
gen(f_virt, mode->xres, mode->yres);
|
||||||
|
f_phys = xlat_virt(f_virt, mode->yres);
|
||||||
|
|
||||||
disable_interrupts();
|
disable_interrupts();
|
||||||
|
|
||||||
setup_noirq();
|
setup_noirq();
|
||||||
|
|
||||||
for (i = 0; i != frames; i++)
|
for (i = 0; i != frames; i++) {
|
||||||
frame(f);
|
frame(f_phys);
|
||||||
|
if (DTC(DMA)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"DMA locked up. Need hardware reset.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cleanup_noirq();
|
cleanup_noirq();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user