summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorTomasz Moń <desowin@gmail.com>2011-11-16 14:08:01 +0000
committerTomasz Moń <desowin@gmail.com>2011-11-16 14:08:01 +0000
commite8a8a1be43afe63079ae48ce1a9eb3052df3b1a4 (patch)
tree084e1cdf27a339ce58e24cff8fec8c31432b52db /firmware
parent992d4eb775cac48e107e18d72783ebfb39c4234f (diff)
downloadrockbox-e8a8a1be43afe63079ae48ce1a9eb3052df3b1a4.tar.gz
rockbox-e8a8a1be43afe63079ae48ce1a9eb3052df3b1a4.zip
Sandisk Sansa Connect port (FS #12363)
Included are drivers for buttons, backlight, lcd, audio and storage. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31000 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES23
-rw-r--r--firmware/drivers/audio/aic3x.c247
-rw-r--r--firmware/export/aic3x.h77
-rw-r--r--firmware/export/audiohw.h2
-rw-r--r--firmware/export/config.h6
-rw-r--r--firmware/export/config/sansaconnect.h201
-rw-r--r--firmware/export/dm320.h51
-rw-r--r--firmware/sound.c2
-rw-r--r--firmware/target/arm/tms320dm320/app.lds2
-rw-r--r--firmware/target/arm/tms320dm320/boot.lds19
-rw-r--r--firmware/target/arm/tms320dm320/debug-dm320.c2
-rw-r--r--firmware/target/arm/tms320dm320/dma-dm320.c78
-rw-r--r--firmware/target/arm/tms320dm320/dma-target.h44
-rw-r--r--firmware/target/arm/tms320dm320/i2c-dm320.c138
-rw-r--r--firmware/target/arm/tms320dm320/kernel-dm320.c9
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c35
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/adc-target.h25
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c461
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h38
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c93
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/backlight-target.h33
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/button-target.h64
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/crt0-board.S238
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c273
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h25
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c207
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c59
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c56
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c53
-rw-r--r--firmware/target/arm/tms320dm320/sansa-connect/usb-target.h32
-rw-r--r--firmware/target/arm/tms320dm320/sdmmc-dm320.c949
-rw-r--r--firmware/target/arm/tms320dm320/system-dm320.c33
-rw-r--r--firmware/target/arm/tms320dm320/system-target.h5
33 files changed, 3567 insertions, 13 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 6a84b5fc11..b918a19418 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -355,6 +355,8 @@ drivers/audio/uda1341.c
355drivers/audio/cs42l55.c 355drivers/audio/cs42l55.c
356#elif defined (HAVE_RK27XX_CODEC) 356#elif defined (HAVE_RK27XX_CODEC)
357drivers/audio/rk27xx_codec.c 357drivers/audio/rk27xx_codec.c
358#elif defined(HAVE_AIC3X)
359drivers/audio/aic3x.c
358#elif defined (HAVE_DUMMY_CODEC) 360#elif defined (HAVE_DUMMY_CODEC)
359drivers/audio/dummy_codec.c 361drivers/audio/dummy_codec.c
360#endif /* defined(HAVE_*) */ 362#endif /* defined(HAVE_*) */
@@ -1064,6 +1066,9 @@ target/arm/bits-armv4.S
1064target/arm/tms320dm320/debug-dm320.c 1066target/arm/tms320dm320/debug-dm320.c
1065target/arm/tms320dm320/dsp-dm320.c 1067target/arm/tms320dm320/dsp-dm320.c
1066target/arm/tms320dm320/i2c-dm320.c 1068target/arm/tms320dm320/i2c-dm320.c
1069#ifdef HAVE_SOFTWARE_I2C
1070drivers/generic_i2c.c
1071#endif
1067target/arm/tms320dm320/kernel-dm320.c 1072target/arm/tms320dm320/kernel-dm320.c
1068target/arm/tms320dm320/spi-dm320.c 1073target/arm/tms320dm320/spi-dm320.c
1069target/arm/tms320dm320/system-dm320.c 1074target/arm/tms320dm320/system-dm320.c
@@ -1112,6 +1117,24 @@ target/arm/tms320dm320/creative-zvm/usb-creativezvm.c
1112#endif /* SIMULATOR */ 1117#endif /* SIMULATOR */
1113#endif /* CREATIVE_ZVx */ 1118#endif /* CREATIVE_ZVx */
1114 1119
1120#ifdef SANSA_CONNECT
1121#ifndef SIMULATOR
1122target/arm/mmu-arm.S
1123target/arm/lcd-as-memframe.S
1124target/arm/tms320dm320/sdmmc-dm320.c
1125target/arm/tms320dm320/sansa-connect/crt0-board.S
1126target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
1127target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c
1128target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
1129target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c
1130target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
1131target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
1132target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c
1133target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c
1134target/arm/tms320dm320/dma-dm320.c
1135#endif /* SIMULATOR */
1136#endif /* SANSA_CONNECT */
1137
1115#ifdef MROBE_100 1138#ifdef MROBE_100
1116#ifndef SIMULATOR 1139#ifndef SIMULATOR
1117#ifndef BOOTLOADER 1140#ifndef BOOTLOADER
diff --git a/firmware/drivers/audio/aic3x.c b/firmware/drivers/audio/aic3x.c
new file mode 100644
index 0000000000..3284326565
--- /dev/null
+++ b/firmware/drivers/audio/aic3x.c
@@ -0,0 +1,247 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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 "config.h"
22#include "logf.h"
23#include "system.h"
24#include "string.h"
25#include "audio.h"
26
27#ifdef SANSA_CONNECT
28#include "avr-sansaconnect.h"
29#endif
30
31#if CONFIG_I2C == I2C_DM320
32#include "i2c-dm320.h"
33#endif
34#include "audiohw.h"
35
36/* (7-bit) address is 0x18, the LSB is read/write flag */
37#define AIC3X_ADDR (0x18 << 1)
38
39static char volume_left = 0, volume_right = 0;
40
41const struct sound_settings_info audiohw_settings[] = {
42 [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN/10, VOLUME_MAX/10, -25},
43 /* HAVE_SW_TONE_CONTROLS */
44 [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
45 [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
46 [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
47 [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
48 [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
49};
50
51/* convert tenth of dB volume to master volume register value */
52int tenthdb2master(int db)
53{
54 /* 0 to -63.0dB in 1dB steps, aic3x can goto -63.5 in 0.5dB steps */
55 if (db < VOLUME_MIN)
56 {
57 return 0x7E;
58 }
59 else if (db >= VOLUME_MAX)
60 {
61 return 0x00;
62 }
63 else
64 {
65 return (-((db)/5)); /* VOLUME_MIN is negative */
66 }
67}
68
69static void aic3x_write_reg(unsigned reg, unsigned value)
70{
71 unsigned char data[2];
72
73 data[0] = reg;
74 data[1] = value;
75
76#if CONFIG_I2C == I2C_DM320
77 if (i2c_write(AIC3X_ADDR, data, 2) != 0)
78#else
79 #warning Implement aic3x_write_reg()
80#endif
81 {
82 logf("AIC3X error reg=0x%x", reg);
83 return;
84 }
85}
86
87static void aic3x_apply_volume(void)
88{
89 unsigned char data[3];
90
91#if 0 /* handle page switching onve we use first page at all */
92 aic3x_write_reg(0, 0); /* switch to page 0 */
93#endif
94
95 data[0] = AIC3X_LEFT_VOL;
96 data[1] = volume_left;
97 data[2] = volume_right;
98
99 /* use autoincrement write */
100#if CONFIG_I2C == I2C_DM320
101 if (i2c_write(AIC3X_ADDR, data, 3) != 0)
102#else
103 #warning Implement aic3x_apply_volume()
104#endif
105 {
106 logf("AIC3X error in apply volume");
107 return;
108 }
109}
110
111
112static void audiohw_mute(bool mute)
113{
114 if (mute)
115 {
116 volume_left |= 0x80;
117 volume_right |= 0x80;
118 }
119 else
120 {
121 volume_left &= 0x7F;
122 volume_right &= 0x7F;
123 }
124
125 aic3x_apply_volume();
126}
127
128/* public functions */
129
130/**
131 * Init our tlv with default values
132 */
133void audiohw_init(void)
134{
135 logf("AIC3X init");
136
137 /* Do software reset (self-clearing) */
138 aic3x_write_reg(AIC3X_SOFT_RESET, 0x80);
139
140 /* ADC fs = fs(ref)/5.5; DAC fs = fs(ref) */
141 aic3x_write_reg(AIC3X_SMPL_RATE, 0x90);
142
143 /* Enable PLL. Set Q=16, P=1 */
144 aic3x_write_reg(AIC3X_PLL_REG_A, 0x81);
145 /* PLL J = 53 */
146 aic3x_write_reg(AIC3X_PLL_REG_B, 0xD4);
147 /* PLL D = 5211 */
148 aic3x_write_reg(AIC3X_PLL_REG_C, 0x51);
149 aic3x_write_reg(AIC3X_PLL_REG_D, 0x6C); /* PLL D = 5211 */
150
151 /* Left DAC plays left channel, Right DAC plays right channel */
152 aic3x_write_reg(AIC3X_DATAPATH, 0xA);
153
154 /* Audio data interface */
155 /* BCLK and WCLK are outputs (master mode) */
156 aic3x_write_reg(AIC3X_DATA_REG_A, 0xC0);
157 /* right-justified mode */
158 aic3x_write_reg(AIC3X_DATA_REG_B, 0x80);
159 /* data offset = 0 clocks */
160 aic3x_write_reg(AIC3X_DATA_REG_C, 0);
161
162 /* GPIO1 used for audio serial data bus ADC word clock */
163 aic3x_write_reg(AIC3X_GPIO1_CTRL, 0x10);
164
165 /* power left and right DAC, HPLCOM constant VCM output */
166 aic3x_write_reg(AIC3X_DAC_POWER, 0xD0);
167 /* HPRCOM as constant VCM output. Enable short-circuit protection
168 (limit current) */
169 aic3x_write_reg(AIC3X_HIGH_POWER, 0xC);
170
171 /* driver power-on time 200 ms, ramp-up step time 4 ms */
172 aic3x_write_reg(AIC3X_POP_REDUCT, 0x7C);
173
174 /* DAC_L1 routed to HPLOUT, volume analog gain 0xC (-6.0dB) */
175 aic3x_write_reg(AIC3X_DAC_L1_VOL, 0x8C);
176 /* HPLOUT output level 0dB, not muted, fully powered up */
177 aic3x_write_reg(AIC3X_HPLOUT_LVL, 0xB);
178
179 /* HPLCOM is muted */
180 aic3x_write_reg(AIC3X_HPLCOM_LVL, 0x7);
181
182 /* DAC_R1 routed to HPROUT, volume analog gain 0xC (-6.0 dB) */
183 aic3x_write_reg(AIC3X_DAC_R1_VOL, 0x8C);
184 /* HPROUT output level 0dB, not muted, fully powered up */
185 aic3x_write_reg(AIC3X_HPROUT_LVL, 0xB);
186
187 /* DAC_L1 routed to MONO_LOP/M, gain 0x2 (-1.0dB) */
188 aic3x_write_reg(AIC3X_DAC_L1_MONO_LOP_M_VOL, 0x92);
189 /* DAC_R1 routed to MONO_LOP/M, gain 0x2 (-1.0dB) */
190 aic3x_write_reg(AIC3X_DAC_R1_MONO_LOP_M_VOL, 0x92);
191
192 /* MONO_LOP output level 6dB, not muted, fully powered up */
193 aic3x_write_reg(AIC3X_MONO_LOP_M_LVL, 0x6b);
194
195 /* DAC_L1 routed to LEFT_LOP/M */
196 aic3x_write_reg(AIC3X_DAC_L1_LEFT_LOP_M_VOL, 0x80);
197 /* LEFT_LOP/M output level 0dB, not muted */
198 aic3x_write_reg(AIC3X_LEFT_LOP_M_LVL, 0xB);
199
200 /* DAC_R1 routed to RIGHT_LOP/M */
201 aic3x_write_reg(AIC3X_DAC_R1_RIGHT_LOP_M_VOL, 0x80);
202 /* RIGHT_LOP/M output level 0dB, not muted */
203 aic3x_write_reg(AIC3X_RIGHT_LOP_M_LVL, 0xB);
204}
205
206void audiohw_postinit(void)
207{
208 audiohw_mute(false);
209
210 /* Power up Left, Right DAC/LOP, HPLOUT and HPROUT */
211 aic3x_write_reg(AIC3X_MOD_POWER, 0xFE);
212}
213
214void audiohw_set_frequency(int fsel)
215{
216 (void)fsel;
217 /* TODO */
218}
219
220void audiohw_set_headphone_vol(int vol_l, int vol_r)
221{
222 if ((volume_left & 0x7F) == (vol_l & 0x7F) &&
223 (volume_right & 0x7F) == (vol_r & 0x7F))
224 {
225 /* Volume already set to this value */
226 return;
227 }
228
229 volume_left &= 0x80; /* preserve mute bit */
230 volume_left |= (vol_l & 0x7F); /* set gain */
231
232 volume_right &= 0x80; /* preserve mute bit */
233 volume_right |= (vol_r & 0x7F); /* set gain */
234
235 aic3x_apply_volume();
236}
237
238/* Nice shutdown of AIC3X codec */
239void audiohw_close(void)
240{
241 audiohw_mute(true);
242#ifdef SANSA_CONNECT
243 avr_hid_reset_codec();
244#endif
245}
246
247
diff --git a/firmware/export/aic3x.h b/firmware/export/aic3x.h
new file mode 100644
index 0000000000..17e5ea019a
--- /dev/null
+++ b/firmware/export/aic3x.h
@@ -0,0 +1,77 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#ifndef _AIC3X_H_
23#define _AIC3X_H_
24
25#define VOLUME_MIN -630
26#define VOLUME_MAX 0
27
28extern int tenthdb2master(int db);
29
30/*** definitions ***/
31extern void audiohw_set_headphone_vol(int vol_l, int vol_r);
32
33/* Page 0 registers */
34#define AIC3X_PAGE_SELECT 0
35#define AIC3X_SOFT_RESET 1
36#define AIC3X_SMPL_RATE 2
37#define AIC3X_PLL_REG_A 3
38#define AIC3X_PLL_REG_B 4
39#define AIC3X_PLL_REG_C 5
40#define AIC3X_PLL_REG_D 6
41#define AIC3X_DATAPATH 7
42#define AIC3X_DATA_REG_A 8
43#define AIC3X_DATA_REG_B 9
44#define AIC3X_DATA_REG_C 10
45
46#define AIC3X_DAC_POWER 37
47#define AIC3X_HIGH_POWER 38
48
49#define AIC3X_POP_REDUCT 42
50#define AIC3X_LEFT_VOL 43
51#define AIC3X_RIGHT_VOL 44
52
53#define AIC3X_DAC_L1_VOL 47
54#define AIC3X_HPLOUT_LVL 51
55
56#define AIC3X_HPLCOM_LVL 58
57
58#define AIC3X_DAC_R1_VOL 64
59#define AIC3X_HPROUT_LVL 65
60
61#define AIC3X_DAC_L1_MONO_LOP_M_VOL 75
62
63#define AIC3X_DAC_R1_MONO_LOP_M_VOL 76
64
65#define AIC3X_MONO_LOP_M_LVL 79
66
67#define AIC3X_DAC_L1_LEFT_LOP_M_VOL 82
68
69#define AIC3X_LEFT_LOP_M_LVL 86
70
71#define AIC3X_DAC_R1_RIGHT_LOP_M_VOL 92
72#define AIC3X_RIGHT_LOP_M_LVL 93
73#define AIC3X_MOD_POWER 94
74
75#define AIC3X_GPIO1_CTRL 98
76
77#endif /*_AIC3X_H_*/
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index 6bf4d71810..102d107d8a 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -70,6 +70,8 @@
70#include "ak4537.h" 70#include "ak4537.h"
71#elif defined(HAVE_RK27XX_CODEC) 71#elif defined(HAVE_RK27XX_CODEC)
72#include "rk27xx_codec.h" 72#include "rk27xx_codec.h"
73#elif defined(HAVE_AIC3X)
74#include "aic3x.h"
73#elif defined(HAVE_CS42L55) 75#elif defined(HAVE_CS42L55)
74#include "cs42l55.h" 76#include "cs42l55.h"
75#elif defined(HAVE_IMX233_CODEC) 77#elif defined(HAVE_IMX233_CODEC)
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 55a194817d..2e7b4dc4d6 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -142,6 +142,7 @@
142#define RK27XX_GENERIC_PAD 49 142#define RK27XX_GENERIC_PAD 49
143#define HM60X_PAD 50 143#define HM60X_PAD 50
144#define HM801_PAD 51 144#define HM801_PAD 51
145#define SANSA_CONNECT_PAD 52
145 146
146/* CONFIG_REMOTE_KEYPAD */ 147/* CONFIG_REMOTE_KEYPAD */
147#define H100_REMOTE 1 148#define H100_REMOTE 1
@@ -229,6 +230,7 @@
229#define LCD_SPFD5420A 42 /* rk27xx */ 230#define LCD_SPFD5420A 42 /* rk27xx */
230#define LCD_CLIPZIP 43 /* as used by the Sandisk Sansa Clip Zip */ 231#define LCD_CLIPZIP 43 /* as used by the Sandisk Sansa Clip Zip */
231#define LCD_HX8340B 44 /* as used by the HiFiMAN HM-601/HM-602/HM-801 */ 232#define LCD_HX8340B 44 /* as used by the HiFiMAN HM-601/HM-602/HM-801 */
233#define LCD_CONNECT 45 /* as used by the Sandisk Sansa Connect */
232 234
233/* LCD_PIXELFORMAT */ 235/* LCD_PIXELFORMAT */
234#define HORIZONTAL_PACKING 1 236#define HORIZONTAL_PACKING 1
@@ -302,6 +304,7 @@ Lyre prototype 1 */
302#define RTC_D2 18 /* Either PCF50606 or PCF50635 */ 304#define RTC_D2 18 /* Either PCF50606 or PCF50635 */
303#define RTC_S35380A 19 305#define RTC_S35380A 19
304#define RTC_IMX233 20 306#define RTC_IMX233 20
307#define RTC_STM41T62 21 /* ST M41T62 */
305 308
306/* USB On-the-go */ 309/* USB On-the-go */
307#define USBOTG_M66591 6591 /* M:Robe 500 */ 310#define USBOTG_M66591 6591 /* M:Robe 500 */
@@ -314,6 +317,7 @@ Lyre prototype 1 */
314#define USBOTG_AS3525v2 3535 /* AMS AS3525v2 FIXME : same as S3C6400X */ 317#define USBOTG_AS3525v2 3535 /* AMS AS3525v2 FIXME : same as S3C6400X */
315#define USBOTG_S3C6400X 6400 /* Samsung S3C6400X, also used in the S5L8701/S5L8702/S5L8720 */ 318#define USBOTG_S3C6400X 6400 /* Samsung S3C6400X, also used in the S5L8701/S5L8702/S5L8720 */
316#define USBOTG_RK27XX 2700 /* Rockchip rk27xx */ 319#define USBOTG_RK27XX 2700 /* Rockchip rk27xx */
320#define USBOTG_TNETV105 105 /* TI TNETV105 */
317 321
318/* Multiple cores */ 322/* Multiple cores */
319#define CPU 0 323#define CPU 0
@@ -466,6 +470,8 @@ Lyre prototype 1 */
466#include "config/hifimanhm60x.h" 470#include "config/hifimanhm60x.h"
467#elif defined(HM801) 471#elif defined(HM801)
468#include "config/hifimanhm801.h" 472#include "config/hifimanhm801.h"
473#elif defined(SANSA_CONNECT)
474#include "config/sansaconnect.h"
469#elif defined(SDLAPP) 475#elif defined(SDLAPP)
470#include "config/sdlapp.h" 476#include "config/sdlapp.h"
471#elif defined(ANDROID) 477#elif defined(ANDROID)
diff --git a/firmware/export/config/sansaconnect.h b/firmware/export/config/sansaconnect.h
new file mode 100644
index 0000000000..714534d6ad
--- /dev/null
+++ b/firmware/export/config/sansaconnect.h
@@ -0,0 +1,201 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2011 by Tomasz Moń
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21/*
22 * This config file is for the Sansa Connect
23 */
24#define TARGET_TREE /* this target is using the target tree system */
25
26/* This is the absolute address on the bus set by OF bootloader */
27#define CONFIG_SDRAM_START 0x01000000
28
29#define SANSA_CONNECT 1
30#define MODEL_NAME "Sandisk Sansa Connect"
31
32/* For Rolo and boot loader */
33#define MODEL_NUMBER 81
34
35/* define this if you have a flash memory storage */
36#define HAVE_FLASH_STORAGE
37
38/* define this if you use an SD controller */
39#define CONFIG_STORAGE STORAGE_SD
40
41#define HAVE_MULTIDRIVE
42#define NUM_DRIVES 2
43#define HAVE_HOTSWAP
44#define HAVE_HOTSWAP_STORAGE_AS_MAIN
45
46/* define this if you have a bitmap LCD display */
47#define HAVE_LCD_BITMAP
48
49/* define this if you have a colour LCD */
50#define HAVE_LCD_COLOR
51
52/* define this if you want album art for this target */
53#define HAVE_ALBUMART
54
55/* define this to enable bitmap scaling */
56#define HAVE_BMP_SCALING
57
58/* define this to enable JPEG decoding */
59#define HAVE_JPEG
60
61/* define this if you have access to the quickscreen */
62#define HAVE_QUICKSCREEN
63
64/* define this if you have access to the pitchscreen */
65#define HAVE_PITCHSCREEN
66
67/* define this if you would like tagcache to build on this target */
68#define HAVE_TAGCACHE
69
70/* define this if the target has volume keys which can be used in the lists */
71#define HAVE_VOLUME_IN_LIST
72
73/* define this if you want viewport clipping enabled for safe LCD functions */
74#define HAVE_VIEWPORT_CLIP
75
76/* LCD dimensions */
77#define CONFIG_LCD LCD_CONNECT
78
79#define LCD_WIDTH 240
80#define LCD_HEIGHT 320
81
82#define LCD_DEPTH 16 /* 65k colours */
83#define LCD_PIXELFORMAT RGB565 /* rgb565 */
84
85#define HAVE_LCD_ENABLE
86#ifndef BOOTLOADER
87#define HAVE_LCD_SLEEP
88#endif
89
90#define LCD_SLEEP_TIMEOUT (2*HZ)
91
92#define MAX_ICON_HEIGHT 35
93#define MAX_ICON_WIDTH 35
94
95
96#define CONFIG_KEYPAD SANSA_CONNECT_PAD
97
98/* Define this to have CPU bootsted while scrolling in the UI */
99#define HAVE_GUI_BOOST
100
101/* define this if the target has volume keys which can be used in the lists */
102#define HAVE_VOLUME_IN_LIST
103
104#define HAVE_MORSE_INPUT
105
106/* Define this if you do software codec */
107#define CONFIG_CODEC SWCODEC
108
109//#define HAVE_HARDWARE_BEEP
110
111/* There is no hardware tone control */
112#define HAVE_SW_TONE_CONTROLS
113
114#define HAVE_AIC3X
115
116//#define HW_SAMPR_CAPS SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11 | SAMPR_CAP_8
117
118/* define this if you have a real-time clock */
119//#define CONFIG_RTC RTC_STM41T62
120
121/* define this if the unit uses a scrollwheel for navigation */
122#define HAVE_SCROLLWHEEL
123
124/* Define this for LCD backlight available */
125#define HAVE_BACKLIGHT
126
127#define HAVE_BACKLIGHT_BRIGHTNESS
128
129#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
130
131/* Main LCD backlight brightness range and defaults */
132#define MIN_BRIGHTNESS_SETTING 1
133#define MAX_BRIGHTNESS_SETTING 20
134#define DEFAULT_BRIGHTNESS_SETTING 16 /* OF default brightness (80%) */
135#define DEFAULT_DIMNESS_SETTING 6 /* OF default inactive (30%) */
136
137/* Define this if you have a software controlled poweroff */
138#define HAVE_SW_POWEROFF
139
140/* The number of bytes reserved for loadable codecs */
141#define CODEC_SIZE 0x100000
142
143/* The number of bytes reserved for loadable plugins */
144#define PLUGIN_BUFFER_SIZE 0x200000
145
146#define BATTERY_CAPACITY_DEFAULT 800 /* default battery capacity */
147#define BATTERY_CAPACITY_MIN 700 /* min. capacity selectable */
148#define BATTERY_CAPACITY_MAX 1000 /* max. capacity selectable */
149#define BATTERY_CAPACITY_INC 100 /* capacity increment */
150#define BATTERY_TYPES_COUNT 1 /* only one type */
151
152/* define current usage levels */
153#if 0
154/* TODO */
155#define CURRENT_NORMAL 85
156#define CURRENT_BACKLIGHT 200
157#endif
158
159/* Hardware controlled charging with monitoring */
160//#define CONFIG_CHARGING CHARGING_MONITOR
161
162#define CONFIG_CPU DM320
163
164#define CONFIG_I2C I2C_DM320
165#define HAVE_SOFTWARE_I2C
166
167/* define this if the hardware can be powered off while charging */
168#define HAVE_POWEROFF_WHILE_CHARGING
169
170/* The size of the flash ROM */
171#define FLASH_SIZE 0x400000
172
173/* Define this to the CPU frequency */
174#define CPU_FREQ 150000000
175
176/* Define this if you have ATA power-off control */
177#define HAVE_ATA_POWER_OFF
178
179/* Offset ( in the firmware file's header ) to the file CRC */
180#define FIRMWARE_OFFSET_FILE_CRC 0
181
182/* Offset ( in the firmware file's header ) to the real data */
183#define FIRMWARE_OFFSET_FILE_DATA 8
184
185#if 0
186#define HAVE_USBSTACK
187#define USB_VENDOR_ID 0x0781
188#define USB_PRODUCT_ID 0x7480
189#endif
190
191#define INCLUDE_TIMEOUT_API
192
193/* Define this if you have adjustable CPU frequency */
194#define HAVE_ADJUSTABLE_CPU_FREQ
195
196#define BOOTFILE_EXT "sansa"
197#define BOOTFILE "rockbox." BOOTFILE_EXT
198#define BOOTDIR "/.rockbox"
199
200/* Define this if a programmable hotkey is mapped */
201#define HAVE_HOTKEY
diff --git a/firmware/export/dm320.h b/firmware/export/dm320.h
index a629586be8..def8508b0b 100644
--- a/firmware/export/dm320.h
+++ b/firmware/export/dm320.h
@@ -870,6 +870,8 @@ extern unsigned long _ttbstart;
870#define CLK_MOD2_TMR0 (1 << 1) 870#define CLK_MOD2_TMR0 (1 << 1)
871#define CLK_MOD2_WDT (1 << 0) 871#define CLK_MOD2_WDT (1 << 0)
872 872
873#define CLK_SEL0_UART0 (1 << 5)
874
873#define CLK_SEL1_OSD (1 << 12) 875#define CLK_SEL1_OSD (1 << 12)
874#define CLK_SEL1_CCD (1 << 8) 876#define CLK_SEL1_CCD (1 << 8)
875#define CLK_SEL1_VENCPLL (1 << 4) 877#define CLK_SEL1_VENCPLL (1 << 4)
@@ -884,6 +886,55 @@ extern unsigned long _ttbstart;
884#define CLK_BYP_DSP (1 << 4) 886#define CLK_BYP_DSP (1 << 4)
885#define CLK_BYP_ARM (1 << 0) 887#define CLK_BYP_ARM (1 << 0)
886 888
889#define CLK_INV_MMC (1 << 0)
890#define CLK_INV_VENC (1 << 4)
891#define CLK_INV_CCD (1 << 8)
892#define CLK_INV_SIF0 (1 << 12)
893#define CLK_INV_SIF1 (1 << 13)
894
895#define MMC_CTRL_DATRST (1 << 0)
896#define MMC_CTRL_CMDRST (1 << 1)
897#define MMC_CTRL_WIDTH (1 << 2)
898#define MMC_CTRL_DMASZEN (1 << 4)
899#define MMC_CTRL_TEST2 (1 << 8)
900#define MMC_CTRL_PERMDR (1 << 9)
901#define MMC_CTRL_PERMDX (1 << 10)
902
903#define MMC_CMD_CMD_MASK (0x3F)
904#define MMC_CMD_PPLEN (1 << 7)
905#define MMC_CMD_BSYEXP (1 << 8)
906#define MMC_CMD_RSPFMT_SHIFT 9
907#define MMC_CMD_RSPFMT_MASK (3 << MMC_CMD_RSPFMT_SHIFT)
908#define MMC_CMD_WRITE (1 << 11)
909#define MMC_CMD_STREAM (1 << 12)
910#define MMC_CMD_DATA (1 << 13)
911#define MMC_CMD_INITCLK (1 << 14)
912#define MMC_CMD_DCLR (1 << 15)
913
914#define MMC_ST0_DATDNE (1 << 0)
915#define MMC_ST0_BSYDNE (1 << 1)
916#define MMC_ST0_RSPDNE (1 << 2)
917#define MMC_ST0_DATA_TIMEOUT (1 << 3)
918#define MMC_ST0_CMD_TIMEOUT (1 << 4)
919#define MMC_ST0_WR_CRCERR (1 << 5)
920#define MMC_ST0_RD_CRCERR (1 << 6)
921#define MMC_ST0_RESP_CRCERR (1 << 7)
922#define MMC_ST0_DMADNE (1 << 8)
923#define MMC_ST0_DXRDY (1 << 9)
924#define MMC_ST0_DRRDY (1 << 10)
925#define MMC_ST0_DAT3_EDGE (1 << 11)
926
927#define MMC_ST1_BUSY (1 << 0)
928#define MMC_ST1_CLKSTP (1 << 1)
929#define MMC_ST1_DXEMPTY (1 << 2)
930#define MMC_ST1_DXFULL (1 << 3)
931#define MMC_ST1_DAT3ST (1 << 4)
932
933#define MMC_DMAMODE_RD_WORDSWAP (1 << 10)
934#define MMC_DMAMODE_WR_WORDSWAP (1 << 11)
935#define MMC_DMAMODE_WRITE (1 << 12)
936#define MMC_DMAMODE_ENABLE (1 << 13)
937#define MMC_DMAMODE_TIMEOUTIRQ_EN (1 << 14)
887/* 938/*
888 * IO_EINTx bits 939 * IO_EINTx bits
889 */ 940 */
diff --git a/firmware/sound.c b/firmware/sound.c
index ec577d6a10..c97ccc243f 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -250,7 +250,7 @@ static void set_prescaled_volume(void)
250 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0)); 250 audiohw_set_lineout_vol(tenthdb2master(0), tenthdb2master(0));
251#endif 251#endif
252 252
253#elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985) || defined(HAVE_IMX233_CODEC) 253#elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985) || defined(HAVE_IMX233_CODEC) || defined(HAVE_AIC3X)
254 audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r)); 254 audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r));
255#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO) || defined(ANDROID) 255#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO) || defined(ANDROID)
256 audiohw_set_volume(current_volume); 256 audiohw_set_volume(current_volume);
diff --git a/firmware/target/arm/tms320dm320/app.lds b/firmware/target/arm/tms320dm320/app.lds
index 1e0d1839c0..4ea22a7902 100644
--- a/firmware/target/arm/tms320dm320/app.lds
+++ b/firmware/target/arm/tms320dm320/app.lds
@@ -29,7 +29,7 @@ STARTUP(target/arm/tms320dm320/crt0.o)
29 29
30#define DRAMSIZE (MEMORYSIZE * 0x100000) 30#define DRAMSIZE (MEMORYSIZE * 0x100000)
31 31
32#define DRAMORIG 0x00900000 32#define DRAMORIG CONFIG_SDRAM_START
33 33
34#define FLASHORIG 0x00100000 34#define FLASHORIG 0x00100000
35#define FLASHSIZE 0x00800000 35#define FLASHSIZE 0x00800000
diff --git a/firmware/target/arm/tms320dm320/boot.lds b/firmware/target/arm/tms320dm320/boot.lds
index 2b9f345a23..65649d7268 100644
--- a/firmware/target/arm/tms320dm320/boot.lds
+++ b/firmware/target/arm/tms320dm320/boot.lds
@@ -28,14 +28,27 @@ STARTUP(target/arm/tms320dm320/crt0.o)
28#define LCD_TTB_AREA 0x100000*((LCD_BUFFER_SIZE>>19)+1) 28#define LCD_TTB_AREA 0x100000*((LCD_BUFFER_SIZE>>19)+1)
29 29
30/* Bootloader only uses/knows about the upper 32 M */ 30/* Bootloader only uses/knows about the upper 32 M */
31#define DRAMORIG 0x02900000 31#define DRAMORIG CONFIG_SDRAM_START+0x02000000
32#define DRAMSIZE (MEMORYSIZE * 0x80000) 32#define DRAMSIZE (MEMORYSIZE * 0x80000)
33 33
34#define IRAMORIG 0x00000000 34#define IRAMORIG 0x00000000
35#define IRAMSIZE 0x4000 35#define IRAMSIZE 0x4000
36 36
37#ifdef SANSA_CONNECT
38/* Offset in flash from beginning, we don't want overwrite OF bootloader
39 due to recovery mode and more importantly - hardware block protection.
40 This offset makes Rockbox bootloader a replacement for OF vmlinux.
41 In .srr file header add any valid memory address from following
42 <0x1000000; 0x1300180) u (0x131EAF4; 0x1420000) u (0x1440000; 0x5000000>
43 ensuring that complete bootloader fits in.
44 Entry point in .srr file should be 0x120010. */
45#define FLASHOFFSET 0x20010
46#else
47#define FLASHOFFSET 0
48#endif
49
37#define FLASHORIG 0x00100000 50#define FLASHORIG 0x00100000
38#define FLASHSIZE 0x00800000 51#define FLASHSIZE 0x00800000-FLASHOFFSET
39 52
40PRO_STACK_SIZE = 0x2000; 53PRO_STACK_SIZE = 0x2000;
41IRQ_STACK_SIZE = 0x400; 54IRQ_STACK_SIZE = 0x400;
@@ -48,7 +61,7 @@ MEMORY
48{ 61{
49 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE 62 DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
50 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE 63 IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
51 FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE 64 FLASH : ORIGIN = FLASHORIG+FLASHOFFSET, LENGTH = FLASHSIZE
52} 65}
53 66
54SECTIONS 67SECTIONS
diff --git a/firmware/target/arm/tms320dm320/debug-dm320.c b/firmware/target/arm/tms320dm320/debug-dm320.c
index de17d54843..262d843bfc 100644
--- a/firmware/target/arm/tms320dm320/debug-dm320.c
+++ b/firmware/target/arm/tms320dm320/debug-dm320.c
@@ -212,6 +212,7 @@ bool dbg_hw_info(void)
212 button = button_get(false); 212 button = button_get(false);
213 if(button & BUTTON_POWER) 213 if(button & BUTTON_POWER)
214 done = true; 214 done = true;
215#if defined(CREATIVE_ZVx)
215 else if(button & BUTTON_LEFT) 216 else if(button & BUTTON_LEFT)
216 lcd_set_direct_fb(false); 217 lcd_set_direct_fb(false);
217 else if(button & BUTTON_RIGHT) 218 else if(button & BUTTON_RIGHT)
@@ -222,6 +223,7 @@ bool dbg_hw_info(void)
222 (lcd_get_direct_fb() ? "yes" : "no")); 223 (lcd_get_direct_fb() ? "yes" : "no"));
223 line++; 224 line++;
224#endif 225#endif
226#endif
225 lcd_puts(0, line++, "[Rockbox info]"); 227 lcd_puts(0, line++, "[Rockbox info]");
226 lcd_putsf(0, line++, "current tick: %08x Seconds running: %08d", 228 lcd_putsf(0, line++, "current tick: %08x Seconds running: %08d",
227 (unsigned int)current_tick, (unsigned int)current_tick/100); 229 (unsigned int)current_tick, (unsigned int)current_tick/100);
diff --git a/firmware/target/arm/tms320dm320/dma-dm320.c b/firmware/target/arm/tms320dm320/dma-dm320.c
new file mode 100644
index 0000000000..e60102b6fb
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/dma-dm320.c
@@ -0,0 +1,78 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "config.h"
23#include "kernel.h"
24#include "thread.h"
25#include "system.h"
26#include "dma-target.h"
27#include "dm320.h"
28#include <stdbool.h>
29
30void dma_init(void)
31{
32 /* TODO */
33}
34
35/*
36 Requests channel for peripheral.
37 Returns channel assigned for caller which must be released after
38 transfer complete using dma_release_channel().
39*/
40int dma_request_channel(int peripheral, int mode)
41{
42 /* TODO: proper checking if channel is already taken
43 currently only SDMMC and DSP uses DMA on this target */
44 int channel = -1;
45
46 if (peripheral == DMA_PERIPHERAL_MMCSD)
47 {
48 /* Set first DMA channel */
49 IO_SDRAM_SDDMASEL = (IO_SDRAM_SDDMASEL & 0xFFE0) | peripheral |
50 (mode << 3);
51 channel = 1;
52 }
53 else if (peripheral == DMA_PERIPHERAL_DSP)
54 {
55 /* Set second DMA channel */
56 IO_SDRAM_SDDMASEL = (IO_SDRAM_SDDMASEL & 0xFC1F) |
57 (peripheral << 5) |
58 (mode << 8);
59 channel = 2;
60 }
61 else if (peripheral == DMA_PERIPHERAL_SIF)
62 {
63 IO_SDRAM_SDDMASEL = (IO_SDRAM_SDDMASEL & 0x83FF) |
64 (peripheral << 10) |
65 (mode << 13);
66 channel = 3;
67 }
68
69 return channel;
70}
71
72void dma_release_channel(int channel)
73{
74 (void)channel;
75 /* TODO */
76}
77
78
diff --git a/firmware/target/arm/tms320dm320/dma-target.h b/firmware/target/arm/tms320dm320/dma-target.h
new file mode 100644
index 0000000000..37053b319b
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/dma-target.h
@@ -0,0 +1,44 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#ifndef DMA_TARGET_H
23#define DMA_TARGET_H
24
25/* These defines match DMA Select bits */
26#define DMA_PERIPHERAL_MTC 0
27#define DMA_PERIPHERAL_SIF 1
28#define DMA_PERIPHERAL_MS 2
29#define DMA_PERIPHERAL_MMCSD 3
30#define DMA_PERIPHERAL_DSP 4
31
32/* These defines match DMA Burst bits */
33/* 1 burst DMA - address must be 4 byte aligned */
34#define DMA_MODE_1_BURST 0
35/* 4 burst DMA - address must be 16 byte aligned */
36#define DMA_MODE_4_BURST 1
37/* 8 burst DMA - address must be 32 byte aligned */
38#define DMA_MODE_8_BURST 2
39
40void dma_init(void);
41int dma_request_channel(int peripheral, int mode);
42void dma_release_channel(int channel);
43
44#endif
diff --git a/firmware/target/arm/tms320dm320/i2c-dm320.c b/firmware/target/arm/tms320dm320/i2c-dm320.c
index 8bcc84dd8f..990dad0721 100644
--- a/firmware/target/arm/tms320dm320/i2c-dm320.c
+++ b/firmware/target/arm/tms320dm320/i2c-dm320.c
@@ -7,6 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2011 by Tomasz Moń
10 * Copyright (C) 2008 by Maurus Cuelenaere 11 * Copyright (C) 2008 by Maurus Cuelenaere
11 * 12 *
12 * DM320 I²C driver 13 * DM320 I²C driver
@@ -24,11 +25,11 @@
24#include "thread.h" 25#include "thread.h"
25#include "i2c-dm320.h" 26#include "i2c-dm320.h"
26 27
27#define I2C_SCS_COND_START 0x0001 28#ifdef HAVE_SOFTWARE_I2C
28#define I2C_SCS_COND_STOP 0x0002 29#include "generic_i2c.h"
29#define I2C_SCS_XMIT 0x0004 30#endif
30 31
31#define I2C_TX_ACK (1 << 8) 32#ifndef HAVE_SOFTWARE_I2C
32 33
33static struct mutex i2c_mtx; 34static struct mutex i2c_mtx;
34 35
@@ -42,6 +43,12 @@ static inline void i2c_end(void)
42 mutex_unlock(&i2c_mtx); 43 mutex_unlock(&i2c_mtx);
43} 44}
44 45
46#define I2C_SCS_COND_START 0x0001
47#define I2C_SCS_COND_STOP 0x0002
48#define I2C_SCS_XMIT 0x0004
49
50#define I2C_TX_ACK (1 << 8)
51
45static inline bool i2c_getack(void) 52static inline bool i2c_getack(void)
46{ 53{
47 return (IO_I2C_RXDATA >> 8) & 1; 54 return (IO_I2C_RXDATA >> 8) & 1;
@@ -158,3 +165,126 @@ void i2c_init(void)
158 IO_I2C_SCS &= ~0x8; //set clock to 100 kHz 165 IO_I2C_SCS &= ~0x8; //set clock to 100 kHz
159 IO_INTC_EINT2 &= ~INTR_EINT2_I2C; // disable I²C interrupt 166 IO_INTC_EINT2 &= ~INTR_EINT2_I2C; // disable I²C interrupt
160} 167}
168
169#else /* Software I2C implementation */
170
171#ifdef SANSA_CONNECT
172 /* SDA - GIO35 */
173 #define SDA_SET_REG IO_GIO_BITSET2
174 #define SDA_CLR_REG IO_GIO_BITCLR2
175 #define SOFTI2C_SDA (1 << 3)
176 /* SCL - GIO36 */
177 #define SCL_SET_REG IO_GIO_BITSET2
178 #define SCL_CLR_REG IO_GIO_BITCLR2
179 #define SOFTI2C_SCL (1 << 4)
180#else
181 #error Configure SDA and SCL lines
182#endif
183
184static int dm320_i2c_bus;
185
186static void dm320_scl_dir(bool out)
187{
188 if (out)
189 {
190 IO_GIO_DIR2 &= ~(SOFTI2C_SCL);
191 }
192 else
193 {
194 IO_GIO_DIR2 |= SOFTI2C_SCL;
195 }
196}
197
198static void dm320_sda_dir(bool out)
199{
200 if (out)
201 {
202 IO_GIO_DIR2 &= ~(SOFTI2C_SDA);
203 }
204 else
205 {
206 IO_GIO_DIR2 |= SOFTI2C_SDA;
207 }
208}
209
210static void dm320_scl_out(bool high)
211{
212 if (high)
213 {
214 SCL_SET_REG = SOFTI2C_SCL;
215 }
216 else
217 {
218 SCL_CLR_REG = SOFTI2C_SCL;
219 }
220}
221
222static void dm320_sda_out(bool high)
223{
224 if (high)
225 {
226 SDA_SET_REG = SOFTI2C_SDA;
227 }
228 else
229 {
230 SDA_CLR_REG = SOFTI2C_SDA;
231 }
232}
233
234static bool dm320_scl_in(void)
235{
236 return (SCL_SET_REG & SOFTI2C_SCL);
237}
238
239static bool dm320_sda_in(void)
240{
241 return (SDA_SET_REG & SOFTI2C_SDA);
242}
243
244/* simple delay */
245static void dm320_i2c_delay(int delay)
246{
247 udelay(delay);
248}
249
250/* interface towards the generic i2c driver */
251static const struct i2c_interface dm320_i2c_interface = {
252 .scl_dir = dm320_scl_dir,
253 .sda_dir = dm320_sda_dir,
254 .scl_out = dm320_scl_out,
255 .sda_out = dm320_sda_out,
256 .scl_in = dm320_scl_in,
257 .sda_in = dm320_sda_in,
258 .delay = dm320_i2c_delay,
259
260 /* uncalibrated */
261 .delay_hd_sta = 1,
262 .delay_hd_dat = 1,
263 .delay_su_dat = 1,
264 .delay_su_sto = 1,
265 .delay_su_sta = 1,
266 .delay_thigh = 1
267};
268
269void i2c_init(void)
270{
271#ifdef SANSA_CONNECT
272 IO_GIO_FSEL3 &= 0xFF0F; /* GIO35, GIO36 as normal GIO */
273 IO_GIO_INV2 &= ~(SOFTI2C_SDA | SOFTI2C_SCL); /* not inverted */
274#endif
275
276 /* generic_i2c takes care of setting direction */
277 dm320_i2c_bus = i2c_add_node(&dm320_i2c_interface);
278}
279
280int i2c_write(unsigned short address, const unsigned char* buf, int count)
281{
282 return i2c_write_data(dm320_i2c_bus, address, -1, buf, count);
283}
284
285int i2c_read(unsigned short address, unsigned char* buf, int count)
286{
287 return i2c_read_data(dm320_i2c_bus, address, -1, buf, count);
288}
289
290#endif
diff --git a/firmware/target/arm/tms320dm320/kernel-dm320.c b/firmware/target/arm/tms320dm320/kernel-dm320.c
index 08c50432e4..79206c3413 100644
--- a/firmware/target/arm/tms320dm320/kernel-dm320.c
+++ b/firmware/target/arm/tms320dm320/kernel-dm320.c
@@ -37,7 +37,7 @@ void tick_start(unsigned int interval_in_ms)
37 37
38 /* Setup the Divisor */ 38 /* Setup the Divisor */
39 IO_TIMER1_TMDIV = (TIMER_FREQ / (10*1000))*interval_in_ms - 1; 39 IO_TIMER1_TMDIV = (TIMER_FREQ / (10*1000))*interval_in_ms - 1;
40 40
41 /* Turn Timer1 to Free Run mode */ 41 /* Turn Timer1 to Free Run mode */
42 IO_TIMER1_TMMD = CONFIG_TIMER1_TMMD_FREE_RUN; 42 IO_TIMER1_TMMD = CONFIG_TIMER1_TMMD_FREE_RUN;
43 43
@@ -45,6 +45,13 @@ void tick_start(unsigned int interval_in_ms)
45 bitset16(&IO_INTC_EINT0, INTR_EINT0_TMR1); 45 bitset16(&IO_INTC_EINT0, INTR_EINT0_TMR1);
46} 46}
47 47
48#ifdef BOOTLOADER
49void tick_stop(void)
50{
51 bitclr16(&IO_CLK_MOD2, CLK_MOD2_TMR1); /* disable TIMER1 clock */
52}
53#endif
54
48void TIMER1(void) __attribute__ ((section(".icode"))); 55void TIMER1(void) __attribute__ ((section(".icode")));
49void TIMER1(void) 56void TIMER1(void)
50{ 57{
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c
new file mode 100644
index 0000000000..b3e427b9a5
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/adc-sansaconnect.c
@@ -0,0 +1,35 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "cpu.h"
23#include "adc.h"
24#include "adc-target.h"
25#include "kernel.h"
26
27void adc_init(void)
28{
29}
30
31/* Called to get the recent ADC reading */
32inline unsigned short adc_read(int channel)
33{
34 return (short)channel;
35}
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/adc-target.h b/firmware/target/arm/tms320dm320/sansa-connect/adc-target.h
new file mode 100644
index 0000000000..49244b4c3b
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/adc-target.h
@@ -0,0 +1,25 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#ifndef _ADC_TARGET_H_
23#define _ADC_TARGET_H_
24
25#endif
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
new file mode 100644
index 0000000000..3a6a748621
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.c
@@ -0,0 +1,461 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id: $
9*
10* Copyright (C) 2011 by Tomasz Moń
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#include <stdio.h>
23#include "config.h"
24#include "system.h"
25#include "kernel.h"
26#include "logf.h"
27#include "avr-sansaconnect.h"
28#include "uart-target.h"
29#include "button.h"
30#include "backlight.h"
31#include "powermgmt.h"
32
33//#define BUTTON_DEBUG
34
35#ifdef BUTTON_DEBUG
36#include "lcd-target.h"
37#include "lcd.h"
38#include "font.h"
39#include "common.h"
40#endif
41
42#ifdef BUTTON_DEBUG
43#define dbgprintf DEBUGF
44#else
45#define dbgprintf(...)
46#endif
47
48#define CMD_SYNC 0xAA
49#define CMD_CLOSE 0xCC
50#define CMD_LCM_POWER 0xC9
51#define LCM_POWER_OFF 0x00
52#define LCM_POWER_ON 0x01
53#define LCM_POWER_SLEEP 0x02
54#define LCM_POWER_WAKE 0x03
55#define LCM_REPOWER_ON 0x04
56
57#define CMD_STATE 0xBB
58#define CMD_VER 0xBC
59#define CMD_WHEEL_EN 0xD0
60#define CMD_SET_INTCHRG 0xD1
61#define CMD_CODEC_RESET 0xD7
62#define CMD_FILL 0xFF
63
64#define CMD_SYS_CTRL 0xDA
65#define SYS_CTRL_POWEROFF 0x00
66
67/* protects spi avr commands from concurrent access */
68static struct mutex avr_mtx;
69
70/* buttons thread */
71#define BTN_INTERRUPT 1
72static int btn = 0;
73static bool hold_switch;
74#ifndef BOOTLOADER
75static long btn_stack[DEFAULT_STACK_SIZE/sizeof(long)];
76static const char btn_thread_name[] = "buttons";
77static struct event_queue btn_queue;
78#endif
79
80static inline unsigned short be2short(unsigned char* buf)
81{
82 return (unsigned short)((buf[0] << 8) | buf[1]);
83}
84
85#define BUTTON_DIRECT_MASK (BUTTON_LEFT | BUTTON_UP | BUTTON_RIGHT | BUTTON_DOWN | BUTTON_SELECT | BUTTON_VOL_UP | BUTTON_VOL_DOWN | BUTTON_NEXT | BUTTON_PREV)
86
87#ifndef BOOTLOADER
88static void handle_wheel(unsigned char wheel)
89{
90 static int key = 0;
91 static unsigned char velocity = 0;
92 static unsigned long wheel_delta = 1ul << 24;
93 static unsigned char wheel_prev = 0;
94 static long next_backlight_on = 0;
95 static int prev_key = -1;
96 static int prev_key_post = 0;
97
98 if (TIME_AFTER(current_tick, next_backlight_on))
99 {
100 backlight_on();
101 reset_poweroff_timer();
102 next_backlight_on = current_tick + HZ/4;
103 }
104
105 if (wheel_prev < wheel)
106 {
107 key = BUTTON_SCROLL_FWD;
108 velocity = wheel - wheel_prev;
109 }
110 else if (wheel_prev > wheel)
111 {
112 key = BUTTON_SCROLL_BACK;
113 velocity = wheel_prev - wheel;
114 }
115
116 if (prev_key != key && velocity < 2 /* filter "rewinds" */)
117 {
118 /* direction reversal */
119 prev_key = key;
120 wheel_delta = 1ul << 24;
121 return;
122 }
123
124 /* TODO: take velocity into account */
125 if (queue_empty(&button_queue))
126 {
127 if (prev_key_post == key)
128 {
129 key |= BUTTON_REPEAT;
130 }
131
132 /* Post directly, don't update btn as avr doesn't give
133 interrupt on scroll stop */
134 queue_post(&button_queue, key, wheel_delta);
135
136 wheel_delta = 1ul << 24;
137
138 prev_key_post = key;
139 }
140 else
141 {
142 /* skipped post - increment delta and limit to 7 bits */
143 wheel_delta += 1ul << 24;
144
145 if (wheel_delta > (0x7ful << 24))
146 wheel_delta = 0x7ful << 24;
147 }
148
149 wheel_prev = wheel;
150
151 prev_key = key;
152}
153#endif
154
155/* buf must be 11-byte array of byte (reply from avr_hid_get_state() */
156static void parse_button_state(unsigned char *buf)
157{
158 unsigned short main_btns_state = be2short(&buf[4]);
159#ifdef BUTTON_DEBUG
160 unsigned short main_btns_changed = be2short(&buf[6]);
161#endif
162
163 /* make sure other bits doesn't conflict with our "free bits" buttons */
164 main_btns_state &= BUTTON_DIRECT_MASK;
165
166 if (buf[3] & 0x01) /* is power button pressed? */
167 {
168 main_btns_state |= BUTTON_POWER;
169 }
170
171 btn = main_btns_state;
172
173#ifndef BOOTLOADER
174 /* check if stored hold_switch state changed (prevents lost changes) */
175 if ((buf[3] & 0x20) /* hold change notification */ ||
176 (hold_switch != ((buf[3] & 0x02) >> 1)))
177 {
178#endif
179 hold_switch = (buf[3] & 0x02) >> 1;
180#ifdef BUTTON_DEBUG
181 dbgprintf("HOLD changed (%d)", hold_switch);
182#endif
183#ifndef BOOTLOADER
184 backlight_hold_changed(hold_switch);
185 }
186#endif
187#ifndef BOOTLOADER
188 if ((hold_switch == false) && (buf[3] & 0x80)) /* scrollwheel change */
189 {
190 handle_wheel(buf[2]);
191 }
192#endif
193
194#ifdef BUTTON_DEBUG
195 if (buf[3] & 0x10) /* power button change */
196 {
197 /* power button state has changed */
198 main_btns_changed |= BUTTON_POWER;
199 }
200
201 if (btn & BUTTON_LEFT) dbgprintf("LEFT");
202 if (btn & BUTTON_UP) dbgprintf("UP");
203 if (btn & BUTTON_RIGHT) dbgprintf("RIGHT");
204 if (btn & BUTTON_DOWN) dbgprintf("DOWN");
205 if (btn & BUTTON_SELECT) dbgprintf("SELECT");
206 if (btn & BUTTON_VOL_UP) dbgprintf("VOL UP");
207 if (btn & BUTTON_VOL_DOWN) dbgprintf("VOL DOWN");
208 if (btn & BUTTON_NEXT) dbgprintf("NEXT");
209 if (btn & BUTTON_PREV) dbgprintf("PREV");
210 if (btn & BUTTON_POWER) dbgprintf("POWER");
211 if (btn & BUTTON_HOLD) dbgprintf("HOLD");
212 if (btn & BUTTON_SCROLL_FWD) dbgprintf("SCROLL FWD");
213 if (btn & BUTTON_SCROLL_BACK) dbgprintf("SCROLL BACK");
214#endif
215}
216
217/* HID Slave Select - GIO14 */
218#define HID_SS (1<<14)
219
220static inline void select_hid(bool on)
221{
222 if (on == true)
223 {
224 /* SS is active low */
225 IO_GIO_BITCLR0 = HID_SS;
226 }
227 else
228 {
229 IO_GIO_BITSET0 = HID_SS;
230 }
231}
232
233static void spi_txrx(unsigned char *buf_tx, unsigned char *buf_rx, int n)
234{
235 int i;
236 unsigned short rxdata;
237
238 mutex_lock(&avr_mtx);
239
240 bitset16(&IO_CLK_MOD2, CLK_MOD2_SIF1);
241 IO_SERIAL1_TX_ENABLE = 0x0001;
242 select_hid(true);
243
244 for (i = 0; i<n; i++)
245 {
246 IO_SERIAL1_TX_DATA = buf_tx[i];
247 udelay(100);
248
249 do
250 {
251 rxdata = IO_SERIAL1_RX_DATA;
252 } while (rxdata & (1<<8));
253
254 if (buf_rx != NULL)
255 buf_rx[i] = rxdata & 0xFF;
256
257 //udelay(100);
258 }
259
260 select_hid(false);
261 IO_SERIAL1_TX_ENABLE = 0;
262 bitclr16(&IO_CLK_MOD2, CLK_MOD2_SIF1);
263
264 mutex_unlock(&avr_mtx);
265}
266
267static void avr_hid_sync(void)
268{
269 int i;
270 unsigned char prg[4] = {CMD_SYNC, CMD_VER, CMD_FILL, CMD_CLOSE};
271
272 /* Send SYNC three times */
273 for (i = 0; i<3; i++)
274 {
275 spi_txrx(prg, NULL, sizeof(prg));
276 }
277}
278
279void avr_hid_init(void)
280{
281 /*
282 setup alternate GIO functions:
283 GIO29 - SIF1 Enable
284 GIO30 - SIF1 Clock
285 GIO31 - SIF1 Data In
286 GIO32 - SIF1 Data Out
287 */
288 IO_GIO_FSEL2 = (IO_GIO_FSEL2 & 0x00FF) | 0xAA00;
289
290 bitclr16(&IO_GIO_DIR0, HID_SS); /* set GIO14 as output */
291
292 /* RATE = 219 (0xDB) -> 200 kHz */
293 IO_SERIAL1_MODE = 0x6DB;
294
295 mutex_init(&avr_mtx);
296
297 avr_hid_sync();
298}
299
300
301static void avr_hid_get_state(void)
302{
303 static unsigned char cmd[11] = {CMD_SYNC, CMD_STATE,
304 CMD_FILL, CMD_FILL, CMD_FILL, CMD_FILL, CMD_FILL, CMD_FILL, CMD_FILL, CMD_FILL,
305 CMD_CLOSE};
306
307 static unsigned char buf[11];
308 static unsigned char cmd_empty[1] = {0xCC};
309
310 spi_txrx(cmd, buf, sizeof(cmd));
311
312 spi_txrx(cmd_empty, NULL, 1); /* request interrupt on button press */
313
314 parse_button_state(buf);
315}
316
317static void avr_hid_enable_wheel(void)
318{
319 unsigned char wheel_en[4] = {CMD_SYNC, CMD_WHEEL_EN, 0x01, CMD_CLOSE};
320
321 spi_txrx(wheel_en, NULL, sizeof(wheel_en));
322}
323
324/* command that is sent by "hidtool -J 1" issued on every OF boot */
325void avr_hid_enable_charger(void)
326{
327 unsigned char charger_en[4] = {CMD_SYNC, CMD_SET_INTCHRG, 0x01, CMD_CLOSE};
328
329 spi_txrx(charger_en, NULL, sizeof(charger_en));
330}
331
332void avr_hid_lcm_sleep(void)
333{
334 unsigned char lcm_sleep[4] = {CMD_SYNC, CMD_LCM_POWER, LCM_POWER_SLEEP, CMD_CLOSE};
335
336 spi_txrx(lcm_sleep, NULL, sizeof(lcm_sleep));
337}
338
339
340void avr_hid_lcm_wake(void)
341{
342 unsigned char lcm_wake[4] = {CMD_SYNC, CMD_LCM_POWER, LCM_POWER_WAKE, CMD_CLOSE};
343
344 spi_txrx(lcm_wake, NULL, sizeof(lcm_wake));
345}
346
347void avr_hid_lcm_power_on(void)
348{
349 unsigned char lcm_power_on[4] = {CMD_SYNC, CMD_LCM_POWER, LCM_POWER_ON, CMD_CLOSE};
350
351 spi_txrx(lcm_power_on, NULL, sizeof(lcm_power_on));
352}
353
354void avr_hid_lcm_power_off(void)
355{
356 unsigned char lcm_power_off[4] = {CMD_SYNC, CMD_LCM_POWER, LCM_POWER_OFF, CMD_CLOSE};
357
358 spi_txrx(lcm_power_off, NULL, sizeof(lcm_power_off));
359}
360
361void avr_hid_reset_codec(void)
362{
363 unsigned char codec_reset[4] = {CMD_SYNC, CMD_CODEC_RESET, CMD_CLOSE, CMD_FILL};
364
365 spi_txrx(codec_reset, NULL, sizeof(codec_reset));
366}
367
368void avr_hid_power_off(void)
369{
370 unsigned char prg[4] = {CMD_SYNC, CMD_SYS_CTRL, SYS_CTRL_POWEROFF, CMD_CLOSE};
371
372 spi_txrx(prg, NULL, sizeof(prg));
373}
374
375#ifndef BOOTLOADER
376void btn_thread(void)
377{
378 struct queue_event ev;
379
380 while (1)
381 {
382 queue_wait(&btn_queue, &ev);
383
384 /* Ignore all messages except BTN_INTERRUPT */
385 if (ev.id != BTN_INTERRUPT)
386 continue;
387
388 /* Enable back button interrupt */
389 IO_INTC_EINT1 |= INTR_EINT1_EXT0;
390
391 /* Read buttons state */
392 avr_hid_get_state();
393
394 yield();
395
396 if (queue_empty(&btn_queue) && ((IO_GIO_BITSET0 & 0x1) == 0))
397 {
398 /* for some reason we have lost next interrupt */
399 queue_post(&btn_queue, BTN_INTERRUPT, 0);
400 }
401 }
402}
403
404void GIO0(void) __attribute__ ((section(".icode")));
405void GIO0(void)
406{
407 /* Clear interrupt */
408 IO_INTC_IRQ1 = (1 << 5);
409 /* Disable interrupt */
410 IO_INTC_EINT1 &= ~INTR_EINT1_EXT0;
411
412 /* interrupt will be enabled back after button read */
413 queue_post(&btn_queue, BTN_INTERRUPT, 0);
414}
415#endif
416
417void button_init_device(void)
418{
419 btn = 0;
420 hold_switch = false;
421#ifndef BOOTLOADER
422 queue_init(&btn_queue, true);
423 create_thread(btn_thread, btn_stack, sizeof(btn_stack), 0,
424 btn_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
425 IF_COP(, CPU));
426#endif
427 IO_GIO_DIR0 |= 0x01; /* Set GIO0 as input */
428
429 /* Enable wheel */
430 avr_hid_enable_wheel();
431 /* Read button status and tell avr we want interrupt on next change */
432 avr_hid_get_state();
433
434#ifndef BOOTLOADER
435 IO_GIO_IRQPORT |= 0x01; /* Enable GIO0 external interrupt */
436 IO_GIO_INV0 &= ~0x01; /* Clear INV for GIO0 (falling edge detection) */
437 IO_GIO_IRQEDGE &= ~0x01; /* Set edge detection (falling) */
438
439 /* Enable GIO0 interrupt */
440 IO_INTC_EINT1 |= INTR_EINT1_EXT0;
441#endif
442}
443
444int button_read_device(void)
445{
446 if(hold_switch)
447 return 0;
448 else
449 return btn;
450}
451
452bool button_hold(void)
453{
454 return hold_switch;
455}
456
457void lcd_enable(bool on)
458{
459 (void)on;
460}
461
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h
new file mode 100644
index 0000000000..64b44675f7
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/avr-sansaconnect.h
@@ -0,0 +1,38 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id: $
9*
10* Copyright (C) 2011 by Tomasz Moń
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#ifndef _AVR_SANSACONNECT_H_
23#define _AVR_SANSACONNECT_H_
24
25#include "config.h"
26
27void avr_hid_init(void);
28
29void avr_hid_enable_charger(void);
30
31void avr_hid_lcm_sleep(void);
32void avr_hid_lcm_wake(void);
33void avr_hid_lcm_power_on(void);
34void avr_hid_lcm_power_off(void);
35void avr_hid_reset_codec(void);
36void avr_hid_power_off(void);
37
38#endif /* _AVR_SANSACONNECT_H_ */
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c
new file mode 100644
index 0000000000..b7989849d7
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/backlight-sansaconnect.c
@@ -0,0 +1,93 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "config.h"
23#include "cpu.h"
24#include "system.h"
25#include "backlight-target.h"
26#include "backlight.h"
27#include "lcd.h"
28#include "power.h"
29#include "spi-target.h"
30#include "lcd-target.h"
31
32static void _backlight_write_brightness(int brightness)
33{
34 /*
35 Maps brightness int to percentage value found in OF
36
37 OF PWM1H
38 5% 14
39 10% 140
40 15% 210
41 20% 280
42 ...
43 95% 1330
44 100% 1400
45 */
46 if (brightness > 20)
47 brightness = 20;
48 else if (brightness < 0)
49 brightness = 0;
50
51 IO_CLK_PWM1H = brightness*70;
52}
53
54void _backlight_on(void)
55{
56 /* set GIO34 as PWM1 */
57 IO_GIO_FSEL3 = (IO_GIO_FSEL3 & 0xFFF3) | (1 << 2);
58
59#if (CONFIG_BACKLIGHT_FADING == BACKLIGHT_NO_FADING)
60 _backlight_write_brightness(backlight_brightness);
61#endif
62}
63
64void _backlight_off(void)
65{
66 _backlight_write_brightness(0);
67
68 bitclr16(&IO_GIO_FSEL3, 0xC); /* set GIO34 to normal GIO */
69 bitclr16(&IO_GIO_INV2, (1 << 2)); /* make sure GIO34 is not inverted */
70 IO_GIO_BITCLR2 = (1 << 2); /* drive GIO34 low */
71}
72
73/* Assumes that the backlight has been initialized */
74void _backlight_set_brightness(int brightness)
75{
76 _backlight_write_brightness(brightness);
77}
78
79void __backlight_dim(bool dim_now)
80{
81 _backlight_set_brightness(dim_now ?
82 DEFAULT_BRIGHTNESS_SETTING :
83 DEFAULT_DIMNESS_SETTING);
84}
85
86bool _backlight_init(void)
87{
88 IO_CLK_PWM1C = 0x58D; /* as found in OF */
89
90 _backlight_set_brightness(backlight_brightness);
91 return true;
92}
93
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/backlight-target.h b/firmware/target/arm/tms320dm320/sansa-connect/backlight-target.h
new file mode 100644
index 0000000000..89bd837cee
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/backlight-target.h
@@ -0,0 +1,33 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#ifndef BACKLIGHT_TARGET_H
23#define BACKLIGHT_TARGET_H
24
25bool _backlight_init(void);
26void _backlight_on(void);
27void _backlight_off(void);
28void _backlight_set_brightness(int brightness);
29
30/* true: backlight fades off - false: backlight fades on */
31void __backlight_dim(bool dim);
32
33#endif
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/button-target.h b/firmware/target/arm/tms320dm320/sansa-connect/button-target.h
new file mode 100644
index 0000000000..2eb571ae68
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/button-target.h
@@ -0,0 +1,64 @@
1/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id: $
9*
10* Copyright (C) 2011 by Tomasz Moń
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#ifndef _BUTTON_TARGET_H_
23#define _BUTTON_TARGET_H_
24
25#include "config.h"
26
27#define BUTTON_REMOTE 0
28
29/* these definitions match the avr hid reply */
30#define BUTTON_LEFT (1 << 2)
31#define BUTTON_UP (1 << 3)
32#define BUTTON_RIGHT (1 << 4)
33#define BUTTON_DOWN (1 << 5)
34#define BUTTON_SELECT (1 << 6)
35#define BUTTON_VOL_UP (1 << 10)
36#define BUTTON_VOL_DOWN (1 << 11)
37#define BUTTON_NEXT (1 << 13)
38#define BUTTON_PREV (1 << 14)
39
40/* following definitions use "free bits" from avr hid reply */
41#define BUTTON_POWER (1 << 0)
42#define BUTTON_HOLD (1 << 1)
43#define BUTTON_SCROLL_FWD (1 << 7)
44#define BUTTON_SCROLL_BACK (1 << 8)
45
46
47#define BUTTON_REMOTE 0
48#define BUTTON_MAIN (BUTTON_LEFT | BUTTON_UP | BUTTON_RIGHT | BUTTON_DOWN |\
49 BUTTON_SELECT | BUTTON_VOL_UP | BUTTON_VOL_DOWN |\
50 BUTTON_NEXT | BUTTON_PREV | BUTTON_POWER |\
51 BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK)
52
53#define POWEROFF_BUTTON BUTTON_POWER
54#define POWEROFF_COUNT 5
55
56#define HAS_BUTTON_HOLD
57
58void button_init_device(void);
59int button_read_device(void);
60bool button_hold(void);
61
62int get_debug_info(int choice);
63
64#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/crt0-board.S b/firmware/target/arm/tms320dm320/sansa-connect/crt0-board.S
new file mode 100644
index 0000000000..debd2cd2be
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/crt0-board.S
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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 "config.h"
22#include "cpu.h"
23
24/* Macro for reading a register */
25.macro mrh register
26 ldr r1, =\register
27 ldrh r0, [r1]
28.endm
29
30/* Macro for writing a register */
31.macro mwh register, value
32 ldr r0, =\value
33 ldr r1, =\register
34 strh r0, [r1]
35.endm
36
37/* This version uses a mov to save on the literal pool size. Otherwise it is
38 * functionally equivalent.
39 */
40.macro mwhm register, value
41 mov r0, #\value
42 ldr r1, =\register
43 strh r0, [r1]
44.endm
45
46 /*
47 * _init_board:
48 * This function initializes the specific board this SoC is on.
49 */
50.section .init, "ax"
51.code 32
52.align 0x04
53.global _init_board
54.type _init_board, %function
55
56_init_board:
57
58 /* Setup the EMIF interface timings */
59
60 /* FLASH interface:
61 * These are based on the OF setup
62 */
63 /* IO_EMIF_CS0CTRL1 and
64 * IO_EMIF_CS0CTRL2
65 */
66 mwh 0x30A00, 0x889A
67 mwh 0x30A02, 0x1110
68
69 mwhm 0x30A04, 0
70 mwh 0x30A06, 0x1415
71 mwh 0x30A08, 0x1109
72
73 mwh 0x30A0A, 0x1220
74 mwh 0x30A0C, 0x1104
75 mwh 0x30A0E, 0x0222
76
77 /* IO_EMIF_CS3CTRL1 and
78 * IO_EMIF_CS3CTRL2
79 */
80 mwh 0x30A10, 0x8899
81 mwh 0x30A12, 0x5110
82
83 /* USB interface */
84 /* IO_EMIF_CS4CTRL1 and
85 * IO_EMIF_CS4CTRL2
86 */
87 mwh 0x30A14, 0x77DF
88 mwh 0x30A16, 0x7740
89
90 /* IO_EMIF_BUSCTRL */
91 mwhm 0x30A18, 0
92 mwhm 0x30A1A, 0
93 mwhm 0x30A1C, 0
94 mwhm 0x30A1E, 0
95
96_clock_setup:
97 /* Clock initialization */
98
99 /* IO_CLK_BYP: Bypass the PLLs for the following changes */
100 mwh 0x30894, 0x1111
101
102 /*
103 * IO_CLK_PLLA
104 * IO_CLK_PLLB
105 */
106 mwhm 0x30880, 0x00A0
107 mwhm 0x30882, 0x1000
108
109 /* IO_CLK_SEL0 */
110 mwh 0x30884, 0x0066
111
112 /* IO_CLK_SEL1 */
113 mwhm 0x30886, 0x0003
114
115 # IO_CLK_SEL2: ARM, AXL, SDRAM and DSP are from PLLA */
116 mwh 0x30888, 0
117
118 /* IO_CLK_DIV0: Set the slow clock speed for the ARM/AHB */
119 mwh 0x3088A, 0x0101
120
121 /* IO_CLK_DIV1: Accelerator, SDRAM */
122 mwh 0x3088C, 0x0102
123
124 /* IO_CLK_DIV2: DSP, MS Clock */
125 mwhm 0x3088E, 0x0200
126
127 # PLLA &= ~0x1000 (BIC #0x1000)
128 mrh 0x30880
129 bic r0, r0, #0x1000
130 strh r0, [r1]
131
132 /* Wait for PLLs to lock before feeding them to the downstream devices */
133_plla_wait:
134 mrh 0x30880
135 bic r0, r0, #0x7F
136 tst r0, r0
137 beq _plla_wait
138
139 /* IO_CLK_BYP: Enable PLL feeds */
140 mwhm 0x30894, 0x0
141
142 /* IO_CLK_MOD0 */
143 mwh 0x30898, 0x01A7
144
145 /* IO_CLK_MOD1 */
146 mwhm 0x3089A, 0x18
147
148 /* IO_CLK_MOD2 */
149 mwhm 0x3089C, 0x4A0
150
151 /* Setup the SDRAM range on the AHB bus */
152 /* SDRAMSA */
153 mov r0, #0x60000
154 mov r1, #0x1000000
155 str r1, [r0, #0xF00]
156
157 /* SDRAMEA: 64MB */
158 mov r1, #0x5000000
159 str r1, [r0, #0xF04]
160
161 /* SDRC_REFCTL */
162 mwh 0x309A8, 0
163
164 ldr r0, =0x309A6
165 mov r2, #0x1380
166 orr r1, r2, #2
167 strh r1, [r0]
168 orr r1, r2, #4
169 strh r1, [r0]
170 strh r1, [r0]
171 strh r1, [r0]
172 strh r1, [r0]
173 strh r1, [r0]
174 strh r1, [r0]
175 strh r1, [r0]
176 strh r1, [r0]
177 orr r1, r2, #1
178 strh r1, [r0]
179 strh r2, [r0]
180 strh r2, [r0]
181
182 mwhm 0x309A8, 0x0140
183
184 mwhm 0x309BE, 0x4
185 mwhm 0x309BC, 0x2
186 ldr r0, =0x309C4
187 ldr r1, [r0]
188 orr r1, r1, #1
189 strh r1, [r0]
190
191 ldr r0, =0x309A6
192 mov r1, #0x1380
193 strh r1, [r0]
194 bic r1, r1, #0x80
195 strh r1, [r0]
196 orr r1, r1, #0x40
197 strh r1, [r0]
198
199 mwhm 0x309A8, 0x0140
200
201 /* Go through the GPIO initialization */
202 /* Warning: setting some of the functions wrong will make OF unable
203 to boot (freeze during startup) */
204 /* IO_GIO_FSEL0: Set up the GPIO pin functions 0-16 */
205 mwhm 0x305A4, 0xC000
206
207 /* IO_GIO_FSEL1: 17-24 */
208 mwh 0x305A6, 0xAAAA
209
210 /* IO_GIO_FSEL2: 18-32 */
211 mwh 0x305A8, 0xA80A
212
213 /* IO_GIO_FSEL3: 33-40 */
214 mwh 0x305AA, 0x1007
215
216 /* IO_GIO_DIR0 */
217 mwh 0x30580, 0xFF77
218
219 /* IO_GIO_DIR1 */
220 mwh 0x30582, 0xEFFE
221
222 /* IO_GIO_DIR2 */
223 mwh 0x30584, 0x01FD
224
225 /* IO_GIO_INV0 */
226 mwh 0x30586, 0x0000
227
228 /* IO_GIO_INV1 */
229 mwh 0x30588, 0x0000
230
231 /* IO_GIO_INV2 */
232 mwh 0x3058A, 0x0000
233
234 bx lr
235
236.ltorg
237.size _init_board, .-_init_board
238
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
new file mode 100644
index 0000000000..fcfc82e876
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c
@@ -0,0 +1,273 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include <sys/types.h>
23#include "config.h"
24#include "cpu.h"
25#include "string.h"
26#include "kernel.h"
27#include "system.h"
28#include "system-target.h"
29#include "lcd.h"
30#include "lcd-target.h"
31#include "avr-sansaconnect.h"
32
33/* Copies a rectangle from one framebuffer to another. Can be used in
34 single transfer mode with width = num pixels, and height = 1 which
35 allows a full-width rectangle to be copied more efficiently. */
36extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src,
37 int width, int height);
38
39static bool lcd_on = true;
40
41bool lcd_active(void)
42{
43 return lcd_on;
44}
45
46#if defined(HAVE_LCD_SLEEP)
47void lcd_sleep(void)
48{
49 if (lcd_on)
50 {
51 lcd_on = false;
52 avr_hid_lcm_sleep();
53 sleep(HZ/20);
54
55 /* disable video encoder */
56 bitclr16(&IO_VID_ENC_VMOD, 0x01);
57
58 sleep(HZ/20);
59
60 /* disable video encoder clock */
61 bitclr16(&IO_CLK_MOD1, CLK_MOD1_VENC);
62 }
63}
64
65void lcd_awake(void)
66{
67 if (!lcd_on)
68 {
69 lcd_on = true;
70 /* enable video encoder clock */
71 bitset16(&IO_CLK_MOD1, CLK_MOD1_VENC);
72
73 /* enable video encoder */
74 bitset16(&IO_VID_ENC_VMOD, 0x01);
75
76 avr_hid_lcm_wake();
77
78 send_event(LCD_EVENT_ACTIVATION, NULL);
79
80 lcd_update();
81 }
82}
83#endif
84
85void lcd_init_device(void)
86{
87 unsigned int addr;
88
89 /* Disable Video Encoder clock */
90 bitclr16(&IO_CLK_MOD1, CLK_MOD1_VENC);
91
92 /* configure GIO39, GIO34 and GIO33 as outputs */
93 IO_GIO_DIR2 &= ~((1 << 7) /* GIO39 */ | (1 << 2) /* GIO34 */ |
94 (1 << 1) /* GIO33 */);
95
96 IO_GIO_FSEL3 = (IO_GIO_FSEL3 & ~(0x300F)) |
97 (0x1000) /* GIO39 - FIELD_VENC */ |
98 (0x3) /* GIO33 - CLKOUT1B (bootloader does this) */ |
99 (0x4); /* GIO34 - PWM1 (brightness control) */
100
101 /* OSD Clock = VENC Clock /2,
102 CCD clock PCLK,
103 VENC Clock from PLLA */
104 IO_CLK_SEL1 = 0x3;
105
106 /* Set VENC Clock Division to 11
107 OF bootloader sets division to 8, vmlinux sets it to 11 */
108 IO_CLK_DIV3 = (IO_CLK_DIV3 & ~(0x1F00)) | 0xB00;
109
110 /* Enable DAC and OSD clocks */
111 bitset16(&IO_CLK_MOD1, CLK_MOD1_DAC | CLK_MOD1_OSD);
112
113 /* magic values based on OF bootloader initialization */
114 IO_VID_ENC_VMOD = 0x2010;
115 IO_VID_ENC_VDPRO = 0x80;
116 IO_VID_ENC_HSPLS = 0x4;
117 IO_VID_ENC_HINT = 0x4B0;
118 IO_VID_ENC_HSTART = 0x88;
119 IO_VID_ENC_HVALID = 0x3C0;
120 IO_VID_ENC_HSDLY = 0;
121 IO_VID_ENC_VSPLS = 0x2;
122 IO_VID_ENC_VINT = 0x152;
123 IO_VID_ENC_VSTART = 0x6;
124 IO_VID_ENC_VVALID = 0x140;
125 IO_VID_ENC_VSDLY = 0;
126 IO_VID_ENC_DCLKCTL = 0x3;
127 IO_VID_ENC_DCLKPTN0 = 0xC;
128 IO_VID_ENC_VDCTL = 0x6000;
129 IO_VID_ENC_SYNCTL = 0x2;
130 IO_VID_ENC_LCDOUT = 0x101;
131 IO_VID_ENC_VMOD = 0x2011;
132
133 /* Copy Rockbox frame buffer to the second framebuffer */
134 lcd_update();
135
136 avr_hid_lcm_power_on();
137
138 /* set framebuffer address - OF sets RAM start address to 0x1000000 */
139 addr = ((int)FRAME-CONFIG_SDRAM_START)/32;
140
141 IO_OSD_OSDWINADH = addr >> 16;
142 IO_OSD_OSDWIN0ADL = addr & 0xFFFF;
143
144 IO_OSD_BASEPX = 0x44;
145 IO_OSD_BASEPY = 0x6;
146 IO_OSD_OSDWIN0XP = 0;
147 IO_OSD_OSDWIN0YP = 0;
148 IO_OSD_OSDWIN0XL = LCD_WIDTH*2; /* OF bootloader sets 480 */
149 IO_OSD_OSDWIN0YL = LCD_HEIGHT; /* OF bootloader sets 320 */
150 IO_OSD_OSDWIN0OFST = 0xF;
151 IO_OSD_OSDWINMD0 = 0x25FB;/* OF bootloader sets 25C3,
152 vmlinux changes this to 0x25FB */
153 IO_OSD_VIDWINMD = 0; /* disable video windows (OF sets 0x03) */
154
155 IO_OSD_OSDWINMD1 = 0; /* disable OSD window 1 */
156
157 /* Enable DAC, Video Encoder and OSD clocks */
158 bitset16(&IO_CLK_MOD1, CLK_MOD1_DAC | CLK_MOD1_VENC | CLK_MOD1_OSD);
159
160 /* Enable Video Encoder - RGB666, custom timing */
161 IO_VID_ENC_VMOD = 0x2011;
162 avr_hid_lcm_wake();
163}
164
165/* Update a fraction of the display. */
166void lcd_update_rect(int x, int y, int width, int height)
167 __attribute__ ((section(".icode")));
168void lcd_update_rect(int x, int y, int width, int height)
169{
170 register fb_data *dst, *src;
171
172 if (!lcd_on)
173 return;
174
175 if ((width | height) < 0)
176 return; /* Nothing left to do */
177
178 if (x + width > LCD_WIDTH)
179 width = LCD_WIDTH - x; /* Clip right */
180 if (x < 0)
181 width += x, x = 0; /* Clip left */
182
183 if (y + height > LCD_HEIGHT)
184 height = LCD_HEIGHT - y; /* Clip bottom */
185 if (y < 0)
186 height += y, y = 0; /* Clip top */
187
188 dst = FRAME + LCD_WIDTH*y + x;
189 src = &lcd_framebuffer[y][x];
190
191 /* Copy part of the Rockbox framebuffer to the second framebuffer */
192 if (width < LCD_WIDTH)
193 {
194 /* Not full width - do line-by-line */
195 lcd_copy_buffer_rect(dst, src, width, height);
196 }
197 else
198 {
199 /* Full width - copy as one line */
200 lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1);
201 }
202}
203
204/* Update the display.
205 This must be called after all other LCD functions that change the display. */
206void lcd_update(void) __attribute__ ((section(".icode")));
207void lcd_update(void)
208{
209 if (!lcd_on)
210 return;
211
212 lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
213}
214
215void lcd_set_contrast(int val) {
216 (void) val;
217 // TODO:
218}
219
220void lcd_set_invert_display(bool yesno) {
221 (void) yesno;
222 // TODO:
223}
224
225void lcd_set_flip(bool yesno) {
226 (void) yesno;
227 // TODO:
228}
229
230/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
231extern void lcd_write_yuv420_lines(fb_data *dst,
232 unsigned char chroma_buf[LCD_HEIGHT/2*3],
233 unsigned char const * const src[3],
234 int width, int stride);
235
236/* Performance function to blit a YUV bitmap directly to the LCD */
237void lcd_blit_yuv(unsigned char * const src[3],
238 int src_x, int src_y, int stride,
239 int x, int y, int width, int height)
240{
241 /* Caches for chroma data so it only need be recalculated every other
242 line */
243 unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */
244 unsigned char const * yuv_src[3];
245 off_t z;
246
247 if (!lcd_on)
248 return;
249
250 /* Sorry, but width and height must be >= 2 or else */
251 width &= ~1;
252 height >>= 1;
253
254 fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1;
255
256 z = stride*src_y;
257 yuv_src[0] = src[0] + z + src_x;
258 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
259 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
260
261 do
262 {
263 lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width,
264 stride);
265
266 yuv_src[0] += stride << 1; /* Skip down two luma lines */
267 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
268 yuv_src[2] += stride >> 1;
269 dst -= 2;
270 }
271 while (--height > 0);
272}
273
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h
new file mode 100644
index 0000000000..0c1ad0d5f5
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h
@@ -0,0 +1,25 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#ifndef _LCD_TARGET_H_
23#define _LCD_TARGET_H_
24
25#endif
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c
new file mode 100644
index 0000000000..3f04838388
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/pcm-sansaconnect.c
@@ -0,0 +1,207 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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 <stdlib.h>
22#include "system.h"
23#include "kernel.h"
24#include "logf.h"
25#include "audio.h"
26#include "sound.h"
27#include "file.h"
28#include "dsp-target.h"
29#include "dsp/ipc.h"
30#include "mmu-arm.h"
31#include "pcm-internal.h"
32#include "dma-target.h"
33
34/* This is global to save some latency when pcm_play_dma_get_peak_buffer is
35 * called.
36 */
37static void *start;
38static int dma_channel;
39
40void pcm_play_dma_postinit(void)
41{
42 audiohw_postinit();
43}
44
45/* Return the current location in the SDRAM to SARAM transfer along with the
46 * number of bytes read in the current buffer (count). There is latency with
47 * this method equivalent to ~ the size of the SARAM buffer since there is
48 * another buffer between your ears and this calculation, but this works for
49 * key clicks and an approximate peak meter.
50 */
51const void * pcm_play_dma_get_peak_buffer(int *count)
52{
53 int cnt = DSP_(_sdem_level);
54
55 unsigned long addr = (unsigned long) start + cnt;
56
57 *count = (cnt & 0xFFFFF) >> 1;
58 return (void *)((addr + 2) & ~3);
59}
60
61void pcm_play_dma_init(void)
62{
63 /* GIO16 is DSP/AIC3X CLK */
64 IO_GIO_FSEL0 &= 0x3FFF;
65 IO_CLK_OSEL = (IO_CLK_OSEL & 0xFFF0) | 4; /* PLLIN clock */
66 IO_CLK_O0DIV = 7;
67 IO_GIO_DIR1 &= ~(1 << 0); /* GIO16 - output */
68 IO_GIO_FSEL0 |= 0xC000; /* GIO16 - CLKOUT0 */
69
70 audiohw_init();
71 audiohw_set_frequency(HW_FREQ_DEFAULT);
72
73 IO_INTC_IRQ0 = INTR_IRQ0_IMGBUF;
74 bitset16(&IO_INTC_EINT0, INTR_EINT0_IMGBUF);
75
76 /* Set this as a FIQ */
77 bitset16(&IO_INTC_FISEL0, INTR_EINT0_IMGBUF);
78
79 /* Enable the HPIB clock */
80 bitset16(&IO_CLK_MOD0, (CLK_MOD0_HPIB | CLK_MOD0_DSP));
81
82 /* Enable IMGBUF clock */
83 bitset16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF);
84
85 dma_channel = dma_request_channel(DMA_PERIPHERAL_DSP,
86 DMA_MODE_1_BURST);
87
88 IO_DSPC_HPIB_CONTROL = 1 << 10 | 1 << 9 | 1 << 8 | 1 << 7 | 1 << 3 | 1 << 0;
89
90 dsp_reset();
91 dsp_load(dsp_image);
92
93 DSP_(_dma0_stopped)=1;
94 dsp_wake();
95}
96
97void pcm_dma_apply_settings(void)
98{
99 audiohw_set_frequency(pcm_fsel);
100}
101
102/* Note that size is actually limited to the size of a short right now due to
103 * the implementation on the DSP side (and the way that we access it)
104 */
105void pcm_play_dma_start(const void *addr, size_t size)
106{
107 unsigned long sdem_addr=(unsigned long)addr - CONFIG_SDRAM_START;
108 /* Initialize codec. */
109 DSP_(_sdem_addrl) = sdem_addr & 0xffff;
110 DSP_(_sdem_addrh) = sdem_addr >> 16;
111 DSP_(_sdem_dsp_size) = size;
112 DSP_(_dma0_stopped)=0;
113
114 dsp_wake();
115}
116
117void pcm_play_dma_stop(void)
118{
119 DSP_(_dma0_stopped)=1;
120 dsp_wake();
121}
122
123void pcm_play_lock(void)
124{
125
126}
127
128void pcm_play_unlock(void)
129{
130
131}
132
133void pcm_play_dma_pause(bool pause)
134{
135 if (pause)
136 {
137 DSP_(_dma0_stopped)=2;
138 dsp_wake();
139 }
140 else
141 {
142 DSP_(_dma0_stopped)=0;
143 dsp_wake();
144 }
145}
146
147size_t pcm_get_bytes_waiting(void)
148{
149 return DSP_(_sdem_dsp_size)-DSP_(_sdem_level);
150}
151
152/* Only used when debugging */
153static char buffer[80];
154
155void DSPHINT(void) __attribute__ ((section(".icode")));
156void DSPHINT(void)
157{
158 unsigned int i;
159 size_t size;
160
161 IO_INTC_FIQ0 = INTR_IRQ0_IMGBUF;
162
163 switch (dsp_message.msg)
164 {
165 case MSG_DEBUGF:
166 /* DSP stores one character per word. */
167 for (i = 0; i < sizeof(buffer); i++)
168 {
169 buffer[i] = dsp_message.payload.debugf.buffer[i];
170 }
171
172 DEBUGF("DSP: %s", buffer);
173 break;
174
175 case MSG_REFILL:
176 /* Buffer empty. Try to get more. */
177 pcm_play_get_more_callback(&start, &size);
178
179 if (size != 0)
180 {
181 unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START;
182 /* Flush any pending cache writes */
183 clean_dcache_range(start, size);
184
185 /* set the new DMA values */
186 DSP_(_sdem_addrl) = sdem_addr & 0xffff;
187 DSP_(_sdem_addrh) = sdem_addr >> 16;
188 DSP_(_sdem_dsp_size) = size;
189
190 DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx",
191 (unsigned long)start, (unsigned long)sdem_addr);
192
193 pcm_play_dma_started_callback();
194 }
195
196 break;
197 default:
198 DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg);
199 break;
200 }
201
202 /* Re-Activate the channel */
203 dsp_wake();
204
205 DEBUGF("DSP: %s", buffer);
206}
207
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
new file mode 100644
index 0000000000..52ea9be1d9
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/power-sansaconnect.c
@@ -0,0 +1,59 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "config.h"
23#include "cpu.h"
24#include <stdbool.h>
25#include "kernel.h"
26#include "system.h"
27#include "power.h"
28#include "backlight.h"
29#include "backlight-target.h"
30#include "avr-sansaconnect.h"
31
32void power_init(void)
33{
34}
35
36void power_off(void)
37{
38 avr_hid_reset_codec();
39 avr_hid_power_off();
40}
41
42#if CONFIG_CHARGING
43unsigned int power_input_status(void)
44{
45 return POWER_INPUT_NONE;
46}
47
48/* Returns true if the unit is charging the batteries. */
49bool charging_state(void)
50{
51 return false;
52}
53#endif
54
55void ide_power_enable(bool on)
56{
57 (void)on;
58}
59
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c
new file mode 100644
index 0000000000..bd90c51072
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/powermgmt-sansaconnect.c
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "config.h"
23#include "adc.h"
24#include "powermgmt.h"
25#include "kernel.h"
26
27/* THIS CONTAINS CURRENTLY DUMMY CODE! */
28
29static const unsigned short current_voltage = 3910;
30const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
31{
32 0
33};
34
35const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
36{
37 0
38};
39
40/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
41const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
42{
43 { 100, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1320 },
44};
45
46/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
47const unsigned short percent_to_volt_charge[11] =
48{
49 100, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1320,
50};
51
52/* Returns battery voltage from ADC [millivolts] */
53unsigned int battery_adc_voltage(void)
54{
55 return current_voltage;
56}
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
new file mode 100644
index 0000000000..ab42beb2b4
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/usb-sansaconnect.c
@@ -0,0 +1,53 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "config.h"
23#include "system.h"
24#include "kernel.h"
25#include "usb.h"
26#ifdef HAVE_USBSTACK
27#include "usb_drv.h"
28#include "usb_core.h"
29#endif
30
31bool usb_drv_connected(void)
32{
33 return false;
34}
35
36int usb_detect(void)
37{
38 return USB_EXTRACTED;
39}
40
41void usb_init_device(void)
42{
43 return;
44}
45
46void usb_enable(bool on)
47{
48 (void)on;
49}
50
51void usb_attach(void)
52{
53}
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/usb-target.h b/firmware/target/arm/tms320dm320/sansa-connect/usb-target.h
new file mode 100644
index 0000000000..6142b09f0b
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sansa-connect/usb-target.h
@@ -0,0 +1,32 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#ifndef USB_TARGET_H
23#define USB_TARGET_H
24
25#include "dm320.h"
26
27#include <stdbool.h>
28int usb_detect(void);
29void usb_init_device(void);
30bool usb_drv_connected(void);
31
32#endif
diff --git a/firmware/target/arm/tms320dm320/sdmmc-dm320.c b/firmware/target/arm/tms320dm320/sdmmc-dm320.c
new file mode 100644
index 0000000000..307b90ec3b
--- /dev/null
+++ b/firmware/target/arm/tms320dm320/sdmmc-dm320.c
@@ -0,0 +1,949 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: $
9 *
10 * Copyright (C) 2011 by Tomasz Moń
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#include "sd.h"
23#include "system.h"
24#include <string.h>
25#include "gcc_extensions.h"
26#include "thread.h"
27#include "panic.h"
28#include "kernel.h"
29#include "dma-target.h"
30
31//#define SD_DEBUG
32
33#ifdef SD_DEBUG
34#include "lcd-target.h"
35#include "lcd.h"
36#include "font.h"
37#ifdef BOOTLOADER
38#include "common.h"
39#else
40#include "debug.h"
41#endif
42#endif
43#include "sdmmc.h"
44#include "disk.h"
45#include "fat.h"
46#include "system-target.h"
47
48/* The configuration method is not very flexible. */
49#define CARD_NUM_SLOT 1
50#define NUM_CARDS 2
51
52#define EC_OK 0
53#define EC_FAILED 1
54#define EC_NOCARD 2
55#define EC_WAIT_STATE_FAILED 3
56#define EC_POWER_UP 4
57#define EC_FIFO_WR_EMPTY 5
58#define EC_FIFO_WR_DONE 6
59#define EC_TRAN_READ_ENTRY 7
60#define EC_TRAN_READ_EXIT 8
61#define EC_TRAN_WRITE_ENTRY 9
62#define EC_TRAN_WRITE_EXIT 10
63#define EC_COMMAND 11
64#define EC_WRITE_PROTECT 12
65#define EC_DATA_TIMEOUT 13
66#define EC_RESP_TIMEOUT 14
67#define EC_CRC_ERROR 15
68#define NUM_EC 16
69
70#define MIN_YIELD_PERIOD 1000
71#define UNALIGNED_NUM_SECTORS 10
72#define MAX_TRANSFER_ERRORS 10
73
74#define SECTOR_SIZE 512
75#define BLOCKS_PER_BANK 0x7A7800
76
77/* command flags for send_cmd */
78#define SDHC_RESP_FMT_NONE 0x0000
79#define SDHC_RESP_FMT_1 0x0200
80#define SDHC_RESP_FMT_2 0x0400
81#define SDHC_RESP_FMT_3 0x0600
82
83#define INITIAL_CLK 312500 /* Initial clock */
84#define SD_CLK 24000000 /* Clock for SD cards */
85#define MMC_CLK 15000000 /* Clock for MMC cards */
86
87#ifdef SD_DEBUG
88#ifdef BOOTLOADER
89#define dbgprintf printf
90#else
91#define dbgprintf DEBUGF
92#endif
93#else
94#define dbgprintf(...)
95#endif
96
97struct sd_card_status
98{
99 int retry;
100 int retry_max;
101};
102
103/** static, private data **/
104
105/* for compatibility */
106static long last_disk_activity = -1;
107
108static bool initialized = false;
109static unsigned int sd_thread_id = 0;
110
111static bool sd_enabled = false;
112static long next_yield = 0;
113
114static tCardInfo card_info [NUM_CARDS];
115static tCardInfo *currcard;
116
117static struct sd_card_status sd_status[NUM_CARDS] =
118{
119#if NUM_CARDS > 1
120 {0, 10},
121#endif
122 {0, 10}
123};
124
125/* Shoot for around 75% usage */
126static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
127static const char sd_thread_name[] = "sd";
128static struct mutex sd_mtx SHAREDBSS_ATTR;
129static struct event_queue sd_queue;
130static volatile unsigned int transfer_error[NUM_DRIVES];
131/* align on cache line size */
132static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS * SD_BLOCK_SIZE]
133 __attribute__((aligned(32)));
134
135static void sd_card_mux(int card_no)
136{
137#ifdef HAVE_MULTIDRIVE
138#ifdef SANSA_CONNECT
139 /* GIO6 - select Card; GIO5 - select iNAND (both active low) */
140 if (card_no == CARD_NUM_SLOT)
141 {
142 IO_GIO_BITSET0 = (1 << 5); /* deselect iNAND (GIO5) */
143 IO_GIO_BITCLR0 = (1 << 6); /* select card (GIO6) */
144 }
145 else
146 {
147 IO_GIO_BITSET0 = (1 << 6); /* deselect card (GIO6) */
148 IO_GIO_BITCLR0 = (1 << 5); /* select iNAND (GIO5) */
149 }
150#else /* Different players */
151 (void)card_no;
152#endif
153#else /* No multidrive */
154 (void)card_no;
155#endif
156}
157
158
159void sd_enable(bool on)
160{
161 if (sd_enabled == on)
162 return; /* nothing to do */
163
164 if (on)
165 {
166 sd_enabled = true;
167 }
168 else
169 {
170 sd_enabled = false;
171 }
172}
173
174/* sets clock rate just like OF does */
175static void sd_set_clock_rate(unsigned long rate)
176{
177 unsigned char rate_val = 0;
178
179 if (rate == INITIAL_CLK)
180 {
181 rate_val = 0x3B;
182 }
183 else if (rate > INITIAL_CLK)
184 {
185 rate_val = 0;
186 }
187 else
188 {
189 rate_val = 0xFF;
190 }
191
192 IO_MMC_MEM_CLK_CONTROL = (IO_MMC_MEM_CLK_CONTROL & 0xFF00) | rate_val;
193}
194
195static int sd_poll_status(int st_reg_num, volatile unsigned int flag)
196{
197 unsigned int status;
198 unsigned int status1;
199 bool done;
200
201 do
202 {
203 long time = current_tick;
204
205 if (TIME_AFTER(time, next_yield))
206 {
207 long ty = current_tick;
208 yield();
209 next_yield = ty + MIN_YIELD_PERIOD;
210 }
211
212 status = IO_MMC_STATUS0;
213 status1 = IO_MMC_STATUS1;
214
215 if (status & MMC_ST0_CMD_TIMEOUT)
216 {
217 dbgprintf("CMD timeout");
218 return -EC_RESP_TIMEOUT;
219 }
220 if (status & MMC_ST0_DATA_TIMEOUT)
221 {
222 dbgprintf("DATA timeout");
223 return -EC_DATA_TIMEOUT;
224 }
225
226 if (status &
227 (MMC_ST0_WR_CRCERR | MMC_ST0_RD_CRCERR | MMC_ST0_RESP_CRCERR))
228 {
229 dbgprintf("CRC error");
230 return -EC_CRC_ERROR;
231 }
232
233 if (st_reg_num == 0)
234 {
235 done = status & flag;
236 }
237 else
238 {
239 done = status1 & flag;
240 }
241 } while (!done);
242
243 return EC_OK;
244}
245
246static int dma_wait_for_completion(void)
247{
248 unsigned short dma_status;
249
250 do
251 {
252 long time = current_tick;
253
254 if (TIME_AFTER(time, next_yield))
255 {
256 long ty = current_tick;
257 yield();
258 next_yield = ty + MIN_YIELD_PERIOD;
259 }
260
261 dma_status = IO_MMC_SD_DMA_STATUS1;
262 if (dma_status & (1 << 13))
263 {
264 return -EC_DATA_TIMEOUT;
265 }
266 } while (dma_status & (1 << 12));
267
268 return EC_OK;
269}
270
271static int sd_command(int cmd, unsigned long arg,
272 int cmdat, unsigned long *response)
273{
274 int ret;
275
276 /* Clear response registers */
277 IO_MMC_RESPONSE0 = 0;
278 IO_MMC_RESPONSE1 = 0;
279 IO_MMC_RESPONSE2 = 0;
280 IO_MMC_RESPONSE3 = 0;
281 IO_MMC_RESPONSE4 = 0;
282 IO_MMC_RESPONSE5 = 0;
283 IO_MMC_RESPONSE6 = 0;
284 IO_MMC_RESPONSE7 = 0;
285 IO_MMC_COMMAND_INDEX = 0;
286 IO_MMC_SPI_DATA = 0;
287
288 IO_MMC_ARG_LOW = (unsigned int)((arg & 0xFFFF));
289 IO_MMC_ARG_HI = (unsigned int)((arg & 0xFFFF0000) >> 16);
290
291 /* SD is always in push-pull mode */
292 cmdat |= MMC_CMD_PPLEN;
293
294 cmdat |= (cmd & MMC_CMD_CMD_MASK);
295
296 if (cmdat & MMC_CMD_DATA)
297 cmdat |= MMC_CMD_DCLR;
298
299 IO_MMC_COMMAND = cmdat;
300
301 if (cmdat & MMC_CMD_DATA)
302 {
303 /* Command requires data - do not wait for RSPDNE */
304 ret = EC_OK;
305 }
306 else
307 {
308 ret = sd_poll_status(0, MMC_ST0_RSPDNE);
309 }
310
311 if (ret != EC_OK)
312 {
313 dbgprintf("Command failed (ret %d)", ret);
314 return ret;
315 }
316
317 if (response == NULL)
318 {
319 /* discard response */
320 }
321 else if ((cmdat & SDHC_RESP_FMT_1) || (cmdat & SDHC_RESP_FMT_3))
322 {
323 response[0] = (IO_MMC_RESPONSE7 << 16) | IO_MMC_RESPONSE6;
324 }
325 else if (cmdat & SDHC_RESP_FMT_2)
326 {
327 response[0] = (IO_MMC_RESPONSE7 << 16) | IO_MMC_RESPONSE6;
328 response[1] = (IO_MMC_RESPONSE5 << 16) | IO_MMC_RESPONSE4;
329 response[2] = (IO_MMC_RESPONSE3 << 16) | IO_MMC_RESPONSE2;
330 response[3] = (IO_MMC_RESPONSE1 << 16) | IO_MMC_RESPONSE0;
331 }
332
333 return 0;
334}
335
336static int sd_init_card(const int card_no)
337{
338 bool sdhc = false;
339 unsigned long response[4];
340 int ret;
341 int i;
342
343 memset(currcard, 0, sizeof(*currcard));
344 sd_card_mux(card_no);
345
346 /* Set data bus width to 1 bit */
347 bitclr16(&IO_MMC_CONTROL, MMC_CTRL_WIDTH);
348 sd_set_clock_rate(INITIAL_CLK);
349
350 ret = sd_command(SD_GO_IDLE_STATE, 0, MMC_CMD_INITCLK, NULL);
351
352 if (ret < 0)
353 return -1;
354
355 ret = sd_command(SD_SEND_IF_COND, 0x1AA,
356 SDHC_RESP_FMT_3, response);
357 if ((response[0] & 0xFFF) == 0x1AA)
358 {
359 sdhc = true;
360 dbgprintf("found sdhc card");
361 }
362
363 while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */
364 {
365 ret = sd_command(SD_APP_CMD, currcard->rca,
366 SDHC_RESP_FMT_1, NULL);
367 if (ret < 0)
368 {
369 dbgprintf("SD_APP_CMD failed");
370 return -1;
371 }
372
373 ret = sd_command(SD_APP_OP_COND,
374 (1 << 20) /* 3.2-3.3V */ |
375 (1 << 21) /* 3.3-3.4V */ |
376 (sdhc ? (1 << 30) : 0),
377 SDHC_RESP_FMT_3, &currcard->ocr);
378
379 if (ret < 0)
380 {
381 dbgprintf("SD_APP_OP_COND failed");
382 return -1;
383 }
384 }
385
386 dbgprintf("Card powered up");
387
388 ret = sd_command(SD_ALL_SEND_CID, 0,
389 SDHC_RESP_FMT_2, response);
390 if (ret < 0)
391 {
392 dbgprintf("SD_ALL_SEND_CID failed");
393 return -1;
394 }
395
396 for (i = 0; i<4; i++)
397 {
398 currcard->cid[i] = response[i];
399 }
400
401 ret = sd_command(SD_SEND_RELATIVE_ADDR, 0,
402 SDHC_RESP_FMT_1, &currcard->rca);
403 if (ret < 0)
404 {
405 dbgprintf("SD_SEND_RELATIVE_ADDR failed");
406 return -1;
407 }
408
409 ret = sd_command(SD_SEND_CSD, currcard->rca,
410 SDHC_RESP_FMT_2, response);
411 if (ret < 0)
412 {
413 dbgprintf("SD_SEND_CSD failed");
414 return -1;
415 }
416
417 for (i = 0; i<4; i++)
418 {
419 currcard->csd[i] = response[i];
420 }
421
422 sd_parse_csd(currcard);
423
424 sd_set_clock_rate(currcard->speed);
425
426 ret = sd_command(SD_SELECT_CARD, currcard->rca,
427 SDHC_RESP_FMT_1, NULL);
428 if (ret < 0)
429 {
430 dbgprintf("SD_SELECT_CARD failed");
431 return -1;
432 }
433
434 ret = sd_command(SD_APP_CMD, currcard->rca,
435 SDHC_RESP_FMT_1, NULL);
436 if (ret < 0)
437 {
438 dbgprintf("SD_APP_CMD failed");
439 return -1;
440 }
441
442 ret = sd_command(SD_SET_BUS_WIDTH, currcard->rca | 2,
443 SDHC_RESP_FMT_1, NULL); /* 4 bit */
444 if (ret < 0)
445 {
446 dbgprintf("SD_SET_BUS_WIDTH failed");
447 return -1;
448 }
449
450 /* Set data bus width to 4 bits */
451 bitset16(&IO_MMC_CONTROL, MMC_CTRL_WIDTH);
452
453 ret = sd_command(SD_SET_BLOCKLEN, currcard->blocksize,
454 SDHC_RESP_FMT_1, NULL);
455 if (ret < 0)
456 {
457 dbgprintf("SD_SET_BLOCKLEN failed");
458 return -1;
459 }
460
461 IO_MMC_BLOCK_LENGTH = currcard->blocksize;
462
463 dbgprintf("Card initialized");
464 currcard->initialized = 1;
465
466 return EC_OK;
467}
468
469/* lock must already by aquired */
470static void sd_select_device(int card_no)
471{
472 currcard = &card_info[card_no];
473
474 if (card_no == 0)
475 {
476 /* Main card always gets a chance */
477 sd_status[0].retry = 0;
478 }
479
480 if (currcard->initialized > 0)
481 {
482 /* This card is already initialized - switch to it */
483 sd_card_mux(card_no);
484 return;
485 }
486
487 if (currcard->initialized == 0)
488 {
489 /* Card needs (re)init */
490 sd_init_card(card_no);
491 }
492}
493
494static inline bool card_detect_target(void)
495{
496#ifdef SANSA_CONNECT
497 bool removed;
498
499 removed = IO_GIO_BITSET0 & (1 << 14);
500
501 return !removed;
502#else
503 return false;
504#endif
505}
506
507
508#ifdef HAVE_HOTSWAP
509
510static int sd1_oneshot_callback(struct timeout *tmo)
511{
512 (void)tmo;
513
514 /* This is called only if the state was stable for 300ms - check state
515 * and post appropriate event. */
516 if (card_detect_target())
517 {
518 queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
519 }
520 else
521 queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
522 return 0;
523}
524
525#ifdef SANSA_CONNECT
526void GIO14(void) __attribute__ ((section(".icode")));
527void GIO14(void)
528{
529 static struct timeout sd1_oneshot;
530
531 /* clear interrupt */
532 IO_INTC_IRQ2 = (1<<3);
533
534 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
535}
536#endif
537
538bool sd_removable(IF_MD_NONVOID(int card_no))
539{
540#ifndef HAVE_MULTIDRIVE
541 const int card_no = 0;
542#endif
543
544 return (card_no == CARD_NUM_SLOT);
545}
546
547bool sd_present(IF_MD_NONVOID(int card_no))
548{
549#ifndef HAVE_MULTIDRIVE
550 const int card_no = 0;
551#endif
552
553 return (card_no == CARD_NUM_SLOT) ? card_detect_target() :
554#ifdef SANSA_CONNECT
555 true; /* iNAND is always present */
556#else
557 false;
558#endif
559}
560
561#else /* no hotswap */
562
563bool sd_removable(IF_MD_NONVOID(int card_no))
564{
565#ifdef HAVE_MULTIDRIVE
566 (void)card_no;
567#endif
568
569 /* not applicable */
570 return false;
571}
572
573#endif /* HAVE_HOTSWAP */
574
575static void sd_thread(void) NORETURN_ATTR;
576static void sd_thread(void)
577{
578 struct queue_event ev;
579
580 /* TODO */
581 while (1)
582 {
583 queue_wait_w_tmo(&sd_queue, &ev, HZ);
584 switch ( ev.id )
585 {
586#ifdef HAVE_HOTSWAP
587 case SYS_HOTSWAP_INSERTED:
588 case SYS_HOTSWAP_EXTRACTED:
589 {
590 int success = 1;
591 fat_lock(); /* lock-out FAT activity first -
592 prevent deadlocking via disk_mount that
593 would cause a reverse-order attempt with
594 another thread */
595 mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
596 into driver that bypass the fat cache */
597
598 /* We now have exclusive control of fat cache and ata */
599
600 disk_unmount(0); /* release "by force", ensure file
601 descriptors aren't leaked and any busy
602 ones are invalid if mounting */
603
604 /* Force card init for new card, re-init for re-inserted one or
605 * clear if the last attempt to init failed with an error. */
606 card_info[0].initialized = 0;
607
608 if (ev.id == SYS_HOTSWAP_INSERTED)
609 {
610 /* FIXME: once sd_enabled is implement properly,
611 * reinitializing the controllers might be needed */
612 sd_enable(true);
613 if (success < 0) /* initialisation failed */
614 panicf("SD init failed : %d", success);
615 success = disk_mount(0); /* 0 if fail */
616 }
617
618 /* notify the system about the changed filesystems
619 */
620 if (success)
621 queue_broadcast(SYS_FS_CHANGED, 0);
622
623 /* Access is now safe */
624 mutex_unlock(&sd_mtx);
625 fat_unlock();
626 sd_enable(false);
627 }
628 break;
629#endif
630 }
631 }
632}
633
634static int sd_wait_for_state(unsigned int state)
635{
636 unsigned long response = 0;
637 unsigned int timeout = HZ; /* ticks */
638 long t = current_tick;
639
640 while (1)
641 {
642 long tick;
643 int ret = sd_command(SD_SEND_STATUS, currcard->rca,
644 SDHC_RESP_FMT_1, &response);
645 if (ret < 0)
646 return ret;
647
648 if ((SD_R1_CURRENT_STATE(response) == state))
649 {
650 return EC_OK;
651 }
652
653 if(TIME_AFTER(current_tick, t + timeout))
654 return -2;
655
656 if (TIME_AFTER((tick = current_tick), next_yield))
657 {
658 yield();
659 timeout += current_tick - tick;
660 next_yield = tick + MIN_YIELD_PERIOD;
661 }
662 }
663}
664
665static int sd_transfer_sectors(int card_no, unsigned long start,
666 int count, void *buffer, bool write)
667{
668 int ret;
669 unsigned long start_addr;
670 int dma_channel = -1;
671 bool use_direct_dma;
672 int count_per_dma;
673 unsigned long rel_addr;
674
675 dbgprintf("transfer %d %d %d", card_no, start, count);
676 mutex_lock(&sd_mtx);
677 sd_enable(true);
678
679sd_transfer_retry:
680 if (card_no == CARD_NUM_SLOT && !card_detect_target())
681 {
682 /* no external sd-card inserted */
683 ret = -EC_NOCARD;
684 goto sd_transfer_error;
685 }
686
687 sd_select_device(card_no);
688
689 if (currcard->initialized < 0)
690 {
691 ret = currcard->initialized;
692 goto sd_transfer_error;
693 }
694
695 last_disk_activity = current_tick;
696
697 ret = sd_wait_for_state(SD_TRAN);
698 if (ret < EC_OK)
699 {
700 goto sd_transfer_error;
701 }
702
703 IO_MMC_BLOCK_LENGTH = currcard->blocksize;
704
705 start_addr = start;
706
707 do
708 {
709 count_per_dma = count;
710
711 if (((unsigned long)buffer) & 0x1F)
712 {
713 /* MMC/SD interface requires 32-byte alignment of buffer */
714 use_direct_dma = false;
715 if (count > UNALIGNED_NUM_SECTORS)
716 {
717 count_per_dma = UNALIGNED_NUM_SECTORS;
718 }
719 }
720 else
721 {
722 use_direct_dma = true;
723 }
724
725 if (write == true)
726 {
727 if (use_direct_dma == false)
728 {
729 memcpy(aligned_buffer, buffer, count_per_dma*SD_BLOCK_SIZE);
730 }
731 commit_dcache_range(use_direct_dma ? buffer : aligned_buffer,
732 count_per_dma*SD_BLOCK_SIZE);
733 }
734
735 IO_MMC_NR_BLOCKS = count_per_dma;
736
737 /* Set start_addr to the correct unit (blocks or bytes) */
738 if (!(card_info[card_no].ocr & SD_OCR_CARD_CAPACITY_STATUS))
739 start_addr *= SD_BLOCK_SIZE; /* not SDHC */
740
741 ret = sd_command(write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK,
742 start_addr, MMC_CMD_DCLR | MMC_CMD_DATA |
743 SDHC_RESP_FMT_1 | (write ? MMC_CMD_WRITE : 0),
744 NULL);
745
746 if (ret < 0)
747 goto sd_transfer_error;
748
749 /* other burst modes are not supported for this peripheral */
750 dma_channel = dma_request_channel(DMA_PERIPHERAL_MMCSD,
751 DMA_MODE_8_BURST);
752
753 if (use_direct_dma == true)
754 {
755 rel_addr = ((unsigned long)buffer)-CONFIG_SDRAM_START;
756 }
757 else
758 {
759 rel_addr = ((unsigned long)aligned_buffer)-CONFIG_SDRAM_START;
760 }
761
762 IO_MMC_SD_DMA_ADDR_LOW = rel_addr & 0xFFFF;
763 IO_MMC_SD_DMA_ADDR_HI = (rel_addr & 0xFFFF0000) >> 16;
764
765 IO_MMC_SD_DMA_MODE |= MMC_DMAMODE_ENABLE;
766 if (write == true)
767 {
768 IO_MMC_SD_DMA_MODE |= MMC_DMAMODE_WRITE;
769 }
770
771 IO_MMC_SD_DMA_TRIGGER = 1;
772
773 dbgprintf("SD DMA transfer in progress");
774
775 ret = dma_wait_for_completion();
776 dma_release_channel(dma_channel);
777
778 dbgprintf("SD DMA transfer complete");
779
780 if (ret != EC_OK)
781 {
782 goto sd_transfer_error;
783 }
784
785 count -= count_per_dma;
786
787 if (write == false)
788 {
789 discard_dcache_range(use_direct_dma ? buffer : aligned_buffer,
790 count_per_dma*SD_BLOCK_SIZE);
791
792 if (use_direct_dma == false)
793 {
794 memcpy(buffer, aligned_buffer, count_per_dma*SD_BLOCK_SIZE);
795 }
796 }
797
798 buffer += count_per_dma*SD_BLOCK_SIZE;
799 start_addr += count_per_dma;
800
801 last_disk_activity = current_tick;
802
803 ret = sd_command(SD_STOP_TRANSMISSION, 0, SDHC_RESP_FMT_1, NULL);
804 if (ret < 0)
805 {
806 goto sd_transfer_error;
807 }
808
809 ret = sd_wait_for_state(SD_TRAN);
810 if (ret < 0)
811 {
812 goto sd_transfer_error;
813 }
814 } while (count > 0);
815
816 while (1)
817 {
818 sd_enable(false);
819 mutex_unlock(&sd_mtx);
820
821 return ret;
822
823sd_transfer_error:
824 if (sd_status[card_no].retry < sd_status[card_no].retry_max
825 && ret != -EC_NOCARD)
826 {
827 sd_status[card_no].retry++;
828 currcard->initialized = 0;
829 goto sd_transfer_retry;
830 }
831 }
832}
833
834int sd_read_sectors(IF_MD2(int card_no,) unsigned long start, int incount,
835 void* inbuf)
836{
837#ifndef HAVE_MULTIDRIVE
838 const int card_no = 0;
839#endif
840 return sd_transfer_sectors(card_no, start, incount, inbuf, false);
841}
842
843int sd_write_sectors(IF_MD2(int card_no,) unsigned long start, int count,
844 const void* outbuf)
845{
846#ifndef BOOTLOADER
847#ifndef HAVE_MULTIDRIVE
848 const int card_no = 0;
849#endif
850 return sd_transfer_sectors(card_no, start, count, (void*)outbuf, true);
851#else /* we don't need write support in bootloader */
852#ifdef HAVE_MULTIDRIVE
853 (void)card_no;
854#endif
855 (void)start;
856 (void)count;
857 (void)outbuf;
858 return 0;
859#endif
860}
861
862int sd_init(void)
863{
864 int ret = EC_OK;
865
866#ifndef BOOTLOADER
867 sd_enabled = true;
868 sd_enable(false);
869#endif
870 mutex_init(&sd_mtx);
871
872 mutex_lock(&sd_mtx);
873 initialized = true;
874
875 /* based on linux/drivers/mmc/dm320mmc.c
876 Copyright (C) 2006 ZSI, All Rights Reserved.
877 Written by: Ben Bostwick */
878
879 bitclr16(&IO_CLK_MOD2, CLK_MOD2_MMC);
880 bitset16(&IO_CLK_INV, CLK_INV_MMC);
881
882 /* mmc module clock: 75 Mhz (AHB) / 2 = ~37.5 Mhz */
883 /* OF uses 1, but for some reason it freezes on us */
884 IO_CLK_DIV3 = (IO_CLK_DIV3 & 0xFF00) | 0x02;
885
886 bitset16(&IO_CLK_MOD2, CLK_MOD2_MMC);
887
888 /* set mmc module into reset */
889 bitset16(&IO_MMC_CONTROL, (MMC_CTRL_DATRST | MMC_CTRL_CMDRST));
890
891 /* set resp timeout to max */
892 IO_MMC_RESPONSE_TIMEOUT |= 0x1FFF;
893 IO_MMC_READ_TIMEOUT = 0xFFFF;
894
895 /* all done, take mmc module out of reset */
896 bitclr16(&IO_MMC_CONTROL, (MMC_CTRL_DATRST | MMC_CTRL_CMDRST));
897
898#ifdef SANSA_CONNECT
899 /* GIO37 - Power Card; GIO38 - Power iNAND (both active low) */
900 IO_GIO_DIR2 &= ~((1 << 5) /* GIO37 */ | (1 << 6) /* GIO38 */);
901 IO_GIO_INV2 &= ~((1 << 5) /* GIO37 */ | (1 << 6) /* GIO38 */);
902 IO_GIO_BITCLR2 = (1 << 5) | (1 << 6);
903
904 /* GIO6 - select Card; GIO5 - select iNAND (both active low) */
905 IO_GIO_DIR0 &= ~((1 << 6) /* GIO6 */ | (1 << 5) /* GIO5 */);
906 IO_GIO_INV0 &= ~((1 << 6) /* GIO6 */ | (1 << 5) /* GIO5 */);
907 IO_GIO_BITSET0 = (1 << 6) | (1 << 5);
908
909#ifdef HAVE_HOTSWAP
910 /* GIO14 is card detect */
911 IO_GIO_DIR0 |= (1 << 14); /* Set GIO14 as input */
912 IO_GIO_INV0 &= ~(1 << 14); /* GIO14 not inverted */
913 IO_GIO_IRQPORT |= (1 << 14); /* Enable GIO14 external interrupt */
914 IO_GIO_IRQEDGE |= (1 << 14); /* Any edge detection */
915
916 /* Enable GIO14 interrupt */
917 IO_INTC_EINT2 |= INTR_EINT2_EXT14;
918#endif
919#endif
920
921 sd_select_device(1);
922
923 /* Enable Memory Card CLK */
924 bitset16(&IO_MMC_MEM_CLK_CONTROL, (1 << 8));
925
926 queue_init(&sd_queue, true);
927 sd_thread_id = create_thread(sd_thread, sd_stack, sizeof(sd_stack),
928 0, sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
929 IF_COP(, CPU));
930
931 mutex_unlock(&sd_mtx);
932
933 return ret;
934}
935
936long sd_last_disk_activity(void)
937{
938 return last_disk_activity;
939}
940
941tCardInfo *card_get_info_target(int card_no)
942{
943 return &card_info[card_no];
944}
945
946void sd_sleepnow(void)
947{
948}
949
diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c
index f2a4aacb68..528d442ce5 100644
--- a/firmware/target/arm/tms320dm320/system-dm320.c
+++ b/firmware/target/arm/tms320dm320/system-dm320.c
@@ -26,11 +26,16 @@
26#include "uart-target.h" 26#include "uart-target.h"
27#include "system-arm.h" 27#include "system-arm.h"
28#include "spi.h" 28#include "spi.h"
29#include "i2c.h"
29#ifdef CREATIVE_ZVx 30#ifdef CREATIVE_ZVx
30#include "dma-target.h" 31#include "dma-target.h"
31#else 32#endif
33#ifdef MROBE_500
32#include "usb-mr500.h" 34#include "usb-mr500.h"
33#endif 35#endif
36#ifdef SANSA_CONNECT
37#include "avr-sansaconnect.h"
38#endif
34 39
35static unsigned short clock_arm_slow = 0xFFFF; 40static unsigned short clock_arm_slow = 0xFFFF;
36static unsigned short clock_arm_fast = 0xFFFF; 41static unsigned short clock_arm_fast = 0xFFFF;
@@ -182,7 +187,12 @@ void system_exception_wait(void)
182 IO_INTC_EINT0 = 0; 187 IO_INTC_EINT0 = 0;
183 IO_INTC_EINT1 = 0; 188 IO_INTC_EINT1 = 0;
184 IO_INTC_EINT2 = 0; 189 IO_INTC_EINT2 = 0;
190#ifdef MROBE_500
185 while ((IO_GIO_BITSET0&0x01) != 0); /* Wait for power button */ 191 while ((IO_GIO_BITSET0&0x01) != 0); /* Wait for power button */
192#endif
193#ifdef SANSA_CONNECT
194 while (1); /* Holding power button for a while makes avr system reset */
195#endif
186} 196}
187 197
188void system_init(void) 198void system_init(void)
@@ -311,7 +321,7 @@ void system_init(void)
311 clock_arm_slow = (0 << 8) | 3; 321 clock_arm_slow = (0 << 8) | 3;
312 clock_arm_fast = (1 << 8) | 1; 322 clock_arm_fast = (1 << 8) | 1;
313 } 323 }
314 324
315 /* M48XI disabled, USB buffer powerdown */ 325 /* M48XI disabled, USB buffer powerdown */
316 IO_CLK_LPCTL1 = 0x11; /* I2C wodn't work with this disabled */ 326 IO_CLK_LPCTL1 = 0x11; /* I2C wodn't work with this disabled */
317 327
@@ -337,14 +347,22 @@ void system_init(void)
337 uart_init(); 347 uart_init();
338 spi_init(); 348 spi_init();
339 349
350#ifdef MROBE_500
340 /* Initialization is done so shut the front LED off so that the battery 351 /* Initialization is done so shut the front LED off so that the battery
341 * can charge. 352 * can charge.
342 */ 353 */
343 IO_GIO_BITCLR2 = 0x0001; 354 IO_GIO_BITCLR2 = 0x0001;
344 355#endif
356
345#ifdef CREATIVE_ZVx 357#ifdef CREATIVE_ZVx
346 dma_init(); 358 dma_init();
347#endif 359#endif
360
361#ifdef SANSA_CONNECT
362 i2c_init();
363 avr_hid_init();
364 avr_hid_enable_charger();
365#endif
348} 366}
349 367
350int system_memory_guard(int newmode) 368int system_memory_guard(int newmode)
@@ -388,4 +406,13 @@ void udelay(int usec) {
388 } 406 }
389} 407}
390 408
409#ifdef BOOTLOADER
410void system_prepare_fw_start(void)
411{
412 tick_stop();
413 IO_INTC_EINT0 = 0;
414 IO_INTC_EINT1 = 0;
415 IO_INTC_EINT2 = 0;
416}
417#endif
391 418
diff --git a/firmware/target/arm/tms320dm320/system-target.h b/firmware/target/arm/tms320dm320/system-target.h
index 22cf5546b2..59ae61f8df 100644
--- a/firmware/target/arm/tms320dm320/system-target.h
+++ b/firmware/target/arm/tms320dm320/system-target.h
@@ -41,4 +41,9 @@ void udelay(int usec);
41 true; }) /* handled here */ 41 true; }) /* handled here */
42#endif 42#endif
43 43
44#ifdef BOOTLOADER
45void tick_stop(void);
46void system_prepare_fw_start(void);
47#endif
48
44#endif /* SYSTEM_TARGET_H */ 49#endif /* SYSTEM_TARGET_H */