rockbox/firmware/target/arm/as3525/dbop-as3525.c
Thomas Martitz dc07c79263 Sansa AMS: Time has shown that switching between 16 and 32bit mode costs much time (due to the micro delay needed), so do 32bit transfers unconditionally for lcd updates at the cost of updating slightly larger rectangles (gives upto 15% speed up, nearly at maximum now).
Unify this optimized dbop transfer function and re-use it more often (it still handles 16bit transfers).

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24198 a1c6a512-1295-4272-9138-f99709370657
2010-01-07 22:21:41 +00:00

125 lines
4 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 by Bertrik Sikken
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include <inttypes.h>
#include "as3525.h"
#include "dbop-as3525.h"
#if defined(SANSA_FUZE)
#define DBOP_PRECHARGE 0x80FF
#elif defined(SANSA_E200V2) || defined(SANSA_C200V2)
#define DBOP_PRECHARGE 0xF0FF
#endif
static short int dbop_input_value = 0;
/* read the DBOP data pins */
unsigned short dbop_read_input(void)
{
unsigned int dbop_ctrl_old = DBOP_CTRL;
unsigned int dbop_timpol23_old = DBOP_TIMPOL_23;
/* make sure that the DBOP FIFO is empty */
while ((DBOP_STAT & (1<<10)) == 0);
/* write DBOP_DOUT to pre-charge DBOP data lines with a defined level */
DBOP_TIMPOL_23 = 0xe007e007; /* no strobe towards lcd */
int delay = 10;
while (delay--) asm volatile ("nop\n");
DBOP_CTRL = (1 << 19) | /* tri-state output */
(1 << 16) | /* enw=1 (enable write) */
(1 << 12); /* ow=1 (16-bit data width) */
DBOP_DOUT = DBOP_PRECHARGE;
while ((DBOP_STAT & (1<<10)) == 0);
#if defined(SANSA_FUZE) || defined(SANSA_E200V2)
delay = 50;
while (delay--) asm volatile ("nop\n");
#endif
/* perform a DBOP read */
DBOP_CTRL = (1 << 19) | /* tri-state output */
(1 << 15) | /* strd=1 (start read) */
(1 << 12) | /* ow=1 (16-bit data width) */
(31 << 0); /* rs_t=31 (read DBOP at end of cycle) */
while ((DBOP_STAT & (1<<16)) == 0);
dbop_input_value = DBOP_DIN;
/* restore previous values */
DBOP_TIMPOL_23 = dbop_timpol23_old;
DBOP_CTRL = dbop_ctrl_old;
return dbop_input_value;
}
/* for the debug menu */
unsigned short dbop_debug(void)
{
return dbop_input_value;
}
static inline void dbop_set_mode(int mode)
{
int delay = 10;
if (mode == 32 && (!(DBOP_CTRL & (1<<13|1<<14))))
DBOP_CTRL |= (1<<13|1<<14);
else if (mode == 16 && (DBOP_CTRL & (1<<13|1<<14)))
DBOP_CTRL &= ~(1<<14|1<<13);
else
return;
while(delay--) asm volatile("nop");
}
void dbop_write_data(const int16_t* p_bytes, int count)
{
const int32_t *data;
if ((intptr_t)p_bytes & 0x3 || count == 1)
{ /* need to do a single 16bit write beforehand if the address is
* not word aligned or count is 1, switch to 16bit mode if needed */
dbop_set_mode(16);
DBOP_DOUT16 = *p_bytes++;
if (!(--count))
return;
}
/* from here, 32bit transfers are save
* set it to transfer 4*(outputwidth) units at a time,
* if bit 12 is set it only does 2 halfwords though (we never set it)
* switch to 32bit output if needed */
dbop_set_mode(32);
data = (int32_t*)p_bytes;
while (count > 1)
{
DBOP_DOUT32 = *data++;
count -= 2;
/* Wait if push fifo is full */
while ((DBOP_STAT & (1<<6)) != 0);
}
/* While push fifo is not empty */
while ((DBOP_STAT & (1<<10)) == 0);
/* due to the 32bit alignment requirement or uneven count,
* we possibly need to do a 16bit transfer at the end also */
if (count > 0)
dbop_write_data((int16_t*)data, 1);
}