diff options
-rw-r--r-- | apps/lang/english.lang | 6 | ||||
-rw-r--r-- | firmware/drivers/ata.c | 152 | ||||
-rw-r--r-- | firmware/drivers/audio/cs42l55.c | 46 | ||||
-rw-r--r-- | firmware/export/cs42l55.h | 5 | ||||
-rw-r--r-- | firmware/sound.c | 4 |
5 files changed, 204 insertions, 9 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 0fad5bf5b0..c39face719 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -10517,14 +10517,17 @@ | |||
10517 | <source> | 10517 | <source> |
10518 | *: none | 10518 | *: none |
10519 | ipodvideo: "Bass Cutoff" | 10519 | ipodvideo: "Bass Cutoff" |
10520 | ipod6g: "Bass Cutoff" | ||
10520 | </source> | 10521 | </source> |
10521 | <dest> | 10522 | <dest> |
10522 | *: none | 10523 | *: none |
10523 | ipodvideo: "Bass Cutoff" | 10524 | ipodvideo: "Bass Cutoff" |
10525 | ipod6g: "Bass Cutoff" | ||
10524 | </dest> | 10526 | </dest> |
10525 | <voice> | 10527 | <voice> |
10526 | *: none | 10528 | *: none |
10527 | ipodvideo: "Bass Cutoff" | 10529 | ipodvideo: "Bass Cutoff" |
10530 | ipod6g: "Bass Cutoff" | ||
10528 | </voice> | 10531 | </voice> |
10529 | </phrase> | 10532 | </phrase> |
10530 | <phrase> | 10533 | <phrase> |
@@ -10534,14 +10537,17 @@ | |||
10534 | <source> | 10537 | <source> |
10535 | *: none | 10538 | *: none |
10536 | ipodvideo: "Treble Cutoff" | 10539 | ipodvideo: "Treble Cutoff" |
10540 | ipod6g: "Treble Cutoff" | ||
10537 | </source> | 10541 | </source> |
10538 | <dest> | 10542 | <dest> |
10539 | *: none | 10543 | *: none |
10540 | ipodvideo: "Treble Cutoff" | 10544 | ipodvideo: "Treble Cutoff" |
10545 | ipod6g: "Treble Cutoff" | ||
10541 | </dest> | 10546 | </dest> |
10542 | <voice> | 10547 | <voice> |
10543 | *: none | 10548 | *: none |
10544 | ipodvideo: "Treble Cutoff" | 10549 | ipodvideo: "Treble Cutoff" |
10550 | ipod6g: "Treble Cutoff" | ||
10545 | </voice> | 10551 | </voice> |
10546 | </phrase> | 10552 | </phrase> |
10547 | <phrase> | 10553 | <phrase> |
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index 77cd89f13f..08aee5dc0b 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #include "ata-defines.h" | 36 | #include "ata-defines.h" |
37 | #include "storage.h" | 37 | #include "storage.h" |
38 | 38 | ||
39 | #define ATA_HAVE_BBT | ||
40 | #define ATA_BBT_PAGES 2304 | ||
41 | |||
39 | #define SECTOR_SIZE 512 | 42 | #define SECTOR_SIZE 512 |
40 | 43 | ||
41 | #define SELECT_DEVICE1 0x10 | 44 | #define SELECT_DEVICE1 0x10 |
@@ -79,6 +82,23 @@ | |||
79 | static unsigned int ata_thread_id = 0; | 82 | static unsigned int ata_thread_id = 0; |
80 | #endif | 83 | #endif |
81 | 84 | ||
85 | #ifdef ATA_HAVE_BBT | ||
86 | uint16_t ata_bbt[ATA_BBT_PAGES][0x20]; | ||
87 | uint64_t virtual_sectors; | ||
88 | uint32_t ata_last_offset; | ||
89 | uint64_t ata_last_phys; | ||
90 | int ata_rw_sectors_internal(unsigned long sector, int count, void* buffer, int write); | ||
91 | int ata_rw_chunk(unsigned long sector, int count, void* buffer, int write); | ||
92 | |||
93 | void ata_bbt_read_sectors(uint32_t sector, int count, void* buffer) | ||
94 | { | ||
95 | int rc = ata_rw_sectors_internal(sector * 8, count * 8, buffer, 0); | ||
96 | if (rc < 0) | ||
97 | panicf("ATA: Error %d while reading BBT (sector %u, count %d)", | ||
98 | rc, (unsigned)sector, count); | ||
99 | } | ||
100 | #endif | ||
101 | |||
82 | #if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64 | 102 | #if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64 |
83 | /* Hack - what's the deal with 5g? */ | 103 | /* Hack - what's the deal with 5g? */ |
84 | struct ata_lock | 104 | struct ata_lock |
@@ -335,6 +355,109 @@ static int ata_transfer_sectors(unsigned long start, | |||
335 | void* inbuf, | 355 | void* inbuf, |
336 | int write) | 356 | int write) |
337 | { | 357 | { |
358 | #ifdef ATA_HAVE_BBT | ||
359 | char* orig = (char*)inbuf; | ||
360 | int realcount = incount; | ||
361 | incount = (incount + 7) / 8; | ||
362 | unsigned long startoffs = start & 7; | ||
363 | start /= 8; | ||
364 | if (start + incount > (unsigned)(virtual_sectors / 8)) return -9; | ||
365 | while (realcount) | ||
366 | { | ||
367 | uint32_t offset; | ||
368 | uint32_t l0idx = start >> 15; | ||
369 | uint32_t l0offs = start & 0x7fff; | ||
370 | uint32_t cnt = MIN((unsigned)incount, 0x8000 - l0offs); | ||
371 | uint32_t l0data = ata_bbt[0][l0idx << 1]; | ||
372 | uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12; | ||
373 | if (l0data < 0x8000) offset = l0data + base; | ||
374 | else | ||
375 | { | ||
376 | uint32_t l1idx = (start >> 10) & 0x1f; | ||
377 | uint32_t l1offs = start & 0x3ff; | ||
378 | cnt = MIN((unsigned)incount, 0x400 - l1offs); | ||
379 | uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx]; | ||
380 | if (l1data < 0x8000) offset = l1data + base; | ||
381 | else | ||
382 | { | ||
383 | uint32_t l2idx = (start >> 5) & 0x1f; | ||
384 | uint32_t l2offs = start & 0x1f; | ||
385 | cnt = MIN((unsigned)incount, 0x20 - l2offs); | ||
386 | uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx]; | ||
387 | if (l2data < 0x8000) offset = l2data + base; | ||
388 | else | ||
389 | { | ||
390 | uint32_t l3idx = start & 0x1f; | ||
391 | uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx]; | ||
392 | for (cnt = 1; cnt < (unsigned)incount && l3idx + cnt < 0x20; cnt++) | ||
393 | if (ata_bbt[l2data & 0x7fff][l3idx + cnt] != l3data) | ||
394 | break; | ||
395 | offset = l3data + base; | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | uint64_t phys = start + offset; | ||
400 | if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset(); | ||
401 | ata_last_offset = offset; | ||
402 | ata_last_phys = phys + cnt; | ||
403 | cnt = MIN(cnt * 8, (unsigned)realcount); | ||
404 | int rc = ata_rw_sectors_internal(phys * 8 + startoffs, cnt, inbuf, write); | ||
405 | if (rc < 0) return rc; | ||
406 | inbuf += cnt * SECTOR_SIZE; | ||
407 | start += cnt / 8; | ||
408 | incount -= cnt / 8; | ||
409 | realcount -= cnt; | ||
410 | } | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | int ata_rw_sectors_internal(unsigned long start, | ||
415 | int incount, | ||
416 | void* inbuf, | ||
417 | int write) | ||
418 | { | ||
419 | if (start + incount > total_sectors) return -9; | ||
420 | while (incount) | ||
421 | { | ||
422 | uint32_t cnt = MIN(lba48 ? 65536 : 256, incount); | ||
423 | int rc = -1; | ||
424 | int tries = 3; | ||
425 | while (tries-- && rc < 0) | ||
426 | { | ||
427 | rc = ata_rw_chunk(start, cnt, inbuf, write); | ||
428 | if (rc < 0) ata_soft_reset(); | ||
429 | } | ||
430 | if (rc < 0) | ||
431 | { | ||
432 | void* buf = inbuf; | ||
433 | unsigned long sect; | ||
434 | for (sect = start; sect < start + cnt; sect++) | ||
435 | { | ||
436 | rc = -1; | ||
437 | tries = 3; | ||
438 | while (tries-- && rc < 0) | ||
439 | { | ||
440 | rc = ata_rw_chunk(sect, 1, buf, write); | ||
441 | if (rc < 0) ata_soft_reset(); | ||
442 | } | ||
443 | if (rc < 0) break; | ||
444 | inbuf += SECTOR_SIZE; | ||
445 | } | ||
446 | } | ||
447 | if (rc < 0) return rc; | ||
448 | inbuf += SECTOR_SIZE * cnt; | ||
449 | start += cnt; | ||
450 | incount -= cnt; | ||
451 | } | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | int ata_rw_chunk(unsigned long start, | ||
456 | int incount, | ||
457 | void* inbuf, | ||
458 | int write) | ||
459 | { | ||
460 | #endif | ||
338 | int ret = 0; | 461 | int ret = 0; |
339 | long timeout; | 462 | long timeout; |
340 | int count; | 463 | int count; |
@@ -1389,6 +1512,31 @@ int ata_init(void) | |||
1389 | 1512 | ||
1390 | mutex_lock(&ata_mtx); /* Balance unlock below */ | 1513 | mutex_lock(&ata_mtx); /* Balance unlock below */ |
1391 | 1514 | ||
1515 | #ifdef ATA_HAVE_BBT | ||
1516 | memset(ata_bbt, 0, sizeof(ata_bbt)); | ||
1517 | uint32_t* buf = (uint32_t*)(ata_bbt[ARRAYLEN(ata_bbt) - 64]); | ||
1518 | ata_bbt_read_sectors(0, 1, buf); | ||
1519 | if (!memcmp(buf, "emBIbbth", 8)) | ||
1520 | { | ||
1521 | virtual_sectors = ((((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc]) * 8; | ||
1522 | uint32_t count = buf[0x1ff]; | ||
1523 | if (count > (ATA_BBT_PAGES >> 6)) | ||
1524 | panicf("ATA: BBT too big! (%d pages, limit: %d)", | ||
1525 | (unsigned)(count << 6), ATA_BBT_PAGES); | ||
1526 | uint32_t i; | ||
1527 | uint32_t cnt; | ||
1528 | for (i = 0; i < count; i += cnt) | ||
1529 | { | ||
1530 | uint32_t phys = buf[0x200 + i]; | ||
1531 | for (cnt = 1; cnt < count; cnt++) | ||
1532 | if (buf[0x200 + i + cnt] != phys + cnt) | ||
1533 | break; | ||
1534 | ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]); | ||
1535 | } | ||
1536 | } | ||
1537 | else virtual_sectors = total_sectors; | ||
1538 | #endif | ||
1539 | |||
1392 | last_disk_activity = current_tick; | 1540 | last_disk_activity = current_tick; |
1393 | #ifdef ATA_DRIVER_CLOSE | 1541 | #ifdef ATA_DRIVER_CLOSE |
1394 | ata_thread_id = | 1542 | ata_thread_id = |
@@ -1456,7 +1604,11 @@ void ata_get_info(IF_MD2(int drive,)struct storage_info *info) | |||
1456 | #endif | 1604 | #endif |
1457 | int i; | 1605 | int i; |
1458 | info->sector_size = SECTOR_SIZE; | 1606 | info->sector_size = SECTOR_SIZE; |
1607 | #ifdef ATA_HAVE_BBT | ||
1608 | info->num_sectors = virtual_sectors; | ||
1609 | #else | ||
1459 | info->num_sectors = total_sectors; | 1610 | info->num_sectors = total_sectors; |
1611 | #endif | ||
1460 | 1612 | ||
1461 | src = (unsigned short*)&identify_info[27]; | 1613 | src = (unsigned short*)&identify_info[27]; |
1462 | dest = (unsigned short*)vendor; | 1614 | dest = (unsigned short*)vendor; |
diff --git a/firmware/drivers/audio/cs42l55.c b/firmware/drivers/audio/cs42l55.c index 79b6d283b6..5541a26ee0 100644 --- a/firmware/drivers/audio/cs42l55.c +++ b/firmware/drivers/audio/cs42l55.c | |||
@@ -36,6 +36,8 @@ const struct sound_settings_info audiohw_settings[] = { | |||
36 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, | 36 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, |
37 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, | 37 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, |
38 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, | 38 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, |
39 | [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 2}, | ||
40 | [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1}, | ||
39 | }; | 41 | }; |
40 | 42 | ||
41 | static int bass, treble; | 43 | static int bass, treble; |
@@ -157,24 +159,56 @@ void audiohw_enable_lineout(bool enable) | |||
157 | PWRCTL2_PDN_LINA_ALWAYS | PWRCTL2_PDN_LINB_ALWAYS); | 159 | PWRCTL2_PDN_LINA_ALWAYS | PWRCTL2_PDN_LINB_ALWAYS); |
158 | } | 160 | } |
159 | 161 | ||
162 | static void handle_dsp_power() | ||
163 | { | ||
164 | if (bass || treble) | ||
165 | { | ||
166 | cscodec_setbits(PLAYCTL, PLAYCTL_PDN_DSP, 0); | ||
167 | cscodec_setbits(BTCTL, 0, BTCTL_TCEN); | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | cscodec_setbits(BTCTL, BTCTL_TCEN, 0); | ||
172 | cscodec_setbits(PLAYCTL, 0, PLAYCTL_PDN_DSP); | ||
173 | } | ||
174 | } | ||
175 | |||
160 | void audiohw_set_bass(int value) | 176 | void audiohw_set_bass(int value) |
161 | { | 177 | { |
162 | bass = value; | 178 | bass = value; |
163 | if (bass || treble) cscodec_setbits(PLAYCTL, PLAYCTL_PDN_DSP, 0); | 179 | handle_dsp_power(); |
164 | else cscodec_setbits(PLAYCTL, 0, PLAYCTL_PDN_DSP); | ||
165 | if (value >= -105 && value <= 120) | 180 | if (value >= -105 && value <= 120) |
166 | cscodec_setbits(TONECTL, TONECTL_BASS_MASK, | 181 | cscodec_setbits(TONECTL, TONECTL_BASS_MASK, |
167 | (value / 15) << TONECTL_BASS_SHIFT); | 182 | (8 - value / 15) << TONECTL_BASS_SHIFT); |
168 | } | 183 | } |
169 | 184 | ||
170 | void audiohw_set_treble(int value) | 185 | void audiohw_set_treble(int value) |
171 | { | 186 | { |
172 | treble = value; | 187 | treble = value; |
173 | if (bass || treble) cscodec_setbits(PLAYCTL, PLAYCTL_PDN_DSP, 0); | 188 | handle_dsp_power(); |
174 | else cscodec_setbits(PLAYCTL, 0, PLAYCTL_PDN_DSP); | ||
175 | if (value >= -105 && value <= 120) | 189 | if (value >= -105 && value <= 120) |
176 | cscodec_setbits(TONECTL, TONECTL_TREB_MASK, | 190 | cscodec_setbits(TONECTL, TONECTL_TREB_MASK, |
177 | (value / 15) << TONECTL_TREB_SHIFT); | 191 | (8 - value / 15) << TONECTL_TREB_SHIFT); |
192 | } | ||
193 | |||
194 | void audiohw_set_bass_cutoff(int value) | ||
195 | { | ||
196 | cscodec_setbits(BTCTL, BTCTL_BASSCF_MASK, | ||
197 | (value - 1) << BTCTL_BASSCF_SHIFT); | ||
198 | } | ||
199 | |||
200 | void audiohw_set_treble_cutoff(int value) | ||
201 | { | ||
202 | cscodec_setbits(BTCTL, BTCTL_TREBCF_MASK, | ||
203 | (value - 1) << BTCTL_TREBCF_SHIFT); | ||
204 | } | ||
205 | |||
206 | void audiohw_set_prescaler(int value) | ||
207 | { | ||
208 | cscodec_setbits(MSTAVOL, MSTAVOL_VOLUME_MASK, | ||
209 | (-value / 5) << MSTAVOL_VOLUME_SHIFT); | ||
210 | cscodec_setbits(MSTBVOL, MSTBVOL_VOLUME_MASK, | ||
211 | (-value / 5) << MSTBVOL_VOLUME_SHIFT); | ||
178 | } | 212 | } |
179 | 213 | ||
180 | /* Nice shutdown of CS42L55 codec */ | 214 | /* Nice shutdown of CS42L55 codec */ |
diff --git a/firmware/export/cs42l55.h b/firmware/export/cs42l55.h index 8a6640f7c2..86b54ef272 100644 --- a/firmware/export/cs42l55.h +++ b/firmware/export/cs42l55.h | |||
@@ -26,7 +26,8 @@ | |||
26 | #define VOLUME_MIN -580 | 26 | #define VOLUME_MIN -580 |
27 | #define VOLUME_MAX 120 | 27 | #define VOLUME_MAX 120 |
28 | 28 | ||
29 | #define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP) | 29 | #define AUDIOHW_CAPS (BASS_CAP | TREBLE_CAP | BASS_CUTOFF_CAP \ |
30 | | TREBLE_CUTOFF_CAP | PRESCALER_CAP) | ||
30 | 31 | ||
31 | extern int tenthdb2master(int db); | 32 | extern int tenthdb2master(int db); |
32 | 33 | ||
@@ -269,11 +270,13 @@ extern void audiohw_enable_lineout(bool enable); | |||
269 | #define BTCTL 0x16 | 270 | #define BTCTL 0x16 |
270 | #define BTCTL_TCEN (1 << 0) | 271 | #define BTCTL_TCEN (1 << 0) |
271 | #define BTCTL_BASSCF_MASK (3 << 1) | 272 | #define BTCTL_BASSCF_MASK (3 << 1) |
273 | #define BTCTL_BASSCF_SHIFT 1 | ||
272 | #define BTCTL_BASSCF_50 (0 << 1) | 274 | #define BTCTL_BASSCF_50 (0 << 1) |
273 | #define BTCTL_BASSCF_100 (1 << 1) | 275 | #define BTCTL_BASSCF_100 (1 << 1) |
274 | #define BTCTL_BASSCF_200 (2 << 1) | 276 | #define BTCTL_BASSCF_200 (2 << 1) |
275 | #define BTCTL_BASSCF_250 (3 << 1) | 277 | #define BTCTL_BASSCF_250 (3 << 1) |
276 | #define BTCTL_TREBCF_MASK (3 << 3) | 278 | #define BTCTL_TREBCF_MASK (3 << 3) |
279 | #define BTCTL_TREBCF_SHIFT 3 | ||
277 | #define BTCTL_TREBCF_5000 (0 << 3) | 280 | #define BTCTL_TREBCF_5000 (0 << 3) |
278 | #define BTCTL_TREBCF_7000 (1 << 3) | 281 | #define BTCTL_TREBCF_7000 (1 << 3) |
279 | #define BTCTL_TREBCF_10000 (2 << 3) | 282 | #define BTCTL_TREBCF_10000 (2 << 3) |
diff --git a/firmware/sound.c b/firmware/sound.c index 0eec4f8b5c..de96360198 100644 --- a/firmware/sound.c +++ b/firmware/sound.c | |||
@@ -308,7 +308,7 @@ void sound_set_bass(int value) | |||
308 | return; | 308 | return; |
309 | 309 | ||
310 | #if !defined(AUDIOHW_HAVE_CLIPPING) | 310 | #if !defined(AUDIOHW_HAVE_CLIPPING) |
311 | #if defined(HAVE_WM8750) || defined(HAVE_WM8751) | 311 | #if defined(HAVE_WM8750) || defined(HAVE_WM8751) || defined(HAVE_CS42L55) |
312 | current_bass = value; | 312 | current_bass = value; |
313 | #else | 313 | #else |
314 | current_bass = value * 10; | 314 | current_bass = value * 10; |
@@ -334,7 +334,7 @@ void sound_set_treble(int value) | |||
334 | return; | 334 | return; |
335 | 335 | ||
336 | #if !defined(AUDIOHW_HAVE_CLIPPING) | 336 | #if !defined(AUDIOHW_HAVE_CLIPPING) |
337 | #if defined(HAVE_WM8750) || defined(HAVE_WM8751) | 337 | #if defined(HAVE_WM8750) || defined(HAVE_WM8751) || defined(HAVE_CS42L55) |
338 | current_treble = value; | 338 | current_treble = value; |
339 | #else | 339 | #else |
340 | current_treble = value * 10; | 340 | current_treble = value * 10; |