diff options
Diffstat (limited to 'firmware/drivers/audio/es9018k2m.c')
-rw-r--r-- | firmware/drivers/audio/es9018k2m.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/firmware/drivers/audio/es9018k2m.c b/firmware/drivers/audio/es9018k2m.c new file mode 100644 index 0000000000..e19cf6e8a9 --- /dev/null +++ b/firmware/drivers/audio/es9018k2m.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * | ||
11 | * Copyright (c) 2023 Dana Conrad | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #include "system.h" | ||
24 | #include "es9018k2m.h" | ||
25 | #include "i2c-async.h" | ||
26 | #include "action.h" | ||
27 | |||
28 | //====================================================================================== | ||
29 | // ES9018K2M support stuff | ||
30 | |||
31 | #ifndef ES9018K2M_BUS | ||
32 | # error "No definition for ES9018K2M I2C bus!" | ||
33 | #endif | ||
34 | |||
35 | #ifndef ES9018K2M_ADDR | ||
36 | # error "No definition for ES9018K2M I2C address!" | ||
37 | #endif | ||
38 | |||
39 | static int vol_tenthdb2hw(const int tdb) | ||
40 | { | ||
41 | if (tdb < ES9018K2M_VOLUME_MIN) { | ||
42 | return 0xff; | ||
43 | } else if (tdb > ES9018K2M_VOLUME_MAX) { | ||
44 | return 0x00; | ||
45 | } else { | ||
46 | return (-tdb/5); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | /* NOTE: This implementation is for the ES9018K2M specifically. */ | ||
51 | /* Register defaults from the datasheet. */ | ||
52 | /* These are basically just for reference. All defaults work out for us. | ||
53 | * static uint8_t reg0_system_settings = 0x00; // System settings. Default value of register 0 | ||
54 | * static uint8_t reg1_input_configuration = 0x8C; // Input settings. I2S input, 32-bit | ||
55 | * static uint8_t reg4_automute_time = 0x00; // Automute time. Default = disabled | ||
56 | * static uint8_t reg5_automute_level = 0x68; // Automute level. Default is some level | ||
57 | * static uint8_t reg6_deemphasis = 0x4A; // Deemphasis. Default = disabled | ||
58 | * static uint8_t reg7_general_settings = 0x80; // General settings. Default sharp fir, pcm iir and unmuted | ||
59 | * static uint8_t reg8_gpio_configuration = 0x10; // GPIO configuration | ||
60 | * static uint8_t reg10_master_mode_control = 0x05; // Master Mode Control. Default value: master mode off | ||
61 | * static uint8_t reg11_channel_mapping = 0x02; // Channel Mapping. Default stereo is Ch1=left, Ch2=right | ||
62 | * static uint8_t reg12_dpll_settings = 0x5A; // DPLL Settings. Default = 5 for I2S, A for DSD | ||
63 | * static uint8_t reg13_thd_comp = 0x40; // THD Compensation | ||
64 | * static uint8_t reg14_softstart_settings = 0x8A; // Soft Start Settings | ||
65 | * static uint8_t reg21_gpio_input_selection = 0x00; // Oversampling filter. Default: oversampling ON | ||
66 | */ | ||
67 | |||
68 | static uint8_t vol_reg_l = ES9018K2M_REG15_VOLUME_L; | ||
69 | static uint8_t reg15_vol_l = 0; | ||
70 | i2c_descriptor vol_desc_l = { | ||
71 | .slave_addr = ES9018K2M_ADDR, | ||
72 | .bus_cond = I2C_START | I2C_STOP, | ||
73 | .tran_mode = I2C_WRITE, | ||
74 | .buffer[0] = &vol_reg_l, | ||
75 | .count[0] = 1, | ||
76 | .buffer[1] = ®15_vol_l, | ||
77 | .count[1] = 1, | ||
78 | .callback = NULL, | ||
79 | .arg = 0, | ||
80 | .next = NULL, | ||
81 | }; | ||
82 | |||
83 | static uint8_t vol_reg_r = ES9018K2M_REG16_VOLUME_R; | ||
84 | static uint8_t reg16_vol_r = 0; | ||
85 | i2c_descriptor vol_desc_r = { | ||
86 | .slave_addr = ES9018K2M_ADDR, | ||
87 | .bus_cond = I2C_START | I2C_STOP, | ||
88 | .tran_mode = I2C_WRITE, | ||
89 | .buffer[0] = &vol_reg_r, | ||
90 | .count[0] = 1, | ||
91 | .buffer[1] = ®16_vol_r, | ||
92 | .count[1] = 1, | ||
93 | .callback = NULL, | ||
94 | .arg = 0, | ||
95 | .next = NULL, | ||
96 | }; | ||
97 | |||
98 | void es9018k2m_set_volume(int vol_l, int vol_r) | ||
99 | { | ||
100 | /* Queue writes to the DAC's volume. | ||
101 | * Note that this needs to be done asynchronously. From testing, calling | ||
102 | * synchronous writes from HP/LO detect causes hangs. */ | ||
103 | reg15_vol_l = vol_tenthdb2hw(vol_l); | ||
104 | reg16_vol_r = vol_tenthdb2hw(vol_r); | ||
105 | i2c_async_queue(ES9018K2M_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, &vol_desc_l); | ||
106 | i2c_async_queue(ES9018K2M_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, &vol_desc_r); | ||
107 | } | ||
108 | |||
109 | /* returns I2C_STATUS_OK upon success, I2C_STATUS_* errors upon error */ | ||
110 | int es9018k2m_write_reg(uint8_t reg, uint8_t val) | ||
111 | { | ||
112 | return i2c_reg_write1(ES9018K2M_BUS, ES9018K2M_ADDR, reg, val); | ||
113 | } | ||
114 | |||
115 | /* returns register value, or -1 upon error */ | ||
116 | int es9018k2m_read_reg(uint8_t reg) | ||
117 | { | ||
118 | return i2c_reg_read1(ES9018K2M_BUS, ES9018K2M_ADDR, reg); | ||
119 | } \ No newline at end of file | ||