summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/creative-zen
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/creative-zen')
-rw-r--r--firmware/target/arm/imx233/creative-zen/backlight-zen.c8
-rw-r--r--firmware/target/arm/imx233/creative-zen/button-target.h8
-rw-r--r--firmware/target/arm/imx233/creative-zen/button-zen.c46
-rw-r--r--firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c311
4 files changed, 364 insertions, 9 deletions
diff --git a/firmware/target/arm/imx233/creative-zen/backlight-zen.c b/firmware/target/arm/imx233/creative-zen/backlight-zen.c
index 74e1e91a49..6d162817c8 100644
--- a/firmware/target/arm/imx233/creative-zen/backlight-zen.c
+++ b/firmware/target/arm/imx233/creative-zen/backlight-zen.c
@@ -26,10 +26,14 @@
26#include "backlight-target.h" 26#include "backlight-target.h"
27#include "uartdbg-imx233.h" 27#include "uartdbg-imx233.h"
28#include "pinctrl-imx233.h" 28#include "pinctrl-imx233.h"
29#include "pwm-imx233.h"
29 30
30void _backlight_set_brightness(int level) 31void _backlight_set_brightness(int level)
31{ 32{
32#ifdef CREATIVE_ZENV 33#if defined(CREATIVE_ZENXFISTYLE)
34 imx233_pwm_setup_simple(4, 24000, level);
35 imx233_pwm_enable(4, true);
36#elif defined(CREATIVE_ZENV)
33 lcd_set_contrast(level); 37 lcd_set_contrast(level);
34#else 38#else
35 unsigned val = (level + 200) * level / 1000; 39 unsigned val = (level + 200) * level / 1000;
@@ -47,7 +51,7 @@ void _backlight_set_brightness(int level)
47 51
48bool _backlight_init(void) 52bool _backlight_init(void)
49{ 53{
50#ifndef CREATIVE_ZENV 54#if !defined(CREATIVE_ZENV) && !defined(CREATIVE_ZENXFISTYLE)
51 imx233_pinctrl_acquire(1, 12, "backlight_enable"); 55 imx233_pinctrl_acquire(1, 12, "backlight_enable");
52 imx233_pinctrl_set_function(1, 12, PINCTRL_FUNCTION_GPIO); 56 imx233_pinctrl_set_function(1, 12, PINCTRL_FUNCTION_GPIO);
53 imx233_pinctrl_enable_gpio(1, 12, true); 57 imx233_pinctrl_enable_gpio(1, 12, true);
diff --git a/firmware/target/arm/imx233/creative-zen/button-target.h b/firmware/target/arm/imx233/creative-zen/button-target.h
index 7974ae42ad..65521d66e4 100644
--- a/firmware/target/arm/imx233/creative-zen/button-target.h
+++ b/firmware/target/arm/imx233/creative-zen/button-target.h
@@ -25,10 +25,16 @@
25 25
26bool button_debug_screen(void); 26bool button_debug_screen(void);
27 27
28#if !defined(CREATIVE_ZENXFISTYLE)
28#define HAS_BUTTON_HOLD 29#define HAS_BUTTON_HOLD
30#define IMX233_BUTTON_LRADC_HOLD_DET BLH_ADC
31#endif
29 32
33#if defined(CREATIVE_ZENXFISTYLE)
34#define IMX233_BUTTON_LRADC_CHANNEL 2
35#else
30#define IMX233_BUTTON_LRADC_CHANNEL 0 36#define IMX233_BUTTON_LRADC_CHANNEL 0
31#define IMX233_BUTTON_LRADC_HOLD_DET BLH_ADC 37#endif
32 38
33/* Main unit's buttons */ 39/* Main unit's buttons */
34#define BUTTON_POWER 0x00000001 40#define BUTTON_POWER 0x00000001
diff --git a/firmware/target/arm/imx233/creative-zen/button-zen.c b/firmware/target/arm/imx233/creative-zen/button-zen.c
index 8f20961a57..c0e7205675 100644
--- a/firmware/target/arm/imx233/creative-zen/button-zen.c
+++ b/firmware/target/arm/imx233/creative-zen/button-zen.c
@@ -25,6 +25,14 @@
25#include "power-imx233.h" 25#include "power-imx233.h"
26#include "button-lradc-imx233.h" 26#include "button-lradc-imx233.h"
27 27
28#if defined(CREATIVE_ZENXFI) || defined(CREATIVE_ZENMOZAIC)
29#define JACK_DET_BANK 2
30#define JACK_DET_PIN 8
31#elif defined(CREATIVE_ZENXFISTYLE)
32#define JACK_DET_BANK 2
33#define JACK_DET_PIN 7
34#endif
35
28struct imx233_button_lradc_mapping_t imx233_button_lradc_mapping[] = 36struct imx233_button_lradc_mapping_t imx233_button_lradc_mapping[] =
29{ 37{
30#if defined(CREATIVE_ZEN) 38#if defined(CREATIVE_ZEN)
@@ -84,6 +92,18 @@ struct imx233_button_lradc_mapping_t imx233_button_lradc_mapping[] =
84 {2945, BUTTON_PLAYPAUSE}, 92 {2945, BUTTON_PLAYPAUSE},
85 {3400, 0}, 93 {3400, 0},
86 {0, IMX233_BUTTON_LRADC_END}, 94 {0, IMX233_BUTTON_LRADC_END},
95#elif defined(CREATIVE_ZENXFISTYLE)
96 {230, BUTTON_MENU},
97 {480, BUTTON_SHORTCUT},
98 {690, BUTTON_UP},
99 {920, BUTTON_LEFT},
100 {1120, BUTTON_RIGHT},
101 {1335, BUTTON_DOWN},
102 {1565, BUTTON_SELECT},
103 {2850, BUTTON_BACK},
104 {3110, BUTTON_PLAYPAUSE},
105 {3620, 0},
106 {0, IMX233_BUTTON_LRADC_END},
87#else 107#else
88#error wrong target 108#error wrong target
89#endif 109#endif
@@ -92,29 +112,43 @@ struct imx233_button_lradc_mapping_t imx233_button_lradc_mapping[] =
92void button_init_device(void) 112void button_init_device(void)
93{ 113{
94 imx233_button_lradc_init(); 114 imx233_button_lradc_init();
95#if defined(CREATIVE_ZENXFI) || defined(CREATIVE_ZENMOZAIC) 115#ifdef HAVE_HEADPHONE_DETECTION
96 imx233_pinctrl_acquire(2, 8, "jack_detect"); 116 imx233_pinctrl_acquire(JACK_DET_BANK, JACK_DET_PIN, "jack_detect");
97 imx233_pinctrl_set_function(2, 8, PINCTRL_FUNCTION_GPIO); 117 imx233_pinctrl_set_function(JACK_DET_BANK, JACK_DET_PIN, PINCTRL_FUNCTION_GPIO);
98 imx233_pinctrl_enable_gpio(2, 8, false); 118 imx233_pinctrl_enable_gpio(JACK_DET_BANK, JACK_DET_PIN, false);
119#endif
120#ifdef CREATIVE_ZENXFISTYLE
121 imx233_pinctrl_acquire(0, 11, "power_detect");
122 imx233_pinctrl_set_function(0, 11, PINCTRL_FUNCTION_GPIO);
123 imx233_pinctrl_enable_gpio(0, 11, false);
99#endif 124#endif
100} 125}
101 126
127#ifdef HAS_BUTTON_HOLD
102bool button_hold(void) 128bool button_hold(void)
103{ 129{
104 return imx233_button_lradc_hold(); 130 return imx233_button_lradc_hold();
105} 131}
132#endif
106 133
107#if defined(CREATIVE_ZENXFI) || defined(CREATIVE_ZENMOZAIC) 134#ifdef HAVE_HEADPHONE_DETECTION
108bool headphones_inserted(void) 135bool headphones_inserted(void)
109{ 136{
110 return !imx233_pinctrl_get_gpio(2, 8); 137 return !imx233_pinctrl_get_gpio(JACK_DET_BANK, JACK_DET_PIN);
111} 138}
112#endif 139#endif
113 140
114int button_read_device(void) 141int button_read_device(void)
115{ 142{
116 int btn = 0; 143 int btn = 0;
144#ifdef CREATIVE_ZENXFISTYLE
145 /* The ZEN X-Fi Style uses a GPIO because both select and power are wired
146 * to PSWITCH resulting in slow and unreliable readings */
147 if(!imx233_pinctrl_get_gpio(0, 11))
148 btn |= BUTTON_POWER;
149#else
117 if(imx233_power_read_pswitch() == 1) 150 if(imx233_power_read_pswitch() == 1)
118 btn |= BUTTON_POWER; 151 btn |= BUTTON_POWER;
152#endif
119 return imx233_button_lradc_read(btn); 153 return imx233_button_lradc_read(btn);
120} 154}
diff --git a/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c b/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c
new file mode 100644
index 0000000000..5a4542ca67
--- /dev/null
+++ b/firmware/target/arm/imx233/creative-zen/lcd-zenxfistyle.c
@@ -0,0 +1,311 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2013 by Amaury Pouly
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#include <sys/types.h> /* off_t */
22#include <string.h>
23#include "cpu.h"
24#include "system.h"
25#include "backlight-target.h"
26#include "lcd.h"
27#include "lcdif-imx233.h"
28#include "clkctrl-imx233.h"
29#include "pinctrl-imx233.h"
30#include "logf.h"
31
32#ifdef HAVE_LCD_ENABLE
33static bool lcd_on;
34#endif
35static int lcd_model;
36
37static inline uint32_t encode_16_to_18(uint32_t a)
38{
39 return ((a & 0xff) << 1) | (((a >> 8) & 0xff) << 10);
40}
41
42static void lcd_write_reg(uint32_t reg, uint32_t data)
43{
44 uint32_t old_reg = reg;
45 /* get back to 18-bit word length */
46 imx233_lcdif_set_word_length(18);
47 reg = encode_16_to_18(reg);
48 data = encode_16_to_18(data);
49
50 imx233_lcdif_pio_send(false, 1, &reg);
51 if(old_reg != 0x22)
52 imx233_lcdif_pio_send(true, 1, &data);
53}
54
55static void lcd_init_seq(void)
56{
57 if(lcd_model == 0)
58 {
59 lcd_write_reg(0xe3, 0x3008);
60 lcd_write_reg(0xe7, 0x12);
61 lcd_write_reg(0xef, 0x1231);
62 lcd_write_reg(0x01, 0x100);
63 lcd_write_reg(0x02, 0x700);
64 lcd_write_reg(0x03, 0x1028);
65 lcd_write_reg(0x04, 0);
66 lcd_write_reg(0x08, 0x207);
67 lcd_write_reg(0x09, 0);
68 lcd_write_reg(0x0a, 0);
69 lcd_write_reg(0x0c, 0);
70 lcd_write_reg(0x0d, 0);
71 lcd_write_reg(0x0f, 0);
72 lcd_write_reg(0x10, 0);
73 lcd_write_reg(0x11, 7);
74 lcd_write_reg(0x12, 0);
75 lcd_write_reg(0x13, 0);
76 mdelay(200);
77 lcd_write_reg(0x10, 0x1490);
78 lcd_write_reg(0x11, 0x227);
79 mdelay(50);
80 lcd_write_reg(0x12, 0x9c);
81 mdelay(50);
82 lcd_write_reg(0x13, 0xc00);
83 lcd_write_reg(0x29, 5);
84 lcd_write_reg(0x2b, 0xc);
85 lcd_write_reg(0x20, 0xef);
86 lcd_write_reg(0x21, 0);
87 lcd_write_reg(0x30, 6);
88 lcd_write_reg(0x31, 0x703);
89 lcd_write_reg(0x32, 0x206);
90 lcd_write_reg(0x35, 4);
91 lcd_write_reg(0x36, 0x1a05);
92 lcd_write_reg(0x37, 0x600);
93 lcd_write_reg(0x38, 0x307);
94 lcd_write_reg(0x39, 0x707);
95 lcd_write_reg(0x3c, 0x400);
96 lcd_write_reg(0x3d, 0x50f);
97 lcd_write_reg(0x50, 0);
98 lcd_write_reg(0x51, 0xef);
99 lcd_write_reg(0x52, 0);
100 lcd_write_reg(0x53, 0x13f);
101 lcd_write_reg(0x60, 0xa700);
102 lcd_write_reg(0x61, 1);
103 lcd_write_reg(0x6a, 0);
104 lcd_write_reg(0x80, 0);
105 lcd_write_reg(0x81, 0);
106 lcd_write_reg(0x82, 0);
107 lcd_write_reg(0x83, 0);
108 lcd_write_reg(0x84, 0);
109 lcd_write_reg(0x85, 0);
110 lcd_write_reg(0x90, 0x10);
111 lcd_write_reg(0x92, 0x600);
112 lcd_write_reg(0x07, 0x133);
113 }
114 else
115 {
116 lcd_write_reg(0x01, 0x100);
117 lcd_write_reg(0x02, 0x700);
118 lcd_write_reg(0x03, 0x1028);
119 lcd_write_reg(0x04, 0);
120 lcd_write_reg(0x08, 0x207);
121 lcd_write_reg(0x09, 0);
122 lcd_write_reg(0x0a, 0);
123 lcd_write_reg(0x0c, 0);
124 lcd_write_reg(0x0d, 0);
125 lcd_write_reg(0x0f, 0);
126 lcd_write_reg(0x10, 0);
127 lcd_write_reg(0x11, 7);
128 lcd_write_reg(0x12, 0);
129 lcd_write_reg(0x13, 0);
130 mdelay(200);
131 lcd_write_reg(0x10, 0x1290);
132 lcd_write_reg(0x11, 0x227);
133 mdelay(50);
134 lcd_write_reg(0x12, 0x9c);
135 mdelay(50);
136 lcd_write_reg(0x13, 0x1f00);
137 lcd_write_reg(0x29, 0x30);
138 lcd_write_reg(0x2b, 0xd);
139 lcd_write_reg(0x20, 0xef);
140 lcd_write_reg(0x21, 0);
141 lcd_write_reg(0x30, 0x404);
142 lcd_write_reg(0x31, 0x404);
143 lcd_write_reg(0x32, 0x404);
144 lcd_write_reg(0x37, 0x303);
145 lcd_write_reg(0x38, 0x303);
146 lcd_write_reg(0x39, 0x303);
147 lcd_write_reg(0x35, 0x103);
148 lcd_write_reg(0x3c, 0x301);
149 lcd_write_reg(0x36, 0x1e00);
150 lcd_write_reg(0x3d, 0xf);
151 lcd_write_reg(0x50, 0);
152 lcd_write_reg(0x51, 0xef);
153 lcd_write_reg(0x52, 0);
154 lcd_write_reg(0x53, 0x13f);
155 lcd_write_reg(0x60, 0xa700);
156 lcd_write_reg(0x61, 0);
157 lcd_write_reg(0x6a, 0);
158 lcd_write_reg(0x80, 0);
159 lcd_write_reg(0x81, 0);
160 lcd_write_reg(0x82, 0);
161 lcd_write_reg(0x83, 0);
162 lcd_write_reg(0x84, 0);
163 lcd_write_reg(0x85, 0);
164 lcd_write_reg(0x2b, 0xd);
165 mdelay(50);
166 lcd_write_reg(0x90, 0x17);
167 lcd_write_reg(0x92, 0);
168 lcd_write_reg(0x93, 3);
169 lcd_write_reg(0x95, 0x110);
170 lcd_write_reg(0x97, 0);
171 lcd_write_reg(0x98, 0);
172 lcd_write_reg(0x07, 0x133);
173 }
174}
175
176void lcd_init_device(void)
177{
178 /* clock at 24MHZ */
179 imx233_clkctrl_enable(CLK_PIX, false);
180 imx233_clkctrl_set_div(CLK_PIX, 1);
181 imx233_clkctrl_set_bypass(CLK_PIX, true); /* use XTAL */
182 imx233_clkctrl_enable(CLK_PIX, true);
183 imx233_lcdif_init();
184 imx233_lcdif_set_lcd_databus_width(18);
185 imx233_lcdif_enable_underflow_recover(true);
186 imx233_lcdif_setup_system_pins(18);
187 imx233_lcdif_set_timings(2, 2, 2, 2);
188
189 imx233_pinctrl_acquire(2, 8, "lcd_model");
190 imx233_pinctrl_set_function(2, 8, PINCTRL_FUNCTION_GPIO);
191 imx233_pinctrl_enable_gpio(2, 8, false);
192 lcd_model = imx233_pinctrl_get_gpio(2, 8);
193
194 // reset device
195 imx233_lcdif_reset_lcd(true);
196 mdelay(50);
197 imx233_lcdif_reset_lcd(false);
198 mdelay(10);
199 imx233_lcdif_reset_lcd(true);
200
201 lcd_init_seq();
202#ifdef HAVE_LCD_ENABLE
203 lcd_on = true;
204#endif
205}
206
207#ifdef HAVE_LCD_ENABLE
208bool lcd_active(void)
209{
210 return lcd_on;
211}
212
213static void lcd_enable_seq(bool enable)
214{
215 if(!enable)
216 {
217 }
218 else
219 {
220 }
221}
222
223void lcd_enable(bool enable)
224{
225 if(lcd_on == enable)
226 return;
227
228 lcd_on = enable;
229
230 lcd_enable_seq(enable);
231 if(enable)
232 send_event(LCD_EVENT_ACTIVATION, NULL);
233}
234#endif
235
236void lcd_update(void)
237{
238 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
239}
240
241/* NOTE the LCD is rotated: it's a 240x320 panel with (0,0) being the bottom-left
242 * corner when the player is hold in landscape mode. This means x and y axis and
243 * exchanged and the y axis is reversed. */
244
245void lcd_update_rect(int x, int y, int w, int h)
246{
247#ifdef HAVE_LCD_ENABLE
248 if(!lcd_on)
249 return;
250#endif
251 /* make sure the rectangle is included in the screen */
252 x = MIN(x, LCD_WIDTH);
253 y = MIN(y, LCD_HEIGHT);
254 w = MIN(w, LCD_WIDTH - x);
255 h = MIN(h, LCD_HEIGHT - y);
256
257 imx233_lcdif_wait_ready();
258 lcd_write_reg(0x50, LCD_HEIGHT - y - h);
259 lcd_write_reg(0x51, LCD_HEIGHT - y - 1);
260 lcd_write_reg(0x52, x);
261 lcd_write_reg(0x53, x + w - 1);
262 lcd_write_reg(0x20, LCD_HEIGHT - y - 1);
263 lcd_write_reg(0x21, x);
264 lcd_write_reg(0x22, 0);
265 imx233_lcdif_wait_ready();
266 imx233_lcdif_set_word_length(16);
267 imx233_lcdif_set_byte_packing_format(0xf); /* two pixels per 32-bit word */
268
269 /* there are two cases here:
270 * - either width = LCD_WIDTH and we can directly memcopy a part of lcd_framebuffer to FRAME
271 * and send it
272 * - either width != LCD_WIDTH and we have to build a contiguous copy of the rectangular area
273 * into FRAME before sending it (which is slower and doesn't use the hardware)
274 * In all cases, FRAME just acts as a temporary buffer.
275 * NOTE It's more interesting to do a copy to FRAME in all cases since in system mode
276 * the clock runs at 24MHz which provides barely 10MB/s bandwidth compared to >100MB/s
277 * for memcopy operations
278 */
279 if(w == LCD_WIDTH)
280 {
281 memcpy((void *)FRAME, FBADDR(x,y), w * h * sizeof(fb_data));
282 }
283 else
284 {
285 for(int i = 0; i < h; i++)
286 memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
287 }
288 /* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
289 * (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
290 * field must be a multiple of 2. Furthermore, it seems the lcd controller doesn't
291 * really like when both w and h are even, probably because the writes to the GRAM
292 * are done on several words and the controller requires dummy writes.
293 * The workaround is to always make sure that we send a number of pixels which is
294 * a multiple of 4 so that both the lcdif and the controller are happy. If any
295 * of w or h is odd, we will send a copy of the first pixels as dummy writes. We will
296 * send at most 3 bytes. We then send (w * h + 3) / 4 x 4 bytes.
297 */
298 if(w % 2 == 1 || h % 2 == 1)
299 {
300 /* copy three pixel after the last one */
301 for(int i = 0; i < 3; i++)
302 *((fb_data *)FRAME + w * h + i) = *((fb_data *)FRAME + i);
303 /* WARNING we need to update w and h to reflect the pixel count BUT it
304 * has no relation to w * h (it can even be 2 * prime). Hopefully, w <= 240 and
305 * h <= 320 so w * h <= 76800 and (w * h + 3) / 4 <= 38400 which fits into
306 * a 16-bit integer (horizontal count). */
307 h = (w * h + 3) / 4;
308 w = 4;
309 }
310 imx233_lcdif_dma_send((void *)FRAME_PHYS_ADDR, w, h);
311}