diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2009-06-17 19:55:27 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2009-06-17 19:55:27 +0000 |
commit | 3520d8e90e7f6e3ffc88f8d1ff47fa3cc0efe960 (patch) | |
tree | 814a3bcd5d0fc6ee0c99d57d5f188e7f113ec29f /firmware/target/arm | |
parent | bc1fd05dc1f025bdeb2e79fb552472775bedd156 (diff) | |
download | rockbox-3520d8e90e7f6e3ffc88f8d1ff47fa3cc0efe960.tar.gz rockbox-3520d8e90e7f6e3ffc88f8d1ff47fa3cc0efe960.zip |
Sansa c200v2 : lcd & backlight support, using the c200v1 lcd driver
The LCD driver is unified and lcd_send_command now takes 2 arguments : the command and its argument.
If there is no argument, it's set to 0 and a NOP command is issued
If there is more than one argument (set X/Y address), the 2nd argument is sent as a 2nd command, and a NOP command is issued after it.
Benefit : c200v2 transfers the command and the argument in one 16 bits transfer
Performance should not be affected since commands without argument are only used in lcd_init() and lcd_enable()
lcd_send_data() now transfers whole lines (or columns) instead of single pixels
yuv is disabled for c200v2 for now
Some buttons can be read, including left button (bit 6 of DBOP_DIN), but for some reason they have no effect in rockbox: to be investigated
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21321 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c | 12 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-c200v2/backlight-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c | 85 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c | 429 | ||||
-rw-r--r-- | firmware/target/arm/lcd-c200_c200v2.c (renamed from firmware/target/arm/sandisk/sansa-c200/lcd-c200.c) | 306 |
5 files changed, 265 insertions, 571 deletions
diff --git a/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c b/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c index f036792fc0..858e9aed49 100644 --- a/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c +++ b/firmware/target/arm/as3525/sansa-c200v2/backlight-c200v2.c | |||
@@ -26,8 +26,12 @@ | |||
26 | #include "ascodec-target.h" | 26 | #include "ascodec-target.h" |
27 | #include "as3514.h" | 27 | #include "as3514.h" |
28 | 28 | ||
29 | /* TODO: This file is copy & pasted from backlight-e200v2-fuze.c, as I think | 29 | bool _backlight_init(void) |
30 | * it'll be the same for c200v2; prove it */ | 30 | { |
31 | GPIOA_DIR |= 1<<5; | ||
32 | return true; | ||
33 | } | ||
34 | |||
31 | void _backlight_set_brightness(int brightness) | 35 | void _backlight_set_brightness(int brightness) |
32 | { | 36 | { |
33 | if (brightness > 0) | 37 | if (brightness > 0) |
@@ -41,12 +45,12 @@ void _backlight_on(void) | |||
41 | #ifdef HAVE_LCD_ENABLE | 45 | #ifdef HAVE_LCD_ENABLE |
42 | lcd_enable(true); /* power on lcd + visible display */ | 46 | lcd_enable(true); /* power on lcd + visible display */ |
43 | #endif | 47 | #endif |
44 | ascodec_write(AS3514_DCDC15, backlight_brightness); | 48 | GPIOA_PIN(5) = 1<<5; |
45 | } | 49 | } |
46 | 50 | ||
47 | void _backlight_off(void) | 51 | void _backlight_off(void) |
48 | { | 52 | { |
49 | ascodec_write(AS3514_DCDC15, 0x0); | 53 | GPIOA_PIN(5) = 0; |
50 | #ifdef HAVE_LCD_ENABLE | 54 | #ifdef HAVE_LCD_ENABLE |
51 | lcd_enable(false); /* power off visible display */ | 55 | lcd_enable(false); /* power off visible display */ |
52 | #endif | 56 | #endif |
diff --git a/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h b/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h index e8a60fa881..06076dd39f 100644 --- a/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h +++ b/firmware/target/arm/as3525/sansa-c200v2/backlight-target.h | |||
@@ -21,7 +21,9 @@ | |||
21 | #ifndef BACKLIGHT_TARGET_H | 21 | #ifndef BACKLIGHT_TARGET_H |
22 | #define BACKLIGHT_TARGET_H | 22 | #define BACKLIGHT_TARGET_H |
23 | 23 | ||
24 | #define _backlight_init() true | 24 | #include <stdbool.h> |
25 | |||
26 | bool _backlight_init(void); | ||
25 | void _backlight_on(void); | 27 | void _backlight_on(void); |
26 | void _backlight_off(void); | 28 | void _backlight_off(void); |
27 | void _backlight_set_brightness(int brightness); | 29 | void _backlight_set_brightness(int brightness); |
diff --git a/firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c b/firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c index 86a6eb0c73..d3504c97e9 100644 --- a/firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c +++ b/firmware/target/arm/as3525/sansa-c200v2/button-c200v2.c | |||
@@ -19,47 +19,70 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | /* Taken from button-h10.c by Barry Wardell and reverse engineering by MrH. */ | ||
23 | |||
24 | #include "system.h" | 22 | #include "system.h" |
23 | #include "button-target.h" | ||
25 | #include "button.h" | 24 | #include "button.h" |
26 | #include "backlight.h" | 25 | #include "backlight.h" |
27 | #include "powermgmt.h" | 26 | #include "powermgmt.h" |
28 | 27 | ||
29 | 28 | ||
30 | #ifndef BOOTLOADER | 29 | unsigned short _dbop_din = 0; |
31 | /* Buttons */ | 30 | |
31 | /* in the lcd driver */ | ||
32 | extern bool lcd_button_support(void); | ||
33 | |||
32 | static bool hold_button = false; | 34 | static bool hold_button = false; |
35 | #ifndef BOOTLOADER | ||
33 | static bool hold_button_old = false; | 36 | static bool hold_button_old = false; |
34 | #define _button_hold() hold_button | 37 | #endif |
35 | #else | ||
36 | #define _button_hold() false /* FIXME */ | ||
37 | #endif /* BOOTLOADER */ | ||
38 | static int int_btn = BUTTON_NONE; | ||
39 | 38 | ||
40 | void button_init_device(void) | 39 | void button_init_device(void) |
41 | { | 40 | { |
41 | GPIOA_DIR &= ~(1<<3); | ||
42 | } | 42 | } |
43 | 43 | ||
44 | bool button_hold(void) | 44 | bool button_hold(void) |
45 | { | 45 | { |
46 | return _button_hold(); | 46 | return hold_button; |
47 | } | ||
48 | |||
49 | static void button_read_dbop(void) | ||
50 | { | ||
51 | /* Set up dbop for input */ | ||
52 | DBOP_CTRL |= (1<<19); /* Tri-state DBOP on read cycle */ | ||
53 | DBOP_CTRL &= ~(1<<16); /* disable output (1:write enabled) */ | ||
54 | DBOP_TIMPOL_01 = 0xe167e167; /* Set Timing & Polarity regs 0 & 1 */ | ||
55 | DBOP_TIMPOL_23 = 0xe167006e; /* Set Timing & Polarity regs 2 & 3 */ | ||
56 | |||
57 | int i = 50; | ||
58 | while(i--) asm volatile ("nop\n"); | ||
59 | |||
60 | DBOP_CTRL |= (1<<15); /* start read */ | ||
61 | while (!(DBOP_STAT & (1<<16))); /* wait for valid data */ | ||
62 | |||
63 | _dbop_din = DBOP_DIN; /* Read dbop data*/ | ||
64 | |||
65 | /* Reset dbop for output */ | ||
66 | DBOP_TIMPOL_01 = 0x6e167; /* Set Timing & Polarity regs 0 & 1 */ | ||
67 | DBOP_TIMPOL_23 = 0xa167e06f; /* Set Timing & Polarity regs 2 & 3 */ | ||
68 | DBOP_CTRL |= (1<<16); /* Enable output (0:write disable) */ | ||
69 | DBOP_CTRL &= ~(1<<19); /* Tri-state when no active write */ | ||
47 | } | 70 | } |
48 | 71 | ||
49 | /* device buttons */ | 72 | /* |
50 | void button_int(void) | 73 | * Get button pressed from hardware |
74 | */ | ||
75 | int button_read_device(void) | ||
51 | { | 76 | { |
52 | int delay = 0x50; | 77 | int delay; |
53 | int dir_save_c = 0; | 78 | int dir_save_c = 0; |
54 | int afsel_save_c = 0; | 79 | int afsel_save_c = 0; |
55 | 80 | int btn = BUTTON_NONE; | |
56 | int_btn = BUTTON_NONE; | ||
57 | 81 | ||
58 | /* Save the current direction and afsel */ | 82 | /* Save the current direction and afsel */ |
59 | dir_save_c = GPIOC_DIR; | 83 | dir_save_c = GPIOC_DIR; |
60 | afsel_save_c = GPIOC_AFSEL; | 84 | afsel_save_c = GPIOC_AFSEL; |
61 | 85 | ||
62 | GPIOA_DIR &= ~(1<<3); | ||
63 | GPIOC_AFSEL &= ~(1<<6|1<<5|1<<4|1<<3); | 86 | GPIOC_AFSEL &= ~(1<<6|1<<5|1<<4|1<<3); |
64 | GPIOC_DIR |= (1<<6|1<<5|1<<4|1<<3); | 87 | GPIOC_DIR |= (1<<6|1<<5|1<<4|1<<3); |
65 | 88 | ||
@@ -72,32 +95,32 @@ void button_int(void) | |||
72 | GPIOC_PIN(3) = (1<<3); | 95 | GPIOC_PIN(3) = (1<<3); |
73 | GPIOC_DIR &= ~(1<<6|1<<5|1<<4|1<<3); | 96 | GPIOC_DIR &= ~(1<<6|1<<5|1<<4|1<<3); |
74 | 97 | ||
75 | while(delay--); | 98 | delay = 100; |
99 | while(delay--) | ||
100 | asm volatile("nop\n"); | ||
76 | 101 | ||
77 | /* direct GPIO connections */ | 102 | /* direct GPIO connections */ |
78 | if (GPIOA_PIN(3)) | 103 | if (GPIOA_PIN(3)) |
79 | int_btn |= BUTTON_POWER; | 104 | btn |= BUTTON_POWER; |
80 | if (!GPIOC_PIN(6)) | 105 | if (!GPIOC_PIN(6)) |
81 | int_btn |= BUTTON_RIGHT; | 106 | btn |= BUTTON_RIGHT; |
82 | if (!GPIOC_PIN(5)) | 107 | if (!GPIOC_PIN(5)) |
83 | int_btn |= BUTTON_UP; | 108 | btn |= BUTTON_UP; |
84 | if (!GPIOC_PIN(4)) | 109 | if (!GPIOC_PIN(4)) |
85 | int_btn |= BUTTON_SELECT; | 110 | btn |= BUTTON_SELECT; |
86 | if (!GPIOC_PIN(3)) | 111 | if (!GPIOC_PIN(3)) |
87 | int_btn |= BUTTON_DOWN; | 112 | btn |= BUTTON_DOWN; |
88 | 113 | ||
89 | /* return to settings needed for lcd */ | 114 | /* return to settings needed for lcd */ |
90 | GPIOC_DIR = dir_save_c; | 115 | GPIOC_DIR = dir_save_c; |
91 | GPIOC_AFSEL = afsel_save_c; | 116 | GPIOC_AFSEL = afsel_save_c; |
92 | } | ||
93 | 117 | ||
94 | /* | 118 | if(lcd_button_support()) |
95 | * Get button pressed from hardware | 119 | button_read_dbop(); |
96 | */ | 120 | |
97 | int button_read_device(void) | 121 | if(_dbop_din & (1<<6)) |
98 | { | 122 | btn |= BUTTON_LEFT; |
99 | /* Read buttons directly */ | 123 | |
100 | button_int(); | ||
101 | #ifndef BOOTLOADER | 124 | #ifndef BOOTLOADER |
102 | /* light handling */ | 125 | /* light handling */ |
103 | if (hold_button != hold_button_old) | 126 | if (hold_button != hold_button_old) |
@@ -107,5 +130,5 @@ int button_read_device(void) | |||
107 | } | 130 | } |
108 | #endif /* BOOTLOADER */ | 131 | #endif /* BOOTLOADER */ |
109 | 132 | ||
110 | return int_btn; | 133 | return btn; |
111 | } | 134 | } |
diff --git a/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c b/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c deleted file mode 100644 index e16b082ce5..0000000000 --- a/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c +++ /dev/null | |||
@@ -1,429 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: lcd-e200v2.c 19453 2008-12-16 02:50:39Z saratoga $ | ||
9 | * | ||
10 | * Copyright (C) 2004 by Linus Nielsen Feltzing | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /* FIXME: Copied from e200v2 lcd driver, unlikely to work, but maybe */ | ||
23 | |||
24 | #include "config.h" | ||
25 | |||
26 | #include "cpu.h" | ||
27 | #include "lcd.h" | ||
28 | #include "kernel.h" | ||
29 | #include "thread.h" | ||
30 | #include <string.h> | ||
31 | #include <stdlib.h> | ||
32 | #include "file.h" | ||
33 | #include "debug.h" | ||
34 | #include "system.h" | ||
35 | #include "font.h" | ||
36 | #include "bidi.h" | ||
37 | #include "clock-target.h" | ||
38 | |||
39 | static bool display_on = false; /* is the display turned on? */ | ||
40 | static bool display_flipped = false; | ||
41 | static int y_offset = 0; /* needed for flip */ | ||
42 | |||
43 | /* register defines */ | ||
44 | #define R_START_OSC 0x00 | ||
45 | #define R_DRV_OUTPUT_CONTROL 0x01 | ||
46 | #define R_DRV_WAVEFORM_CONTROL 0x02 | ||
47 | #define R_ENTRY_MODE 0x03 | ||
48 | #define R_COMPARE_REG1 0x04 | ||
49 | #define R_COMPARE_REG2 0x05 | ||
50 | |||
51 | #define R_DISP_CONTROL1 0x07 | ||
52 | #define R_DISP_CONTROL2 0x08 | ||
53 | #define R_DISP_CONTROL3 0x09 | ||
54 | |||
55 | #define R_FRAME_CYCLE_CONTROL 0x0b | ||
56 | #define R_EXT_DISP_IF_CONTROL 0x0c | ||
57 | |||
58 | #define R_POWER_CONTROL1 0x10 | ||
59 | #define R_POWER_CONTROL2 0x11 | ||
60 | #define R_POWER_CONTROL3 0x12 | ||
61 | #define R_POWER_CONTROL4 0x13 | ||
62 | |||
63 | #define R_RAM_ADDR_SET 0x21 | ||
64 | #define R_WRITE_DATA_2_GRAM 0x22 | ||
65 | |||
66 | #define R_GAMMA_FINE_ADJ_POS1 0x30 | ||
67 | #define R_GAMMA_FINE_ADJ_POS2 0x31 | ||
68 | #define R_GAMMA_FINE_ADJ_POS3 0x32 | ||
69 | #define R_GAMMA_GRAD_ADJ_POS 0x33 | ||
70 | |||
71 | #define R_GAMMA_FINE_ADJ_NEG1 0x34 | ||
72 | #define R_GAMMA_FINE_ADJ_NEG2 0x35 | ||
73 | #define R_GAMMA_FINE_ADJ_NEG3 0x36 | ||
74 | #define R_GAMMA_GRAD_ADJ_NEG 0x37 | ||
75 | |||
76 | #define R_GAMMA_AMP_ADJ_RES_POS 0x38 | ||
77 | #define R_GAMMA_AMP_AVG_ADJ_RES_NEG 0x39 | ||
78 | |||
79 | #define R_GATE_SCAN_POS 0x40 | ||
80 | #define R_VERT_SCROLL_CONTROL 0x41 | ||
81 | #define R_1ST_SCR_DRV_POS 0x42 | ||
82 | #define R_2ND_SCR_DRV_POS 0x43 | ||
83 | #define R_HORIZ_RAM_ADDR_POS 0x44 | ||
84 | #define R_VERT_RAM_ADDR_POS 0x45 | ||
85 | |||
86 | #define R_ENTRY_MODE_HORZ 0x7030 | ||
87 | #define R_ENTRY_MODE_VERT 0x7038 | ||
88 | #define R_ENTRY_MODE_SOLID_VERT 0x1038 | ||
89 | |||
90 | /* TODO: Implement this function */ | ||
91 | static void lcd_delay(int x) | ||
92 | { | ||
93 | /* This is just arbitrary - the OF does something more complex */ | ||
94 | x *= 1024; | ||
95 | while (x--); | ||
96 | } | ||
97 | |||
98 | /* DBOP initialisation, do what OF does */ | ||
99 | static void ams3525_dbop_init(void) | ||
100 | { | ||
101 | CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; | ||
102 | |||
103 | DBOP_TIMPOL_01 = 0xe167e167; | ||
104 | DBOP_TIMPOL_23 = 0xe167006e; | ||
105 | DBOP_CTRL = 0x41008; | ||
106 | |||
107 | GPIOB_AFSEL = 0xfc; | ||
108 | GPIOC_AFSEL = 0xff; | ||
109 | |||
110 | DBOP_TIMPOL_23 = 0x6000e; | ||
111 | DBOP_CTRL = 0x51008; | ||
112 | DBOP_TIMPOL_01 = 0x6e167; | ||
113 | DBOP_TIMPOL_23 = 0xa167e06f; | ||
114 | |||
115 | /* TODO: The OF calls some other functions here, but maybe not important */ | ||
116 | } | ||
117 | |||
118 | |||
119 | static void lcd_write_cmd(int cmd) | ||
120 | { | ||
121 | /* Write register */ | ||
122 | DBOP_CTRL &= ~(1<<14); | ||
123 | |||
124 | DBOP_TIMPOL_23 = 0xa167006e; | ||
125 | |||
126 | DBOP_DOUT = cmd; | ||
127 | |||
128 | /* Wait for fifo to empty */ | ||
129 | while ((DBOP_STAT & (1<<10)) == 0); | ||
130 | |||
131 | DBOP_TIMPOL_23 = 0xa167e06f; | ||
132 | } | ||
133 | |||
134 | void lcd_write_data(const fb_data* p_bytes, int count) | ||
135 | { | ||
136 | while (count--) | ||
137 | { | ||
138 | DBOP_DOUT = *p_bytes++; | ||
139 | |||
140 | /* Wait for fifo to empty */ | ||
141 | while ((DBOP_STAT & (1<<10)) == 0); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static void lcd_write_reg(int reg, int value) | ||
146 | { | ||
147 | unsigned short data = value; | ||
148 | |||
149 | lcd_write_cmd(reg); | ||
150 | lcd_write_data(&data, 1); | ||
151 | } | ||
152 | |||
153 | /*** hardware configuration ***/ | ||
154 | |||
155 | void lcd_set_contrast(int val) | ||
156 | { | ||
157 | (void)val; | ||
158 | } | ||
159 | |||
160 | void lcd_set_invert_display(bool yesno) | ||
161 | { | ||
162 | (void)yesno; | ||
163 | } | ||
164 | |||
165 | static void flip_lcd(bool yesno) | ||
166 | { | ||
167 | (void)yesno; | ||
168 | } | ||
169 | |||
170 | |||
171 | /* turn the display upside down (call lcd_update() afterwards) */ | ||
172 | void lcd_set_flip(bool yesno) | ||
173 | { | ||
174 | display_flipped = yesno; | ||
175 | y_offset = yesno ? 4 : 0; /* FIXME: Is a y_offset needed? */ | ||
176 | |||
177 | if (display_on) | ||
178 | flip_lcd(yesno); | ||
179 | } | ||
180 | |||
181 | static void _display_on(void) | ||
182 | { | ||
183 | /* Initialisation the display the same way as the original firmware */ | ||
184 | |||
185 | lcd_write_reg(R_START_OSC, 0x0001); /* Start Oscilation */ | ||
186 | |||
187 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, 0x011b); /* 220 lines, GS=0, SS=1 */ | ||
188 | |||
189 | /* B/C = 1: n-line inversion form | ||
190 | * EOR = 1: polarity inversion occurs by applying an EOR to odd/even | ||
191 | * frame select signal and an n-line inversion signal. | ||
192 | * FLD = 01b: 1 field interlaced scan, external display iface */ | ||
193 | lcd_write_reg(R_DRV_WAVEFORM_CONTROL, 0x0700); | ||
194 | |||
195 | /* Address counter updated in horizontal direction; left to right; | ||
196 | * vertical increment horizontal increment. | ||
197 | * data format for 8bit transfer or spi = 65k (5,6,5) */ | ||
198 | lcd_write_reg(R_ENTRY_MODE, 0x0030); | ||
199 | |||
200 | /* Replace data on writing to GRAM */ | ||
201 | lcd_write_reg(R_COMPARE_REG1, 0); | ||
202 | lcd_write_reg(R_COMPARE_REG2, 0); | ||
203 | |||
204 | lcd_write_reg(R_DISP_CONTROL1, 0x0000); /* GON = 0, DTE = 0, D1-0 = 00b */ | ||
205 | |||
206 | /* Front porch lines: 2; Back porch lines: 2; */ | ||
207 | lcd_write_reg(R_DISP_CONTROL2, 0x0203); | ||
208 | |||
209 | /* Scan cycle = 0 frames */ | ||
210 | lcd_write_reg(R_DISP_CONTROL3, 0x0000); | ||
211 | |||
212 | /* 16 clocks */ | ||
213 | lcd_write_reg(R_FRAME_CYCLE_CONTROL, 0x0000); | ||
214 | |||
215 | /* 18-bit RGB interface (one transfer/pixel) | ||
216 | * internal clock operation; | ||
217 | * System interface/VSYNC interface */ | ||
218 | lcd_write_reg(R_EXT_DISP_IF_CONTROL, 0x0000); | ||
219 | |||
220 | |||
221 | /* zero everything*/ | ||
222 | lcd_write_reg(R_POWER_CONTROL1, 0x0000); /* STB = 0, SLP = 0 */ | ||
223 | |||
224 | lcd_delay(10); | ||
225 | |||
226 | /* initialise power supply */ | ||
227 | |||
228 | /* DC12-10 = 000b: Step-up1 = clock/8, | ||
229 | * DC02-00 = 000b: Step-up2 = clock/16, | ||
230 | * VC2-0 = 010b: VciOUT = 0.87 * VciLVL */ | ||
231 | lcd_write_reg(R_POWER_CONTROL2, 0x0002); | ||
232 | |||
233 | /* VRH3-0 = 1000b: Vreg1OUT = REGP * 1.90 */ | ||
234 | lcd_write_reg(R_POWER_CONTROL3, 0x0008); | ||
235 | |||
236 | lcd_delay(40); | ||
237 | |||
238 | lcd_write_reg(R_POWER_CONTROL4, 0x0000); /* VCOMG = 0 */ | ||
239 | |||
240 | /* This register is unknown */ | ||
241 | lcd_write_reg(0x56, 0x80f); | ||
242 | |||
243 | |||
244 | lcd_write_reg(R_POWER_CONTROL1, 0x4140); | ||
245 | |||
246 | lcd_delay(10); | ||
247 | |||
248 | lcd_write_reg(R_POWER_CONTROL2, 0x0000); | ||
249 | lcd_write_reg(R_POWER_CONTROL3, 0x0013); | ||
250 | |||
251 | lcd_delay(20); | ||
252 | |||
253 | lcd_write_reg(R_POWER_CONTROL4, 0x6d0e); | ||
254 | |||
255 | lcd_delay(20); | ||
256 | |||
257 | lcd_write_reg(R_POWER_CONTROL4, 0x6d0e); | ||
258 | |||
259 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0002); | ||
260 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS2, 0x0707); | ||
261 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS3, 0x0182); | ||
262 | lcd_write_reg(R_GAMMA_GRAD_ADJ_POS, 0x0203); | ||
263 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG1, 0x0706); | ||
264 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG2, 0x0006); | ||
265 | lcd_write_reg(R_GAMMA_FINE_ADJ_NEG3, 0x0706); | ||
266 | lcd_write_reg(R_GAMMA_GRAD_ADJ_NEG, 0x0000); | ||
267 | lcd_write_reg(R_GAMMA_AMP_ADJ_RES_POS, 0x030f); | ||
268 | lcd_write_reg(R_GAMMA_AMP_AVG_ADJ_RES_NEG, 0x0f08); | ||
269 | |||
270 | |||
271 | lcd_write_reg(R_RAM_ADDR_SET, 0); | ||
272 | lcd_write_reg(R_GATE_SCAN_POS, 0); | ||
273 | lcd_write_reg(R_VERT_SCROLL_CONTROL, 0); | ||
274 | |||
275 | lcd_write_reg(R_1ST_SCR_DRV_POS, (LCD_HEIGHT-1) << 8); | ||
276 | lcd_write_reg(R_2ND_SCR_DRV_POS, (LCD_HEIGHT-1) << 8); | ||
277 | |||
278 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (LCD_WIDTH-1) << 8); | ||
279 | lcd_write_reg(R_VERT_RAM_ADDR_POS, (LCD_HEIGHT-1) << 8); | ||
280 | |||
281 | |||
282 | lcd_write_reg(R_DISP_CONTROL1, 0x0037); | ||
283 | |||
284 | display_on=true; /* must be done before calling lcd_update() */ | ||
285 | lcd_update(); | ||
286 | } | ||
287 | |||
288 | /* LCD init */ | ||
289 | void lcd_init_device(void) | ||
290 | { | ||
291 | ams3525_dbop_init(); | ||
292 | |||
293 | /* Init GPIOs the same as the OF */ | ||
294 | |||
295 | GPIOA_DIR |= (1<<5); | ||
296 | GPIOA_PIN(5) = 0; | ||
297 | |||
298 | GPIOA_PIN(3) = (1<<3); | ||
299 | |||
300 | GPIOA_DIR |= (3<<3); | ||
301 | |||
302 | GPIOA_PIN(3) = (1<<3); | ||
303 | |||
304 | GPIOA_PIN(4) = 0; /*c80b0040 := 0;*/ | ||
305 | |||
306 | GPIOA_DIR |= (1<<7); | ||
307 | GPIOA_PIN(7) = 0; | ||
308 | |||
309 | lcd_delay(1); | ||
310 | |||
311 | GPIOA_PIN(5) = (1<<5); | ||
312 | |||
313 | lcd_delay(1); | ||
314 | |||
315 | _display_on(); | ||
316 | } | ||
317 | |||
318 | void lcd_enable(bool on) | ||
319 | { | ||
320 | if(display_on!=on) | ||
321 | { | ||
322 | if(on) | ||
323 | { | ||
324 | _display_on(); | ||
325 | lcd_activation_call_hook(); | ||
326 | } | ||
327 | else | ||
328 | { | ||
329 | /* TODO: Implement off sequence */ | ||
330 | display_on=false; | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | |||
335 | bool lcd_active(void) | ||
336 | { | ||
337 | return display_on; | ||
338 | } | ||
339 | |||
340 | void lcd_sleep(void) | ||
341 | { | ||
342 | /* TODO */ | ||
343 | } | ||
344 | |||
345 | /*** update functions ***/ | ||
346 | |||
347 | /* Performance function to blit a YUV bitmap directly to the LCD | ||
348 | * src_x, src_y, width and height should be even | ||
349 | * x, y, width and height have to be within LCD bounds | ||
350 | */ | ||
351 | void lcd_blit_yuv(unsigned char * const src[3], | ||
352 | int src_x, int src_y, int stride, | ||
353 | int x, int y, int width, int height) | ||
354 | { | ||
355 | (void)src; | ||
356 | (void)src_x; | ||
357 | (void)src_y; | ||
358 | (void)stride; | ||
359 | (void)x; | ||
360 | (void)y; | ||
361 | (void)width; | ||
362 | (void)height; | ||
363 | } | ||
364 | |||
365 | /* Update the display. | ||
366 | This must be called after all other LCD functions that change the display. */ | ||
367 | void lcd_update(void) | ||
368 | { | ||
369 | if (!display_on) | ||
370 | return; | ||
371 | |||
372 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); | ||
373 | |||
374 | /* Set start position and window */ | ||
375 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (LCD_WIDTH-1) << 8); | ||
376 | lcd_write_reg(R_VERT_RAM_ADDR_POS, | ||
377 | ((y_offset + LCD_HEIGHT-1) << 8) | y_offset); | ||
378 | lcd_write_reg(R_RAM_ADDR_SET, (y_offset) << 8); | ||
379 | |||
380 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
381 | |||
382 | lcd_write_data((unsigned short *)lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT); | ||
383 | |||
384 | } /* lcd_update */ | ||
385 | |||
386 | |||
387 | /* Update a fraction of the display. */ | ||
388 | void lcd_update_rect(int x, int y, int width, int height) | ||
389 | { | ||
390 | int ymax; | ||
391 | const unsigned short *ptr; | ||
392 | |||
393 | if (!display_on) | ||
394 | return; | ||
395 | |||
396 | if (x + width > LCD_WIDTH) | ||
397 | width = LCD_WIDTH - x; /* Clip right */ | ||
398 | if (x < 0) | ||
399 | width += x, x = 0; /* Clip left */ | ||
400 | if (width <= 0) | ||
401 | return; /* nothing left to do */ | ||
402 | |||
403 | ymax = y + height; | ||
404 | if (ymax > LCD_HEIGHT) | ||
405 | ymax = LCD_HEIGHT; /* Clip bottom */ | ||
406 | if (y < 0) | ||
407 | y = 0; /* Clip top */ | ||
408 | if (y >= ymax) | ||
409 | return; /* nothing left to do */ | ||
410 | |||
411 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_HORZ); | ||
412 | /* Set start position and window */ | ||
413 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, | ||
414 | ((x + width-1) << 8) | x); | ||
415 | lcd_write_reg(R_VERT_RAM_ADDR_POS, | ||
416 | ((y_offset + y + height - 1) << 8) | (y_offset + y)); | ||
417 | lcd_write_reg(R_RAM_ADDR_SET, ((y + y_offset) << 8) | x); | ||
418 | |||
419 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
420 | |||
421 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; | ||
422 | |||
423 | do | ||
424 | { | ||
425 | lcd_write_data(ptr, width); | ||
426 | ptr += LCD_WIDTH; | ||
427 | } | ||
428 | while (++y < ymax); | ||
429 | } /* lcd_update_rect */ | ||
diff --git a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c b/firmware/target/arm/lcd-c200_c200v2.c index 69578455ac..b3e8f0eb4f 100644 --- a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c +++ b/firmware/target/arm/lcd-c200_c200v2.c | |||
@@ -24,6 +24,11 @@ | |||
24 | #include "kernel.h" | 24 | #include "kernel.h" |
25 | #include "system.h" | 25 | #include "system.h" |
26 | 26 | ||
27 | #ifdef SANSA_C200V2 | ||
28 | /* button driver needs to know if a lcd operation is in progress */ | ||
29 | static bool lcd_busy = false; | ||
30 | #endif | ||
31 | |||
27 | /* Display status */ | 32 | /* Display status */ |
28 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | 33 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; |
29 | static bool is_lcd_enabled = true; | 34 | static bool is_lcd_enabled = true; |
@@ -65,7 +70,7 @@ static bool is_lcd_enabled = true; | |||
65 | #define R_SCROLL_START_LINE 0x5a | 70 | #define R_SCROLL_START_LINE 0x5a |
66 | #define R_DATA_FORMAT_SELECT 0x60 | 71 | #define R_DATA_FORMAT_SELECT 0x60 |
67 | 72 | ||
68 | 73 | #if defined(SANSA_C200) | |
69 | /* wait for LCD */ | 74 | /* wait for LCD */ |
70 | static inline void lcd_wait_write(void) | 75 | static inline void lcd_wait_write(void) |
71 | { | 76 | { |
@@ -73,23 +78,28 @@ static inline void lcd_wait_write(void) | |||
73 | } | 78 | } |
74 | 79 | ||
75 | /* send LCD data */ | 80 | /* send LCD data */ |
76 | static void lcd_send_data(unsigned data) | 81 | static void lcd_send_data(const fb_data *data, int width) |
77 | { | 82 | { |
78 | lcd_wait_write(); | 83 | while(width--) |
79 | LCD1_DATA = data >> 8; | 84 | { |
80 | lcd_wait_write(); | 85 | lcd_wait_write(); |
81 | LCD1_DATA = data & 0xff; | 86 | LCD1_DATA = *data >> 8; |
87 | lcd_wait_write(); | ||
88 | LCD1_DATA = *data++ & 0xff; | ||
89 | } | ||
82 | } | 90 | } |
83 | 91 | ||
84 | /* send LCD command */ | 92 | /* send LCD command */ |
85 | static void lcd_send_command(unsigned cmd) | 93 | static void lcd_send_command(unsigned char cmd, unsigned char arg) |
86 | { | 94 | { |
87 | lcd_wait_write(); | 95 | lcd_wait_write(); |
88 | LCD1_CMD = cmd; | 96 | LCD1_CMD = cmd; |
97 | /* if the argument is 0, we send a NOP (= 0) command */ | ||
98 | lcd_wait_write(); | ||
99 | LCD1_CMD = arg; | ||
89 | } | 100 | } |
90 | 101 | ||
91 | /* LCD init */ | 102 | static inline void c200v1_lcd_init(void) |
92 | void lcd_init_device(void) | ||
93 | { | 103 | { |
94 | /* This is from the c200 of bootloader beginning at offset 0xbbf4 */ | 104 | /* This is from the c200 of bootloader beginning at offset 0xbbf4 */ |
95 | outl(inl(0x70000010) & ~0xfc000000, 0x70000010); | 105 | outl(inl(0x70000010) & ~0xfc000000, 0x70000010); |
@@ -97,7 +107,7 @@ void lcd_init_device(void) | |||
97 | 107 | ||
98 | DEV_INIT2 &= ~0x400; | 108 | DEV_INIT2 &= ~0x400; |
99 | udelay(10000); | 109 | udelay(10000); |
100 | 110 | ||
101 | LCD1_CONTROL &= ~0x4; | 111 | LCD1_CONTROL &= ~0x4; |
102 | udelay(15); | 112 | udelay(15); |
103 | 113 | ||
@@ -106,70 +116,138 @@ void lcd_init_device(void) | |||
106 | 116 | ||
107 | LCD1_CONTROL = 0x0084; /* bits (9,10) = 00 -> fastest setting */ | 117 | LCD1_CONTROL = 0x0084; /* bits (9,10) = 00 -> fastest setting */ |
108 | udelay(10000); | 118 | udelay(10000); |
119 | } | ||
120 | |||
121 | #define lcd_delay(delay) udelay((delay) * 1000) | ||
122 | |||
123 | #elif defined(SANSA_C200V2) | ||
124 | |||
125 | static inline void lcd_delay(int delay) | ||
126 | { //TUNEME : delay is in milliseconds | ||
127 | delay <<= 14; | ||
128 | while(delay--) ; | ||
129 | } | ||
130 | |||
131 | /* send LCD data */ | ||
132 | static void lcd_send_data(const fb_data *data, int width) | ||
133 | { | ||
134 | while(width--) | ||
135 | { | ||
136 | DBOP_DOUT = *data << 8 | *data >> 8; | ||
137 | data++; | ||
138 | while ((DBOP_STAT & (1<<10)) == 0); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* send LCD command */ | ||
143 | static void lcd_send_command(unsigned char cmd, unsigned char val) | ||
144 | { | ||
145 | DBOP_TIMPOL_23 = 0xa167006e; | ||
146 | |||
147 | DBOP_DOUT = cmd | val << 8; | ||
148 | |||
149 | while ((DBOP_STAT & (1<<10)) == 0); | ||
150 | |||
151 | DBOP_TIMPOL_23 = 0xa167e06f; | ||
152 | } | ||
153 | |||
154 | static inline void as3525_dbop_init(void) | ||
155 | { | ||
156 | CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; | ||
157 | |||
158 | DBOP_TIMPOL_01 = 0xe167e167; | ||
159 | DBOP_TIMPOL_23 = 0xe167006e; | ||
160 | DBOP_CTRL = 0x40008; | ||
161 | |||
162 | GPIOB_AFSEL = 0xc; | ||
163 | GPIOC_AFSEL = 0xff; | ||
164 | |||
165 | DBOP_TIMPOL_23 = 0x6006e; | ||
166 | DBOP_CTRL = 0x52008; | ||
167 | DBOP_TIMPOL_01 = 0x6e167; | ||
168 | DBOP_TIMPOL_23 = 0xa167e06f; | ||
169 | |||
170 | lcd_delay(20); | ||
171 | } | ||
109 | 172 | ||
110 | lcd_send_command(R_STANDBY_OFF); | 173 | /* we need to set the DBOP_DOUT pins high, for correct dbop reads */ |
111 | udelay(20000); | 174 | bool lcd_button_support(void) |
175 | { | ||
176 | const fb_data data = 0xffff; | ||
177 | |||
178 | if (lcd_busy) /* we can't use dbop for reading if we are in the */ | ||
179 | return false; /* middle of a write operation */ | ||
180 | |||
181 | /* use out of screen coordinates */ | ||
182 | lcd_send_command(R_X_ADDR_AREA, 0); | ||
183 | lcd_send_command(1, 0); | ||
184 | lcd_send_command(R_Y_ADDR_AREA, 0); | ||
185 | lcd_send_command(1, 0); | ||
186 | |||
187 | lcd_send_data(&data, 1); | ||
188 | |||
189 | return true; | ||
190 | } | ||
191 | #endif | ||
192 | |||
193 | /* LCD init */ | ||
194 | void lcd_init_device(void) | ||
195 | { | ||
196 | #if defined(SANSA_C200) | ||
197 | c200v1_lcd_init(); | ||
198 | #elif defined(SANSA_C200V2) | ||
199 | as3525_dbop_init(); | ||
200 | #endif | ||
201 | |||
202 | lcd_send_command(R_STANDBY_OFF, 0); | ||
203 | lcd_delay(20); | ||
204 | |||
205 | lcd_send_command(R_OSCILLATION_MODE, 0x01); | ||
206 | lcd_delay(20); | ||
112 | 207 | ||
113 | lcd_send_command(R_OSCILLATION_MODE); | 208 | lcd_send_command(R_DCDC_AMP_ONOFF, 0x01); |
114 | lcd_send_command(0x01); | 209 | lcd_delay(20); |
115 | udelay(20000); | ||
116 | 210 | ||
117 | lcd_send_command(R_DCDC_AMP_ONOFF); | 211 | lcd_send_command(R_DCDC_AMP_ONOFF, 0x09); |
118 | lcd_send_command(0x01); | 212 | lcd_delay(20); |
119 | udelay(20000); | ||
120 | 213 | ||
121 | lcd_send_command(R_DCDC_AMP_ONOFF); | 214 | lcd_send_command(R_DCDC_AMP_ONOFF, 0x0b); |
122 | lcd_send_command(0x09); | 215 | lcd_delay(20); |
123 | udelay(20000); | ||
124 | 216 | ||
125 | lcd_send_command(R_DCDC_AMP_ONOFF); | 217 | lcd_send_command(R_DCDC_AMP_ONOFF, 0x0f); |
126 | lcd_send_command(0x0b); | 218 | lcd_delay(20); |
127 | udelay(20000); | ||
128 | 219 | ||
129 | lcd_send_command(R_DCDC_AMP_ONOFF); | 220 | lcd_send_command(R_DRIVER_OUTPUT_MODE, 0x07); |
130 | lcd_send_command(0x0f); | ||
131 | udelay(20000); | ||
132 | 221 | ||
133 | lcd_send_command(R_DRIVER_OUTPUT_MODE); | 222 | lcd_send_command(R_DCDC_SET, 0x03); |
134 | lcd_send_command(0x07); | ||
135 | 223 | ||
136 | lcd_send_command(R_DCDC_SET); | 224 | lcd_send_command(R_DCDC_CLOCK_DIV, 0x03); |
137 | lcd_send_command(0x03); | ||
138 | 225 | ||
139 | lcd_send_command(R_DCDC_CLOCK_DIV); | 226 | lcd_send_command(R_TEMP_COMPENSATION, 0x01); |
140 | lcd_send_command(0x03); | ||
141 | 227 | ||
142 | lcd_send_command(R_TEMP_COMPENSATION); | 228 | lcd_send_command(R_CONTRAST_CONTROL1, 0x55); |
143 | lcd_send_command(0x01); | ||
144 | 229 | ||
145 | lcd_send_command(R_CONTRAST_CONTROL1); | 230 | lcd_send_command(R_ADDRESSING_MODE, 0x10); |
146 | lcd_send_command(0x55); | ||
147 | 231 | ||
148 | lcd_send_command(R_ADDRESSING_MODE); | 232 | lcd_send_command(R_ROW_VECTOR_MODE, 0x0e); |
149 | lcd_send_command(0x10); | ||
150 | 233 | ||
151 | lcd_send_command(R_ROW_VECTOR_MODE); | 234 | lcd_send_command(R_N_LINE_INVERSION, 0x0d); |
152 | lcd_send_command(0x0e); | ||
153 | 235 | ||
154 | lcd_send_command(R_N_LINE_INVERSION); | 236 | lcd_send_command(R_FRAME_FREQ_CONTROL, 0); |
155 | lcd_send_command(0x0d); | ||
156 | 237 | ||
157 | lcd_send_command(R_FRAME_FREQ_CONTROL); | 238 | lcd_send_command(R_ENTRY_MODE, 0x82); |
158 | lcd_send_command(0); | ||
159 | 239 | ||
160 | lcd_send_command(R_ENTRY_MODE); | 240 | /* vertical dimensions */ |
161 | lcd_send_command(0x82); | 241 | lcd_send_command(R_Y_ADDR_AREA, 0x1a); /* y1 + 0x1a */ |
242 | lcd_send_command(LCD_HEIGHT - 1 + 0x1a, 0); /* y2 + 0x1a */ | ||
162 | 243 | ||
163 | lcd_send_command(R_Y_ADDR_AREA); /* vertical dimensions */ | 244 | /* horizontal dimensions */ |
164 | lcd_send_command(0x1a); /* y1 + 0x1a */ | 245 | lcd_send_command(R_X_ADDR_AREA, 0); /* x1 */ |
165 | lcd_send_command(LCD_HEIGHT - 1 + 0x1a); /* y2 + 0x1a */ | 246 | lcd_send_command(LCD_WIDTH - 1, 0); /* x2 */ |
166 | 247 | ||
167 | lcd_send_command(R_X_ADDR_AREA); /* horizontal dimensions */ | 248 | lcd_delay(100); |
168 | lcd_send_command(0); /* x1 */ | ||
169 | lcd_send_command(LCD_WIDTH - 1); /* x2 */ | ||
170 | udelay(100000); | ||
171 | 249 | ||
172 | lcd_send_command(R_DISPLAY_ON); | 250 | lcd_send_command(R_DISPLAY_ON, 0); |
173 | } | 251 | } |
174 | 252 | ||
175 | /*** hardware configuration ***/ | 253 | /*** hardware configuration ***/ |
@@ -180,8 +258,13 @@ int lcd_default_contrast(void) | |||
180 | 258 | ||
181 | void lcd_set_contrast(int val) | 259 | void lcd_set_contrast(int val) |
182 | { | 260 | { |
183 | lcd_send_command(R_CONTRAST_CONTROL1); | 261 | #ifdef SANSA_C200V2 |
184 | lcd_send_command(val); | 262 | lcd_busy = true; |
263 | #endif | ||
264 | lcd_send_command(R_CONTRAST_CONTROL1, val); | ||
265 | #ifdef SANSA_C200V2 | ||
266 | lcd_busy = false; | ||
267 | #endif | ||
185 | } | 268 | } |
186 | 269 | ||
187 | void lcd_set_invert_display(bool yesno) | 270 | void lcd_set_invert_display(bool yesno) |
@@ -196,16 +279,22 @@ void lcd_enable(bool yesno) | |||
196 | if (yesno == is_lcd_enabled) | 279 | if (yesno == is_lcd_enabled) |
197 | return; | 280 | return; |
198 | 281 | ||
282 | #ifdef SANSA_C200V2 | ||
283 | lcd_busy = true; | ||
284 | #endif | ||
199 | if ((is_lcd_enabled = yesno)) | 285 | if ((is_lcd_enabled = yesno)) |
200 | { | 286 | { |
201 | lcd_send_command(R_STANDBY_OFF); | 287 | lcd_send_command(R_STANDBY_OFF, 0); |
202 | lcd_send_command(R_DISPLAY_ON); | 288 | lcd_send_command(R_DISPLAY_ON, 0); |
203 | lcd_activation_call_hook(); | 289 | lcd_activation_call_hook(); |
204 | } | 290 | } |
205 | else | 291 | else |
206 | { | 292 | { |
207 | lcd_send_command(R_STANDBY_ON); | 293 | lcd_send_command(R_STANDBY_ON, 0); |
208 | } | 294 | } |
295 | #ifdef SANSA_C200V2 | ||
296 | lcd_busy = false; | ||
297 | #endif | ||
209 | } | 298 | } |
210 | #endif | 299 | #endif |
211 | 300 | ||
@@ -220,8 +309,13 @@ bool lcd_active(void) | |||
220 | /* turn the display upside down (call lcd_update() afterwards) */ | 309 | /* turn the display upside down (call lcd_update() afterwards) */ |
221 | void lcd_set_flip(bool yesno) | 310 | void lcd_set_flip(bool yesno) |
222 | { | 311 | { |
223 | lcd_send_command(R_DRIVER_OUTPUT_MODE); | 312 | #ifdef SANSA_C200V2 |
224 | lcd_send_command(yesno ? 0x02 : 0x07); | 313 | lcd_busy = true; |
314 | #endif | ||
315 | lcd_send_command(R_DRIVER_OUTPUT_MODE, yesno ? 0x02 : 0x07); | ||
316 | #ifdef SANSA_C200V2 | ||
317 | lcd_busy = false; | ||
318 | #endif | ||
225 | } | 319 | } |
226 | 320 | ||
227 | /*** update functions ***/ | 321 | /*** update functions ***/ |
@@ -248,10 +342,14 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
248 | unsigned char const * yuv_src[3]; | 342 | unsigned char const * yuv_src[3]; |
249 | off_t z; | 343 | off_t z; |
250 | 344 | ||
345 | #ifdef SANSA_C200V2 | ||
346 | lcd_busy = true; | ||
347 | #endif | ||
348 | |||
251 | /* Sorry, but width and height must be >= 2 or else */ | 349 | /* Sorry, but width and height must be >= 2 or else */ |
252 | width &= ~1; | 350 | width &= ~1; |
253 | height >>= 1; | 351 | height >>= 1; |
254 | 352 | ||
255 | y += 0x1a; | 353 | y += 0x1a; |
256 | 354 | ||
257 | z = stride*src_y; | 355 | z = stride*src_y; |
@@ -259,27 +357,21 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
259 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | 357 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); |
260 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | 358 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); |
261 | 359 | ||
262 | lcd_send_command(R_ENTRY_MODE); | 360 | lcd_send_command(R_ENTRY_MODE, 0x80); |
263 | lcd_send_command(0x80); | ||
264 | 361 | ||
265 | lcd_send_command(R_X_ADDR_AREA); | 362 | lcd_send_command(R_X_ADDR_AREA, x); |
266 | lcd_send_command(x); | 363 | lcd_send_command(x + width - 1, 0); |
267 | lcd_send_command(x + width - 1); | ||
268 | 364 | ||
269 | if (lcd_yuv_options & LCD_YUV_DITHER) | 365 | if (lcd_yuv_options & LCD_YUV_DITHER) |
270 | { | 366 | { |
271 | do | 367 | do |
272 | { | 368 | { |
273 | lcd_send_command(R_Y_ADDR_AREA); | 369 | lcd_send_command(R_Y_ADDR_AREA, y); |
274 | lcd_send_command(y); | 370 | lcd_send_command(y + 1, 0); |
275 | lcd_send_command(y + 1); | ||
276 | |||
277 | /* NOP needed because on some c200s, the previous lcd_send_command | ||
278 | is interpreted as a separate command instead of part of | ||
279 | R_Y_ADDR_AREA. */ | ||
280 | lcd_send_command(R_NOP); | ||
281 | 371 | ||
372 | #ifndef SANSA_C200V2 // TODO | ||
282 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y); | 373 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y); |
374 | #endif | ||
283 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | 375 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ |
284 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | 376 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ |
285 | yuv_src[2] += stride >> 1; | 377 | yuv_src[2] += stride >> 1; |
@@ -291,13 +383,12 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
291 | { | 383 | { |
292 | do | 384 | do |
293 | { | 385 | { |
294 | lcd_send_command(R_Y_ADDR_AREA); | 386 | lcd_send_command(R_Y_ADDR_AREA, y); |
295 | lcd_send_command(y); | 387 | lcd_send_command(y + 1, 0); |
296 | lcd_send_command(y + 1); | ||
297 | |||
298 | lcd_send_command(R_NOP); | ||
299 | 388 | ||
389 | #ifndef SANSA_C200V2 // TODO | ||
300 | lcd_write_yuv420_lines(yuv_src, width, stride); | 390 | lcd_write_yuv420_lines(yuv_src, width, stride); |
391 | #endif | ||
301 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | 392 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ |
302 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | 393 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ |
303 | yuv_src[2] += stride >> 1; | 394 | yuv_src[2] += stride >> 1; |
@@ -305,6 +396,10 @@ void lcd_blit_yuv(unsigned char * const src[3], | |||
305 | } | 396 | } |
306 | while (--height > 0); | 397 | while (--height > 0); |
307 | } | 398 | } |
399 | |||
400 | #ifdef SANSA_C200V2 | ||
401 | lcd_busy = false; | ||
402 | #endif | ||
308 | } | 403 | } |
309 | 404 | ||
310 | /* Update the display. | 405 | /* Update the display. |
@@ -318,44 +413,43 @@ void lcd_update(void) | |||
318 | void lcd_update_rect(int x, int y, int width, int height) | 413 | void lcd_update_rect(int x, int y, int width, int height) |
319 | { | 414 | { |
320 | const fb_data *addr; | 415 | const fb_data *addr; |
321 | 416 | ||
322 | if (x + width >= LCD_WIDTH) | 417 | if (x + width >= LCD_WIDTH) |
323 | width = LCD_WIDTH - x; | 418 | width = LCD_WIDTH - x; |
324 | if (y + height >= LCD_HEIGHT) | 419 | if (y + height >= LCD_HEIGHT) |
325 | height = LCD_HEIGHT - y; | 420 | height = LCD_HEIGHT - y; |
326 | 421 | ||
327 | if ((width <= 0) || (height <= 0)) | 422 | if ((width <= 0) || (height <= 0)) |
328 | return; /* Nothing left to do. */ | 423 | return; /* Nothing left to do. */ |
329 | 424 | ||
330 | addr = &lcd_framebuffer[y][x]; | 425 | addr = &lcd_framebuffer[y][x]; |
331 | 426 | ||
332 | if (width <= 1) { | 427 | #ifdef SANSA_C200V2 |
333 | lcd_send_command(R_ENTRY_MODE); /* The X end address must be larger */ | 428 | lcd_busy = true; |
334 | lcd_send_command(0x80); /* that the X start address, so we */ | 429 | #endif |
335 | lcd_send_command(R_X_ADDR_AREA); /* switch to vertical mode for */ | 430 | |
336 | lcd_send_command(x); /* single column updates and set */ | 431 | if (width <= 1) { |
337 | lcd_send_command(x + 1); /* the window width to 2 */ | 432 | /* The X end address must be larger than the X start address, so we |
433 | * switch to vertical mode for single column updates and set the | ||
434 | * window width to 2 */ | ||
435 | lcd_send_command(R_ENTRY_MODE, 0x80); | ||
436 | lcd_send_command(R_X_ADDR_AREA, x); | ||
437 | lcd_send_command(x + 1, 0); | ||
338 | } else { | 438 | } else { |
339 | lcd_send_command(R_ENTRY_MODE); | 439 | lcd_send_command(R_ENTRY_MODE, 0x82); |
340 | lcd_send_command(0x82); | 440 | lcd_send_command(R_X_ADDR_AREA, x); |
341 | lcd_send_command(R_X_ADDR_AREA); | 441 | lcd_send_command(x + width - 1, 0); |
342 | lcd_send_command(x); | ||
343 | lcd_send_command(x + width - 1); | ||
344 | } | 442 | } |
345 | 443 | ||
346 | lcd_send_command(R_Y_ADDR_AREA); | 444 | lcd_send_command(R_Y_ADDR_AREA, y + 0x1a); |
347 | lcd_send_command(y + 0x1a); | 445 | lcd_send_command(y + height - 1 + 0x1a, 0); |
348 | lcd_send_command(y + height - 1 + 0x1a); | ||
349 | |||
350 | /* NOP needed because on some c200s, the previous lcd_send_command is | ||
351 | interpreted as a separate command instead of part of R_Y_ADDR_AREA. */ | ||
352 | lcd_send_command(R_NOP); | ||
353 | 446 | ||
354 | do { | 447 | do { |
355 | int w = width; | 448 | lcd_send_data(addr, width); |
356 | do { | 449 | addr += LCD_WIDTH; |
357 | lcd_send_data(*addr++); | ||
358 | } while (--w > 0); | ||
359 | addr += LCD_WIDTH - width; | ||
360 | } while (--height > 0); | 450 | } while (--height > 0); |
451 | |||
452 | #ifdef SANSA_C200V2 | ||
453 | lcd_busy = false; | ||
454 | #endif | ||
361 | } | 455 | } |