diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/ata-common.c | 238 | ||||
-rw-r--r-- | firmware/drivers/ata.c | 364 | ||||
-rw-r--r-- | firmware/drivers/audio/erosqlinux_codec.c | 81 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 44 | ||||
-rw-r--r-- | firmware/drivers/lcd-scroll.c | 8 | ||||
-rw-r--r-- | firmware/drivers/ramdisk.c | 9 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_pcf50606.c | 4 | ||||
-rw-r--r-- | firmware/drivers/sd.c | 12 | ||||
-rw-r--r-- | firmware/drivers/tuner/rda5802.c | 32 |
9 files changed, 476 insertions, 316 deletions
diff --git a/firmware/drivers/ata-common.c b/firmware/drivers/ata-common.c new file mode 100644 index 0000000000..53a7780262 --- /dev/null +++ b/firmware/drivers/ata-common.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2024 Solomon Peachy | ||
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 | /* This is intended to be #included into the ATA driver */ | ||
22 | |||
23 | #ifdef MAX_PHYS_SECTOR_SIZE | ||
24 | |||
25 | struct sector_cache_entry { | ||
26 | unsigned char data[MAX_PHYS_SECTOR_SIZE]; | ||
27 | sector_t sectornum; /* logical sector */ | ||
28 | bool inuse; | ||
29 | }; | ||
30 | /* buffer for reading and writing large physical sectors */ | ||
31 | static struct sector_cache_entry sector_cache STORAGE_ALIGN_ATTR; | ||
32 | static int phys_sector_mult = 1; | ||
33 | |||
34 | static int cache_sector(sector_t sector) | ||
35 | { | ||
36 | int rc; | ||
37 | |||
38 | /* round down to physical sector boundary */ | ||
39 | sector &= ~(phys_sector_mult - 1); | ||
40 | |||
41 | /* check whether the sector is already cached */ | ||
42 | if (sector_cache.inuse && (sector_cache.sectornum == sector)) | ||
43 | return 0; | ||
44 | |||
45 | /* not found: read the sector */ | ||
46 | sector_cache.inuse = false; | ||
47 | rc = ata_transfer_sectors(sector, phys_sector_mult, sector_cache.data, false); | ||
48 | if (!rc) | ||
49 | { | ||
50 | sector_cache.sectornum = sector; | ||
51 | sector_cache.inuse = true; | ||
52 | } | ||
53 | return rc; | ||
54 | } | ||
55 | |||
56 | static inline int flush_current_sector(void) | ||
57 | { | ||
58 | return ata_transfer_sectors(sector_cache.sectornum, phys_sector_mult, | ||
59 | sector_cache.data, true); | ||
60 | } | ||
61 | |||
62 | int ata_read_sectors(IF_MD(int drive,) | ||
63 | sector_t start, | ||
64 | int incount, | ||
65 | void* inbuf) | ||
66 | { | ||
67 | int rc = 0; | ||
68 | int offset; | ||
69 | |||
70 | #ifdef HAVE_MULTIDRIVE | ||
71 | (void)drive; /* unused for now */ | ||
72 | #endif | ||
73 | mutex_lock(&ata_mutex); | ||
74 | |||
75 | offset = start & (phys_sector_mult - 1); | ||
76 | |||
77 | if (offset) /* first partial sector */ | ||
78 | { | ||
79 | int partcount = MIN(incount, phys_sector_mult - offset); | ||
80 | |||
81 | rc = cache_sector(start); | ||
82 | if (rc) | ||
83 | { | ||
84 | rc = rc * 10 - 1; | ||
85 | goto error; | ||
86 | } | ||
87 | memcpy(inbuf, sector_cache.data + offset * SECTOR_SIZE, | ||
88 | partcount * SECTOR_SIZE); | ||
89 | |||
90 | start += partcount; | ||
91 | inbuf += partcount * SECTOR_SIZE; | ||
92 | incount -= partcount; | ||
93 | } | ||
94 | if (incount) | ||
95 | { | ||
96 | offset = incount & (phys_sector_mult - 1); | ||
97 | incount -= offset; | ||
98 | |||
99 | if (incount) | ||
100 | { | ||
101 | rc = ata_transfer_sectors(start, incount, inbuf, false); | ||
102 | if (rc) | ||
103 | { | ||
104 | rc = rc * 10 - 2; | ||
105 | goto error; | ||
106 | } | ||
107 | start += incount; | ||
108 | inbuf += incount * SECTOR_SIZE; | ||
109 | } | ||
110 | if (offset) | ||
111 | { | ||
112 | rc = cache_sector(start); | ||
113 | if (rc) | ||
114 | { | ||
115 | rc = rc * 10 - 3; | ||
116 | goto error; | ||
117 | } | ||
118 | memcpy(inbuf, sector_cache.data, offset * SECTOR_SIZE); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | error: | ||
123 | mutex_unlock(&ata_mutex); | ||
124 | |||
125 | return rc; | ||
126 | } | ||
127 | |||
128 | int ata_write_sectors(IF_MD(int drive,) | ||
129 | sector_t start, | ||
130 | int count, | ||
131 | const void* buf) | ||
132 | { | ||
133 | int rc = 0; | ||
134 | int offset; | ||
135 | |||
136 | #ifdef HAVE_MULTIDRIVE | ||
137 | (void)drive; /* unused for now */ | ||
138 | #endif | ||
139 | mutex_lock(&ata_mutex); | ||
140 | |||
141 | offset = start & (phys_sector_mult - 1); | ||
142 | |||
143 | if (offset) /* first partial sector */ | ||
144 | { | ||
145 | int partcount = MIN(count, phys_sector_mult - offset); | ||
146 | |||
147 | rc = cache_sector(start); | ||
148 | if (rc) | ||
149 | { | ||
150 | rc = rc * 10 - 1; | ||
151 | goto error; | ||
152 | } | ||
153 | memcpy(sector_cache.data + offset * SECTOR_SIZE, buf, | ||
154 | partcount * SECTOR_SIZE); | ||
155 | rc = flush_current_sector(); | ||
156 | if (rc) | ||
157 | { | ||
158 | rc = rc * 10 - 2; | ||
159 | goto error; | ||
160 | } | ||
161 | start += partcount; | ||
162 | buf += partcount * SECTOR_SIZE; | ||
163 | count -= partcount; | ||
164 | } | ||
165 | if (count) | ||
166 | { | ||
167 | offset = count & (phys_sector_mult - 1); | ||
168 | count -= offset; | ||
169 | |||
170 | if (count) | ||
171 | { | ||
172 | rc = ata_transfer_sectors(start, count, (void*)buf, true); | ||
173 | if (rc) | ||
174 | { | ||
175 | rc = rc * 10 - 3; | ||
176 | goto error; | ||
177 | } | ||
178 | start += count; | ||
179 | buf += count * SECTOR_SIZE; | ||
180 | } | ||
181 | if (offset) | ||
182 | { | ||
183 | rc = cache_sector(start); | ||
184 | if (rc) | ||
185 | { | ||
186 | rc = rc * 10 - 4; | ||
187 | goto error; | ||
188 | } | ||
189 | memcpy(sector_cache.data, buf, offset * SECTOR_SIZE); | ||
190 | rc = flush_current_sector(); | ||
191 | if (rc) | ||
192 | { | ||
193 | rc = rc * 10 - 5; | ||
194 | goto error; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | error: | ||
200 | mutex_unlock(&ata_mutex); | ||
201 | |||
202 | return rc; | ||
203 | } | ||
204 | |||
205 | static int ata_get_phys_sector_mult(void) | ||
206 | { | ||
207 | int rc = 0; | ||
208 | |||
209 | /* Find out the physical sector size */ | ||
210 | if((identify_info[106] & 0xe000) == 0x6000) /* B14, B13 */ | ||
211 | phys_sector_mult = BIT_N(identify_info[106] & 0x000f); | ||
212 | else | ||
213 | phys_sector_mult = 1; | ||
214 | |||
215 | DEBUGF("ata: %d logical sectors per phys sector", phys_sector_mult); | ||
216 | |||
217 | if (phys_sector_mult > 1) | ||
218 | { | ||
219 | /* Check if drive really needs emulation - if we can access | ||
220 | sector 1 then assume the drive supports "512e" and will handle | ||
221 | it better than us, so ignore the large physical sectors. | ||
222 | */ | ||
223 | char throwaway[SECTOR_SIZE]; | ||
224 | rc = ata_transfer_sectors(1, 1, &throwaway, false); | ||
225 | if (rc == 0) | ||
226 | phys_sector_mult = 1; | ||
227 | } | ||
228 | |||
229 | if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE)) | ||
230 | panicf("Unsupported physical sector size: %d", | ||
231 | phys_sector_mult * SECTOR_SIZE); | ||
232 | |||
233 | memset(§or_cache, 0, sizeof(sector_cache)); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | #endif /* MAX_PHYS_SECTOR_SIZE */ | ||
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index d82fb173cc..7b43d3c536 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -90,7 +90,7 @@ enum { | |||
90 | 90 | ||
91 | static int ata_state = ATA_BOOT; | 91 | static int ata_state = ATA_BOOT; |
92 | 92 | ||
93 | static struct mutex ata_mtx SHAREDBSS_ATTR; | 93 | static struct mutex ata_mutex SHAREDBSS_ATTR; |
94 | static int ata_device; /* device 0 (master) or 1 (slave) */ | 94 | static int ata_device; /* device 0 (master) or 1 (slave) */ |
95 | 95 | ||
96 | static int spinup_time = 0; | 96 | static int spinup_time = 0; |
@@ -101,30 +101,19 @@ static bool ata_led_on = false; | |||
101 | 101 | ||
102 | static long sleep_timeout = 5*HZ; | 102 | static long sleep_timeout = 5*HZ; |
103 | #ifdef HAVE_LBA48 | 103 | #ifdef HAVE_LBA48 |
104 | static bool lba48 = false; /* set for 48 bit addressing */ | 104 | static bool ata_lba48 = false; /* set for 48 bit addressing */ |
105 | #endif | 105 | #endif |
106 | static bool canflush = true; | ||
106 | 107 | ||
107 | static long last_disk_activity = -1; | 108 | static long last_disk_activity = -1; |
108 | #ifdef HAVE_ATA_POWER_OFF | 109 | #ifdef HAVE_ATA_POWER_OFF |
109 | static long power_off_tick = 0; | 110 | static long power_off_tick = 0; |
110 | #endif | 111 | #endif |
111 | 112 | ||
112 | static unsigned long total_sectors; | 113 | static sector_t total_sectors; |
113 | static int multisectors; /* number of supported multisectors */ | 114 | static int multisectors; /* number of supported multisectors */ |
114 | static unsigned short identify_info[SECTOR_SIZE/2]; | ||
115 | 115 | ||
116 | #ifdef MAX_PHYS_SECTOR_SIZE | 116 | static unsigned short identify_info[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR; |
117 | |||
118 | struct sector_cache_entry { | ||
119 | bool inuse; | ||
120 | unsigned long sectornum; /* logical sector */ | ||
121 | unsigned char data[MAX_PHYS_SECTOR_SIZE]; | ||
122 | }; | ||
123 | /* buffer for reading and writing large physical sectors */ | ||
124 | #define NUMCACHES 2 | ||
125 | static struct sector_cache_entry sector_cache; | ||
126 | static int phys_sector_mult = 1; | ||
127 | #endif | ||
128 | 117 | ||
129 | #ifdef HAVE_ATA_DMA | 118 | #ifdef HAVE_ATA_DMA |
130 | static int dma_mode = 0; | 119 | static int dma_mode = 0; |
@@ -142,11 +131,6 @@ static inline void keep_ata_active(void) | |||
142 | last_disk_activity = current_tick; | 131 | last_disk_activity = current_tick; |
143 | } | 132 | } |
144 | 133 | ||
145 | static inline void schedule_ata_sleep(long from_now) | ||
146 | { | ||
147 | last_disk_activity = current_tick - sleep_timeout + from_now; | ||
148 | } | ||
149 | |||
150 | static inline bool ata_sleep_timed_out(void) | 134 | static inline bool ata_sleep_timed_out(void) |
151 | { | 135 | { |
152 | return sleep_timeout && | 136 | return sleep_timeout && |
@@ -224,7 +208,7 @@ static int ata_perform_wakeup(int state) | |||
224 | static int ata_perform_sleep(void) | 208 | static int ata_perform_sleep(void) |
225 | { | 209 | { |
226 | /* If device doesn't support PM features, don't try to sleep. */ | 210 | /* If device doesn't support PM features, don't try to sleep. */ |
227 | if (!ata_disk_can_poweroff()) | 211 | if (!ata_disk_can_sleep()) |
228 | return 0; // XXX or return a failure? | 212 | return 0; // XXX or return a failure? |
229 | 213 | ||
230 | logf("ata SLEEP %ld", current_tick); | 214 | logf("ata SLEEP %ld", current_tick); |
@@ -258,13 +242,18 @@ static int ata_perform_flush_cache(void) | |||
258 | { | 242 | { |
259 | uint8_t cmd; | 243 | uint8_t cmd; |
260 | 244 | ||
261 | if (identify_info[83] & (1 << 13)) { | 245 | if (!canflush) { |
262 | cmd = CMD_FLUSH_CACHE_EXT; | 246 | return 0; |
247 | } else if (ata_lba48 && identify_info[83] & (1 << 13)) { | ||
248 | cmd = CMD_FLUSH_CACHE_EXT; /* Flag, optional, ATA-6 and up, for use with LBA48 devices */ | ||
263 | } else if (identify_info[83] & (1 << 12)) { | 249 | } else if (identify_info[83] & (1 << 12)) { |
264 | cmd = CMD_FLUSH_CACHE; | 250 | cmd = CMD_FLUSH_CACHE; /* Flag, mandatory, ATA-6 and up */ |
251 | } else if (identify_info[80] >= (1 << 5)) { /* Use >= instead of '&' because bits lower than the latest standard we support don't have to be set */ | ||
252 | cmd = CMD_FLUSH_CACHE; /* No flag, mandatory, ATA-5 (Optional for ATA-4) */ | ||
265 | } else { | 253 | } else { |
266 | /* If neither (mandatory!) command is supported | 254 | /* If neither (mandatory!) command is supported |
267 | then don't issue it. */ | 255 | then don't issue it. */ |
256 | canflush = 0; | ||
268 | return 0; | 257 | return 0; |
269 | } | 258 | } |
270 | 259 | ||
@@ -287,6 +276,16 @@ static int ata_perform_flush_cache(void) | |||
287 | return 0; | 276 | return 0; |
288 | } | 277 | } |
289 | 278 | ||
279 | int ata_flush(void) | ||
280 | { | ||
281 | if (ata_state >= ATA_SPINUP) { | ||
282 | mutex_lock(&ata_mutex); | ||
283 | ata_perform_flush_cache(); | ||
284 | mutex_unlock(&ata_mutex); | ||
285 | } | ||
286 | return 0; | ||
287 | } | ||
288 | |||
290 | static ICODE_ATTR int wait_for_start_of_transfer(void) | 289 | static ICODE_ATTR int wait_for_start_of_transfer(void) |
291 | { | 290 | { |
292 | if (!wait_for_bsy()) | 291 | if (!wait_for_bsy()) |
@@ -381,7 +380,7 @@ static ICODE_ATTR void copy_write_sectors(const unsigned char* buf, | |||
381 | } | 380 | } |
382 | #endif /* !ATA_OPTIMIZED_WRITING */ | 381 | #endif /* !ATA_OPTIMIZED_WRITING */ |
383 | 382 | ||
384 | static int ata_transfer_sectors(unsigned long start, | 383 | static int ata_transfer_sectors(uint64_t start, |
385 | int incount, | 384 | int incount, |
386 | void* inbuf, | 385 | void* inbuf, |
387 | int write) | 386 | int write) |
@@ -437,15 +436,15 @@ static int ata_transfer_sectors(unsigned long start, | |||
437 | #endif | 436 | #endif |
438 | 437 | ||
439 | #ifdef HAVE_LBA48 | 438 | #ifdef HAVE_LBA48 |
440 | if (lba48) | 439 | if (ata_lba48) |
441 | { | 440 | { |
442 | ATA_OUT8(ATA_NSECTOR, count >> 8); | 441 | ATA_OUT8(ATA_NSECTOR, count >> 8); |
443 | ATA_OUT8(ATA_NSECTOR, count & 0xff); | 442 | ATA_OUT8(ATA_NSECTOR, count & 0xff); |
444 | ATA_OUT8(ATA_SECTOR, (start >> 24) & 0xff); /* 31:24 */ | 443 | ATA_OUT8(ATA_SECTOR, (start >> 24) & 0xff); /* 31:24 */ |
445 | ATA_OUT8(ATA_SECTOR, start & 0xff); /* 7:0 */ | 444 | ATA_OUT8(ATA_SECTOR, start & 0xff); /* 7:0 */ |
446 | ATA_OUT8(ATA_LCYL, 0); /* 39:32 */ | 445 | ATA_OUT8(ATA_LCYL, (start >> 32) & 0xff); /* 39:32 */ |
447 | ATA_OUT8(ATA_LCYL, (start >> 8) & 0xff); /* 15:8 */ | 446 | ATA_OUT8(ATA_LCYL, (start >> 8) & 0xff); /* 15:8 */ |
448 | ATA_OUT8(ATA_HCYL, 0); /* 47:40 */ | 447 | ATA_OUT8(ATA_HCYL, (start >> 40) & 0xff); /* 47:40 */ |
449 | ATA_OUT8(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */ | 448 | ATA_OUT8(ATA_HCYL, (start >> 16) & 0xff); /* 23:16 */ |
450 | ATA_OUT8(ATA_SELECT, SELECT_LBA | ata_device); | 449 | ATA_OUT8(ATA_SELECT, SELECT_LBA | ata_device); |
451 | #ifdef HAVE_ATA_DMA | 450 | #ifdef HAVE_ATA_DMA |
@@ -464,7 +463,7 @@ static int ata_transfer_sectors(unsigned long start, | |||
464 | ATA_OUT8(ATA_SECTOR, start & 0xff); | 463 | ATA_OUT8(ATA_SECTOR, start & 0xff); |
465 | ATA_OUT8(ATA_LCYL, (start >> 8) & 0xff); | 464 | ATA_OUT8(ATA_LCYL, (start >> 8) & 0xff); |
466 | ATA_OUT8(ATA_HCYL, (start >> 16) & 0xff); | 465 | ATA_OUT8(ATA_HCYL, (start >> 16) & 0xff); |
467 | ATA_OUT8(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); | 466 | ATA_OUT8(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); /* LBA28, mask off upper 4 bits of 32-bit sector address */ |
468 | #ifdef HAVE_ATA_DMA | 467 | #ifdef HAVE_ATA_DMA |
469 | if (write) | 468 | if (write) |
470 | ATA_OUT8(ATA_COMMAND, usedma ? CMD_WRITE_DMA : CMD_WRITE_MULTIPLE); | 469 | ATA_OUT8(ATA_COMMAND, usedma ? CMD_WRITE_DMA : CMD_WRITE_MULTIPLE); |
@@ -590,9 +589,11 @@ static int ata_transfer_sectors(unsigned long start, | |||
590 | return ret; | 589 | return ret; |
591 | } | 590 | } |
592 | 591 | ||
592 | #include "ata-common.c" | ||
593 | |||
593 | #ifndef MAX_PHYS_SECTOR_SIZE | 594 | #ifndef MAX_PHYS_SECTOR_SIZE |
594 | int ata_read_sectors(IF_MD(int drive,) | 595 | int ata_read_sectors(IF_MD(int drive,) |
595 | unsigned long start, | 596 | sector_t start, |
596 | int incount, | 597 | int incount, |
597 | void* inbuf) | 598 | void* inbuf) |
598 | { | 599 | { |
@@ -600,14 +601,14 @@ int ata_read_sectors(IF_MD(int drive,) | |||
600 | (void)drive; /* unused for now */ | 601 | (void)drive; /* unused for now */ |
601 | #endif | 602 | #endif |
602 | 603 | ||
603 | mutex_lock(&ata_mtx); | 604 | mutex_lock(&ata_mutex); |
604 | int rc = ata_transfer_sectors(start, incount, inbuf, false); | 605 | int rc = ata_transfer_sectors(start, incount, inbuf, false); |
605 | mutex_unlock(&ata_mtx); | 606 | mutex_unlock(&ata_mutex); |
606 | return rc; | 607 | return rc; |
607 | } | 608 | } |
608 | 609 | ||
609 | int ata_write_sectors(IF_MD(int drive,) | 610 | int ata_write_sectors(IF_MD(int drive,) |
610 | unsigned long start, | 611 | sector_t start, |
611 | int count, | 612 | int count, |
612 | const void* buf) | 613 | const void* buf) |
613 | { | 614 | { |
@@ -615,186 +616,13 @@ int ata_write_sectors(IF_MD(int drive,) | |||
615 | (void)drive; /* unused for now */ | 616 | (void)drive; /* unused for now */ |
616 | #endif | 617 | #endif |
617 | 618 | ||
618 | mutex_lock(&ata_mtx); | 619 | mutex_lock(&ata_mutex); |
619 | int rc = ata_transfer_sectors(start, count, (void*)buf, true); | 620 | int rc = ata_transfer_sectors(start, count, (void*)buf, true); |
620 | mutex_unlock(&ata_mtx); | 621 | mutex_unlock(&ata_mutex); |
621 | return rc; | 622 | return rc; |
622 | } | 623 | } |
623 | #endif /* ndef MAX_PHYS_SECTOR_SIZE */ | 624 | #endif /* ndef MAX_PHYS_SECTOR_SIZE */ |
624 | 625 | ||
625 | #ifdef MAX_PHYS_SECTOR_SIZE | ||
626 | static int cache_sector(unsigned long sector) | ||
627 | { | ||
628 | int rc; | ||
629 | |||
630 | sector &= ~(phys_sector_mult - 1); | ||
631 | /* round down to physical sector boundary */ | ||
632 | |||
633 | /* check whether the sector is already cached */ | ||
634 | if (sector_cache.inuse && (sector_cache.sectornum == sector)) | ||
635 | return 0; | ||
636 | |||
637 | /* not found: read the sector */ | ||
638 | sector_cache.inuse = false; | ||
639 | rc = ata_transfer_sectors(sector, phys_sector_mult, sector_cache.data, false); | ||
640 | if (!rc) | ||
641 | { | ||
642 | sector_cache.sectornum = sector; | ||
643 | sector_cache.inuse = true; | ||
644 | } | ||
645 | return rc; | ||
646 | } | ||
647 | |||
648 | static inline int flush_current_sector(void) | ||
649 | { | ||
650 | return ata_transfer_sectors(sector_cache.sectornum, phys_sector_mult, | ||
651 | sector_cache.data, true); | ||
652 | } | ||
653 | |||
654 | int ata_read_sectors(IF_MD(int drive,) | ||
655 | unsigned long start, | ||
656 | int incount, | ||
657 | void* inbuf) | ||
658 | { | ||
659 | int rc = 0; | ||
660 | int offset; | ||
661 | |||
662 | #ifdef HAVE_MULTIDRIVE | ||
663 | (void)drive; /* unused for now */ | ||
664 | #endif | ||
665 | mutex_lock(&ata_mtx); | ||
666 | |||
667 | offset = start & (phys_sector_mult - 1); | ||
668 | |||
669 | if (offset) /* first partial sector */ | ||
670 | { | ||
671 | int partcount = MIN(incount, phys_sector_mult - offset); | ||
672 | |||
673 | rc = cache_sector(start); | ||
674 | if (rc) | ||
675 | { | ||
676 | rc = rc * 10 - 1; | ||
677 | goto error; | ||
678 | } | ||
679 | memcpy(inbuf, sector_cache.data + offset * SECTOR_SIZE, | ||
680 | partcount * SECTOR_SIZE); | ||
681 | |||
682 | start += partcount; | ||
683 | inbuf += partcount * SECTOR_SIZE; | ||
684 | incount -= partcount; | ||
685 | } | ||
686 | if (incount) | ||
687 | { | ||
688 | offset = incount & (phys_sector_mult - 1); | ||
689 | incount -= offset; | ||
690 | |||
691 | if (incount) | ||
692 | { | ||
693 | rc = ata_transfer_sectors(start, incount, inbuf, false); | ||
694 | if (rc) | ||
695 | { | ||
696 | rc = rc * 10 - 2; | ||
697 | goto error; | ||
698 | } | ||
699 | start += incount; | ||
700 | inbuf += incount * SECTOR_SIZE; | ||
701 | } | ||
702 | if (offset) | ||
703 | { | ||
704 | rc = cache_sector(start); | ||
705 | if (rc) | ||
706 | { | ||
707 | rc = rc * 10 - 3; | ||
708 | goto error; | ||
709 | } | ||
710 | memcpy(inbuf, sector_cache.data, offset * SECTOR_SIZE); | ||
711 | } | ||
712 | } | ||
713 | |||
714 | error: | ||
715 | mutex_unlock(&ata_mtx); | ||
716 | |||
717 | return rc; | ||
718 | } | ||
719 | |||
720 | int ata_write_sectors(IF_MD(int drive,) | ||
721 | unsigned long start, | ||
722 | int count, | ||
723 | const void* buf) | ||
724 | { | ||
725 | int rc = 0; | ||
726 | int offset; | ||
727 | |||
728 | #ifdef HAVE_MULTIDRIVE | ||
729 | (void)drive; /* unused for now */ | ||
730 | #endif | ||
731 | mutex_lock(&ata_mtx); | ||
732 | |||
733 | offset = start & (phys_sector_mult - 1); | ||
734 | |||
735 | if (offset) /* first partial sector */ | ||
736 | { | ||
737 | int partcount = MIN(count, phys_sector_mult - offset); | ||
738 | |||
739 | rc = cache_sector(start); | ||
740 | if (rc) | ||
741 | { | ||
742 | rc = rc * 10 - 1; | ||
743 | goto error; | ||
744 | } | ||
745 | memcpy(sector_cache.data + offset * SECTOR_SIZE, buf, | ||
746 | partcount * SECTOR_SIZE); | ||
747 | rc = flush_current_sector(); | ||
748 | if (rc) | ||
749 | { | ||
750 | rc = rc * 10 - 2; | ||
751 | goto error; | ||
752 | } | ||
753 | start += partcount; | ||
754 | buf += partcount * SECTOR_SIZE; | ||
755 | count -= partcount; | ||
756 | } | ||
757 | if (count) | ||
758 | { | ||
759 | offset = count & (phys_sector_mult - 1); | ||
760 | count -= offset; | ||
761 | |||
762 | if (count) | ||
763 | { | ||
764 | rc = ata_transfer_sectors(start, count, (void*)buf, true); | ||
765 | if (rc) | ||
766 | { | ||
767 | rc = rc * 10 - 3; | ||
768 | goto error; | ||
769 | } | ||
770 | start += count; | ||
771 | buf += count * SECTOR_SIZE; | ||
772 | } | ||
773 | if (offset) | ||
774 | { | ||
775 | rc = cache_sector(start); | ||
776 | if (rc) | ||
777 | { | ||
778 | rc = rc * 10 - 4; | ||
779 | goto error; | ||
780 | } | ||
781 | memcpy(sector_cache.data, buf, offset * SECTOR_SIZE); | ||
782 | rc = flush_current_sector(); | ||
783 | if (rc) | ||
784 | { | ||
785 | rc = rc * 10 - 5; | ||
786 | goto error; | ||
787 | } | ||
788 | } | ||
789 | } | ||
790 | |||
791 | error: | ||
792 | mutex_unlock(&ata_mtx); | ||
793 | |||
794 | return rc; | ||
795 | } | ||
796 | #endif /* MAX_PHYS_SECTOR_SIZE */ | ||
797 | |||
798 | static int STORAGE_INIT_ATTR check_registers(void) | 626 | static int STORAGE_INIT_ATTR check_registers(void) |
799 | { | 627 | { |
800 | int i; | 628 | int i; |
@@ -845,24 +673,25 @@ void ata_spindown(int seconds) | |||
845 | 673 | ||
846 | bool ata_disk_is_active(void) | 674 | bool ata_disk_is_active(void) |
847 | { | 675 | { |
848 | return ata_state >= ATA_SPINUP; | 676 | return (ata_state >= ATA_SPINUP); |
849 | } | 677 | } |
850 | 678 | ||
851 | void ata_sleepnow(void) | 679 | void ata_sleepnow(void) |
852 | { | 680 | { |
853 | if (ata_state >= ATA_SPINUP) { | 681 | if (ata_state >= ATA_SPINUP) { |
854 | logf("ata SLEEPNOW %ld", current_tick); | 682 | logf("ata SLEEPNOW %ld", current_tick); |
855 | mutex_lock(&ata_mtx); | 683 | mutex_lock(&ata_mutex); |
856 | if (ata_state == ATA_ON) { | 684 | if (ata_state == ATA_ON) { |
857 | if (!ata_perform_flush_cache() && !ata_perform_sleep()) { | 685 | if (!ata_perform_flush_cache() && !ata_perform_sleep()) { |
858 | ata_state = ATA_SLEEPING; | 686 | ata_state = ATA_SLEEPING; |
859 | #ifdef HAVE_ATA_POWER_OFF | 687 | #ifdef HAVE_ATA_POWER_OFF |
860 | if (ata_disk_can_poweroff()) | 688 | if (ata_disk_can_sleep() || canflush) { |
861 | power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT; | 689 | power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT; |
690 | } | ||
862 | #endif | 691 | #endif |
863 | } | 692 | } |
864 | } | 693 | } |
865 | mutex_unlock(&ata_mtx); | 694 | mutex_unlock(&ata_mutex); |
866 | } | 695 | } |
867 | } | 696 | } |
868 | 697 | ||
@@ -880,7 +709,7 @@ static int STORAGE_INIT_ATTR ata_hard_reset(void) | |||
880 | { | 709 | { |
881 | int ret; | 710 | int ret; |
882 | 711 | ||
883 | mutex_lock(&ata_mtx); | 712 | mutex_lock(&ata_mutex); |
884 | 713 | ||
885 | ata_reset(); | 714 | ata_reset(); |
886 | 715 | ||
@@ -891,7 +720,7 @@ static int STORAGE_INIT_ATTR ata_hard_reset(void) | |||
891 | /* Massage the return code so it is 0 on success and -1 on failure */ | 720 | /* Massage the return code so it is 0 on success and -1 on failure */ |
892 | ret = ret?0:-1; | 721 | ret = ret?0:-1; |
893 | 722 | ||
894 | mutex_unlock(&ata_mtx); | 723 | mutex_unlock(&ata_mutex); |
895 | 724 | ||
896 | return ret; | 725 | return ret; |
897 | } | 726 | } |
@@ -916,7 +745,7 @@ static int identify(void) | |||
916 | return -2; | 745 | return -2; |
917 | } | 746 | } |
918 | 747 | ||
919 | for (i=0; i<SECTOR_SIZE/2; i++) { | 748 | for (i=0; i<ATA_IDENTIFY_WORDS; i++) { |
920 | /* the IDENTIFY words are already swapped, so we need to treat | 749 | /* the IDENTIFY words are already swapped, so we need to treat |
921 | this info differently that normal sector data */ | 750 | this info differently that normal sector data */ |
922 | identify_info[i] = ATA_SWAP_IDENTIFY(ATA_IN16(ATA_DATA)); | 751 | identify_info[i] = ATA_SWAP_IDENTIFY(ATA_IN16(ATA_DATA)); |
@@ -968,6 +797,9 @@ static int perform_soft_reset(void) | |||
968 | if (set_multiple_mode(multisectors)) | 797 | if (set_multiple_mode(multisectors)) |
969 | return -3; | 798 | return -3; |
970 | 799 | ||
800 | if (identify()) | ||
801 | return -2; | ||
802 | |||
971 | if (freeze_lock()) | 803 | if (freeze_lock()) |
972 | return -4; | 804 | return -4; |
973 | 805 | ||
@@ -978,13 +810,13 @@ int ata_soft_reset(void) | |||
978 | { | 810 | { |
979 | int ret = -6; | 811 | int ret = -6; |
980 | 812 | ||
981 | mutex_lock(&ata_mtx); | 813 | mutex_lock(&ata_mutex); |
982 | 814 | ||
983 | if (ata_state > ATA_OFF) { | 815 | if (ata_state > ATA_OFF) { |
984 | ret = perform_soft_reset(); | 816 | ret = perform_soft_reset(); |
985 | } | 817 | } |
986 | 818 | ||
987 | mutex_unlock(&ata_mtx); | 819 | mutex_unlock(&ata_mutex); |
988 | return ret; | 820 | return ret; |
989 | } | 821 | } |
990 | 822 | ||
@@ -1018,6 +850,9 @@ static int ata_power_on(void) | |||
1018 | if (set_multiple_mode(multisectors)) | 850 | if (set_multiple_mode(multisectors)) |
1019 | return -3; | 851 | return -3; |
1020 | 852 | ||
853 | if (identify()) | ||
854 | return -2; | ||
855 | |||
1021 | if (freeze_lock()) | 856 | if (freeze_lock()) |
1022 | return -4; | 857 | return -4; |
1023 | 858 | ||
@@ -1068,7 +903,7 @@ static int set_multiple_mode(int sectors) | |||
1068 | } | 903 | } |
1069 | 904 | ||
1070 | #ifdef HAVE_ATA_DMA | 905 | #ifdef HAVE_ATA_DMA |
1071 | static int get_best_mode(unsigned short identword, int max, int modetype) | 906 | static int ata_get_best_mode(unsigned short identword, int max, int modetype) |
1072 | { | 907 | { |
1073 | unsigned short testbit = BIT_N(max); | 908 | unsigned short testbit = BIT_N(max); |
1074 | 909 | ||
@@ -1117,13 +952,18 @@ static int set_features(void) | |||
1117 | 952 | ||
1118 | #ifdef HAVE_ATA_DMA | 953 | #ifdef HAVE_ATA_DMA |
1119 | if (identify_info[53] & (1<<2)) { | 954 | if (identify_info[53] & (1<<2)) { |
955 | int max_udma = ATA_MAX_UDMA; | ||
956 | #if ATA_MAX_UDMA > 2 | ||
957 | if (!(identify_info[93] & (1<<13))) | ||
958 | max_udma = 2; | ||
959 | #endif | ||
1120 | /* Ultra DMA mode info present, find a mode */ | 960 | /* Ultra DMA mode info present, find a mode */ |
1121 | dma_mode = get_best_mode(identify_info[88], ATA_MAX_UDMA, 0x40); | 961 | dma_mode = ata_get_best_mode(identify_info[88], max_udma, 0x40); |
1122 | } | 962 | } |
1123 | 963 | ||
1124 | if (!dma_mode) { | 964 | if (!dma_mode) { |
1125 | /* No UDMA mode found, try to find a multi-word DMA mode */ | 965 | /* No UDMA mode found, try to find a multi-word DMA mode */ |
1126 | dma_mode = get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20); | 966 | dma_mode = ata_get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20); |
1127 | features[1].id_word = 63; | 967 | features[1].id_word = 63; |
1128 | } else { | 968 | } else { |
1129 | features[1].id_word = 88; | 969 | features[1].id_word = 88; |
@@ -1210,19 +1050,16 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1210 | bool coldstart; | 1050 | bool coldstart; |
1211 | 1051 | ||
1212 | if (ata_state == ATA_BOOT) { | 1052 | if (ata_state == ATA_BOOT) { |
1213 | mutex_init(&ata_mtx); | 1053 | mutex_init(&ata_mutex); |
1214 | } | 1054 | } |
1215 | 1055 | ||
1216 | mutex_lock(&ata_mtx); | 1056 | mutex_lock(&ata_mutex); |
1217 | 1057 | ||
1218 | /* must be called before ata_device_init() */ | 1058 | /* must be called before ata_device_init() */ |
1219 | coldstart = ata_is_coldstart(); | 1059 | coldstart = ata_is_coldstart(); |
1220 | ata_led(false); | 1060 | ata_led(false); |
1221 | ata_device_init(); | 1061 | ata_device_init(); |
1222 | ata_enable(true); | 1062 | ata_enable(true); |
1223 | #ifdef MAX_PHYS_SECTOR_SIZE | ||
1224 | memset(§or_cache, 0, sizeof(sector_cache)); | ||
1225 | #endif | ||
1226 | 1063 | ||
1227 | if (ata_state == ATA_BOOT) { | 1064 | if (ata_state == ATA_BOOT) { |
1228 | ata_state = ATA_OFF; | 1065 | ata_state = ATA_OFF; |
@@ -1251,7 +1088,6 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1251 | } | 1088 | } |
1252 | 1089 | ||
1253 | rc = identify(); | 1090 | rc = identify(); |
1254 | |||
1255 | if (rc) { | 1091 | if (rc) { |
1256 | rc = -40 + rc; | 1092 | rc = -40 + rc; |
1257 | goto error; | 1093 | goto error; |
@@ -1263,59 +1099,37 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1263 | 1099 | ||
1264 | DEBUGF("ata: %d sectors per ata request\n",multisectors); | 1100 | DEBUGF("ata: %d sectors per ata request\n",multisectors); |
1265 | 1101 | ||
1266 | total_sectors = identify_info[60] | (identify_info[61] << 16); | 1102 | total_sectors = (identify_info[61] << 16) | identify_info[60]; |
1267 | 1103 | ||
1268 | #ifdef HAVE_LBA48 | 1104 | #ifdef HAVE_LBA48 |
1269 | if (identify_info[83] & 0x0400 /* 48 bit address support */ | 1105 | if (identify_info[83] & 0x0400 && total_sectors == 0x0FFFFFFF) { |
1270 | && total_sectors == 0x0FFFFFFF) /* and disk size >= 128 GiB */ | 1106 | total_sectors = ((uint64_t)identify_info[103] << 48) | |
1271 | { /* (needs BigLBA addressing) */ | 1107 | ((uint64_t)identify_info[102] << 32) | |
1272 | if (identify_info[102] || identify_info[103]) | 1108 | ((uint64_t)identify_info[101] << 16) | |
1273 | panicf("Unsupported disk size: >= 2^32 sectors"); | 1109 | identify_info[100]; |
1274 | 1110 | ata_lba48 = true; /* use BigLBA */ | |
1275 | total_sectors = identify_info[100] | (identify_info[101] << 16); | ||
1276 | lba48 = true; /* use BigLBA */ | ||
1277 | } | 1111 | } |
1278 | #endif /* HAVE_LBA48 */ | 1112 | #endif /* HAVE_LBA48 */ |
1279 | 1113 | ||
1280 | rc = freeze_lock(); | 1114 | rc = freeze_lock(); |
1281 | |||
1282 | if (rc) { | 1115 | if (rc) { |
1283 | rc = -50 + rc; | 1116 | rc = -50 + rc; |
1284 | goto error; | 1117 | goto error; |
1285 | } | 1118 | } |
1286 | 1119 | ||
1287 | rc = set_features(); // rror codes are between -1 and -49 | 1120 | rc = set_features(); // error codes are between -1 and -49 |
1288 | if (rc) { | 1121 | if (rc) { |
1289 | rc = -60 + rc; | 1122 | rc = -60 + rc; |
1290 | goto error; | 1123 | goto error; |
1291 | } | 1124 | } |
1292 | 1125 | ||
1293 | #ifdef MAX_PHYS_SECTOR_SIZE | 1126 | #ifdef MAX_PHYS_SECTOR_SIZE |
1294 | /* Find out the physical sector size */ | 1127 | rc = ata_get_phys_sector_mult(); |
1295 | if((identify_info[106] & 0xe000) == 0x6000) | 1128 | if (rc) { |
1296 | phys_sector_mult = BIT_N(identify_info[106] & 0x000f); | 1129 | rc = -70 + rc; |
1297 | else | 1130 | goto error; |
1298 | phys_sector_mult = 1; | ||
1299 | |||
1300 | DEBUGF("ata: %d logical sectors per phys sector", phys_sector_mult); | ||
1301 | |||
1302 | if (phys_sector_mult > 1) | ||
1303 | { | ||
1304 | /* Check if drive really needs emulation - if we can access | ||
1305 | * sector 1 then assume the drive will handle it better than | ||
1306 | * us, and ignore the large physical sectors. | ||
1307 | */ | ||
1308 | char throwaway[SECTOR_SIZE]; | ||
1309 | rc = ata_transfer_sectors(1, 1, &throwaway, false); | ||
1310 | if (rc == 0) | ||
1311 | phys_sector_mult = 1; | ||
1312 | } | 1131 | } |
1313 | 1132 | #endif | |
1314 | if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE)) | ||
1315 | panicf("Unsupported physical sector size: %d", | ||
1316 | phys_sector_mult * SECTOR_SIZE); | ||
1317 | #endif /* MAX_PHYS_SECTOR_SIZE */ | ||
1318 | |||
1319 | ata_state = ATA_ON; | 1133 | ata_state = ATA_ON; |
1320 | keep_ata_active(); | 1134 | keep_ata_active(); |
1321 | } | 1135 | } |
@@ -1323,8 +1137,14 @@ int STORAGE_INIT_ATTR ata_init(void) | |||
1323 | if (rc) | 1137 | if (rc) |
1324 | rc = -100 + rc; | 1138 | rc = -100 + rc; |
1325 | 1139 | ||
1140 | rc = identify(); | ||
1141 | if (rc) { | ||
1142 | rc = -40 + rc; | ||
1143 | goto error; | ||
1144 | } | ||
1145 | |||
1326 | error: | 1146 | error: |
1327 | mutex_unlock(&ata_mtx); | 1147 | mutex_unlock(&ata_mutex); |
1328 | return rc; | 1148 | return rc; |
1329 | } | 1149 | } |
1330 | 1150 | ||
@@ -1360,7 +1180,13 @@ void ata_get_info(IF_MD(int drive,)struct storage_info *info) | |||
1360 | (void)drive; /* unused for now */ | 1180 | (void)drive; /* unused for now */ |
1361 | #endif | 1181 | #endif |
1362 | int i; | 1182 | int i; |
1363 | info->sector_size = SECTOR_SIZE; | 1183 | |
1184 | /* Logical sector size > 512B ? */ | ||
1185 | if ((identify_info[106] & 0xd000) == 0x5000) /* B14, B12 */ | ||
1186 | info->sector_size = (identify_info[117] | (identify_info[118] << 16)) * 2; | ||
1187 | else | ||
1188 | info->sector_size = SECTOR_SIZE; | ||
1189 | |||
1364 | info->num_sectors = total_sectors; | 1190 | info->num_sectors = total_sectors; |
1365 | 1191 | ||
1366 | src = (unsigned short*)&identify_info[27]; | 1192 | src = (unsigned short*)&identify_info[27]; |
@@ -1418,11 +1244,11 @@ int ata_event(long id, intptr_t data) | |||
1418 | #ifdef HAVE_ATA_POWER_OFF | 1244 | #ifdef HAVE_ATA_POWER_OFF |
1419 | if (ata_state == ATA_SLEEPING && ata_power_off_timed_out()) { | 1245 | if (ata_state == ATA_SLEEPING && ata_power_off_timed_out()) { |
1420 | power_off_tick = 0; | 1246 | power_off_tick = 0; |
1421 | mutex_lock(&ata_mtx); | 1247 | mutex_lock(&ata_mutex); |
1422 | logf("ata OFF %ld", current_tick); | 1248 | logf("ata OFF %ld", current_tick); |
1423 | ide_power_enable(false); | 1249 | ide_power_enable(false); |
1424 | ata_state = ATA_OFF; | 1250 | ata_state = ATA_OFF; |
1425 | mutex_unlock(&ata_mtx); | 1251 | mutex_unlock(&ata_mutex); |
1426 | } | 1252 | } |
1427 | #endif | 1253 | #endif |
1428 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); | 1254 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); |
@@ -1432,7 +1258,7 @@ int ata_event(long id, intptr_t data) | |||
1432 | ata_sleepnow(); | 1258 | ata_sleepnow(); |
1433 | } | 1259 | } |
1434 | else if (id == Q_STORAGE_SLEEP) { | 1260 | else if (id == Q_STORAGE_SLEEP) { |
1435 | schedule_ata_sleep(HZ/5); | 1261 | last_disk_activity = current_tick - sleep_timeout + HZ / 5; |
1436 | } | 1262 | } |
1437 | #ifndef USB_NONE | 1263 | #ifndef USB_NONE |
1438 | else if (id == SYS_USB_CONNECTED) { | 1264 | else if (id == SYS_USB_CONNECTED) { |
@@ -1442,7 +1268,7 @@ int ata_event(long id, intptr_t data) | |||
1442 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); | 1268 | STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); |
1443 | } | 1269 | } |
1444 | else { | 1270 | else { |
1445 | mutex_lock(&ata_mtx); | 1271 | mutex_lock(&ata_mutex); |
1446 | if (ata_state < ATA_ON) { | 1272 | if (ata_state < ATA_ON) { |
1447 | ata_led(true); | 1273 | ata_led(true); |
1448 | if (!(rc = ata_perform_wakeup(ata_state))) { | 1274 | if (!(rc = ata_perform_wakeup(ata_state))) { |
@@ -1450,7 +1276,7 @@ int ata_event(long id, intptr_t data) | |||
1450 | } | 1276 | } |
1451 | ata_led(false); | 1277 | ata_led(false); |
1452 | } | 1278 | } |
1453 | mutex_unlock(&ata_mtx); | 1279 | mutex_unlock(&ata_mutex); |
1454 | } | 1280 | } |
1455 | } | 1281 | } |
1456 | #endif /* ndef USB_NONE */ | 1282 | #endif /* ndef USB_NONE */ |
diff --git a/firmware/drivers/audio/erosqlinux_codec.c b/firmware/drivers/audio/erosqlinux_codec.c index 02c35e3c00..d1b3e884d3 100644 --- a/firmware/drivers/audio/erosqlinux_codec.c +++ b/firmware/drivers/audio/erosqlinux_codec.c | |||
@@ -53,11 +53,29 @@ | |||
53 | BUFFER_BYTES: [4096 524288] | 53 | BUFFER_BYTES: [4096 524288] |
54 | TICK_TIME: ALL | 54 | TICK_TIME: ALL |
55 | 55 | ||
56 | Mixer controls: | 56 | Mixer controls (v1): |
57 | 57 | ||
58 | numid=1,iface=MIXER,name='Output Port Switch' | 58 | numid=1,iface=MIXER,name='Output Port Switch' |
59 | ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0 | 59 | ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0 |
60 | : values=4 | 60 | : values=4 |
61 | |||
62 | Mixer controls (v2+): | ||
63 | |||
64 | numid=3,iface=MIXER,name='ES9018_K2M Digital Filter' | ||
65 | ; type=INTEGER,access=rw------,values=1,min=0,max=4,step=0 | ||
66 | : values=0 | ||
67 | numid=1,iface=MIXER,name='Left Playback Volume' | ||
68 | ; type=INTEGER,access=rw------,values=1,min=0,max=255,step=0 | ||
69 | : values=0 | ||
70 | numid=4,iface=MIXER,name='Output Port Switch' | ||
71 | ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0 | ||
72 | : values=0 | ||
73 | numid=2,iface=MIXER,name='Right Playback Volume' | ||
74 | ; type=INTEGER,access=rw------,values=1,min=0,max=255,step=0 | ||
75 | : values=0 | ||
76 | numid=5,iface=MIXER,name='isDSD' | ||
77 | ; type=BOOLEAN,access=rw------,values=1 | ||
78 | : values=off | ||
61 | */ | 79 | */ |
62 | 80 | ||
63 | static int hw_init = 0; | 81 | static int hw_init = 0; |
@@ -68,6 +86,8 @@ static long int last_ps = -1; | |||
68 | 86 | ||
69 | static int muted = -1; | 87 | static int muted = -1; |
70 | 88 | ||
89 | extern int hwver; | ||
90 | |||
71 | void audiohw_mute(int mute) | 91 | void audiohw_mute(int mute) |
72 | { | 92 | { |
73 | logf("mute %d", mute); | 93 | logf("mute %d", mute); |
@@ -129,6 +149,13 @@ void audiohw_preinit(void) | |||
129 | logf("hw preinit"); | 149 | logf("hw preinit"); |
130 | alsa_controls_init("default"); | 150 | alsa_controls_init("default"); |
131 | hw_init = 1; | 151 | hw_init = 1; |
152 | |||
153 | /* See if we have hw2 or later */ | ||
154 | if (alsa_controls_find("Left Playback Volume") == -1) | ||
155 | hwver = 1; | ||
156 | else if (hwver == 1) | ||
157 | hwver = 23; | ||
158 | |||
132 | audiohw_mute(false); /* No need to stay muted */ | 159 | audiohw_mute(false); /* No need to stay muted */ |
133 | } | 160 | } |
134 | 161 | ||
@@ -154,10 +181,8 @@ void audiohw_set_frequency(int fsel) | |||
154 | const int min_pcm = -740; | 181 | const int min_pcm = -740; |
155 | const int max_pcm = 0; | 182 | const int max_pcm = 0; |
156 | 183 | ||
157 | void audiohw_set_volume(int vol_l, int vol_r) | 184 | static void audiohw_set_volume_v1(int vol_l, int vol_r) |
158 | { | 185 | { |
159 | logf("hw vol %d %d", vol_l, vol_r); | ||
160 | |||
161 | long l,r; | 186 | long l,r; |
162 | 187 | ||
163 | vol_l_hw = vol_l; | 188 | vol_l_hw = vol_l; |
@@ -180,6 +205,39 @@ void audiohw_set_volume(int vol_l, int vol_r) | |||
180 | pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); | 205 | pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); |
181 | } | 206 | } |
182 | 207 | ||
208 | static void audiohw_set_volume_v2(int vol_l, int vol_r) | ||
209 | { | ||
210 | long l,r; | ||
211 | |||
212 | if (lineout_inserted()) { | ||
213 | vol_l_hw = vol_r_hw = global_settings.volume_limit * 10; | ||
214 | } else { | ||
215 | vol_l_hw = -vol_l; | ||
216 | vol_r_hw = -vol_r; | ||
217 | } | ||
218 | |||
219 | if (!hw_init) | ||
220 | return; | ||
221 | |||
222 | l = vol_l_hw / 5; | ||
223 | r = vol_l_hw / 5; | ||
224 | |||
225 | alsa_controls_set_ints("Left Playback Volume", 1, &l); | ||
226 | alsa_controls_set_ints("Right Playback Volume", 1, &r); | ||
227 | |||
228 | /* Dial back PCM mixer to avoid compression */ | ||
229 | pcm_set_mixer_volume(global_settings.volume_limit / 2, global_settings.volume_limit / 2); | ||
230 | } | ||
231 | |||
232 | void audiohw_set_volume(int vol_l, int vol_r) | ||
233 | { | ||
234 | if (hwver >= 2) { | ||
235 | audiohw_set_volume_v2(vol_l, vol_r); | ||
236 | } else { | ||
237 | audiohw_set_volume_v1(vol_l, vol_r); | ||
238 | } | ||
239 | } | ||
240 | |||
183 | void audiohw_set_lineout_volume(int vol_l, int vol_r) | 241 | void audiohw_set_lineout_volume(int vol_l, int vol_r) |
184 | { | 242 | { |
185 | long l,r; | 243 | long l,r; |
@@ -196,7 +254,16 @@ void audiohw_set_lineout_volume(int vol_l, int vol_r) | |||
196 | r = vol_r_hw; | 254 | r = vol_r_hw; |
197 | } | 255 | } |
198 | 256 | ||
199 | int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm); | 257 | if (hwver >= 2) { |
200 | int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm); | 258 | if (hw_init) { |
201 | pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); | 259 | l /= 5; |
260 | r /= 5; | ||
261 | alsa_controls_set_ints("Left Playback Volume", 1, &l); | ||
262 | alsa_controls_set_ints("Right Playback Volume", 1, &r); | ||
263 | } | ||
264 | } else { | ||
265 | int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm); | ||
266 | int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm); | ||
267 | pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); | ||
268 | } | ||
202 | } | 269 | } |
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index ebf0f92798..f3c273cc05 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -173,9 +173,9 @@ union raw_dirent | |||
173 | 173 | ||
174 | struct fsinfo | 174 | struct fsinfo |
175 | { | 175 | { |
176 | unsigned long freecount; /* last known free cluster count */ | 176 | sector_t freecount; /* last known free cluster count */ |
177 | unsigned long nextfree; /* first cluster to start looking for free | 177 | sector_t nextfree; /* first cluster to start looking for free |
178 | clusters, or 0xffffffff for no hint */ | 178 | clusters, or 0xffffffff for no hint */ |
179 | }; | 179 | }; |
180 | /* fsinfo offsets */ | 180 | /* fsinfo offsets */ |
181 | #define FSINFO_SIGNATURE 0 | 181 | #define FSINFO_SIGNATURE 0 |
@@ -233,7 +233,7 @@ static struct bpb | |||
233 | unsigned long totalsectors; | 233 | unsigned long totalsectors; |
234 | unsigned long rootdirsector; | 234 | unsigned long rootdirsector; |
235 | unsigned long firstdatasector; | 235 | unsigned long firstdatasector; |
236 | unsigned long startsector; | 236 | sector_t startsector; |
237 | unsigned long dataclusters; | 237 | unsigned long dataclusters; |
238 | unsigned long fatrgnstart; | 238 | unsigned long fatrgnstart; |
239 | unsigned long fatrgnend; | 239 | unsigned long fatrgnend; |
@@ -241,8 +241,8 @@ static struct bpb | |||
241 | #ifdef HAVE_FAT16SUPPORT | 241 | #ifdef HAVE_FAT16SUPPORT |
242 | unsigned int bpb_rootentcnt; /* Number of dir entries in the root */ | 242 | unsigned int bpb_rootentcnt; /* Number of dir entries in the root */ |
243 | /* internals for FAT16 support */ | 243 | /* internals for FAT16 support */ |
244 | unsigned long rootdirsectornum; /* sector offset of root dir relative to start | 244 | sector_t rootdirsectornum; /* sector offset of root dir relative to start |
245 | * of first pseudo cluster */ | 245 | * of first pseudo cluster */ |
246 | #endif /* HAVE_FAT16SUPPORT */ | 246 | #endif /* HAVE_FAT16SUPPORT */ |
247 | 247 | ||
248 | /** Additional information kept for each volume **/ | 248 | /** Additional information kept for each volume **/ |
@@ -329,7 +329,7 @@ static void cache_discard(IF_MV_NONVOID(struct bpb *fat_bpb)) | |||
329 | } | 329 | } |
330 | 330 | ||
331 | /* caches a FAT or data area sector */ | 331 | /* caches a FAT or data area sector */ |
332 | static void * cache_sector(struct bpb *fat_bpb, unsigned long secnum) | 332 | static void * cache_sector(struct bpb *fat_bpb, sector_t secnum) |
333 | { | 333 | { |
334 | unsigned int flags; | 334 | unsigned int flags; |
335 | void *buf = dc_cache_probe(IF_MV(fat_bpb->volume,) secnum, &flags); | 335 | void *buf = dc_cache_probe(IF_MV(fat_bpb->volume,) secnum, &flags); |
@@ -340,8 +340,8 @@ static void * cache_sector(struct bpb *fat_bpb, unsigned long secnum) | |||
340 | secnum + fat_bpb->startsector, 1, buf); | 340 | secnum + fat_bpb->startsector, 1, buf); |
341 | if (UNLIKELY(rc < 0)) | 341 | if (UNLIKELY(rc < 0)) |
342 | { | 342 | { |
343 | DEBUGF("%s() - Could not read sector %ld" | 343 | DEBUGF("%s() - Could not read sector %llu" |
344 | " (error %d)\n", __func__, secnum, rc); | 344 | " (error %d)\n", __func__, (uint64_t)secnum, rc); |
345 | dc_discard_buf(buf); | 345 | dc_discard_buf(buf); |
346 | return NULL; | 346 | return NULL; |
347 | } | 347 | } |
@@ -354,14 +354,14 @@ static void * cache_sector(struct bpb *fat_bpb, unsigned long secnum) | |||
354 | * contents are NOT loaded before returning - use when completely overwriting | 354 | * contents are NOT loaded before returning - use when completely overwriting |
355 | * a sector's contents in order to avoid a fill */ | 355 | * a sector's contents in order to avoid a fill */ |
356 | static void * cache_sector_buffer(IF_MV(struct bpb *fat_bpb,) | 356 | static void * cache_sector_buffer(IF_MV(struct bpb *fat_bpb,) |
357 | unsigned long secnum) | 357 | sector_t secnum) |
358 | { | 358 | { |
359 | unsigned int flags; | 359 | unsigned int flags; |
360 | return dc_cache_probe(IF_MV(fat_bpb->volume,) secnum, &flags); | 360 | return dc_cache_probe(IF_MV(fat_bpb->volume,) secnum, &flags); |
361 | } | 361 | } |
362 | 362 | ||
363 | /* flush a cache buffer to storage */ | 363 | /* flush a cache buffer to storage */ |
364 | void dc_writeback_callback(IF_MV(int volume,) unsigned long sector, void *buf) | 364 | void dc_writeback_callback(IF_MV(int volume,) sector_t sector, void *buf) |
365 | { | 365 | { |
366 | struct bpb * const fat_bpb = &fat_bpbs[IF_MV_VOL(volume)]; | 366 | struct bpb * const fat_bpb = &fat_bpbs[IF_MV_VOL(volume)]; |
367 | unsigned int copies = !IS_FAT_SECTOR(fat_bpb, sector) ? | 367 | unsigned int copies = !IS_FAT_SECTOR(fat_bpb, sector) ? |
@@ -374,8 +374,8 @@ void dc_writeback_callback(IF_MV(int volume,) unsigned long sector, void *buf) | |||
374 | int rc = storage_write_sectors(IF_MD(fat_bpb->drive,) sector, 1, buf); | 374 | int rc = storage_write_sectors(IF_MD(fat_bpb->drive,) sector, 1, buf); |
375 | if (rc < 0) | 375 | if (rc < 0) |
376 | { | 376 | { |
377 | panicf("%s() - Could not write sector %ld" | 377 | panicf("%s() - Could not write sector %llu" |
378 | " (error %d)\n", __func__, sector, rc); | 378 | " (error %d)\n", __func__, (uint64_t)sector, rc); |
379 | } | 379 | } |
380 | 380 | ||
381 | if (--copies == 0) | 381 | if (--copies == 0) |
@@ -2397,12 +2397,12 @@ unsigned long fat_query_sectornum(const struct fat_filestr *filestr) | |||
2397 | } | 2397 | } |
2398 | 2398 | ||
2399 | /* helper for fat_readwrite */ | 2399 | /* helper for fat_readwrite */ |
2400 | static long transfer(struct bpb *fat_bpb, unsigned long start, long count, | 2400 | static long transfer(struct bpb *fat_bpb, sector_t start, long count, |
2401 | char *buf, bool write) | 2401 | char *buf, bool write) |
2402 | { | 2402 | { |
2403 | long rc = 0; | 2403 | long rc = 0; |
2404 | 2404 | ||
2405 | DEBUGF("%s(s=%lx, c=%lx, wr=%u)\n", __func__, | 2405 | DEBUGF("%s(s=%llx, c=%lx, wr=%u)\n", __func__, |
2406 | start + fat_bpb->startsector, count, write ? 1 : 0); | 2406 | start + fat_bpb->startsector, count, write ? 1 : 0); |
2407 | 2407 | ||
2408 | if (write) | 2408 | if (write) |
@@ -2416,12 +2416,12 @@ static long transfer(struct bpb *fat_bpb, unsigned long start, long count, | |||
2416 | firstallowed = fat_bpb->firstdatasector; | 2416 | firstallowed = fat_bpb->firstdatasector; |
2417 | 2417 | ||
2418 | if (start < firstallowed) | 2418 | if (start < firstallowed) |
2419 | panicf("Write %ld before data\n", firstallowed - start); | 2419 | panicf("Write %llu before data\n", (uint64_t)(firstallowed - start)); |
2420 | 2420 | ||
2421 | if (start + count > fat_bpb->totalsectors) | 2421 | if (start + count > fat_bpb->totalsectors) |
2422 | { | 2422 | { |
2423 | panicf("Write %ld after data\n", | 2423 | panicf("Write %llu after data\n", |
2424 | start + count - fat_bpb->totalsectors); | 2424 | (uint64_t)(start + count - fat_bpb->totalsectors)); |
2425 | } | 2425 | } |
2426 | } | 2426 | } |
2427 | 2427 | ||
@@ -2487,14 +2487,14 @@ long fat_readwrite(struct fat_filestr *filestr, unsigned long sectorcount, | |||
2487 | long rc; | 2487 | long rc; |
2488 | 2488 | ||
2489 | long cluster = filestr->lastcluster; | 2489 | long cluster = filestr->lastcluster; |
2490 | unsigned long sector = filestr->lastsector; | 2490 | sector_t sector = filestr->lastsector; |
2491 | long clusternum = filestr->clusternum; | 2491 | long clusternum = filestr->clusternum; |
2492 | unsigned long sectornum = filestr->sectornum; | 2492 | unsigned long sectornum = filestr->sectornum; |
2493 | 2493 | ||
2494 | DEBUGF("%s(file:%lx,count:0x%lx,buf:%lx,%s)\n", __func__, | 2494 | DEBUGF("%s(file:%lx,count:0x%lx,buf:%lx,%s)\n", __func__, |
2495 | file->firstcluster, sectorcount, (long)buf, | 2495 | file->firstcluster, sectorcount, (long)buf, |
2496 | write ? "write":"read"); | 2496 | write ? "write":"read"); |
2497 | DEBUGF("%s: sec:%lx numsec:%ld eof:%d\n", __func__, | 2497 | DEBUGF("%s: sec:%llx numsec:%ld eof:%d\n", __func__, |
2498 | sector, (long)sectornum, eof ? 1 : 0); | 2498 | sector, (long)sectornum, eof ? 1 : 0); |
2499 | 2499 | ||
2500 | eof = false; | 2500 | eof = false; |
@@ -2534,7 +2534,7 @@ long fat_readwrite(struct fat_filestr *filestr, unsigned long sectorcount, | |||
2534 | 2534 | ||
2535 | unsigned long transferred = 0; | 2535 | unsigned long transferred = 0; |
2536 | unsigned long count = 0; | 2536 | unsigned long count = 0; |
2537 | unsigned long last = sector; | 2537 | sector_t last = sector; |
2538 | 2538 | ||
2539 | while (transferred + count < sectorcount) | 2539 | while (transferred + count < sectorcount) |
2540 | { | 2540 | { |
@@ -2961,7 +2961,7 @@ void fat_recalc_free(IF_MV_NONVOID(int volume)) | |||
2961 | dc_unlock_cache(); | 2961 | dc_unlock_cache(); |
2962 | } | 2962 | } |
2963 | 2963 | ||
2964 | bool fat_size(IF_MV(int volume,) unsigned long *size, unsigned long *free) | 2964 | bool fat_size(IF_MV(int volume,) sector_t *size, sector_t *free) |
2965 | { | 2965 | { |
2966 | struct bpb * const fat_bpb = FAT_BPB(volume); | 2966 | struct bpb * const fat_bpb = FAT_BPB(volume); |
2967 | if (!fat_bpb) | 2967 | if (!fat_bpb) |
diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c index 895cf98cba..2a58d6ff21 100644 --- a/firmware/drivers/lcd-scroll.c +++ b/firmware/drivers/lcd-scroll.c | |||
@@ -195,8 +195,14 @@ static void LCDFN(scroll_worker)(void) | |||
195 | s = &si->scroll[index]; | 195 | s = &si->scroll[index]; |
196 | 196 | ||
197 | /* check pause */ | 197 | /* check pause */ |
198 | if (TIME_BEFORE(current_tick, s->start_tick)) | 198 | if (TIME_BEFORE(current_tick, s->start_tick)) { |
199 | continue; | 199 | continue; |
200 | } | ||
201 | |||
202 | if (global_settings.disable_mainmenu_scrolling && get_current_activity() == ACTIVITY_MAINMENU) { | ||
203 | // No scrolling on the main menu if disabled (to not break themes with lockscreens) | ||
204 | continue; | ||
205 | } | ||
200 | 206 | ||
201 | s->start_tick = current_tick; | 207 | s->start_tick = current_tick; |
202 | 208 | ||
diff --git a/firmware/drivers/ramdisk.c b/firmware/drivers/ramdisk.c index 9f73b6b5c3..5798de252e 100644 --- a/firmware/drivers/ramdisk.c +++ b/firmware/drivers/ramdisk.c | |||
@@ -22,9 +22,10 @@ | |||
22 | #include <stdbool.h> | 22 | #include <stdbool.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | 24 | ||
25 | #include "config.h" | ||
26 | #include "fs_defines.h" | ||
25 | #include "storage.h" | 27 | #include "storage.h" |
26 | 28 | ||
27 | #define SECTOR_SIZE 512 | ||
28 | #define NUM_SECTORS 16384 | 29 | #define NUM_SECTORS 16384 |
29 | 30 | ||
30 | static unsigned char ramdisk[SECTOR_SIZE * NUM_SECTORS]; | 31 | static unsigned char ramdisk[SECTOR_SIZE * NUM_SECTORS]; |
@@ -32,7 +33,7 @@ static unsigned char ramdisk[SECTOR_SIZE * NUM_SECTORS]; | |||
32 | static long last_disk_activity = -1; | 33 | static long last_disk_activity = -1; |
33 | 34 | ||
34 | int ramdisk_read_sectors(IF_MD(int drive,) | 35 | int ramdisk_read_sectors(IF_MD(int drive,) |
35 | unsigned long start, | 36 | sector_t start, |
36 | int count, | 37 | int count, |
37 | void* buf) | 38 | void* buf) |
38 | { | 39 | { |
@@ -48,7 +49,7 @@ int ramdisk_read_sectors(IF_MD(int drive,) | |||
48 | } | 49 | } |
49 | 50 | ||
50 | int ramdisk_write_sectors(IF_MD(int drive,) | 51 | int ramdisk_write_sectors(IF_MD(int drive,) |
51 | unsigned long start, | 52 | sector_t start, |
52 | int count, | 53 | int count, |
53 | const void* buf) | 54 | const void* buf) |
54 | { | 55 | { |
@@ -134,7 +135,7 @@ int ramdisk_num_drives(int first_drive) | |||
134 | { | 135 | { |
135 | /* We don't care which logical drive number(s) we have been assigned */ | 136 | /* We don't care which logical drive number(s) we have been assigned */ |
136 | (void)first_drive; | 137 | (void)first_drive; |
137 | 138 | ||
138 | return 1; | 139 | return 1; |
139 | } | 140 | } |
140 | #endif | 141 | #endif |
diff --git a/firmware/drivers/rtc/rtc_pcf50606.c b/firmware/drivers/rtc/rtc_pcf50606.c index 16ae5a3e9c..8f5371635c 100644 --- a/firmware/drivers/rtc/rtc_pcf50606.c +++ b/firmware/drivers/rtc/rtc_pcf50606.c | |||
@@ -57,7 +57,7 @@ int rtc_read_datetime(struct tm *tm) | |||
57 | tm->tm_mday = buf[4]; | 57 | tm->tm_mday = buf[4]; |
58 | tm->tm_mon = buf[5] - 1; | 58 | tm->tm_mon = buf[5] - 1; |
59 | 59 | ||
60 | #ifdef IRIVER_H300_SERIES | 60 | #ifdef IRIVER_H300_SERIES |
61 | /* Special kludge to coexist with the iriver firmware. The iriver firmware | 61 | /* Special kludge to coexist with the iriver firmware. The iriver firmware |
62 | stores the date as 1965+nn, and allows a range of 1980..2064. We use | 62 | stores the date as 1965+nn, and allows a range of 1980..2064. We use |
63 | 1964+nn here to make leap years work correctly, so the date will be one | 63 | 1964+nn here to make leap years work correctly, so the date will be one |
@@ -158,7 +158,7 @@ bool rtc_check_alarm_started(bool release_alarm) | |||
158 | 158 | ||
159 | if (run_before) { | 159 | if (run_before) { |
160 | rc = alarm_state; | 160 | rc = alarm_state; |
161 | alarm_state &= ~release_alarm; | 161 | alarm_state &= !release_alarm; |
162 | } else { | 162 | } else { |
163 | char rt[3], at[3]; | 163 | char rt[3], at[3]; |
164 | /* The Ipod bootloader seems to read (and thus clear) the PCF interrupt | 164 | /* The Ipod bootloader seems to read (and thus clear) the PCF interrupt |
diff --git a/firmware/drivers/sd.c b/firmware/drivers/sd.c index 6185d5382d..ca83498087 100644 --- a/firmware/drivers/sd.c +++ b/firmware/drivers/sd.c | |||
@@ -49,6 +49,13 @@ void sd_parse_csd(tCardInfo *card) | |||
49 | c_size = card_extract_bits(card->csd, 69, 22) + 1; | 49 | c_size = card_extract_bits(card->csd, 69, 22) + 1; |
50 | card->numblocks = c_size << 10; | 50 | card->numblocks = c_size << 10; |
51 | } | 51 | } |
52 | else if(csd_version == 2) | ||
53 | { | ||
54 | /* CSD version 3.0 */ | ||
55 | c_size = card_extract_bits(card->csd, 75, 28) + 1; | ||
56 | card->numblocks = c_size << 10; | ||
57 | } | ||
58 | card->sd2plus = csd_version >= 1; | ||
52 | 59 | ||
53 | card->blocksize = 512; /* Always use 512 byte blocks */ | 60 | card->blocksize = 512; /* Always use 512 byte blocks */ |
54 | 61 | ||
@@ -62,7 +69,9 @@ void sd_parse_csd(tCardInfo *card) | |||
62 | 69 | ||
63 | card->r2w_factor = card_extract_bits(card->csd, 28, 3); | 70 | card->r2w_factor = card_extract_bits(card->csd, 28, 3); |
64 | 71 | ||
65 | logf("CSD%d.0 numblocks:%ld speed:%ld", csd_version+1, card->numblocks, card->speed); | 72 | |
73 | |||
74 | logf("CSD%d.0 numblocks:%lld speed:%ld", csd_version+1, card->numblocks, card->speed); | ||
66 | logf("nsac: %d taac: %ld r2w: %d", card->nsac, card->taac, card->r2w_factor); | 75 | logf("nsac: %d taac: %ld r2w: %d", card->nsac, card->taac, card->r2w_factor); |
67 | } | 76 | } |
68 | 77 | ||
@@ -99,4 +108,3 @@ void sd_get_info(IF_MD(int drive,) struct storage_info *info) | |||
99 | info->revision="0.00"; | 108 | info->revision="0.00"; |
100 | } | 109 | } |
101 | #endif | 110 | #endif |
102 | |||
diff --git a/firmware/drivers/tuner/rda5802.c b/firmware/drivers/tuner/rda5802.c index 377bdd1e6f..55e775e985 100644 --- a/firmware/drivers/tuner/rda5802.c +++ b/firmware/drivers/tuner/rda5802.c | |||
@@ -42,17 +42,17 @@ | |||
42 | #define RSSI_MAX 70 | 42 | #define RSSI_MAX 70 |
43 | 43 | ||
44 | /** Registers and bits **/ | 44 | /** Registers and bits **/ |
45 | #define CHIPID 0x0 | ||
45 | #define POWERCFG 0x2 | 46 | #define POWERCFG 0x2 |
46 | #define CHANNEL 0x3 | 47 | #define CHANNEL 0x3 |
47 | #define SYSCONFIG1 0x4 | 48 | #define SYSCONFIG1 0x4 |
48 | #define SYSCONFIG2 0x5 | 49 | #define SYSCONFIG2 0x5 |
49 | #define SYSCONFIG3 0x6 | 50 | #define SYSCONFIG3 0x6 |
50 | #define SYSCONFIG4 0x7 /* undocumented */ | 51 | #define SYSCONFIG4 0x7 |
51 | #define SYSCONFIG5 0x8 /* undocumented */ | 52 | #define SYSCONFIG5 0x8 |
52 | #define SYSCONFIG6 0x9 /* undocumented */ | 53 | #define SYSCONFIG6 0x9 /* suspected not to exists */ |
53 | #define READCHAN 0xA | 54 | #define READCHAN 0xA |
54 | #define STATUSRSSI 0xB | 55 | #define STATUSRSSI 0xB |
55 | #define IDENT 0xC | ||
56 | 56 | ||
57 | 57 | ||
58 | /* POWERCFG (0x2) */ | 58 | /* POWERCFG (0x2) */ |
@@ -81,7 +81,7 @@ | |||
81 | 81 | ||
82 | /* SYSCONFIG1 (0x4) */ | 82 | /* SYSCONFIG1 (0x4) */ |
83 | #define SYSCONFIG1_DE (0x1 << 11) | 83 | #define SYSCONFIG1_DE (0x1 << 11) |
84 | #define SYSCONFIG1_SOFTMUTE_EN (0x1 << 9) | 84 | #define SYSCONFIG1_SOFTMUTE_EN (0x1 << 9) |
85 | 85 | ||
86 | /* SYSCONFIG2 (0x5) */ | 86 | /* SYSCONFIG2 (0x5) */ |
87 | #define SYSCONFIG2_VOLUME (0xF << 0) | 87 | #define SYSCONFIG2_VOLUME (0xF << 0) |
@@ -105,9 +105,9 @@ static uint16_t cache[16] = { | |||
105 | [SYSCONFIG1] = 0x0200, /* SYSCONFIG1_SOFTMUTE_EN */ | 105 | [SYSCONFIG1] = 0x0200, /* SYSCONFIG1_SOFTMUTE_EN */ |
106 | [SYSCONFIG2] = 0x867F, /* INT_MODE (def), SEEKTH=1100b, LNA_PORT_SEL=LNAN, | 106 | [SYSCONFIG2] = 0x867F, /* INT_MODE (def), SEEKTH=1100b, LNA_PORT_SEL=LNAN, |
107 | LNA_ICSEL=3.0mA, VOLUME=max */ | 107 | LNA_ICSEL=3.0mA, VOLUME=max */ |
108 | [SYSCONFIG3] = 0x8000, /* I2S slave mode */ | 108 | [SYSCONFIG3] = 0x8000, /* RSVD */ |
109 | [SYSCONFIG4] = 0x4712, /* undocumented, affects stereo blend */ | 109 | [SYSCONFIG4] = 0x4712, /* TH_SOFRBLEND=34dB, 65M_50M MODE=65~76MHz, RSVD, SEEK_TH_OLD=4, SOFTBLEND_EN */ |
110 | [SYSCONFIG5] = 0x5EC6, /* undocumented */ | 110 | [SYSCONFIG5] = 0x5EC6, /* FREQ_DIRECT=24262kHz (unused) */ |
111 | [SYSCONFIG6] = 0x0000 /* undocumented */ | 111 | [SYSCONFIG6] = 0x0000 /* undocumented */ |
112 | }; | 112 | }; |
113 | 113 | ||
@@ -190,7 +190,21 @@ static void rda5802_sleep(int snooze) | |||
190 | 190 | ||
191 | bool rda5802_detect(void) | 191 | bool rda5802_detect(void) |
192 | { | 192 | { |
193 | return ((rda5802_read_reg(IDENT) & 0xFF00) == 0x5800); | 193 | /* The RDA5802 has a weird wrap-around at 0x40. Upon initialisation, it will copy the Chip ID |
194 | * to register 0xC but since this register is also used for RDS, we cannot rely on its content | ||
195 | * until we softreset. But we cannot soft-reset until we confirm the tuner type... So we really | ||
196 | * need to register 0, which means reading 0x40 registers. | ||
197 | * NOTE: the datasheet says that it wraps around at 0x3A but this is wrong. */ | ||
198 | |||
199 | /* we want to read registers 0x00/0x01, aka 0x40/0x41 because of wrapping, tuner starts reading | ||
200 | * at 0xA so we need to read 0x40 - 0xA + 2 registers, each register is two bytes. Thats | ||
201 | * (0x40 - 0xA + 2) * 2 = 0x6e bytes */ | ||
202 | unsigned char buf[0x70]; | ||
203 | fmradio_i2c_read(I2C_ADR, buf, sizeof(buf)); | ||
204 | cache[CHIPID] = buf[0x6c] << 8 | buf[0x6d]; | ||
205 | cache[1] = buf[0x6e] << 8 | buf[0x6f]; /* unknown register, maybe firmware ID or related */ | ||
206 | |||
207 | return ((cache[CHIPID] & 0xFF00) == 0x5800); | ||
194 | } | 208 | } |
195 | 209 | ||
196 | void rda5802_init(void) | 210 | void rda5802_init(void) |