diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 4 | ||||
-rw-r--r-- | firmware/drivers/audio/wm8978.c | 60 | ||||
-rw-r--r-- | firmware/export/audiohw.h | 13 | ||||
-rw-r--r-- | firmware/export/config-gigabeat-s.h | 6 | ||||
-rwxr-xr-x | firmware/export/imx31l.h | 108 | ||||
-rw-r--r-- | firmware/export/wm8978.h | 17 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c | 313 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h | 56 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | 2 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c | 25 |
10 files changed, 571 insertions, 33 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 879800ec96..5083357732 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -210,7 +210,9 @@ drivers/mas.c | |||
210 | drivers/audio/uda1380.c | 210 | drivers/audio/uda1380.c |
211 | #elif defined(HAVE_WM8751) | 211 | #elif defined(HAVE_WM8751) |
212 | drivers/audio/wm8751.c | 212 | drivers/audio/wm8751.c |
213 | #elif defined(HAVE_WM8975) || defined(HAVE_WM8978) | 213 | #elif defined(HAVE_WM8978) |
214 | drivers/audio/wm8978.c | ||
215 | #elif defined(HAVE_WM8975) | ||
214 | drivers/audio/wm8975.c | 216 | drivers/audio/wm8975.c |
215 | #elif defined(HAVE_WM8985) | 217 | #elif defined(HAVE_WM8985) |
216 | drivers/audio/wm8985.c | 218 | drivers/audio/wm8985.c |
diff --git a/firmware/drivers/audio/wm8978.c b/firmware/drivers/audio/wm8978.c new file mode 100644 index 0000000000..01f3d331bb --- /dev/null +++ b/firmware/drivers/audio/wm8978.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 by Michael Sevakis | ||
11 | * | ||
12 | * Driver for WM8978 audio codec | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
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 "system.h" | ||
23 | #include "audiohw.h" | ||
24 | #include "wmcodec.h" | ||
25 | #include "audio.h" | ||
26 | |||
27 | const struct sound_settings_info audiohw_settings[] = { | ||
28 | [SOUND_VOLUME] = {"dB", 0, 1, -58, 6, -25}, | ||
29 | [SOUND_BASS] = {"dB", 0, 1, -12, 12, 0}, | ||
30 | [SOUND_TREBLE] = {"dB", 0, 1, -12, 12, 0}, | ||
31 | [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0}, | ||
32 | [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0}, | ||
33 | [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100}, | ||
34 | [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0}, | ||
35 | [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0}, | ||
36 | [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16}, | ||
37 | #if 0 | ||
38 | [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1}, | ||
39 | [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1}, | ||
40 | #endif | ||
41 | }; | ||
42 | |||
43 | void audiohw_preinit(void) | ||
44 | { | ||
45 | wmcodec_write(WM8978_SOFTWARE_RESET, 0); | ||
46 | } | ||
47 | |||
48 | void audiohw_postinit(void) | ||
49 | { | ||
50 | sleep(HZ); | ||
51 | } | ||
52 | |||
53 | void audiohw_close(void) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | void audiohw_mute(bool mute) | ||
58 | { | ||
59 | (void)mute; | ||
60 | } | ||
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 73c50b8412..190fcca7a8 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h | |||
@@ -27,7 +27,9 @@ | |||
27 | #include "uda1380.h" | 27 | #include "uda1380.h" |
28 | #elif defined(HAVE_WM8751) | 28 | #elif defined(HAVE_WM8751) |
29 | #include "wm8751.h" | 29 | #include "wm8751.h" |
30 | #elif defined(HAVE_WM8975) || defined(HAVE_WM8978) | 30 | #elif defined(HAVE_WM8978) |
31 | #include "wm8978.h" | ||
32 | #elif defined(HAVE_WM8975) | ||
31 | #include "wm8975.h" | 33 | #include "wm8975.h" |
32 | #elif defined(HAVE_WM8985) | 34 | #elif defined(HAVE_WM8985) |
33 | #include "wm8985.h" | 35 | #include "wm8985.h" |
@@ -109,7 +111,14 @@ extern const struct sound_settings_info audiohw_settings[]; | |||
109 | void audiohw_init(void); | 111 | void audiohw_init(void); |
110 | 112 | ||
111 | /** | 113 | /** |
112 | * Do some stuff (codec related) after audiohw_init. | 114 | * Do initial audio codec setup. |
115 | */ | ||
116 | void audiohw_preinit(void); | ||
117 | |||
118 | /** | ||
119 | * Do some stuff (codec related) after audiohw_init that needs to be | ||
120 | * delayed such as enabling outputs to prevent popping. This lets | ||
121 | * other inits in the system complete in the meantime. | ||
113 | */ | 122 | */ |
114 | void audiohw_postinit(void); | 123 | void audiohw_postinit(void); |
115 | 124 | ||
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h index 6eb57b219c..3e36e0c7ea 100644 --- a/firmware/export/config-gigabeat-s.h +++ b/firmware/export/config-gigabeat-s.h | |||
@@ -66,10 +66,9 @@ | |||
66 | /* The number of bytes reserved for loadable plugins */ | 66 | /* The number of bytes reserved for loadable plugins */ |
67 | #define PLUGIN_BUFFER_SIZE 0x80000 | 67 | #define PLUGIN_BUFFER_SIZE 0x80000 |
68 | 68 | ||
69 | /* Define this if you have the WM8975 audio codec */ | 69 | /* Define this if you have the WM8978 audio codec */ |
70 | #define HAVE_WM8978 | 70 | #define HAVE_WM8978 |
71 | 71 | ||
72 | |||
73 | #define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ | 72 | #define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ |
74 | SAMPR_CAP_11) | 73 | SAMPR_CAP_11) |
75 | 74 | ||
@@ -85,8 +84,9 @@ | |||
85 | /* Define this if you want to use coldfire's i2c interface */ | 84 | /* Define this if you want to use coldfire's i2c interface */ |
86 | #define CONFIG_I2C I2C_IMX31L | 85 | #define CONFIG_I2C I2C_IMX31L |
87 | 86 | ||
88 | /* Define the bitmask of serial interface modules (CSPI) used */ | 87 | /* Define the bitmask of modules used */ |
89 | #define SPI_MODULE_MASK (USE_CSPI2_MODULE) | 88 | #define SPI_MODULE_MASK (USE_CSPI2_MODULE) |
89 | #define I2C_MODULE_MASK (USE_I2C1_MODULE) | ||
90 | 90 | ||
91 | /* Define this if target has an additional number of threads specific to it */ | 91 | /* Define this if target has an additional number of threads specific to it */ |
92 | #define TARGET_EXTRA_THREADS 1 | 92 | #define TARGET_EXTRA_THREADS 1 |
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h index aea4b9e151..777fa6981c 100755 --- a/firmware/export/imx31l.h +++ b/firmware/export/imx31l.h | |||
@@ -49,7 +49,7 @@ | |||
49 | #define ETB_SLOT4_BASE_ADDR 0x43F10000 | 49 | #define ETB_SLOT4_BASE_ADDR 0x43F10000 |
50 | #define ETB_SLOT5_BASE_ADDR 0x43F14000 | 50 | #define ETB_SLOT5_BASE_ADDR 0x43F14000 |
51 | #define ECT_CTIO_BASE_ADDR 0x43F18000 | 51 | #define ECT_CTIO_BASE_ADDR 0x43F18000 |
52 | #define I2C_BASE_ADDR 0x43F80000 | 52 | #define I2C1_BASE_ADDR 0x43F80000 |
53 | #define I2C3_BASE_ADDR 0x43F84000 | 53 | #define I2C3_BASE_ADDR 0x43F84000 |
54 | #define OTG_BASE_ADDR 0x43F88000 | 54 | #define OTG_BASE_ADDR 0x43F88000 |
55 | #define ATA_BASE_ADDR 0x43F8C000 | 55 | #define ATA_BASE_ADDR 0x43F8C000 |
@@ -628,6 +628,112 @@ | |||
628 | #define CSPI_TESTREG_SWAP (1 << 15) | 628 | #define CSPI_TESTREG_SWAP (1 << 15) |
629 | #define CSPI_TESTREG_LBC (1 << 14) | 629 | #define CSPI_TESTREG_LBC (1 << 14) |
630 | 630 | ||
631 | /* I2C */ | ||
632 | #define I2C_IADR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x0)) | ||
633 | #define I2C_IFDR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x4)) | ||
634 | #define I2C_I2CR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x8)) | ||
635 | #define I2C_I2SR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0xC)) | ||
636 | #define I2C_I2DR1 (*(REG16_PTR_T)(I2C1_BASE_ADDR+0x10)) | ||
637 | |||
638 | #define I2C_IADR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x0)) | ||
639 | #define I2C_IFDR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x4)) | ||
640 | #define I2C_I2CR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x8)) | ||
641 | #define I2C_I2SR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0xC)) | ||
642 | #define I2C_I2DR2 (*(REG16_PTR_T)(I2C2_BASE_ADDR+0x10)) | ||
643 | |||
644 | #define I2C_IADR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x0)) | ||
645 | #define I2C_IFDR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x4)) | ||
646 | #define I2C_I2CR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x8)) | ||
647 | #define I2C_I2SR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0xC)) | ||
648 | #define I2C_I2DR3 (*(REG16_PTR_T)(I2C3_BASE_ADDR+0x10)) | ||
649 | |||
650 | /* IADR - [7:1] Address */ | ||
651 | |||
652 | /* IFDR */ | ||
653 | #define I2C_IFDR_DIV30 0x00 | ||
654 | #define I2C_IFDR_DIV32 0x01 | ||
655 | #define I2C_IFDR_DIV36 0x02 | ||
656 | #define I2C_IFDR_DIV42 0x03 | ||
657 | #define I2C_IFDR_DIV48 0x04 | ||
658 | #define I2C_IFDR_DIV52 0x05 | ||
659 | #define I2C_IFDR_DIV60 0x06 | ||
660 | #define I2C_IFDR_DIV72 0x07 | ||
661 | #define I2C_IFDR_DIV80 0x08 | ||
662 | #define I2C_IFDR_DIV88 0x09 | ||
663 | #define I2C_IFDR_DIV104 0x0a | ||
664 | #define I2C_IFDR_DIV128 0x0b | ||
665 | #define I2C_IFDR_DIV144 0x0c | ||
666 | #define I2C_IFDR_DIV160 0x0d | ||
667 | #define I2C_IFDR_DIV192 0x0e | ||
668 | #define I2C_IFDR_DIV240 0x0f | ||
669 | #define I2C_IFDR_DIV288 0x10 | ||
670 | #define I2C_IFDR_DIV320 0x11 | ||
671 | #define I2C_IFDR_DIV384 0x12 | ||
672 | #define I2C_IFDR_DIV480 0x13 | ||
673 | #define I2C_IFDR_DIV576 0x14 | ||
674 | #define I2C_IFDR_DIV640 0x15 | ||
675 | #define I2C_IFDR_DIV768 0x16 | ||
676 | #define I2C_IFDR_DIV960 0x17 | ||
677 | #define I2C_IFDR_DIV1152 0x18 | ||
678 | #define I2C_IFDR_DIV1280 0x19 | ||
679 | #define I2C_IFDR_DIV1536 0x1a | ||
680 | #define I2C_IFDR_DIV1920 0x1b | ||
681 | #define I2C_IFDR_DIV2304 0x1c | ||
682 | #define I2C_IFDR_DIV2560 0x1d | ||
683 | #define I2C_IFDR_DIV3072 0x1e | ||
684 | #define I2C_IFDR_DIV3840 0x1f | ||
685 | #define I2C_IFDR_DIV22 0x20 | ||
686 | #define I2C_IFDR_DIV24 0x21 | ||
687 | #define I2C_IFDR_DIV26 0x22 | ||
688 | #define I2C_IFDR_DIV28 0x23 | ||
689 | #define I2C_IFDR_DIV32_2 0x24 | ||
690 | #define I2C_IFDR_DIV36_2 0x25 | ||
691 | #define I2C_IFDR_DIV40 0x26 | ||
692 | #define I2C_IFDR_DIV44 0x27 | ||
693 | #define I2C_IFDR_DIV48_2 0x28 | ||
694 | #define I2C_IFDR_DIV56 0x29 | ||
695 | #define I2C_IFDR_DIV64 0x2a | ||
696 | #define I2C_IFDR_DIV72_2 0x2b | ||
697 | #define I2C_IFDR_DIV80_2 0x2c | ||
698 | #define I2C_IFDR_DIV96 0x2d | ||
699 | #define I2C_IFDR_DIV112 0x2e | ||
700 | #define I2C_IFDR_DIV128_2 0x2f | ||
701 | #define I2C_IFDR_DIV160_2 0x30 | ||
702 | #define I2C_IFDR_DIV192_2 0x31 | ||
703 | #define I2C_IFDR_DIV224 0x32 | ||
704 | #define I2C_IFDR_DIV256 0x33 | ||
705 | #define I2C_IFDR_DIV320_2 0x34 | ||
706 | #define I2C_IFDR_DIV384_2 0x35 | ||
707 | #define I2C_IFDR_DIV448 0x36 | ||
708 | #define I2C_IFDR_DIV512 0x37 | ||
709 | #define I2C_IFDR_DIV640_2 0x38 | ||
710 | #define I2C_IFDR_DIV768_2 0x39 | ||
711 | #define I2C_IFDR_DIV896 0x3a | ||
712 | #define I2C_IFDR_DIV1024 0x3b | ||
713 | #define I2C_IFDR_DIV1280_2 0x3c | ||
714 | #define I2C_IFDR_DIV1536_2 0x3d | ||
715 | #define I2C_IFDR_DIV1792 0x3e | ||
716 | #define I2C_IFDR_DIV2048 0x3f | ||
717 | |||
718 | /* I2CR */ | ||
719 | #define I2C_I2CR_IEN (1 << 7) | ||
720 | #define I2C_I2CR_IIEN (1 << 6) | ||
721 | #define I2C_I2CR_MSTA (1 << 5) | ||
722 | #define I2C_I2CR_MTX (1 << 4) | ||
723 | #define I2C_I2CR_TXAK (1 << 3) | ||
724 | #define I2C_I2CR_RSATA (1 << 2) | ||
725 | |||
726 | /* I2SR */ | ||
727 | #define I2C_I2SR_ICF (1 << 7) | ||
728 | #define I2C_I2SR_IAAS (1 << 6) | ||
729 | #define I2C_I2SR_IBB (1 << 5) | ||
730 | #define I2C_I2SR_IAL (1 << 4) | ||
731 | #define I2C_I2SR_SRW (1 << 2) | ||
732 | #define I2C_I2SR_IIF (1 << 1) | ||
733 | #define I2C_I2SR_RXAK (1 << 0) | ||
734 | |||
735 | /* I2DR - [7:0] Data */ | ||
736 | |||
631 | /* RTC */ | 737 | /* RTC */ |
632 | #define RTC_HOURMIN (*(REG32_PTR_T)(RTC_BASE_ADDR+0x00)) | 738 | #define RTC_HOURMIN (*(REG32_PTR_T)(RTC_BASE_ADDR+0x00)) |
633 | #define RTC_SECONDS (*(REG32_PTR_T)(RTC_BASE_ADDR+0x04)) | 739 | #define RTC_SECONDS (*(REG32_PTR_T)(RTC_BASE_ADDR+0x04)) |
diff --git a/firmware/export/wm8978.h b/firmware/export/wm8978.h index 3a1eb627df..aca1250665 100644 --- a/firmware/export/wm8978.h +++ b/firmware/export/wm8978.h | |||
@@ -21,6 +21,9 @@ | |||
21 | #ifndef _WM8978_H | 21 | #ifndef _WM8978_H |
22 | #define _WM8978_H | 22 | #define _WM8978_H |
23 | 23 | ||
24 | #define VOLUME_MIN -570 | ||
25 | #define VOLUME_MAX 60 | ||
26 | |||
24 | #define WM8978_I2C_ADDR 0x34 | 27 | #define WM8978_I2C_ADDR 0x34 |
25 | 28 | ||
26 | /* Registers */ | 29 | /* Registers */ |
@@ -142,7 +145,7 @@ | |||
142 | #define WM8978_DAC_COMP_U_LAW (2 << 3) | 145 | #define WM8978_DAC_COMP_U_LAW (2 << 3) |
143 | #define WM8978_DAC_COMP_A_LAW (3 << 3) | 146 | #define WM8978_DAC_COMP_A_LAW (3 << 3) |
144 | #define WM8978_ADC_COMP (3 << 1) | 147 | #define WM8978_ADC_COMP (3 << 1) |
145 | #define WM8978_DAC_COMP_OFF (0 << 1) | 148 | #define WM8978_ADC_COMP_OFF (0 << 1) |
146 | #define WM8978_ADC_COMP_U_LAW (2 << 1) | 149 | #define WM8978_ADC_COMP_U_LAW (2 << 1) |
147 | #define WM8978_ADC_COMP_A_LAW (3 << 1) | 150 | #define WM8978_ADC_COMP_A_LAW (3 << 1) |
148 | #define WM8978_LOOPBACK (1 << 0) | 151 | #define WM8978_LOOPBACK (1 << 0) |
@@ -159,12 +162,12 @@ | |||
159 | #define WM8978_MCLKDIV_8 (6 << 5) | 162 | #define WM8978_MCLKDIV_8 (6 << 5) |
160 | #define WM8978_MCLKDIV_12 (7 << 5) | 163 | #define WM8978_MCLKDIV_12 (7 << 5) |
161 | #define WM8978_BCLKDIV (7 << 2) | 164 | #define WM8978_BCLKDIV (7 << 2) |
162 | #define WM8978_MCLKDIV_1 (0 << 2) | 165 | #define WM8978_BCLKDIV_1 (0 << 2) |
163 | #define WM8978_MCLKDIV_2 (1 << 2) | 166 | #define WM8978_BCLKDIV_2 (1 << 2) |
164 | #define WM8978_MCLKDIV_4 (2 << 2) | 167 | #define WM8978_BCLKDIV_4 (2 << 2) |
165 | #define WM8978_MCLKDIV_8 (3 << 2) | 168 | #define WM8978_BCLKDIV_8 (3 << 2) |
166 | #define WM8978_MCLKDIV_16 (4 << 2) | 169 | #define WM8978_BCLKDIV_16 (4 << 2) |
167 | #define WM8978_MCLKDIV_32 (5 << 2) | 170 | #define WM8978_BCLKDIV_32 (5 << 2) |
168 | #define WM8978_MS (1 << 0) | 171 | #define WM8978_MS (1 << 0) |
169 | 172 | ||
170 | /* WM8978_ADDITIONAL_CTRL (0x07) */ | 173 | /* WM8978_ADDITIONAL_CTRL (0x07) */ |
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c index 54ddaa7a46..ccd9efb321 100644 --- a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2007 by Michael Sevakis | 10 | * Copyright (C) 2008 by Michael Sevakis |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 12 | * All files in this archive are subject to the GNU General Public License. |
13 | * See the file COPYING in the source tree root for full license agreement. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -16,38 +16,321 @@ | |||
16 | * KIND, either express or implied. | 16 | * KIND, either express or implied. |
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include <stdlib.h> | ||
20 | #include "config.h" | ||
19 | #include "system.h" | 21 | #include "system.h" |
22 | #include "kernel.h" | ||
23 | #include "avic-imx31.h" | ||
24 | #include "clkctl-imx31.h" | ||
20 | #include "i2c-imx31.h" | 25 | #include "i2c-imx31.h" |
21 | 26 | ||
22 | #if 0 | 27 | /* Forward interrupt handler declarations */ |
23 | static int i2c_getack(void) | 28 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) |
29 | static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void); | ||
30 | #endif | ||
31 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
32 | static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void); | ||
33 | #endif | ||
34 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
35 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void); | ||
36 | #endif | ||
37 | |||
38 | static struct i2c_module_descriptor | ||
24 | { | 39 | { |
25 | return 0; | 40 | struct i2c_map *base; /* Module base address */ |
41 | enum IMX31_CG_LIST cg; /* Clock gating index */ | ||
42 | enum IMX31_INT_LIST ints; /* Module interrupt number */ | ||
43 | int enable; /* Enable count */ | ||
44 | void (*handler)(void); /* Module interrupt handler */ | ||
45 | struct mutex m; /* Node mutual-exclusion */ | ||
46 | struct wakeup w; /* I2C done signal */ | ||
47 | unsigned char *addr_data; /* Additional addressing data */ | ||
48 | int addr_count; /* Addressing byte count */ | ||
49 | unsigned char *data; /* TX/RX buffer (actual data) */ | ||
50 | int data_count; /* TX/RX byte count */ | ||
51 | unsigned char addr; /* Address + r/w bit */ | ||
52 | } i2c_descs[I2C_NUM_I2C] = | ||
53 | { | ||
54 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) | ||
55 | { | ||
56 | .base = (struct i2c_map *)I2C1_BASE_ADDR, | ||
57 | .cg = CG_I2C1, | ||
58 | .ints = I2C1, | ||
59 | .handler = I2C1_HANDLER, | ||
60 | }, | ||
61 | #endif | ||
62 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
63 | { | ||
64 | .base = (struct i2c_map *)I2C2_BASE_ADDR, | ||
65 | .cg = CG_I2C2, | ||
66 | .ints = I2C2, | ||
67 | .handler = I2C2_HANDLER, | ||
68 | }, | ||
69 | #endif | ||
70 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
71 | { | ||
72 | .base = (struct i2c_map *)I2C3_BASE_ADDR, | ||
73 | .cg = CG_I2C3, | ||
74 | .ints = I2C3, | ||
75 | .handler = I2C3_HANDLER, | ||
76 | }, | ||
77 | #endif | ||
78 | }; | ||
79 | |||
80 | static void i2c_interrupt(enum i2c_module_number i2c) | ||
81 | { | ||
82 | struct i2c_module_descriptor *const desc = &i2c_descs[i2c]; | ||
83 | struct i2c_map * const base = desc->base; | ||
84 | uint16_t i2sr = base->i2sr; | ||
85 | |||
86 | base->i2sr = i2sr & ~I2C_I2SR_IIF; /* Clear IIF */ | ||
87 | |||
88 | if (desc->addr_count >= 0) | ||
89 | { | ||
90 | /* ADDR cycle - either done or more to send */ | ||
91 | if ((i2sr & I2C_I2SR_RXAK) != 0) | ||
92 | { | ||
93 | goto i2c_stop; /* problem */ | ||
94 | } | ||
95 | |||
96 | if (--desc->addr_count < 0) | ||
97 | { | ||
98 | /* Switching to data cycle */ | ||
99 | if (desc->addr & 0x1) | ||
100 | { | ||
101 | base->i2cr &= ~I2C_I2CR_MTX; /* Switch to RX mode */ | ||
102 | base->i2dr; /* Dummy read */ | ||
103 | return; | ||
104 | } | ||
105 | /* else remaining data is TX - handle below */ | ||
106 | goto i2c_transmit; | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | base->i2dr = *desc->addr_data++; /* Send next addressing byte */ | ||
111 | return; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (base->i2cr & I2C_I2CR_MTX) | ||
116 | { | ||
117 | i2c_transmit: | ||
118 | /* Transmitting data */ | ||
119 | if ((i2sr & I2C_I2SR_RXAK) == 0 && desc->data_count > 0) | ||
120 | { | ||
121 | /* More bytes to send, got ACK from previous byte */ | ||
122 | base->i2dr = *desc->data++; | ||
123 | desc->data_count--; | ||
124 | return; | ||
125 | } | ||
126 | /* else done or no ACK received */ | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | /* Receiving data */ | ||
131 | if (--desc->data_count > 0) | ||
132 | { | ||
133 | if (desc->data_count == 1) | ||
134 | { | ||
135 | /* 2nd to Last byte - NACK */ | ||
136 | base->i2cr |= I2C_I2CR_TXAK; | ||
137 | } | ||
138 | |||
139 | *desc->data++ = base->i2dr; /* Read data from I2DR and store */ | ||
140 | return; | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | /* Generate STOP signal before reading data */ | ||
145 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | ||
146 | *desc->data++ = base->i2dr; /* Read data from I2DR and store */ | ||
147 | goto i2c_done; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | i2c_stop: | ||
152 | /* Generate STOP signal */ | ||
153 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | ||
154 | i2c_done: | ||
155 | /* Signal thread we're done */ | ||
156 | wakeup_signal(&desc->w); | ||
26 | } | 157 | } |
27 | 158 | ||
28 | static int i2c_start(void) | 159 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) |
160 | static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void) | ||
29 | { | 161 | { |
30 | return 0; | 162 | i2c_interrupt(I2C1_NUM); |
31 | } | 163 | } |
164 | #endif | ||
165 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
166 | static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void) | ||
167 | { | ||
168 | i2c_interrupt(I2C2_NUM); | ||
169 | } | ||
170 | #endif | ||
171 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
172 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void) | ||
173 | { | ||
174 | i2c_interrupt(I2C3_NUM); | ||
175 | } | ||
176 | #endif | ||
32 | 177 | ||
33 | static void i2c_stop(void) | 178 | static int i2c_transfer(struct i2c_node * const node, |
179 | struct i2c_module_descriptor *const desc) | ||
34 | { | 180 | { |
181 | struct i2c_map * const base = desc->base; | ||
182 | int count = desc->data_count; | ||
183 | uint16_t i2cr; | ||
184 | |||
185 | /* Set speed */ | ||
186 | base->ifdr = node->ifdr; | ||
187 | |||
188 | /* Enable module */ | ||
189 | base->i2cr = I2C_I2CR_IEN; | ||
190 | |||
191 | /* Enable Interrupt, Master */ | ||
192 | i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX; | ||
193 | |||
194 | if ((desc->addr & 0x1) && desc->data_count < 2) | ||
195 | { | ||
196 | /* Receiving less than two bytes - disable ACK generation */ | ||
197 | i2cr |= I2C_I2CR_TXAK; | ||
198 | } | ||
199 | |||
200 | /* Set config */ | ||
201 | base->i2cr = i2cr; | ||
202 | |||
203 | /* Generate START */ | ||
204 | base->i2cr |= I2C_I2CR_MSTA; | ||
205 | |||
206 | /* Address slave (first byte sent) and begin session. */ | ||
207 | base->i2dr = desc->addr; | ||
208 | |||
209 | /* Wait for transfer to complete */ | ||
210 | count = (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED) ? | ||
211 | -1 : (count - desc->data_count); | ||
212 | |||
213 | /* Disable module - generate STOP if timeout */ | ||
214 | base->i2cr = 0; | ||
215 | |||
216 | return count; | ||
35 | } | 217 | } |
36 | 218 | ||
37 | static int i2c_outb(unsigned char byte) | 219 | int i2c_read(struct i2c_node *node, int reg, |
220 | unsigned char *data, int data_count) | ||
38 | { | 221 | { |
39 | (void)byte; | 222 | struct i2c_module_descriptor *const desc = &i2c_descs[node->num]; |
40 | return 0; | 223 | unsigned char ad[1]; |
224 | |||
225 | mutex_lock(&desc->m); | ||
226 | |||
227 | desc->addr = (node->addr & 0xfe) | 0x1; /* Slave address/rd */ | ||
228 | |||
229 | if (reg >= 0) | ||
230 | { | ||
231 | /* Sub-address */ | ||
232 | desc->addr_count = 1; | ||
233 | desc->addr_data = ad; | ||
234 | ad[0] = reg; | ||
235 | } | ||
236 | /* else raw read from slave */ | ||
237 | |||
238 | desc->data = data; | ||
239 | desc->data_count = data_count; | ||
240 | |||
241 | data_count = i2c_transfer(node, desc); | ||
242 | |||
243 | desc->addr_count = 0; /* To eliminate zeroing elsewhere */ | ||
244 | |||
245 | mutex_unlock(&desc->m); | ||
246 | |||
247 | return data_count; | ||
41 | } | 248 | } |
42 | #endif | ||
43 | 249 | ||
44 | void i2c_write(int addr, const unsigned char *buf, int count) | 250 | int i2c_write(struct i2c_node *node, const unsigned char *data, int data_count) |
45 | { | 251 | { |
46 | (void)addr; | 252 | struct i2c_module_descriptor *const desc = &i2c_descs[node->num]; |
47 | (void)buf; | 253 | |
48 | (void)count; | 254 | mutex_lock(&desc->m); |
255 | |||
256 | desc->addr = node->addr & 0xfe; /* Slave address/wr */ | ||
257 | desc->data = (unsigned char *)data; | ||
258 | desc->data_count = data_count; | ||
259 | |||
260 | data_count = i2c_transfer(node, desc); | ||
261 | |||
262 | mutex_unlock(&desc->m); | ||
263 | |||
264 | return data_count; | ||
49 | } | 265 | } |
50 | 266 | ||
51 | void i2c_init(void) | 267 | void i2c_init(void) |
52 | { | 268 | { |
269 | int i; | ||
270 | |||
271 | /* Do one-time inits for each module that will be used - leave | ||
272 | * module disabled and unclocked until something wants it */ | ||
273 | for (i = 0; i < I2C_NUM_I2C; i++) | ||
274 | { | ||
275 | struct i2c_module_descriptor *const desc = &i2c_descs[i]; | ||
276 | imx31_clkctl_module_clock_gating(desc->cg, CGM_ON_ALL); | ||
277 | mutex_init(&desc->m); | ||
278 | wakeup_init(&desc->w); | ||
279 | desc->base->i2cr = 0; | ||
280 | imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF); | ||
281 | } | ||
282 | |||
283 | #if 0 | ||
284 | /* Pad config set up by OF bootloader doesn't agree with manual but | ||
285 | * TX works at the moment - probably would't do this here either */ | ||
286 | uint32_t reg = SW_PAD_CTL_CSI_PIXCLK_I2C_CLK_I2C_DAT; | ||
287 | reg &= ~0xfffff; | ||
288 | reg |= (1 << 19) | (3 << 17) | (1 << 15) | (1 << 14) | | ||
289 | (1 << 13) | (0 << 11); | ||
290 | |||
291 | reg |= (1 << 9) | (3 << 7) | (1 << 5) | (1 << 4) | | ||
292 | (1 << 3) | (0 << 1); | ||
293 | |||
294 | SW_PAD_CTL_CSI_PIXCLK_I2C_CLK_I2C_DAT = reg; | ||
295 | #endif | ||
296 | } | ||
297 | |||
298 | void i2c_enable_node(struct i2c_node *node, bool enable) | ||
299 | { | ||
300 | struct i2c_module_descriptor *const desc = &i2c_descs[node->num]; | ||
301 | |||
302 | mutex_lock(&desc->m); | ||
303 | |||
304 | if (enable) | ||
305 | { | ||
306 | if (++desc->enable == 1) | ||
307 | { | ||
308 | /* First enable */ | ||
309 | imx31_clkctl_module_clock_gating(desc->cg, CGM_ON_ALL); | ||
310 | avic_enable_int(desc->ints, IRQ, 7, desc->handler); | ||
311 | } | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | if (desc->enable > 0 && --desc->enable == 0) | ||
316 | { | ||
317 | /* Last enable */ | ||
318 | avic_disable_int(desc->ints); | ||
319 | imx31_clkctl_module_clock_gating(desc->cg, CGM_OFF); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | mutex_unlock(&desc->m); | ||
324 | } | ||
325 | |||
326 | void i2c_lock_node(struct i2c_node *node) | ||
327 | { | ||
328 | struct i2c_module_descriptor *const desc = &i2c_descs[node->num]; | ||
329 | mutex_lock(&desc->m); | ||
330 | } | ||
331 | |||
332 | void i2c_unlock_node(struct i2c_node *node) | ||
333 | { | ||
334 | struct i2c_module_descriptor *const desc = &i2c_descs[node->num]; | ||
335 | mutex_unlock(&desc->m); | ||
53 | } | 336 | } |
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h index c708ebbfb4..d6de5c47e8 100644 --- a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h +++ b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h | |||
@@ -16,7 +16,61 @@ | |||
16 | * KIND, either express or implied. | 16 | * KIND, either express or implied. |
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #ifndef _I2C_IMX31_H_ | ||
20 | #define _I2C_IMX31_H_ | ||
21 | |||
22 | #include <stdbool.h> | ||
23 | |||
24 | /* I2C module usage masks */ | ||
25 | #define USE_I2C1_MODULE (1 << 0) | ||
26 | #define USE_I2C2_MODULE (1 << 1) | ||
27 | #define USE_I2C3_MODULE (1 << 2) | ||
28 | |||
29 | enum i2c_module_number | ||
30 | { | ||
31 | __I2C_NUM_START = -1, | ||
32 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) | ||
33 | I2C1_NUM, | ||
34 | #endif | ||
35 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
36 | I2C2_NUM, | ||
37 | #endif | ||
38 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
39 | I2C3_NUM, | ||
40 | #endif | ||
41 | I2C_NUM_I2C, | ||
42 | }; | ||
43 | |||
44 | /* Module interface map structure */ | ||
45 | struct i2c_map | ||
46 | { | ||
47 | volatile uint16_t iadr; /* 0x00 */ | ||
48 | volatile uint16_t unused1; | ||
49 | volatile uint16_t ifdr; /* 0x04 */ | ||
50 | volatile uint16_t unused2; | ||
51 | volatile uint16_t i2cr; /* 0x08 */ | ||
52 | volatile uint16_t unused3; | ||
53 | volatile uint16_t i2sr; /* 0x0C */ | ||
54 | volatile uint16_t unused4; | ||
55 | volatile uint16_t i2dr; /* 0x10 */ | ||
56 | }; | ||
57 | |||
58 | struct i2c_node | ||
59 | { | ||
60 | enum i2c_module_number num; /* Module that this node uses */ | ||
61 | unsigned int ifdr; /* Maximum frequency for node */ | ||
62 | unsigned char addr; /* Slave address on module */ | ||
63 | }; | ||
19 | 64 | ||
20 | void i2c_init(void); | 65 | void i2c_init(void); |
21 | void i2c_write(int addr, const unsigned char *data, int count); | 66 | /* Enable or disable the node - modules will be switch on/off accordingly. */ |
67 | void i2c_enable_node(struct i2c_node *node, bool enable); | ||
68 | /* If addr < 0, then raw read */ | ||
69 | int i2c_read(struct i2c_node *node, int addr, unsigned char *data, int count); | ||
70 | int i2c_write(struct i2c_node *node, const unsigned char *data, int count); | ||
71 | /* Gain mutually-exclusive access to the node and module to perform multiple | ||
72 | * operations atomically */ | ||
73 | void i2c_lock_node(struct i2c_node *node); | ||
74 | void i2c_unlock_node(struct i2c_node *node); | ||
22 | 75 | ||
76 | #endif /* _I2C_IMX31_H_ */ | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c index 4d2206bd56..e37f6bfbe2 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c | |||
@@ -49,10 +49,12 @@ void pcm_apply_settings(void) | |||
49 | 49 | ||
50 | void pcm_play_dma_init(void) | 50 | void pcm_play_dma_init(void) |
51 | { | 51 | { |
52 | audiohw_init(); | ||
52 | } | 53 | } |
53 | 54 | ||
54 | void pcm_postinit(void) | 55 | void pcm_postinit(void) |
55 | { | 56 | { |
57 | audiohw_postinit(); | ||
56 | } | 58 | } |
57 | 59 | ||
58 | #if 0 | 60 | #if 0 |
diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c index 238ee3aeb2..235ae54bad 100644 --- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Gigabeat specific code for the Wolfson codec | 10 | * Gigabeat S specific code for the WM8978 codec |
11 | * | 11 | * |
12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ | 12 | * Based on code from the ipodlinux project - http://ipodlinux.org/ |
13 | * Adapted for Rockbox in December 2005 | 13 | * Adapted for Rockbox in December 2005 |
@@ -28,12 +28,31 @@ | |||
28 | #include "sound.h" | 28 | #include "sound.h" |
29 | #include "i2c-imx31.h" | 29 | #include "i2c-imx31.h" |
30 | 30 | ||
31 | /* NOTE: Some port-specific bits will have to be moved away (node and GPIO | ||
32 | * writes) for cleanest implementation. */ | ||
33 | |||
34 | static struct i2c_node wm8978_i2c_node = | ||
35 | { | ||
36 | .num = I2C1_NUM, | ||
37 | .ifdr = I2C_IFDR_DIV192, /* 66MHz/.4MHz = 165, closest = 192 = 343750Hz */ | ||
38 | /* Just hard-code for now - scaling may require | ||
39 | * updating */ | ||
40 | .addr = WM8978_I2C_ADDR, | ||
41 | }; | ||
42 | |||
31 | void audiohw_init(void) | 43 | void audiohw_init(void) |
32 | { | 44 | { |
45 | i2c_enable_node(&wm8978_i2c_node, true); | ||
46 | GPIO3_DR |= (1 << 21); /* Turn on analogue LDO */ | ||
47 | sleep(HZ/10); /* Wait for things to stabilize */ | ||
48 | audiohw_preinit(); | ||
33 | } | 49 | } |
34 | 50 | ||
35 | void wmcodec_write(int reg, int data) | 51 | void wmcodec_write(int reg, int data) |
36 | { | 52 | { |
37 | (void)reg; | 53 | unsigned char d[2]; |
38 | (void)data; | 54 | /* |aaaaaaad|dddddddd| */ |
55 | d[0] = (reg << 1) | ((data & 0x100) >> 8); | ||
56 | d[1] = data; | ||
57 | i2c_write(&wm8978_i2c_node, d, 2); | ||
39 | } | 58 | } |