Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

drivers: add TLV320AIC3104 codec driver

Change-Id: Ic8825fc8f057c28316e9f7cb6af3dd34e8200d48

+291
+2
firmware/SOURCES
··· 585 585 drivers/audio/rk27xx_codec.c 586 586 #elif defined(HAVE_AIC3X) 587 587 drivers/audio/aic3x.c 588 + #elif defined(HAVE_AIC310X) 589 + drivers/audio/aic310x.c 588 590 #elif defined (HAVE_DUMMY_CODEC) 589 591 drivers/audio/dummy_codec.c 590 592 #elif defined (HAVE_DF1704_CODEC)
+112
firmware/drivers/audio/aic310x.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2026 Aidan MacDonald 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 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 "aic310x.h" 22 + #include "system.h" 23 + 24 + /* Call with mutex held */ 25 + static int aic310x_set_page(struct aic310x *codec, uint8_t page) 26 + { 27 + if (codec->current_page == page) 28 + return 0; 29 + 30 + codec->current_page = page; 31 + 32 + int err = codec->write_multiple(AIC310X_PAGE_SELECT, &codec->current_page, 1); 33 + if (err) 34 + { 35 + /* Clear current page on error */ 36 + codec->current_page = 0xFF; 37 + } 38 + 39 + return err; 40 + } 41 + 42 + static int aic310x_readwrite_multiple(struct aic310x *codec, bool write, 43 + uint8_t reg, uint8_t *data, size_t count) 44 + { 45 + mutex_lock(&codec->lock); 46 + 47 + uint8_t reg_page = AIC310X_REG_PAGE(reg); 48 + uint8_t reg_addr = AIC310X_REG_ADDR(reg); 49 + 50 + int err = aic310x_set_page(codec, reg_page); 51 + if (err) 52 + goto out; 53 + 54 + if (write) 55 + err = codec->write_multiple(reg_addr, data, count); 56 + else 57 + err = codec->read_multiple(reg_addr, data, count); 58 + 59 + out: 60 + mutex_unlock(&codec->lock); 61 + return err; 62 + } 63 + 64 + void aic310x_init(struct aic310x *codec) 65 + { 66 + mutex_init(&codec->lock); 67 + 68 + /* ensure we issue a page select before any register access */ 69 + codec->current_page = 0xFF; 70 + } 71 + 72 + int aic310x_read_multiple(struct aic310x *codec, 73 + uint8_t reg, uint8_t *data, size_t count) 74 + { 75 + return aic310x_readwrite_multiple(codec, false, reg, data, count); 76 + } 77 + 78 + int aic310x_write_multiple(struct aic310x *codec, 79 + uint8_t reg, const uint8_t *data, size_t count) 80 + { 81 + return aic310x_readwrite_multiple(codec, true, reg, (uint8_t *)data, count); 82 + } 83 + 84 + int aic310x_read(struct aic310x *codec, uint8_t reg, uint8_t *value) 85 + { 86 + return aic310x_read_multiple(codec, reg, value, 1); 87 + } 88 + 89 + int aic310x_write(struct aic310x *codec, uint8_t reg, uint8_t value) 90 + { 91 + return aic310x_write_multiple(codec, reg, &value, 1); 92 + } 93 + 94 + int aic310x_modify(struct aic310x *codec, 95 + uint8_t reg, uint8_t mask, uint8_t newvalue) 96 + { 97 + mutex_lock(&codec->lock); 98 + 99 + uint8_t tmp; 100 + int err = aic310x_read(codec, reg, &tmp); 101 + if (err) 102 + goto out; 103 + 104 + tmp &= ~mask; 105 + tmp |= newvalue; 106 + 107 + err = aic310x_write(codec, reg, tmp); 108 + 109 + out: 110 + mutex_unlock(&codec->lock); 111 + return err; 112 + }
+177
firmware/export/aic310x.h
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2026 Aidan MacDonald 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #ifndef __AIC310X_H__ 22 + #define __AIC310X_H__ 23 + 24 + #include "audiohw.h" 25 + #include "mutex.h" 26 + #include <stdint.h> 27 + #include <stddef.h> 28 + 29 + /* I2C address (7-bit address without r/w bit) */ 30 + #define AIC310X_I2C_ADDR 0x18 31 + 32 + /* Use bit 7 as page indicator */ 33 + #define AIC310X_REG_PAGE_MASK 0x80 34 + #define AIC310X_REG_ADDR_MASK 0x7F 35 + 36 + /* Get register address / page number */ 37 + #define AIC310X_REG_PAGE(x) ((x) & AIC310X_REG_PAGE_MASK ? 1 : 0) 38 + #define AIC310X_REG_ADDR(x) ((x) & AIC310X_REG_ADDR_MASK) 39 + 40 + /* Create page register address */ 41 + #define AIC310X_PAGE0_REG(x) (x) 42 + #define AIC310X_PAGE1_REG(x) ((x) | AIC310X_REG_PAGE_MASK) 43 + 44 + /* Page 0 registers */ 45 + #define AIC310X_PAGE_SELECT AIC310X_PAGE0_REG(0) 46 + #define AIC310X_SW_RESET AIC310X_PAGE0_REG(1) 47 + #define AIC310X_SAMPLE_RATE_SELECT AIC310X_PAGE0_REG(2) 48 + #define AIC310X_PLL_A AIC310X_PAGE0_REG(3) 49 + #define AIC310X_PLL_B AIC310X_PAGE0_REG(4) 50 + #define AIC310X_PLL_C AIC310X_PAGE0_REG(5) 51 + #define AIC310X_PLL_D AIC310X_PAGE0_REG(6) 52 + #define AIC310X_DATA_PATH AIC310X_PAGE0_REG(7) 53 + #define AIC310X_INTERFACE_CONTROL_A AIC310X_PAGE0_REG(8) 54 + #define AIC310X_INTERFACE_CONTROL_B AIC310X_PAGE0_REG(9) 55 + #define AIC310X_INTERFACE_CONTROL_C AIC310X_PAGE0_REG(10) 56 + #define AIC310X_OVERFLOW_FLAG AIC310X_PAGE0_REG(11) 57 + #define AIC310X_DIGITAL_FILTER_CONTROL AIC310X_PAGE0_REG(12) 58 + #define AIC310X_HEADSET_DETECT_A AIC310X_PAGE0_REG(13) 59 + #define AIC310X_HEADSET_DETECT_B AIC310X_PAGE0_REG(14) 60 + #define AIC310X_LEFT_PGA_GAIN AIC310X_PAGE0_REG(15) 61 + #define AIC310X_RIGHT_PGA_GAIN AIC310X_PAGE0_REG(16) 62 + #define AIC310X_MIC2_LEFT_ADC_CTRL AIC310X_PAGE0_REG(17) 63 + #define AIC310X_MIC2_RIGHT_ADC_CTRL AIC310X_PAGE0_REG(18) 64 + #define AIC310X_MIC1LP_LEFT_ADC_CTRL AIC310X_PAGE0_REG(19) 65 + #define AIC310X_MIC1RP_LEFT_ADC_CTRL AIC310X_PAGE0_REG(21) 66 + #define AIC310X_MIC1RP_RIGHT_ADC_CTRL AIC310X_PAGE0_REG(22) 67 + #define AIC310X_MIC1LP_RIGHT_ADC_CTRL AIC310X_PAGE0_REG(24) 68 + #define AIC310X_MICBIAS_CTRL AIC310X_PAGE0_REG(25) 69 + #define AIC310X_LEFT_AGC_CTRL_A AIC310X_PAGE0_REG(26) 70 + #define AIC310X_LEFT_AGC_CTRL_B AIC310X_PAGE0_REG(27) 71 + #define AIC310X_LEFT_AGC_CTRL_C AIC310X_PAGE0_REG(28) 72 + #define AIC310X_RIGHT_AGC_CTRL_A AIC310X_PAGE0_REG(29) 73 + #define AIC310X_RIGHT_AGC_CTRL_B AIC310X_PAGE0_REG(30) 74 + #define AIC310X_RIGHT_AGC_CTRL_C AIC310X_PAGE0_REG(31) 75 + #define AIC310X_LEFT_AGC_GAIN AIC310X_PAGE0_REG(32) 76 + #define AIC310X_RIGHT_AGC_GAIN AIC310X_PAGE0_REG(33) 77 + #define AIC310X_LEFT_AGC_NOISE_GATE AIC310X_PAGE0_REG(34) 78 + #define AIC310X_RIGHT_AGC_NOISE_GATE AIC310X_PAGE0_REG(35) 79 + #define AIC310X_ADC_FLAG AIC310X_PAGE0_REG(36) 80 + #define AIC310X_DAC_POWER_CTRL AIC310X_PAGE0_REG(37) 81 + #define AIC310X_HPOUT_DRIVER_CTRL AIC310X_PAGE0_REG(38) 82 + #define AIC310X_HPOUT_STAGE_CTRL AIC310X_PAGE0_REG(40) 83 + #define AIC310X_DAC_SWITCHING_CTRL AIC310X_PAGE0_REG(41) 84 + #define AIC310X_DRIVER_POP_REDUCTION AIC310X_PAGE0_REG(42) 85 + #define AIC310X_LEFT_DAC_DIGITAL_VOLUME AIC310X_PAGE0_REG(43) 86 + #define AIC310X_RIGHT_DAC_DIGITAL_VOLUME AIC310X_PAGE0_REG(44) 87 + #define AIC310X_PGA_L_TO_HPLOUT_VOLUME AIC310X_PAGE0_REG(46) 88 + #define AIC310X_DAC_L1_TO_HPLOUT_VOLUME AIC310X_PAGE0_REG(47) 89 + #define AIC310X_PGA_R_TO_HPLOUT_VOLUME AIC310X_PAGE0_REG(49) 90 + #define AIC310X_DAC_R1_TO_HPLOUT_VOLUME AIC310X_PAGE0_REG(50) 91 + #define AIC310X_HPLOUT_LEVEL_CONTROL AIC310X_PAGE0_REG(51) 92 + #define AIC310X_PGA_L_TO_HPLCOM_VOLUME AIC310X_PAGE0_REG(53) 93 + #define AIC310X_DAC_L1_TO_HPLCOM_VOLUME AIC310X_PAGE0_REG(54) 94 + #define AIC310X_PGA_R_TO_HPLCOM_VOLUME AIC310X_PAGE0_REG(56) 95 + #define AIC310X_DAC_R1_TO_HPLCOM_VOLUME AIC310X_PAGE0_REG(57) 96 + #define AIC310X_HPLCOM_LEVEL_CONTROL AIC310X_PAGE0_REG(58) 97 + #define AIC310X_PGA_L_TO_HPROUT_VOLUME AIC310X_PAGE0_REG(60) 98 + #define AIC310X_DAC_L1_TO_HPROUT_VOLUME AIC310X_PAGE0_REG(61) 99 + #define AIC310X_PGA_R_TO_HPROUT_VOLUME AIC310X_PAGE0_REG(63) 100 + #define AIC310X_DAC_R1_TO_HPROUT_VOLUME AIC310X_PAGE0_REG(64) 101 + #define AIC310X_HPROUT_LEVEL_CONTROL AIC310X_PAGE0_REG(65) 102 + #define AIC310X_PGA_L_TO_HPRCOM_VOLUME AIC310X_PAGE0_REG(67) 103 + #define AIC310X_DAC_L1_TO_HPRCOM_VOLUME AIC310X_PAGE0_REG(68) 104 + #define AIC310X_PGA_R_TO_HPRCOM_VOLUME AIC310X_PAGE0_REG(70) 105 + #define AIC310X_DAC_R1_TO_HPRCOM_VOLUME AIC310X_PAGE0_REG(71) 106 + #define AIC310X_HPRCOM_LEVEL_CONTROL AIC310X_PAGE0_REG(72) 107 + #define AIC310X_PGA_L_TO_LEFT_LO_VOLUME AIC310X_PAGE0_REG(81) 108 + #define AIC310X_DAC_L1_TO_LEFT_LO_VOLUME AIC310X_PAGE0_REG(82) 109 + #define AIC310X_PGA_R_TO_LEFT_LO_VOLUME AIC310X_PAGE0_REG(84) 110 + #define AIC310X_DAC_R1_TO_LEFT_LO_VOLUME AIC310X_PAGE0_REG(85) 111 + #define AIC310X_LEFT_LO_LEVEL_CONTROL AIC310X_PAGE0_REG(86) 112 + #define AIC310X_PGA_L_TO_RIGHT_LO_VOLUME AIC310X_PAGE0_REG(88) 113 + #define AIC310X_DAC_L1_TO_RIGHT_LO_VOLUME AIC310X_PAGE0_REG(89) 114 + #define AIC310X_PGA_R_TO_RIGHT_LO_VOLUME AIC310X_PAGE0_REG(91) 115 + #define AIC310X_DAC_R1_TO_RIGHT_LO_VOLUME AIC310X_PAGE0_REG(92) 116 + #define AIC310X_RIGHT_LO_LEVEL_CONTROL AIC310X_PAGE0_REG(93) 117 + #define AIC310X_MODULE_PWR_STATUS AIC310X_PAGE0_REG(94) 118 + #define AIC310X_SHORT_CIRCUIT_STATUS AIC310X_PAGE0_REG(95) 119 + #define AIC310X_STICKY_INTERRUPT_FLAGS AIC310X_PAGE0_REG(96) 120 + #define AIC310X_REAL_TIME_INTERRUPT_FLAGS AIC310X_PAGE0_REG(97) 121 + #define AIC310X_CLOCK AIC310X_PAGE0_REG(101) 122 + #define AIC310X_CLOCK_GEN_CTRL AIC310X_PAGE0_REG(102) 123 + #define AIC310X_LEFT_AGC_ATTACK_TIME AIC310X_PAGE0_REG(103) 124 + #define AIC310X_LEFT_AGC_DECAY_TIME AIC310X_PAGE0_REG(104) 125 + #define AIC310X_RIGHT_AGC_ATTACK_TIME AIC310X_PAGE0_REG(105) 126 + #define AIC310X_RIGHT_AGC_DECAY_TIME AIC310X_PAGE0_REG(106) 127 + #define AIC310X_ADC_PATH_AND_I2C_BUS AIC310X_PAGE0_REG(107) 128 + #define AIC310X_BYPASS_SEL AIC310X_PAGE0_REG(108) 129 + #define AIC310X_DAC_CURRENT_ADJUST AIC310X_PAGE0_REG(109) 130 + 131 + /* Page 1 registers */ 132 + #define AIC310X_LEFT_EFF_FILTER AIC310X_PAGE1_REG(1) 133 + #define AIC310X_LEFT_DEEMPH_FILTER AIC310X_PAGE1_REG(21) 134 + #define AIC310X_RIGHT_EFF_FILTER AIC310X_PAGE1_REG(27) 135 + #define AIC310X_RIGHT_DEEMPH_FILTER AIC310X_PAGE1_REG(47) 136 + #define AIC310X_3D_ATTEN_COEFF AIC310X_PAGE1_REG(53) 137 + #define AIC310X_LEFT_ADC_HIGHPASS_FILTER AIC310X_PAGE1_REG(65) 138 + #define AIC310X_RIGHT_ADC_HIGHPASS_FILTER AIC310X_PAGE1_REG(71) 139 + 140 + struct aic310x 141 + { 142 + /* Mutex to protect bus access */ 143 + struct mutex lock; 144 + 145 + /* Cached page select register */ 146 + uint8_t current_page; 147 + 148 + /* I2C bus operations */ 149 + int (*read_multiple) (uint8_t reg, uint8_t *data, size_t count); 150 + int (*write_multiple) (uint8_t reg, const uint8_t *data, size_t count); 151 + }; 152 + 153 + void aic310x_init(struct aic310x *codec); 154 + 155 + /* Read/write multiple I2C registers */ 156 + int aic310x_read_multiple(struct aic310x *codec, 157 + uint8_t reg, uint8_t *data, size_t count); 158 + int aic310x_write_multiple(struct aic310x *codec, 159 + uint8_t reg, const uint8_t *data, size_t count); 160 + 161 + /* Single I2C register read/write and modify operations */ 162 + int aic310x_read(struct aic310x *codec, uint8_t reg, uint8_t *value); 163 + int aic310x_write(struct aic310x *codec, uint8_t reg, uint8_t value); 164 + int aic310x_modify(struct aic310x *codec, uint8_t reg, uint8_t mask, uint8_t newvalue); 165 + 166 + /* Lock/unlock the codec for performing multi-register operations */ 167 + static inline void aic310x_lock(struct aic310x *codec) 168 + { 169 + mutex_lock(&codec->lock); 170 + } 171 + 172 + static inline void aic310x_unlock(struct aic310x *codec) 173 + { 174 + mutex_unlock(&codec->lock); 175 + } 176 + 177 + #endif /* __AIC310X_H__ */