diff options
Diffstat (limited to 'firmware/drivers/audio/ak4376.c')
-rw-r--r-- | firmware/drivers/audio/ak4376.c | 70 |
1 files changed, 27 insertions, 43 deletions
diff --git a/firmware/drivers/audio/ak4376.c b/firmware/drivers/audio/ak4376.c index 494bbabfa4..11714b210d 100644 --- a/firmware/drivers/audio/ak4376.c +++ b/firmware/drivers/audio/ak4376.c | |||
@@ -27,6 +27,18 @@ | |||
27 | #include "system.h" | 27 | #include "system.h" |
28 | #include "i2c-async.h" | 28 | #include "i2c-async.h" |
29 | 29 | ||
30 | /* sample rates supported by the hardware */ | ||
31 | #define CAPS (SAMPR_CAP_192 | SAMPR_CAP_176 | \ | ||
32 | SAMPR_CAP_96 | SAMPR_CAP_88 | SAMPR_CAP_64 | \ | ||
33 | SAMPR_CAP_48 | SAMPR_CAP_44 | SAMPR_CAP_32 | \ | ||
34 | SAMPR_CAP_24 | SAMPR_CAP_22 | SAMPR_CAP_16 | \ | ||
35 | SAMPR_CAP_12 | SAMPR_CAP_11 | SAMPR_CAP_8) | ||
36 | |||
37 | /* future proofing */ | ||
38 | #if (HW_SAMPR_CAPS & ~CAPS) != 0 | ||
39 | # error "incorrect HW_SAMPR_CAPS" | ||
40 | #endif | ||
41 | |||
30 | #ifndef HAVE_SW_VOLUME_CONTROL | 42 | #ifndef HAVE_SW_VOLUME_CONTROL |
31 | # error "AK4376 requires HAVE_SW_VOLUME_CONTROL!" | 43 | # error "AK4376 requires HAVE_SW_VOLUME_CONTROL!" |
32 | #endif | 44 | #endif |
@@ -40,7 +52,7 @@ | |||
40 | */ | 52 | */ |
41 | 53 | ||
42 | /* Converts HW_FREQ_XX constants to register values */ | 54 | /* Converts HW_FREQ_XX constants to register values */ |
43 | static const int ak4376_fsel_to_hw[] = { | 55 | static const uint8_t ak4376_fsel_to_hw[] = { |
44 | HW_HAVE_192_(AK4376_FS_192,) | 56 | HW_HAVE_192_(AK4376_FS_192,) |
45 | HW_HAVE_176_(AK4376_FS_176,) | 57 | HW_HAVE_176_(AK4376_FS_176,) |
46 | HW_HAVE_96_(AK4376_FS_96,) | 58 | HW_HAVE_96_(AK4376_FS_96,) |
@@ -57,19 +69,13 @@ static const int ak4376_fsel_to_hw[] = { | |||
57 | HW_HAVE_8_(AK4376_FS_8,) | 69 | HW_HAVE_8_(AK4376_FS_8,) |
58 | }; | 70 | }; |
59 | 71 | ||
60 | static struct ak4376 { | 72 | static int ak4376_regs[AK4376_NUM_REGS]; |
61 | int fsel; | ||
62 | int low_mode; | ||
63 | int regs[AK4376_NUM_REGS]; | ||
64 | } ak4376; | ||
65 | 73 | ||
66 | void ak4376_init(void) | 74 | void ak4376_open(void) |
67 | { | 75 | { |
68 | /* Initialize DAC state */ | 76 | /* Initialize DAC state */ |
69 | ak4376.fsel = HW_FREQ_48; | ||
70 | ak4376.low_mode = 0; | ||
71 | for(int i = 0; i < AK4376_NUM_REGS; ++i) | 77 | for(int i = 0; i < AK4376_NUM_REGS; ++i) |
72 | ak4376.regs[i] = -1; | 78 | ak4376_regs[i] = -1; |
73 | 79 | ||
74 | /* Initial reset after power-on */ | 80 | /* Initial reset after power-on */ |
75 | ak4376_set_pdn_pin(0); | 81 | ak4376_set_pdn_pin(0); |
@@ -102,9 +108,6 @@ void ak4376_init(void) | |||
102 | /* Write initial configuration prior to power-up */ | 108 | /* Write initial configuration prior to power-up */ |
103 | for(size_t i = 0; i < ARRAYLEN(init_config); i += 2) | 109 | for(size_t i = 0; i < ARRAYLEN(init_config); i += 2) |
104 | ak4376_write(init_config[i], init_config[i+1]); | 110 | ak4376_write(init_config[i], init_config[i+1]); |
105 | |||
106 | /* Initial frequency setting, also handles DAC/amp power-up */ | ||
107 | audiohw_set_frequency(HW_FREQ_48); | ||
108 | } | 111 | } |
109 | 112 | ||
110 | void ak4376_close(void) | 113 | void ak4376_close(void) |
@@ -121,22 +124,22 @@ void ak4376_close(void) | |||
121 | void ak4376_write(int reg, int value) | 124 | void ak4376_write(int reg, int value) |
122 | { | 125 | { |
123 | /* Ensure value is sensible and differs from the last set value */ | 126 | /* Ensure value is sensible and differs from the last set value */ |
124 | if((value & 0xff) == value && ak4376.regs[reg] != value) { | 127 | if((value & 0xff) == value && ak4376_regs[reg] != value) { |
125 | int r = i2c_reg_write1(AK4376_BUS, AK4376_ADDR, reg, value); | 128 | int r = i2c_reg_write1(AK4376_BUS, AK4376_ADDR, reg, value); |
126 | if(r == I2C_STATUS_OK) | 129 | if(r == I2C_STATUS_OK) |
127 | ak4376.regs[reg] = value; | 130 | ak4376_regs[reg] = value; |
128 | else | 131 | else |
129 | ak4376.regs[reg] = -1; | 132 | ak4376_regs[reg] = -1; |
130 | } | 133 | } |
131 | } | 134 | } |
132 | 135 | ||
133 | int ak4376_read(int reg) | 136 | int ak4376_read(int reg) |
134 | { | 137 | { |
135 | /* Only read from I2C if we don't already know the value */ | 138 | /* Only read from I2C if we don't already know the value */ |
136 | if(ak4376.regs[reg] < 0) | 139 | if(ak4376_regs[reg] < 0) |
137 | ak4376.regs[reg] = i2c_reg_read1(AK4376_BUS, AK4376_ADDR, reg); | 140 | ak4376_regs[reg] = i2c_reg_read1(AK4376_BUS, AK4376_ADDR, reg); |
138 | 141 | ||
139 | return ak4376.regs[reg]; | 142 | return ak4376_regs[reg]; |
140 | } | 143 | } |
141 | 144 | ||
142 | static int round_step_up(int x, int step) | 145 | static int round_step_up(int x, int step) |
@@ -180,7 +183,7 @@ static int amp_vol_to_hw(int vol) | |||
180 | return (vol - AK4376_AMP_VOLUME_MIN) / AK4376_AMP_VOLUME_STEP + 1; | 183 | return (vol - AK4376_AMP_VOLUME_MIN) / AK4376_AMP_VOLUME_STEP + 1; |
181 | } | 184 | } |
182 | 185 | ||
183 | void audiohw_set_volume(int vol_l, int vol_r) | 186 | void ak4376_set_volume(int vol_l, int vol_r) |
184 | { | 187 | { |
185 | int amp; | 188 | int amp; |
186 | int mix_l = AK4376_MIX_LCH, dig_l, sw_l; | 189 | int mix_l = AK4376_MIX_LCH, dig_l, sw_l; |
@@ -210,7 +213,7 @@ void audiohw_set_volume(int vol_l, int vol_r) | |||
210 | pcm_set_master_volume(sw_l, sw_r); | 213 | pcm_set_master_volume(sw_l, sw_r); |
211 | } | 214 | } |
212 | 215 | ||
213 | void audiohw_set_filter_roll_off(int val) | 216 | void ak4376_set_filter_roll_off(int val) |
214 | { | 217 | { |
215 | int reg = ak4376_read(AK4376_REG_FILTER); | 218 | int reg = ak4376_read(AK4376_REG_FILTER); |
216 | reg &= ~0xc0; | 219 | reg &= ~0xc0; |
@@ -218,11 +221,8 @@ void audiohw_set_filter_roll_off(int val) | |||
218 | ak4376_write(AK4376_REG_FILTER, reg); | 221 | ak4376_write(AK4376_REG_FILTER, reg); |
219 | } | 222 | } |
220 | 223 | ||
221 | void audiohw_set_frequency(int fsel) | 224 | void ak4376_set_freqmode(int fsel, int mult, int power_mode) |
222 | { | 225 | { |
223 | /* Determine master clock multiplier */ | ||
224 | int mult = ak4376_set_mclk_freq(fsel, false); | ||
225 | |||
226 | /* Calculate clock mode for frequency. Multipliers of 32/64 are only | 226 | /* Calculate clock mode for frequency. Multipliers of 32/64 are only |
227 | * for rates >= 256 KHz which are not supported by Rockbox, so they | 227 | * for rates >= 256 KHz which are not supported by Rockbox, so they |
228 | * are commented out -- but they're in the correct place. */ | 228 | * are commented out -- but they're in the correct place. */ |
@@ -248,27 +248,11 @@ void audiohw_set_frequency(int fsel) | |||
248 | 248 | ||
249 | /* Handle the DSMLP bit in the MODE_CTRL register */ | 249 | /* Handle the DSMLP bit in the MODE_CTRL register */ |
250 | int mode_ctrl = 0x00; | 250 | int mode_ctrl = 0x00; |
251 | if(ak4376.low_mode || hw_freq_sampr[fsel] <= SAMPR_12) | 251 | if(power_mode || hw_freq_sampr[fsel] <= SAMPR_12) |
252 | mode_ctrl |= 0x40; | 252 | mode_ctrl |= 0x40; |
253 | 253 | ||
254 | /* Program the new settings */ | 254 | /* Program the new settings */ |
255 | ak4376_write(AK4376_REG_CLOCK_MODE, clock_mode); | 255 | ak4376_write(AK4376_REG_CLOCK_MODE, clock_mode); |
256 | ak4376_write(AK4376_REG_MODE_CTRL, mode_ctrl); | 256 | ak4376_write(AK4376_REG_MODE_CTRL, mode_ctrl); |
257 | ak4376_write(AK4376_REG_PWR3, ak4376.low_mode ? 0x11 : 0x01); | 257 | ak4376_write(AK4376_REG_PWR3, power_mode ? 0x11 : 0x01); |
258 | |||
259 | /* Enable the master clock */ | ||
260 | ak4376_set_mclk_freq(fsel, true); | ||
261 | |||
262 | /* Remember the frequency */ | ||
263 | ak4376.fsel = fsel; | ||
264 | } | ||
265 | |||
266 | void audiohw_set_power_mode(int mode) | ||
267 | { | ||
268 | /* This is handled via audiohw_set_frequency() since changing LPMODE | ||
269 | * bit requires power-down/power-up & changing other bits as well */ | ||
270 | if(ak4376.low_mode != mode) { | ||
271 | ak4376.low_mode = mode; | ||
272 | audiohw_set_frequency(ak4376.fsel); | ||
273 | } | ||
274 | } | 258 | } |