summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/lang/english.lang6
-rw-r--r--firmware/drivers/ata.c152
-rw-r--r--firmware/drivers/audio/cs42l55.c46
-rw-r--r--firmware/export/cs42l55.h5
-rw-r--r--firmware/sound.c4
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 @@
79static unsigned int ata_thread_id = 0; 82static unsigned int ata_thread_id = 0;
80#endif 83#endif
81 84
85#ifdef ATA_HAVE_BBT
86uint16_t ata_bbt[ATA_BBT_PAGES][0x20];
87uint64_t virtual_sectors;
88uint32_t ata_last_offset;
89uint64_t ata_last_phys;
90int ata_rw_sectors_internal(unsigned long sector, int count, void* buffer, int write);
91int ata_rw_chunk(unsigned long sector, int count, void* buffer, int write);
92
93void 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? */
84struct ata_lock 104struct 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
359char* 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
414int 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
455int 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
41static int bass, treble; 43static 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
162static 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
160void audiohw_set_bass(int value) 176void 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
170void audiohw_set_treble(int value) 185void 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
194void audiohw_set_bass_cutoff(int value)
195{
196 cscodec_setbits(BTCTL, BTCTL_BASSCF_MASK,
197 (value - 1) << BTCTL_BASSCF_SHIFT);
198}
199
200void audiohw_set_treble_cutoff(int value)
201{
202 cscodec_setbits(BTCTL, BTCTL_TREBCF_MASK,
203 (value - 1) << BTCTL_TREBCF_SHIFT);
204}
205
206void 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
31extern int tenthdb2master(int db); 32extern 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;