summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-01-07 22:21:41 +0000
committerThomas Martitz <kugel@rockbox.org>2010-01-07 22:21:41 +0000
commitdc07c792634a95a4906784790460ab570be32fc0 (patch)
treef5bac9dc07e1badcf0e838df41327faa7c49dfca
parent5fd54dee4ff3e0299c8b5d6c12e5633728396c72 (diff)
downloadrockbox-dc07c792634a95a4906784790460ab570be32fc0.tar.gz
rockbox-dc07c792634a95a4906784790460ab570be32fc0.zip
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
-rw-r--r--firmware/target/arm/as3525/dbop-as3525.c48
-rw-r--r--firmware/target/arm/as3525/dbop-as3525.h12
-rw-r--r--firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c50
-rw-r--r--firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c59
4 files changed, 76 insertions, 93 deletions
diff --git a/firmware/target/arm/as3525/dbop-as3525.c b/firmware/target/arm/as3525/dbop-as3525.c
index 938eee2fb1..b54ad17a6c 100644
--- a/firmware/target/arm/as3525/dbop-as3525.c
+++ b/firmware/target/arm/as3525/dbop-as3525.c
@@ -20,6 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "config.h" 22#include "config.h"
23#include <inttypes.h>
23#include "as3525.h" 24#include "as3525.h"
24#include "dbop-as3525.h" 25#include "dbop-as3525.h"
25 26
@@ -75,3 +76,50 @@ unsigned short dbop_debug(void)
75{ 76{
76 return dbop_input_value; 77 return dbop_input_value;
77} 78}
79
80static inline void dbop_set_mode(int mode)
81{
82 int delay = 10;
83 if (mode == 32 && (!(DBOP_CTRL & (1<<13|1<<14))))
84 DBOP_CTRL |= (1<<13|1<<14);
85 else if (mode == 16 && (DBOP_CTRL & (1<<13|1<<14)))
86 DBOP_CTRL &= ~(1<<14|1<<13);
87 else
88 return;
89 while(delay--) asm volatile("nop");
90}
91
92void dbop_write_data(const int16_t* p_bytes, int count)
93{
94
95 const int32_t *data;
96 if ((intptr_t)p_bytes & 0x3 || count == 1)
97 { /* need to do a single 16bit write beforehand if the address is
98 * not word aligned or count is 1, switch to 16bit mode if needed */
99 dbop_set_mode(16);
100 DBOP_DOUT16 = *p_bytes++;
101 if (!(--count))
102 return;
103 }
104 /* from here, 32bit transfers are save
105 * set it to transfer 4*(outputwidth) units at a time,
106 * if bit 12 is set it only does 2 halfwords though (we never set it)
107 * switch to 32bit output if needed */
108 dbop_set_mode(32);
109 data = (int32_t*)p_bytes;
110 while (count > 1)
111 {
112 DBOP_DOUT32 = *data++;
113 count -= 2;
114
115 /* Wait if push fifo is full */
116 while ((DBOP_STAT & (1<<6)) != 0);
117 }
118 /* While push fifo is not empty */
119 while ((DBOP_STAT & (1<<10)) == 0);
120
121 /* due to the 32bit alignment requirement or uneven count,
122 * we possibly need to do a 16bit transfer at the end also */
123 if (count > 0)
124 dbop_write_data((int16_t*)data, 1);
125}
diff --git a/firmware/target/arm/as3525/dbop-as3525.h b/firmware/target/arm/as3525/dbop-as3525.h
index 63156031c4..3db62bd3e1 100644
--- a/firmware/target/arm/as3525/dbop-as3525.h
+++ b/firmware/target/arm/as3525/dbop-as3525.h
@@ -19,5 +19,17 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22
23#ifndef __DBOP_AS3525_H__
24#define __DBOP_AS3525_H__
25#include <inttypes.h>
22unsigned short int dbop_read_input(void); 26unsigned short int dbop_read_input(void);
23unsigned short dbop_debug(void); 27unsigned short dbop_debug(void);
28
29/*
30 * Write any data to dbop
31 * switches to 32bit transfers if possible,
32 * for best performance pre-align count and data
33 **/
34void dbop_write_data(const int16_t *data, int count);
35#endif
diff --git a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c
index f4d1a7cf56..54aa22e398 100644
--- a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c
+++ b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c
@@ -120,19 +120,11 @@ static void as3525_dbop_init(void)
120 /* TODO: The OF calls some other functions here, but maybe not important */ 120 /* TODO: The OF calls some other functions here, but maybe not important */
121} 121}
122 122
123static void lcd_write_value16(unsigned short value) 123static void lcd_write_cmd(short cmd)
124{
125 DBOP_CTRL &= ~(1<<14|1<<13);
126 lcd_delay(10);
127 DBOP_DOUT16 = value;
128 while ((DBOP_STAT & (1<<10)) == 0);
129}
130
131static void lcd_write_cmd(int cmd)
132{ 124{
133 /* Write register */ 125 /* Write register */
134 DBOP_TIMPOL_23 = 0xa167006e; 126 DBOP_TIMPOL_23 = 0xa167006e;
135 lcd_write_value16(cmd); 127 dbop_write_data(&cmd, 1);
136 128
137 /* Wait for fifo to empty */ 129 /* Wait for fifo to empty */
138 while ((DBOP_STAT & (1<<10)) == 0); 130 while ((DBOP_STAT & (1<<10)) == 0);
@@ -144,43 +136,13 @@ static void lcd_write_cmd(int cmd)
144 DBOP_TIMPOL_23 = 0xa167e06f; 136 DBOP_TIMPOL_23 = 0xa167e06f;
145} 137}
146 138
147void lcd_write_data(const fb_data* p_bytes, int count)
148{
149 const long *data;
150 if ((int)p_bytes & 0x3)
151 { /* need to do a single 16bit write beforehand if the address is
152 * not word aligned */
153 lcd_write_value16(*p_bytes);
154 count--;p_bytes++;
155 }
156 /* from here, 32bit transfers are save
157 * set it to transfer 4*(outputwidth) units at a time,
158 * if bit 12 is set it only does 2 halfwords though */
159 DBOP_CTRL |= (1<<13|1<<14);
160 data = (long*)p_bytes;
161 while (count > 1)
162 {
163 DBOP_DOUT32 = *data++;
164 count -= 2;
165
166 /* Wait if push fifo is full */
167 while ((DBOP_STAT & (1<<6)) != 0);
168 }
169 /* While push fifo is not empty */
170 while ((DBOP_STAT & (1<<10)) == 0);
171
172 /* due to the 32bit alignment requirement or uneven count,
173 * we possibly need to do a 16bit transfer at the end also */
174 if (count > 0)
175 lcd_write_value16(*(fb_data*)data);
176}
177 139
178static void lcd_write_reg(int reg, int value) 140static void lcd_write_reg(int reg, int value)
179{ 141{
180 fb_data data = value; 142 unsigned short data = value;
181 143
182 lcd_write_cmd(reg); 144 lcd_write_cmd(reg);
183 lcd_write_value16(data); 145 dbop_write_data(&data, 1);
184} 146}
185 147
186/*** hardware configuration ***/ 148/*** hardware configuration ***/
@@ -486,7 +448,7 @@ void lcd_update(void)
486 448
487 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 449 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
488 450
489 lcd_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); 451 dbop_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
490} 452}
491 453
492/* Update a fraction of the display. */ 454/* Update a fraction of the display. */
@@ -526,7 +488,7 @@ void lcd_update_rect(int x, int y, int width, int height)
526 488
527 do 489 do
528 { 490 {
529 lcd_write_data(ptr, width); 491 dbop_write_data(ptr, width);
530 ptr += LCD_WIDTH; 492 ptr += LCD_WIDTH;
531 } 493 }
532 while (--height > 0); 494 while (--height > 0);
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
index 3332e0c78c..bdf1c704e0 100644
--- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
+++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c
@@ -124,66 +124,23 @@ static void as3525_dbop_init(void)
124 /* TODO: The OF calls some other functions here, but maybe not important */ 124 /* TODO: The OF calls some other functions here, but maybe not important */
125} 125}
126 126
127static void lcd_write_value16(unsigned short value) 127static void lcd_write_cmd(short cmd)
128{
129 DBOP_CTRL &= ~(1<<14|1<<13);
130 lcd_delay(10);
131 DBOP_DOUT16 = value;
132 while ((DBOP_STAT & (1<<10)) == 0);
133}
134
135static void lcd_write_cmd(int cmd)
136{ 128{
137 /* Write register */ 129 /* Write register */
138 DBOP_TIMPOL_23 = 0xa167006e; 130 DBOP_TIMPOL_23 = 0xa167006e;
139 lcd_write_value16(cmd); 131 dbop_write_data(&cmd, 1);
140
141 /* Wait for fifo to empty */
142 while ((DBOP_STAT & (1<<10)) == 0);
143 132
144 lcd_delay(4); 133 lcd_delay(4);
145 134
146 DBOP_TIMPOL_23 = 0xa167e06f; 135 DBOP_TIMPOL_23 = 0xa167e06f;
147} 136}
148 137
149void lcd_write_data(const fb_data* p_bytes, int count)
150{
151 const long *data;
152 if ((int)p_bytes & 0x3)
153 { /* need to do a single 16bit write beforehand if the address is
154 * not word aligned */
155 lcd_write_value16(*p_bytes);
156 count--;p_bytes++;
157 }
158 /* from here, 32bit transfers are save
159 * set it to transfer 4*(outputwidth) units at a time,
160 * if bit 12 is set it only does 2 halfwords though */
161 DBOP_CTRL |= (1<<13|1<<14);
162 lcd_delay(10);
163 data = (long*)p_bytes;
164 while (count > 1)
165 {
166 DBOP_DOUT32 = *data++;
167 count -= 2;
168
169 /* Wait if push fifo is full */
170 while ((DBOP_STAT & (1<<6)) != 0);
171 }
172 /* While push fifo is not empty */
173 while ((DBOP_STAT & (1<<10)) == 0);
174
175 /* due to the 32bit alignment requirement or uneven count,
176 * we possibly need to do a 16bit transfer at the end also */
177 if (count > 0)
178 lcd_write_value16(*(fb_data*)data);
179}
180
181static void lcd_write_reg(int reg, int value) 138static void lcd_write_reg(int reg, int value)
182{ 139{
183 fb_data data = value; 140 int16_t data = value;
184 141
185 lcd_write_cmd(reg); 142 lcd_write_cmd(reg);
186 lcd_write_value16(data); 143 dbop_write_data(&data, 1);
187} 144}
188 145
189/*** hardware configuration ***/ 146/*** hardware configuration ***/
@@ -437,7 +394,7 @@ void lcd_update(void)
437 394
438 lcd_write_cmd(R_WRITE_DATA_2_GRAM); 395 lcd_write_cmd(R_WRITE_DATA_2_GRAM);
439 396
440 lcd_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); 397 dbop_write_data((fb_data*)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT);
441} 398}
442 399
443/* Update a fraction of the display. */ 400/* Update a fraction of the display. */
@@ -470,6 +427,10 @@ void lcd_update_rect(int x, int y, int width, int height)
470 427
471 lcd_write_reg(R_ENTRY_MODE, r_entry_mode); 428 lcd_write_reg(R_ENTRY_MODE, r_entry_mode);
472 429
430 /* we need to make x and width even to enable 32bit transfers */
431 width = (width + (x & 1) + 1) & ~1;
432 x &= ~1;
433
473 lcd_window_x(x, x + width - 1); 434 lcd_window_x(x, x + width - 1);
474 lcd_window_y(y, y + height -1); 435 lcd_window_y(y, y + height -1);
475 436
@@ -479,7 +440,7 @@ void lcd_update_rect(int x, int y, int width, int height)
479 440
480 do 441 do
481 { 442 {
482 lcd_write_data(ptr, width); 443 dbop_write_data(ptr, width);
483 ptr += LCD_WIDTH; 444 ptr += LCD_WIDTH;
484 } 445 }
485 while (--height > 0); 446 while (--height > 0);