[PATCH v2 0/4] ASoc: tac5x1x: mixer-test report

mixer-test report: TAP version 13 # Card 0/titac5x1xsoundc - ti,tac5x1x-soundcard (ti,tac5x1x-soundcard) 1..553 ok 1 get_value.titac5x1xsoundc.78 # titac5x1xsoundc.78 ASI_TX_CH4_EN Capture Switch ok 2 name.titac5x1xsoundc.78 ok 3 write_default.titac5x1xsoundc.78 ok 4 write_valid.titac5x1xsoundc.78 ok 5 write_invalid.titac5x1xsoundc.78 ok 6 event_missing.titac5x1xsoundc.78 ok 7 event_spurious.titac5x1xsoundc.78 ok 8 get_value.titac5x1xsoundc.77 # titac5x1xsoundc.77 ASI_TX_CH3_EN Capture Switch ok 9 name.titac5x1xsoundc.77 ok 10 write_default.titac5x1xsoundc.77 ok 11 write_valid.titac5x1xsoundc.77 ok 12 write_invalid.titac5x1xsoundc.77 ok 13 event_missing.titac5x1xsoundc.77 ok 14 event_spurious.titac5x1xsoundc.77 ok 15 get_value.titac5x1xsoundc.76 # titac5x1xsoundc.76 PDM ch3 & ch4 Datain Select ok 16 name.titac5x1xsoundc.76 ok 17 write_default.titac5x1xsoundc.76 ok 18 write_valid.titac5x1xsoundc.76 ok 19 write_invalid.titac5x1xsoundc.76 ok 20 event_missing.titac5x1xsoundc.76 ok 21 event_spurious.titac5x1xsoundc.76 ok 22 get_value.titac5x1xsoundc.75 # titac5x1xsoundc.75 PDM ch1 & ch2 Datain Select ok 23 name.titac5x1xsoundc.75 ok 24 write_default.titac5x1xsoundc.75 ok 25 write_valid.titac5x1xsoundc.75 ok 26 write_invalid.titac5x1xsoundc.75 ok 27 event_missing.titac5x1xsoundc.75 ok 28 event_spurious.titac5x1xsoundc.75 ok 29 get_value.titac5x1xsoundc.74 # titac5x1xsoundc.74 IN2 Source Mux ok 30 name.titac5x1xsoundc.74 ok 31 write_default.titac5x1xsoundc.74 ok 32 write_valid.titac5x1xsoundc.74 ok 33 write_invalid.titac5x1xsoundc.74 ok 34 event_missing.titac5x1xsoundc.74 ok 35 event_spurious.titac5x1xsoundc.74 ok 36 get_value.titac5x1xsoundc.73 # titac5x1xsoundc.73 IN1 Source Mux ok 37 name.titac5x1xsoundc.73 ok 38 write_default.titac5x1xsoundc.73 ok 39 write_valid.titac5x1xsoundc.73 ok 40 write_invalid.titac5x1xsoundc.73 ok 41 event_missing.titac5x1xsoundc.73 ok 42 event_spurious.titac5x1xsoundc.73 ok 43 get_value.titac5x1xsoundc.72 # titac5x1xsoundc.72 ADC2 Config ok 44 name.titac5x1xsoundc.72 ok 45 write_default.titac5x1xsoundc.72 ok 46 write_valid.titac5x1xsoundc.72 ok 47 write_invalid.titac5x1xsoundc.72 ok 48 event_missing.titac5x1xsoundc.72 ok 49 event_spurious.titac5x1xsoundc.72 ok 50 get_value.titac5x1xsoundc.71 # titac5x1xsoundc.71 ADC2 Full-Scale ok 51 name.titac5x1xsoundc.71 ok 52 write_default.titac5x1xsoundc.71 ok 53 write_valid.titac5x1xsoundc.71 ok 54 write_invalid.titac5x1xsoundc.71 ok 55 event_missing.titac5x1xsoundc.71 ok 56 event_spurious.titac5x1xsoundc.71 ok 57 get_value.titac5x1xsoundc.70 # titac5x1xsoundc.70 ASI_RX_CH2_EN Switch ok 58 name.titac5x1xsoundc.70 ok 59 write_default.titac5x1xsoundc.70 ok 60 write_valid.titac5x1xsoundc.70 ok 61 write_invalid.titac5x1xsoundc.70 ok 62 event_missing.titac5x1xsoundc.70 ok 63 event_spurious.titac5x1xsoundc.70 ok 64 get_value.titac5x1xsoundc.69 # titac5x1xsoundc.69 OUT2x Driver ok 65 name.titac5x1xsoundc.69 ok 66 write_default.titac5x1xsoundc.69 ok 67 write_valid.titac5x1xsoundc.69 ok 68 write_invalid.titac5x1xsoundc.69 ok 69 event_missing.titac5x1xsoundc.69 ok 70 event_spurious.titac5x1xsoundc.69 ok 71 get_value.titac5x1xsoundc.68 # titac5x1xsoundc.68 OUT2x Config ok 72 name.titac5x1xsoundc.68 ok 73 write_default.titac5x1xsoundc.68 ok 74 write_valid.titac5x1xsoundc.68 ok 75 write_invalid.titac5x1xsoundc.68 ok 76 event_missing.titac5x1xsoundc.68 ok 77 event_spurious.titac5x1xsoundc.68 ok 78 get_value.titac5x1xsoundc.67 # titac5x1xsoundc.67 OUT2x Source ok 79 name.titac5x1xsoundc.67 ok 80 write_default.titac5x1xsoundc.67 ok 81 write_valid.titac5x1xsoundc.67 ok 82 write_invalid.titac5x1xsoundc.67 ok 83 event_missing.titac5x1xsoundc.67 ok 84 event_spurious.titac5x1xsoundc.67 ok 85 get_value.titac5x1xsoundc.66 # titac5x1xsoundc.66 ASI_RX_CH1_EN Switch ok 86 name.titac5x1xsoundc.66 ok 87 write_default.titac5x1xsoundc.66 ok 88 write_valid.titac5x1xsoundc.66 ok 89 write_invalid.titac5x1xsoundc.66 ok 90 event_missing.titac5x1xsoundc.66 ok 91 event_spurious.titac5x1xsoundc.66 ok 92 get_value.titac5x1xsoundc.65 # titac5x1xsoundc.65 OUT1x Driver ok 93 name.titac5x1xsoundc.65 ok 94 write_default.titac5x1xsoundc.65 ok 95 write_valid.titac5x1xsoundc.65 ok 96 write_invalid.titac5x1xsoundc.65 ok 97 event_missing.titac5x1xsoundc.65 ok 98 event_spurious.titac5x1xsoundc.65 ok 99 get_value.titac5x1xsoundc.64 # titac5x1xsoundc.64 OUT1x Config ok 100 name.titac5x1xsoundc.64 ok 101 write_default.titac5x1xsoundc.64 ok 102 write_valid.titac5x1xsoundc.64 ok 103 write_invalid.titac5x1xsoundc.64 ok 104 event_missing.titac5x1xsoundc.64 ok 105 event_spurious.titac5x1xsoundc.64 ok 106 get_value.titac5x1xsoundc.63 # titac5x1xsoundc.63 OUT1x Source ok 107 name.titac5x1xsoundc.63 ok 108 write_default.titac5x1xsoundc.63 ok 109 write_valid.titac5x1xsoundc.63 ok 110 write_invalid.titac5x1xsoundc.63 ok 111 event_missing.titac5x1xsoundc.63 ok 112 event_spurious.titac5x1xsoundc.63 ok 113 get_value.titac5x1xsoundc.62 # titac5x1xsoundc.62 ASI_TX_CH2_EN Capture Switch ok 114 name.titac5x1xsoundc.62 ok 115 write_default.titac5x1xsoundc.62 ok 116 write_valid.titac5x1xsoundc.62 ok 117 write_invalid.titac5x1xsoundc.62 ok 118 event_missing.titac5x1xsoundc.62 ok 119 event_spurious.titac5x1xsoundc.62 ok 120 get_value.titac5x1xsoundc.61 # titac5x1xsoundc.61 ASI_TX_CH1_EN Capture Switch ok 121 name.titac5x1xsoundc.61 ok 122 write_default.titac5x1xsoundc.61 ok 123 write_valid.titac5x1xsoundc.61 ok 124 write_invalid.titac5x1xsoundc.61 ok 125 event_missing.titac5x1xsoundc.61 ok 126 event_spurious.titac5x1xsoundc.61 ok 127 get_value.titac5x1xsoundc.60 # titac5x1xsoundc.60 ADC1 Config ok 128 name.titac5x1xsoundc.60 ok 129 write_default.titac5x1xsoundc.60 ok 130 write_valid.titac5x1xsoundc.60 ok 131 write_invalid.titac5x1xsoundc.60 ok 132 event_missing.titac5x1xsoundc.60 ok 133 event_spurious.titac5x1xsoundc.60 ok 134 get_value.titac5x1xsoundc.59 # titac5x1xsoundc.59 ADC1 Full-Scale ok 135 name.titac5x1xsoundc.59 ok 136 write_default.titac5x1xsoundc.59 ok 137 write_valid.titac5x1xsoundc.59 ok 138 write_invalid.titac5x1xsoundc.59 ok 139 event_missing.titac5x1xsoundc.59 ok 140 event_spurious.titac5x1xsoundc.59 ok 141 get_value.titac5x1xsoundc.58 # titac5x1xsoundc.58 IN_CH4_EN Capture Switch ok 142 name.titac5x1xsoundc.58 ok 143 write_default.titac5x1xsoundc.58 ok 144 write_valid.titac5x1xsoundc.58 ok 145 write_invalid.titac5x1xsoundc.58 ok 146 event_missing.titac5x1xsoundc.58 ok 147 event_spurious.titac5x1xsoundc.58 ok 148 get_value.titac5x1xsoundc.57 # titac5x1xsoundc.57 IN_CH3_EN Capture Switch ok 149 name.titac5x1xsoundc.57 ok 150 write_default.titac5x1xsoundc.57 ok 151 write_valid.titac5x1xsoundc.57 ok 152 write_invalid.titac5x1xsoundc.57 ok 153 event_missing.titac5x1xsoundc.57 ok 154 event_spurious.titac5x1xsoundc.57 ok 155 get_value.titac5x1xsoundc.56 # titac5x1xsoundc.56 IN_CH2_EN Capture Switch ok 156 name.titac5x1xsoundc.56 ok 157 write_default.titac5x1xsoundc.56 ok 158 write_valid.titac5x1xsoundc.56 ok 159 write_invalid.titac5x1xsoundc.56 ok 160 event_missing.titac5x1xsoundc.56 ok 161 event_spurious.titac5x1xsoundc.56 ok 162 get_value.titac5x1xsoundc.55 # titac5x1xsoundc.55 IN_CH1_EN Capture Switch ok 163 name.titac5x1xsoundc.55 ok 164 write_default.titac5x1xsoundc.55 ok 165 write_valid.titac5x1xsoundc.55 ok 166 write_invalid.titac5x1xsoundc.55 ok 167 event_missing.titac5x1xsoundc.55 ok 168 event_spurious.titac5x1xsoundc.55 ok 169 get_value.titac5x1xsoundc.54 # titac5x1xsoundc.54 ASI_TX_CH8_CFG ok 170 name.titac5x1xsoundc.54 ok 171 write_default.titac5x1xsoundc.54 ok 172 write_valid.titac5x1xsoundc.54 ok 173 write_invalid.titac5x1xsoundc.54 ok 174 event_missing.titac5x1xsoundc.54 ok 175 event_spurious.titac5x1xsoundc.54 ok 176 get_value.titac5x1xsoundc.53 # titac5x1xsoundc.53 ASI_TX_CH7_CFG ok 177 name.titac5x1xsoundc.53 ok 178 write_default.titac5x1xsoundc.53 ok 179 write_valid.titac5x1xsoundc.53 ok 180 write_invalid.titac5x1xsoundc.53 ok 181 event_missing.titac5x1xsoundc.53 ok 182 event_spurious.titac5x1xsoundc.53 ok 183 get_value.titac5x1xsoundc.52 # titac5x1xsoundc.52 ASI_TX_CH6_CFG ok 184 name.titac5x1xsoundc.52 ok 185 write_default.titac5x1xsoundc.52 ok 186 write_valid.titac5x1xsoundc.52 ok 187 write_invalid.titac5x1xsoundc.52 ok 188 event_missing.titac5x1xsoundc.52 ok 189 event_spurious.titac5x1xsoundc.52 ok 190 get_value.titac5x1xsoundc.51 # titac5x1xsoundc.51 ASI_TX_CH5_CFG ok 191 name.titac5x1xsoundc.51 ok 192 write_default.titac5x1xsoundc.51 ok 193 write_valid.titac5x1xsoundc.51 ok 194 write_invalid.titac5x1xsoundc.51 ok 195 event_missing.titac5x1xsoundc.51 ok 196 event_spurious.titac5x1xsoundc.51 ok 197 get_value.titac5x1xsoundc.50 # titac5x1xsoundc.50 ADC1 Phase Capture Volume ok 198 name.titac5x1xsoundc.50 ok 199 write_default.titac5x1xsoundc.50 ok 200 write_valid.titac5x1xsoundc.50 ok 201 write_invalid.titac5x1xsoundc.50 ok 202 event_missing.titac5x1xsoundc.50 ok 203 event_spurious.titac5x1xsoundc.50 ok 204 get_value.titac5x1xsoundc.49 # titac5x1xsoundc.49 ADC1 Fine Capture Volume ok 205 name.titac5x1xsoundc.49 ok 206 write_default.titac5x1xsoundc.49 ok 207 write_valid.titac5x1xsoundc.49 ok 208 write_invalid.titac5x1xsoundc.49 ok 209 event_missing.titac5x1xsoundc.49 ok 210 event_spurious.titac5x1xsoundc.49 ok 211 get_value.titac5x1xsoundc.48 # titac5x1xsoundc.48 ADC1 Digital Capture Volume ok 212 name.titac5x1xsoundc.48 ok 213 write_default.titac5x1xsoundc.48 ok 214 write_valid.titac5x1xsoundc.48 ok 215 write_invalid.titac5x1xsoundc.48 ok 216 event_missing.titac5x1xsoundc.48 ok 217 event_spurious.titac5x1xsoundc.48 ok 218 get_value.titac5x1xsoundc.47 # titac5x1xsoundc.47 ADC1 Audio BW ok 219 name.titac5x1xsoundc.47 ok 220 write_default.titac5x1xsoundc.47 ok 221 write_valid.titac5x1xsoundc.47 ok 222 write_invalid.titac5x1xsoundc.47 ok 223 event_missing.titac5x1xsoundc.47 ok 224 event_spurious.titac5x1xsoundc.47 ok 225 get_value.titac5x1xsoundc.46 # titac5x1xsoundc.46 Record Decimation Filter ok 226 name.titac5x1xsoundc.46 ok 227 write_default.titac5x1xsoundc.46 ok 228 write_valid.titac5x1xsoundc.46 ok 229 write_invalid.titac5x1xsoundc.46 ok 230 event_missing.titac5x1xsoundc.46 ok 231 event_spurious.titac5x1xsoundc.46 ok 232 get_value.titac5x1xsoundc.45 # titac5x1xsoundc.45 GPI1 GPI ok 233 name.titac5x1xsoundc.45 # GPI1 GPI is not writeable ok 234 # SKIP write_default.titac5x1xsoundc.45 # GPI1 GPI is not writeable ok 235 # SKIP write_valid.titac5x1xsoundc.45 # GPI1 GPI is not writeable ok 236 # SKIP write_invalid.titac5x1xsoundc.45 ok 237 event_missing.titac5x1xsoundc.45 ok 238 event_spurious.titac5x1xsoundc.45 ok 239 get_value.titac5x1xsoundc.44 # titac5x1xsoundc.44 GPIO2 GPI ok 240 name.titac5x1xsoundc.44 # GPIO2 GPI is not writeable ok 241 # SKIP write_default.titac5x1xsoundc.44 # GPIO2 GPI is not writeable ok 242 # SKIP write_valid.titac5x1xsoundc.44 # GPIO2 GPI is not writeable ok 243 # SKIP write_invalid.titac5x1xsoundc.44 ok 244 event_missing.titac5x1xsoundc.44 ok 245 event_spurious.titac5x1xsoundc.44 ok 246 get_value.titac5x1xsoundc.43 # titac5x1xsoundc.43 PDM4 Phase Capture Volume ok 247 name.titac5x1xsoundc.43 ok 248 write_default.titac5x1xsoundc.43 ok 249 write_valid.titac5x1xsoundc.43 ok 250 write_invalid.titac5x1xsoundc.43 ok 251 event_missing.titac5x1xsoundc.43 ok 252 event_spurious.titac5x1xsoundc.43 ok 253 get_value.titac5x1xsoundc.42 # titac5x1xsoundc.42 PDM3 Phase Capture Volume ok 254 name.titac5x1xsoundc.42 ok 255 write_default.titac5x1xsoundc.42 ok 256 write_valid.titac5x1xsoundc.42 ok 257 write_invalid.titac5x1xsoundc.42 ok 258 event_missing.titac5x1xsoundc.42 ok 259 event_spurious.titac5x1xsoundc.42 ok 260 get_value.titac5x1xsoundc.41 # titac5x1xsoundc.41 PDM4 Fine Capture Volume ok 261 name.titac5x1xsoundc.41 ok 262 write_default.titac5x1xsoundc.41 ok 263 write_valid.titac5x1xsoundc.41 ok 264 write_invalid.titac5x1xsoundc.41 ok 265 event_missing.titac5x1xsoundc.41 ok 266 event_spurious.titac5x1xsoundc.41 ok 267 get_value.titac5x1xsoundc.40 # titac5x1xsoundc.40 PDM3 Fine Capture Volume ok 268 name.titac5x1xsoundc.40 ok 269 write_default.titac5x1xsoundc.40 ok 270 write_valid.titac5x1xsoundc.40 ok 271 write_invalid.titac5x1xsoundc.40 ok 272 event_missing.titac5x1xsoundc.40 ok 273 event_spurious.titac5x1xsoundc.40 ok 274 get_value.titac5x1xsoundc.39 # titac5x1xsoundc.39 PDM4 Digital Capture Volume ok 275 name.titac5x1xsoundc.39 ok 276 write_default.titac5x1xsoundc.39 ok 277 write_valid.titac5x1xsoundc.39 ok 278 write_invalid.titac5x1xsoundc.39 ok 279 event_missing.titac5x1xsoundc.39 ok 280 event_spurious.titac5x1xsoundc.39 ok 281 get_value.titac5x1xsoundc.38 # titac5x1xsoundc.38 PDM3 Digital Capture Volume ok 282 name.titac5x1xsoundc.38 ok 283 write_default.titac5x1xsoundc.38 ok 284 write_valid.titac5x1xsoundc.38 ok 285 write_invalid.titac5x1xsoundc.38 ok 286 event_missing.titac5x1xsoundc.38 ok 287 event_spurious.titac5x1xsoundc.38 ok 288 get_value.titac5x1xsoundc.37 # titac5x1xsoundc.37 PDM2 Phase Capture Volume ok 289 name.titac5x1xsoundc.37 ok 290 write_default.titac5x1xsoundc.37 ok 291 write_valid.titac5x1xsoundc.37 ok 292 write_invalid.titac5x1xsoundc.37 ok 293 event_missing.titac5x1xsoundc.37 ok 294 event_spurious.titac5x1xsoundc.37 ok 295 get_value.titac5x1xsoundc.36 # titac5x1xsoundc.36 PDM1 Phase Capture Volume ok 296 name.titac5x1xsoundc.36 ok 297 write_default.titac5x1xsoundc.36 ok 298 write_valid.titac5x1xsoundc.36 ok 299 write_invalid.titac5x1xsoundc.36 ok 300 event_missing.titac5x1xsoundc.36 ok 301 event_spurious.titac5x1xsoundc.36 ok 302 get_value.titac5x1xsoundc.35 # titac5x1xsoundc.35 PDM2 Fine Capture Volume ok 303 name.titac5x1xsoundc.35 ok 304 write_default.titac5x1xsoundc.35 ok 305 write_valid.titac5x1xsoundc.35 ok 306 write_invalid.titac5x1xsoundc.35 ok 307 event_missing.titac5x1xsoundc.35 ok 308 event_spurious.titac5x1xsoundc.35 ok 309 get_value.titac5x1xsoundc.34 # titac5x1xsoundc.34 PDM1 Fine Capture Volume ok 310 name.titac5x1xsoundc.34 ok 311 write_default.titac5x1xsoundc.34 ok 312 write_valid.titac5x1xsoundc.34 ok 313 write_invalid.titac5x1xsoundc.34 ok 314 event_missing.titac5x1xsoundc.34 ok 315 event_spurious.titac5x1xsoundc.34 ok 316 get_value.titac5x1xsoundc.33 # titac5x1xsoundc.33 PDM2 Digital Capture Volume ok 317 name.titac5x1xsoundc.33 ok 318 write_default.titac5x1xsoundc.33 ok 319 write_valid.titac5x1xsoundc.33 ok 320 write_invalid.titac5x1xsoundc.33 ok 321 event_missing.titac5x1xsoundc.33 ok 322 event_spurious.titac5x1xsoundc.33 ok 323 get_value.titac5x1xsoundc.32 # titac5x1xsoundc.32 PDM1 Digital Capture Volume ok 324 name.titac5x1xsoundc.32 ok 325 write_default.titac5x1xsoundc.32 ok 326 write_valid.titac5x1xsoundc.32 ok 327 write_invalid.titac5x1xsoundc.32 ok 328 event_missing.titac5x1xsoundc.32 ok 329 event_spurious.titac5x1xsoundc.32 ok 330 get_value.titac5x1xsoundc.31 # titac5x1xsoundc.31 PDM Clk Divider ok 331 name.titac5x1xsoundc.31 ok 332 write_default.titac5x1xsoundc.31 ok 333 write_valid.titac5x1xsoundc.31 ok 334 write_invalid.titac5x1xsoundc.31 ok 335 event_missing.titac5x1xsoundc.31 ok 336 event_spurious.titac5x1xsoundc.31 ok 337 get_value.titac5x1xsoundc.30 # titac5x1xsoundc.30 DAC2 Audio BW ok 338 name.titac5x1xsoundc.30 ok 339 write_default.titac5x1xsoundc.30 ok 340 write_valid.titac5x1xsoundc.30 ok 341 write_invalid.titac5x1xsoundc.30 ok 342 event_missing.titac5x1xsoundc.30 ok 343 event_spurious.titac5x1xsoundc.30 ok 344 get_value.titac5x1xsoundc.29 # titac5x1xsoundc.29 DAC2 CHB Gain Calibration Playback Volume ok 345 name.titac5x1xsoundc.29 ok 346 write_default.titac5x1xsoundc.29 ok 347 write_valid.titac5x1xsoundc.29 ok 348 write_invalid.titac5x1xsoundc.29 ok 349 event_missing.titac5x1xsoundc.29 ok 350 event_spurious.titac5x1xsoundc.29 ok 351 get_value.titac5x1xsoundc.28 # titac5x1xsoundc.28 DAC2 CHA Gain Calibration Playback Volume ok 352 name.titac5x1xsoundc.28 ok 353 write_default.titac5x1xsoundc.28 ok 354 write_valid.titac5x1xsoundc.28 ok 355 write_invalid.titac5x1xsoundc.28 ok 356 event_missing.titac5x1xsoundc.28 ok 357 event_spurious.titac5x1xsoundc.28 ok 358 get_value.titac5x1xsoundc.27 # titac5x1xsoundc.27 DAC2 CHB Digital Playback Volume ok 359 name.titac5x1xsoundc.27 ok 360 write_default.titac5x1xsoundc.27 ok 361 write_valid.titac5x1xsoundc.27 ok 362 write_invalid.titac5x1xsoundc.27 ok 363 event_missing.titac5x1xsoundc.27 ok 364 event_spurious.titac5x1xsoundc.27 ok 365 get_value.titac5x1xsoundc.26 # titac5x1xsoundc.26 DAC2 CHA Digital Playback Volume ok 366 name.titac5x1xsoundc.26 ok 367 write_default.titac5x1xsoundc.26 ok 368 write_valid.titac5x1xsoundc.26 ok 369 write_invalid.titac5x1xsoundc.26 ok 370 event_missing.titac5x1xsoundc.26 ok 371 event_spurious.titac5x1xsoundc.26 ok 372 get_value.titac5x1xsoundc.25 # titac5x1xsoundc.25 OUT2M Analog Level Playback Volume ok 373 name.titac5x1xsoundc.25 ok 374 write_default.titac5x1xsoundc.25 ok 375 write_valid.titac5x1xsoundc.25 ok 376 write_invalid.titac5x1xsoundc.25 ok 377 event_missing.titac5x1xsoundc.25 ok 378 event_spurious.titac5x1xsoundc.25 ok 379 get_value.titac5x1xsoundc.24 # titac5x1xsoundc.24 OUT2P Analog Level Playback Volume ok 380 name.titac5x1xsoundc.24 ok 381 write_default.titac5x1xsoundc.24 ok 382 write_valid.titac5x1xsoundc.24 ok 383 write_invalid.titac5x1xsoundc.24 ok 384 event_missing.titac5x1xsoundc.24 ok 385 event_spurious.titac5x1xsoundc.24 ok 386 get_value.titac5x1xsoundc.23 # titac5x1xsoundc.23 ADC2 Phase Capture Volume ok 387 name.titac5x1xsoundc.23 ok 388 write_default.titac5x1xsoundc.23 ok 389 write_valid.titac5x1xsoundc.23 ok 390 write_invalid.titac5x1xsoundc.23 ok 391 event_missing.titac5x1xsoundc.23 ok 392 event_spurious.titac5x1xsoundc.23 ok 393 get_value.titac5x1xsoundc.22 # titac5x1xsoundc.22 ADC2 Fine Capture Volume ok 394 name.titac5x1xsoundc.22 ok 395 write_default.titac5x1xsoundc.22 ok 396 write_valid.titac5x1xsoundc.22 ok 397 write_invalid.titac5x1xsoundc.22 ok 398 event_missing.titac5x1xsoundc.22 ok 399 event_spurious.titac5x1xsoundc.22 ok 400 get_value.titac5x1xsoundc.21 # titac5x1xsoundc.21 ADC2 Digital Capture Volume ok 401 name.titac5x1xsoundc.21 ok 402 write_default.titac5x1xsoundc.21 ok 403 write_valid.titac5x1xsoundc.21 ok 404 write_invalid.titac5x1xsoundc.21 ok 405 event_missing.titac5x1xsoundc.21 ok 406 event_spurious.titac5x1xsoundc.21 ok 407 get_value.titac5x1xsoundc.20 # titac5x1xsoundc.20 ADC2 Audio BW ok 408 name.titac5x1xsoundc.20 ok 409 write_default.titac5x1xsoundc.20 ok 410 write_valid.titac5x1xsoundc.20 ok 411 write_invalid.titac5x1xsoundc.20 ok 412 event_missing.titac5x1xsoundc.20 ok 413 event_spurious.titac5x1xsoundc.20 ok 414 get_value.titac5x1xsoundc.19 # titac5x1xsoundc.19 OUT_CH4_EN Playback Switch ok 415 name.titac5x1xsoundc.19 ok 416 write_default.titac5x1xsoundc.19 ok 417 write_valid.titac5x1xsoundc.19 ok 418 write_invalid.titac5x1xsoundc.19 ok 419 event_missing.titac5x1xsoundc.19 ok 420 event_spurious.titac5x1xsoundc.19 ok 421 get_value.titac5x1xsoundc.18 # titac5x1xsoundc.18 OUT_CH3_EN Playback Switch ok 422 name.titac5x1xsoundc.18 ok 423 write_default.titac5x1xsoundc.18 ok 424 write_valid.titac5x1xsoundc.18 ok 425 write_invalid.titac5x1xsoundc.18 ok 426 event_missing.titac5x1xsoundc.18 ok 427 event_spurious.titac5x1xsoundc.18 ok 428 get_value.titac5x1xsoundc.17 # titac5x1xsoundc.17 OUT_CH2_EN Playback Switch ok 429 name.titac5x1xsoundc.17 ok 430 write_default.titac5x1xsoundc.17 ok 431 write_valid.titac5x1xsoundc.17 ok 432 write_invalid.titac5x1xsoundc.17 ok 433 event_missing.titac5x1xsoundc.17 ok 434 event_spurious.titac5x1xsoundc.17 ok 435 get_value.titac5x1xsoundc.16 # titac5x1xsoundc.16 OUT_CH1_EN Playback Switch ok 436 name.titac5x1xsoundc.16 ok 437 write_default.titac5x1xsoundc.16 ok 438 write_valid.titac5x1xsoundc.16 ok 439 write_invalid.titac5x1xsoundc.16 ok 440 event_missing.titac5x1xsoundc.16 ok 441 event_spurious.titac5x1xsoundc.16 ok 442 get_value.titac5x1xsoundc.15 # titac5x1xsoundc.15 ASI_RX_CH8_EN Playback ok 443 name.titac5x1xsoundc.15 ok 444 write_default.titac5x1xsoundc.15 ok 445 write_valid.titac5x1xsoundc.15 ok 446 write_invalid.titac5x1xsoundc.15 ok 447 event_missing.titac5x1xsoundc.15 ok 448 event_spurious.titac5x1xsoundc.15 ok 449 get_value.titac5x1xsoundc.14 # titac5x1xsoundc.14 ASI_RX_CH7_EN Playback ok 450 name.titac5x1xsoundc.14 ok 451 write_default.titac5x1xsoundc.14 ok 452 write_valid.titac5x1xsoundc.14 ok 453 write_invalid.titac5x1xsoundc.14 ok 454 event_missing.titac5x1xsoundc.14 ok 455 event_spurious.titac5x1xsoundc.14 ok 456 get_value.titac5x1xsoundc.13 # titac5x1xsoundc.13 ASI_RX_CH6_EN Playback ok 457 name.titac5x1xsoundc.13 ok 458 write_default.titac5x1xsoundc.13 ok 459 write_valid.titac5x1xsoundc.13 ok 460 write_invalid.titac5x1xsoundc.13 ok 461 event_missing.titac5x1xsoundc.13 ok 462 event_spurious.titac5x1xsoundc.13 ok 463 get_value.titac5x1xsoundc.12 # titac5x1xsoundc.12 ASI_RX_CH5_EN Playback ok 464 name.titac5x1xsoundc.12 ok 465 write_default.titac5x1xsoundc.12 ok 466 write_valid.titac5x1xsoundc.12 ok 467 write_invalid.titac5x1xsoundc.12 ok 468 event_missing.titac5x1xsoundc.12 ok 469 event_spurious.titac5x1xsoundc.12 ok 470 get_value.titac5x1xsoundc.11 # titac5x1xsoundc.11 ASI_RX_CH4_EN Playback Switch ok 471 name.titac5x1xsoundc.11 ok 472 write_default.titac5x1xsoundc.11 ok 473 write_valid.titac5x1xsoundc.11 ok 474 write_invalid.titac5x1xsoundc.11 ok 475 event_missing.titac5x1xsoundc.11 ok 476 event_spurious.titac5x1xsoundc.11 ok 477 get_value.titac5x1xsoundc.10 # titac5x1xsoundc.10 ASI_RX_CH3_EN Playback Switch ok 478 name.titac5x1xsoundc.10 ok 479 write_default.titac5x1xsoundc.10 ok 480 write_valid.titac5x1xsoundc.10 ok 481 write_invalid.titac5x1xsoundc.10 ok 482 event_missing.titac5x1xsoundc.10 ok 483 event_spurious.titac5x1xsoundc.10 ok 484 get_value.titac5x1xsoundc.9 # titac5x1xsoundc.9 DAC1 CHB Gain Calibration Playback Volume ok 485 name.titac5x1xsoundc.9 ok 486 write_default.titac5x1xsoundc.9 ok 487 write_valid.titac5x1xsoundc.9 ok 488 write_invalid.titac5x1xsoundc.9 ok 489 event_missing.titac5x1xsoundc.9 ok 490 event_spurious.titac5x1xsoundc.9 ok 491 get_value.titac5x1xsoundc.8 # titac5x1xsoundc.8 DAC1 CHA Gain Calibration Playback Volume ok 492 name.titac5x1xsoundc.8 ok 493 write_default.titac5x1xsoundc.8 ok 494 write_valid.titac5x1xsoundc.8 ok 495 write_invalid.titac5x1xsoundc.8 ok 496 event_missing.titac5x1xsoundc.8 ok 497 event_spurious.titac5x1xsoundc.8 ok 498 get_value.titac5x1xsoundc.7 # titac5x1xsoundc.7 DAC1 CHB Digital Playback Volume ok 499 name.titac5x1xsoundc.7 ok 500 write_default.titac5x1xsoundc.7 ok 501 write_valid.titac5x1xsoundc.7 ok 502 write_invalid.titac5x1xsoundc.7 ok 503 event_missing.titac5x1xsoundc.7 ok 504 event_spurious.titac5x1xsoundc.7 ok 505 get_value.titac5x1xsoundc.6 # titac5x1xsoundc.6 DAC1 CHA Digital Playback Volume ok 506 name.titac5x1xsoundc.6 ok 507 write_default.titac5x1xsoundc.6 ok 508 write_valid.titac5x1xsoundc.6 ok 509 write_invalid.titac5x1xsoundc.6 ok 510 event_missing.titac5x1xsoundc.6 ok 511 event_spurious.titac5x1xsoundc.6 ok 512 get_value.titac5x1xsoundc.5 # titac5x1xsoundc.5 OUT1M Analog Level Playback Volume ok 513 name.titac5x1xsoundc.5 ok 514 write_default.titac5x1xsoundc.5 ok 515 write_valid.titac5x1xsoundc.5 ok 516 write_invalid.titac5x1xsoundc.5 ok 517 event_missing.titac5x1xsoundc.5 ok 518 event_spurious.titac5x1xsoundc.5 ok 519 get_value.titac5x1xsoundc.4 # titac5x1xsoundc.4 OUT1P Analog Level Playback Volume ok 520 name.titac5x1xsoundc.4 ok 521 write_default.titac5x1xsoundc.4 ok 522 write_valid.titac5x1xsoundc.4 ok 523 write_invalid.titac5x1xsoundc.4 ok 524 event_missing.titac5x1xsoundc.4 ok 525 event_spurious.titac5x1xsoundc.4 ok 526 get_value.titac5x1xsoundc.3 # titac5x1xsoundc.3 DAC1 Audio BW ok 527 name.titac5x1xsoundc.3 ok 528 write_default.titac5x1xsoundc.3 ok 529 write_valid.titac5x1xsoundc.3 ok 530 write_invalid.titac5x1xsoundc.3 ok 531 event_missing.titac5x1xsoundc.3 ok 532 event_spurious.titac5x1xsoundc.3 ok 533 get_value.titac5x1xsoundc.2 # titac5x1xsoundc.2 Playback Decimation Filter ok 534 name.titac5x1xsoundc.2 ok 535 write_default.titac5x1xsoundc.2 ok 536 write_valid.titac5x1xsoundc.2 ok 537 write_invalid.titac5x1xsoundc.2 ok 538 event_missing.titac5x1xsoundc.2 ok 539 event_spurious.titac5x1xsoundc.2 ok 540 get_value.titac5x1xsoundc.1 # titac5x1xsoundc.1 ADC2 Common-mode Tolerance ok 541 name.titac5x1xsoundc.1 ok 542 write_default.titac5x1xsoundc.1 ok 543 write_valid.titac5x1xsoundc.1 ok 544 write_invalid.titac5x1xsoundc.1 ok 545 event_missing.titac5x1xsoundc.1 ok 546 event_spurious.titac5x1xsoundc.1 ok 547 get_value.titac5x1xsoundc.0 # titac5x1xsoundc.0 ADC1 Common-mode Tolerance ok 548 name.titac5x1xsoundc.0 ok 549 write_default.titac5x1xsoundc.0 ok 550 write_valid.titac5x1xsoundc.0 ok 551 write_invalid.titac5x1xsoundc.0 ok 552 event_missing.titac5x1xsoundc.0 ok 553 event_spurious.titac5x1xsoundc.0 # 6 skipped test(s) detected. Consider enabling relevant config options to improve coverage. # Totals: pass:547 fail:0 xfail:0 xpass:0 skip:6 error:0
Signed-off-by: Niranjan H Y niranjan.hy@ti.com
Niranjan H Y (4): ASoc: tac5x1x: add codec driver tac5x1x family Asoc: tac5x1x: document tac5x1x codec Asoc: pcm6240: remove support for taac5x1x family ASoc: pcm6240: dt-bindings device support list update
.../devicetree/bindings/sound/ti,pcm6240.yaml | 10 - .../devicetree/bindings/sound/ti,tac5x1x.yaml | 248 ++ sound/soc/codecs/Kconfig | 12 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/pcm6240.c | 124 +- sound/soc/codecs/pcm6240.h | 4 - sound/soc/codecs/tac5x1x-i2c.c | 2225 +++++++++++++++++ sound/soc/codecs/tac5x1x.h | 300 +++ 8 files changed, 2790 insertions(+), 135 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/ti,tac5x1x.yaml create mode 100644 sound/soc/codecs/tac5x1x-i2c.c create mode 100644 sound/soc/codecs/tac5x1x.h
-- 2.45.2

tac5x1x family are series of low-power and high performance mono/stereo audio codecs consists of ADC and DAC combinations. The patch adds supports for Codecs(DAC & ADC), ADC only and DAC only configurations available in the tac5x1x family.
Signed-off-by: Niranjan H Y niranjan.hy@ti.com
--- v2: - Merge tac5x1x and tac5x1x-i2c into one tac5x1x-i2c - Kconfig changes for * merge to removed SND_SOC_TAC5X1X * select REGMAP_I2C for SND_SOC_TAC5X1X_I2C - Makefile changes for * merging tac5x1x and tac5x1x-i2c * sorted entry added for tac5x1x-i2c - Removed a unwanted log during probe - Removed "Reserved" keyword for bitmask - Removed retry with sleep logic for regmap read/write - Refactored interrupt handling code to have only thread function. Removed work function for interrupt handling. Also removed disabling/enabling interrupts in thread function. - Replace EXPORT_SYMBOL to EXPORT_SYMBOL_GPL for tac5x1x_regmap - Moved impedance related settings to DTS - Used plain control for on/off switch for DAC related channel controls. - Removed TDM slot selection mixer control. Configured the slot for the I2S mode during the .hw_params call - Moved some ADC related settings to device tree as they are one time configurations. - Replaced regulator APIs with regulator bulk APIs - Moved cache sync after regulator enable during _resume - Removed unwanted member variables - Fixed "mixer control" error with certain dts configurations - Fixed number of chars more than 80 for many lines --- sound/soc/codecs/Kconfig | 12 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tac5x1x-i2c.c | 2225 ++++++++++++++++++++++++++++++++ sound/soc/codecs/tac5x1x.h | 300 +++++ 4 files changed, 2539 insertions(+) create mode 100644 sound/soc/codecs/tac5x1x-i2c.c create mode 100644 sound/soc/codecs/tac5x1x.h
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6d7e4725d89c..32f8109add89 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -259,6 +259,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_STA529 imply SND_SOC_STAC9766 imply SND_SOC_STI_SAS + imply SND_SOC_TAC5X1X_I2C imply SND_SOC_TAS2552 imply SND_SOC_TAS2562 imply SND_SOC_TAS2764 @@ -2008,6 +2009,17 @@ config SND_SOC_STAC9766 config SND_SOC_STI_SAS tristate "codec Audio support for STI SAS codec"
+config SND_SOC_TAC5X1X_I2C + tristate "Texas Instruments TAC5X1X family driver based on I2C" + depends on I2C && REGMAP_I2C + select REGMAP_I2C + help + Enable support for Texas Instruments TAC5X1X family Audio chips. + The family consists mono/stereo audio codecs, DACs and ADCs. + Includes support for TAC5311-Q1, TAC5411-Q1, TAC5111, TAC5211, + TAA5212, TAA5412-Q1, TAD5112, TAD5212, TAC5312, TAC5412-Q1, + TAC5112, TAC5212 + config SND_SOC_TAS2552 tristate "Texas Instruments TAS2552 Mono Audio amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index a68c3d192a1b..ba8d3504d561 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -303,6 +303,7 @@ snd-soc-sta350-y := sta350.o snd-soc-sta529-y := sta529.o snd-soc-stac9766-y := stac9766.o snd-soc-sti-sas-y := sti-sas.o +snd-soc-tac5x1x-i2c-y := tac5x1x-i2c.o snd-soc-tas5086-y := tas5086.o snd-soc-tas571x-y := tas571x.o snd-soc-tas5720-y := tas5720.o @@ -721,6 +722,7 @@ obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o +obj-$(CONFIG_SND_SOC_TAC5X1X_I2C) += snd-soc-tac5x1x-i2c.o obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o obj-$(CONFIG_SND_SOC_TAS2764) += snd-soc-tas2764.o diff --git a/sound/soc/codecs/tac5x1x-i2c.c b/sound/soc/codecs/tac5x1x-i2c.c new file mode 100644 index 000000000000..c41e54ddffd6 --- /dev/null +++ b/sound/soc/codecs/tac5x1x-i2c.c @@ -0,0 +1,2225 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// tac5x1x.c +// +// Copyright (C) 2022 - 2025 Texas Instruments Incorporated +// +// Author: Kevin Lu kevin-lu@ti.com +// Author: Kokila Karuppusamy kokila.karuppusamy@ti.com +// Author: Niranjan H Y niranjan.hy@ti.com +// + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/of_irq.h> +#include <linux/regulator/consumer.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> +#include <linux/regmap.h> +#include <linux/device.h> +#include <sound/tlv.h> +#include <linux/i2c.h> +#include <linux/bitops.h> + +#include "tac5x1x.h" + +struct tac5x1x_setup_gpio { + s32 gpio_func[3]; + s32 gpio_drive[3]; + s32 gpi1_func; + s32 gpa_gpio; +}; + +struct tac5x1x_input_diag_config { + s32 in_ch_en; + s32 out_ch_en; + s32 incl_se_inm; + s32 incl_ac_coup; +}; + +struct tac5x1x_irqinfo { + s32 irq_gpio; + s32 irq; + bool irq_enable; + u32 *latch_regs; + u8 *latch_data; +}; + +struct tac5x1x_priv { + struct snd_soc_component *component; + struct regmap *regmap; + struct device *dev; + enum tac5x1x_type codec_type; + s32 vref_vg; + s32 micbias_en; + s32 micbias_vg; + s32 uad_en; + s32 vad_en; + s32 uag_en; + s32 micbias_threshold[2]; + s32 gpa_threshold[2]; + s32 adc_impedance[2]; + s32 out2x_vcom_cfg; + struct tac5x1x_setup_gpio *gpio_setup; + struct tac5x1x_irqinfo irqinfo; + struct tac5x1x_input_diag_config input_diag_config; +}; + +static int tac5x1x_num_regulators = 2; +static struct regulator_bulk_data tac5x1x_regulators[] = { + {.supply = "iovdd"}, + {.supply = "avdd"}, +}; + +struct mask_to_txt { + u8 mask; + const char *const name; +}; + +struct interrupt_info { + u32 reg; + u32 count; + const struct mask_to_txt *mask_str_map; +}; + +#define TAC5X1X_EVENT(bit, evt_txt) (\ + (struct mask_to_txt) { \ + .mask = BIT((bit)), \ + .name = evt_txt \ + }) + +static const struct mask_to_txt int_chx_latch[] = { + TAC5X1X_EVENT(7, "Input Channel1 fault"), + TAC5X1X_EVENT(6, "Input Channel2 fault"), + TAC5X1X_EVENT(5, "Output Channel1 fault"), + TAC5X1X_EVENT(4, "Output Channel2 fault"), + TAC5X1X_EVENT(3, "Short to VBAT_IN"), +}; + +static const struct mask_to_txt in_ch1_latch[] = { + TAC5X1X_EVENT(7, "IN_CH1 open Input"), + TAC5X1X_EVENT(6, "IN_CH1 Input shorted"), + TAC5X1X_EVENT(5, "IN_CH1 INP shorted to GND"), + TAC5X1X_EVENT(4, "IN_CH1 INM shorted to GND"), + TAC5X1X_EVENT(3, "IN_CH1 INP shorted to MICBIAS"), + TAC5X1X_EVENT(2, "IN_CH1 INM shorted to MICBIAS"), + TAC5X1X_EVENT(1, "IN_CH1 INP shorted to VBAT_IN"), + TAC5X1X_EVENT(0, "IN_CH1 INM shorted to VBAT_IN"), +}; + +static const struct mask_to_txt in_ch2_latch[] = { + TAC5X1X_EVENT(7, "IN_CH2 open Input"), + TAC5X1X_EVENT(6, "IN_CH2 Input shorted"), + TAC5X1X_EVENT(5, "IN_CH2 INP shorted to GND"), + TAC5X1X_EVENT(4, "IN_CH2 INM shorted to GND"), + TAC5X1X_EVENT(3, "IN_CH2 INP shorted to MICBIAS"), + TAC5X1X_EVENT(2, "IN_CH2 INM shorted to MICBIAS"), + TAC5X1X_EVENT(1, "IN_CH2 INP shorted to VBAT_IN"), + TAC5X1X_EVENT(0, "IN_CH2 INM shorted to VBAT_IN"), +}; + +static const struct mask_to_txt out_ch1_latch[] = { + TAC5X1X_EVENT(7, "OUT_CH1 OUT1P Short circuit Fault"), + TAC5X1X_EVENT(6, "OUT_CH1 OUT1M Short circuit Fault"), + TAC5X1X_EVENT(5, "OUT_CH1 DRVRP Virtual Ground Fault"), + TAC5X1X_EVENT(4, "OUT_CH1 DRVRM Virtual ground Fault"), + /* masks */ + TAC5X1X_EVENT(3, "OUT_CH1 ADC CH1 Mask"), + TAC5X1X_EVENT(2, "OUT_CH1 ADC CH2 MASK"), +}; + +static const struct mask_to_txt out_ch2_latch[] = { + TAC5X1X_EVENT(7, "OUT_CH2 OUT2P Short circuit Fault"), + TAC5X1X_EVENT(6, "OUT_CH2 OUT2M Short circuit Fault"), + TAC5X1X_EVENT(5, "OUT_CH2 DRVRP Virtual Ground Fault"), + TAC5X1X_EVENT(4, "OUT_CH2 DRVRM Virtual ground Fault"), + /* mask */ + TAC5X1X_EVENT(1, "AREG SC Fault Mask"), + TAC5X1X_EVENT(0, "AREG SC Fault"), +}; + +static const struct mask_to_txt int_latch1[] = { + TAC5X1X_EVENT(7, "CH1 INP Over Voltage"), + TAC5X1X_EVENT(6, "CH1 INM Over Voltage"), + TAC5X1X_EVENT(5, "CH2 INP over Voltage"), + TAC5X1X_EVENT(4, "CH2 INM Over Voltage"), + TAC5X1X_EVENT(3, "Headset Insert Detection"), + TAC5X1X_EVENT(2, "Headset Remove Detection"), + TAC5X1X_EVENT(1, "Headset Hook"), + TAC5X1X_EVENT(0, "MIPS Overload"), +}; + +static const struct mask_to_txt int_latch2[] = { + TAC5X1X_EVENT(7, "GPA Up threashold Fault"), + TAC5X1X_EVENT(6, "GPA low threashold Fault"), + TAC5X1X_EVENT(5, "VAD Power up detect"), + TAC5X1X_EVENT(4, "VAD power down detect"), + TAC5X1X_EVENT(3, "Micbias short circuit"), + TAC5X1X_EVENT(2, "Micbias high current fault"), + TAC5X1X_EVENT(1, "Micbias low current fault"), + TAC5X1X_EVENT(0, "Micbias Over voltage fault"), +}; + +static const struct mask_to_txt int_latch_0[] = { + TAC5X1X_EVENT(7, "Clock Error"), + TAC5X1X_EVENT(6, "PLL Lock"), + TAC5X1X_EVENT(5, "Boost Over Temperature"), + TAC5X1X_EVENT(4, "Boost Over Current"), + TAC5X1X_EVENT(3, "Boost MO"), +}; + +#define LTCH_TO_MASK_STR_MAP(latch_reg, str_map, map_size) (\ + (struct interrupt_info){ \ + .reg = (latch_reg), \ + .count = (map_size), \ + .mask_str_map = (str_map), \ + }) + +static const struct interrupt_info intr_info_list[] = { + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_CHX_LTCH, int_chx_latch, + ARRAY_SIZE(int_chx_latch)), + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_IN_CH1_LTCH, in_ch1_latch, + ARRAY_SIZE(in_ch1_latch)), + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_IN_CH2_LTCH, in_ch2_latch, + ARRAY_SIZE(in_ch2_latch)), + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_OUT_CH1_LTCH, out_ch1_latch, + ARRAY_SIZE(out_ch1_latch)), + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_OUT_CH2_LTCH, out_ch2_latch, + ARRAY_SIZE(out_ch2_latch)), + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_INT_LTCH1, int_latch1, + ARRAY_SIZE(int_latch1)), + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_INT_LTCH2, int_latch2, + ARRAY_SIZE(int_latch2)), + /* This should be the last entry */ + LTCH_TO_MASK_STR_MAP(TAC5X1X_REG_INT_LTCH0, int_latch_0, + ARRAY_SIZE(int_latch_0)), +}; + +static const struct regmap_range_cfg tac5x1x_ranges[] = { + { + .range_min = 0, + .range_max = 12 * 128, + .selector_reg = TAC_PAGE_SELECT, + .selector_mask = GENMASK(7, 0), + .selector_shift = 0, + .window_start = 0, + .window_len = 128, + }, +}; + +static bool tac5x1x_volatile_regs(struct device *dev, unsigned int reg) +{ + bool is_volatile; + + switch (reg) { + case TAC5X1X_RESET: + case TAC5X1X_REG_INT_LTCH0 ... TAC5X1X_REG_INT_LTCH2: + is_volatile = true; + break; + + default: + is_volatile = false; + break; + } + + return is_volatile; +} + +static const struct regmap_config tac5x1x_regmap = { + .max_register = 12 * 128, + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_MAPLE, + .ranges = tac5x1x_ranges, + .volatile_reg = tac5x1x_volatile_regs, + .num_ranges = ARRAY_SIZE(tac5x1x_ranges), +}; + +static void process_one_interrupt(struct tac5x1x_priv *tac5x1x, s32 index, + s32 value) +{ + u32 map_count, i; + const struct mask_to_txt *map_items; + + map_count = intr_info_list[index].count; + map_items = intr_info_list[index].mask_str_map; + + for (i = 0; i < map_count; i++) { + if (value & map_items[i].mask) + dev_err(tac5x1x->dev, "Interrupt %s detected\n", + map_items[i].name); + } +} + +static irqreturn_t irq_thread_func(s32 irq, void *dev_id) +{ + u8 latch_set = 0; + u32 latch_count; + s32 i, ret; + struct tac5x1x_priv *tac5x1x = (struct tac5x1x_priv *)dev_id; + + latch_count = ARRAY_SIZE(intr_info_list); + + ret = regmap_multi_reg_read(tac5x1x->regmap, + tac5x1x->irqinfo.latch_regs, + tac5x1x->irqinfo.latch_data, latch_count); + if (ret) { + dev_err(tac5x1x->dev, + "interrupt: latch register read failed"); + return IRQ_HANDLED; + } + + for (i = 0; i < latch_count; i++) { + dev_dbg(tac5x1x->dev, "reg=0x%0x, val=0x%02x", + tac5x1x->irqinfo.latch_regs[i], + tac5x1x->irqinfo.latch_data[i]); + latch_set |= tac5x1x->irqinfo.latch_data[i] & 0xff; + } + + if (!latch_set) + return IRQ_NONE; + + for (i = 0; i < latch_count; i++) { + if (!tac5x1x->irqinfo.latch_data[i]) + continue; + process_one_interrupt(tac5x1x, i, + tac5x1x->irqinfo.latch_data[i]); + tac5x1x->irqinfo.latch_data[i] = 0; + } + + return IRQ_HANDLED; +} + +static s32 tac5x1x_register_interrupt(struct tac5x1x_priv *tac5x1x) +{ + struct device_node *np = tac5x1x->dev->of_node; + s32 ret, latch_count, i; + u32 *latch_regs; + u8 *latch_data; + + latch_count = ARRAY_SIZE(intr_info_list); + tac5x1x->irqinfo.irq = of_irq_get(np, 0); + if (tac5x1x->irqinfo.irq < 0) + return tac5x1x->irqinfo.irq; + + latch_regs = devm_kzalloc(tac5x1x->dev, latch_count * sizeof(u32), + GFP_KERNEL); + latch_data = devm_kzalloc(tac5x1x->dev, latch_count * sizeof(u8), + GFP_KERNEL); + if (!latch_data || !latch_regs) + return -ENOMEM; + + for (i = 0; i < latch_count; i++) + latch_regs[i] = intr_info_list[i].reg; + + tac5x1x->irqinfo.latch_regs = latch_regs; + tac5x1x->irqinfo.latch_data = latch_data; + + ret = devm_request_threaded_irq(tac5x1x->dev, tac5x1x->irqinfo.irq, + NULL, irq_thread_func, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "TAC-IRQ", tac5x1x); + if (ret) + dev_err(tac5x1x->dev, "request irq failed, irq=%d ret %d\n", + tac5x1x->irqinfo.irq, ret); + + return ret; +} + +static s32 tac5x1x_get_GPIO1_gpio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + s32 val; + + val = snd_soc_component_read(component, TAC5X1X_GPIOVAL); + ucontrol->value.integer.value[0] = !!(val & TAC5X1X_GPIO1_MON); + + return 0; +}; + +static s32 tac5x1x_get_GPIO2_gpio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + s32 val; + + val = snd_soc_component_read(component, TAC5X1X_GPIOVAL); + ucontrol->value.integer.value[0] = !!(val & TAC5X1X_GPIO2_MON); + + return 0; +}; + +static s32 tac5x1x_get_GPI1_gpio(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + s32 val; + + val = snd_soc_component_read(component, TAC5X1X_GPIOVAL); + ucontrol->value.integer.value[0] = !!(val & TAC5X1X_GPI1_MON); + + return 0; +}; + +static const struct snd_kcontrol_new GPIO1_I[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "GPIO1 GPI", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = tac5x1x_get_GPIO1_gpio, + .info = snd_soc_info_bool_ext, + } +}; + +static const struct snd_kcontrol_new GPIO2_I[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "GPIO2 GPI", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = tac5x1x_get_GPIO2_gpio, + .info = snd_soc_info_bool_ext, + } +}; + +static const struct snd_kcontrol_new tac5x1x_GPI1[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "GPI1 GPI", + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = tac5x1x_get_GPI1_gpio, + .info = snd_soc_info_bool_ext, + } +}; + +/* Record */ +/* ADC Analog/PDM Selection */ +static const char *const tac5x1x_input_source_text[] = {"Analog", "PDM"}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_in1_source_enum, TAC5X1X_INTF4, 7, + tac5x1x_input_source_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_in2_source_enum, TAC5X1X_INTF4, 6, + tac5x1x_input_source_text); + +static const struct snd_kcontrol_new tac5x1x_dapm_in1_source_control[] = { + SOC_DAPM_ENUM("CH1 Source MUX", tac5x1x_in1_source_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_dapm_in2_source_control[] = { + SOC_DAPM_ENUM("CH2 Source MUX", tac5x1x_in2_source_enum), +}; + +static const char *const tad5x1x_input_source_text[] = {"Disable", "PDM"}; +static SOC_ENUM_SINGLE_DECL(tad5x1x_in1_source_enum, TAC5X1X_INTF4, 7, + tad5x1x_input_source_text); +static SOC_ENUM_SINGLE_DECL(tad5x1x_in2_source_enum, TAC5X1X_INTF4, 6, + tad5x1x_input_source_text); + +static const struct snd_kcontrol_new tad5x1x_dapm_in1_source_control[] = { + SOC_DAPM_ENUM("CH1 Source MUX", tad5x1x_in1_source_enum), +}; + +static const struct snd_kcontrol_new tad5x1x_dapm_in2_source_control[] = { + SOC_DAPM_ENUM("CH2 Source MUX", tad5x1x_in2_source_enum), +}; + +/* ADC Analog source Selection */ +static const char *const tac5x1x_input_analog_sel_text[] = { + "Differential", + "Single-ended", + "Single-ended mux INxP", + "Single-ended mux INxM", +}; + +static const char *const tac5x1x_input_analog2_sel_text[] = { + "Differential", + "Single-ended", +}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc1_config_enum, TAC5X1X_ADCCH1C0, 6, + tac5x1x_input_analog_sel_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc2_config_enum, TAC5X1X_ADCCH2C0, 6, + tac5x1x_input_analog2_sel_text); + +static const struct snd_kcontrol_new tac5x1x_dapm_adc1_config_control[] = { + SOC_DAPM_ENUM("ADC1 Analog MUX", tac5x1x_adc1_config_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_dapm_adc2_config_control[] = { + SOC_DAPM_ENUM("ADC2 Analog MUX", tac5x1x_adc2_config_enum), +}; + +/* + * ADC full-scale selection + * 2/10-VRMS is for TAX52xx/TAX51xx devices + * 4/5-VRMS is for TAX54xx/TAX53xx devices + */ +static const char *const tac5x1x_adc_fscale_text[] = {"2/10-VRMS", + "4/5-VRMS"}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc1_fscale_enum, TAC5X1X_ADCCH1C0, 1, + tac5x1x_adc_fscale_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc2_fscale_enum, TAC5X1X_ADCCH2C0, 1, + tac5x1x_adc_fscale_text); + +static const struct snd_kcontrol_new tac5x1x_dapm_adc1_fscale_control[] = { + SOC_DAPM_ENUM("ADC1 FSCALE MUX", tac5x1x_adc1_fscale_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_dapm_adc2_fscale_control[] = { + SOC_DAPM_ENUM("ADC2 FSCALE MUX", tac5x1x_adc2_fscale_enum), +}; + +/* PDM Data input pin Selection */ +static const char *const pdm_pin_text[] = { + "Disable", + "GPIO1", + "GPIO2", + "GPI1", +}; + +static SOC_ENUM_SINGLE_DECL(pdm_12_pin_enum, TAC5X1X_INTF4, 2, pdm_pin_text); +static SOC_ENUM_SINGLE_DECL(pdm_34_pin_enum, TAC5X1X_INTF4, 0, pdm_pin_text); +static const struct snd_kcontrol_new pdm_12_pin_controls[] = { + SOC_DAPM_ENUM("PDM chn12 Datain Select", pdm_12_pin_enum), +}; + +static const struct snd_kcontrol_new pdm_34_pin_controls[] = { + SOC_DAPM_ENUM("PDM chn34 Datain Select", pdm_34_pin_enum), +}; + +static const char *const pdmclk_text[] = { + "2.8224 MHz or 3.072 MHz", "1.4112 MHz or 1.536 MHz", + "705.6 kHz or 768 kHz", "5.6448 MHz or 6.144 MHz"}; + +static SOC_ENUM_SINGLE_DECL(pdmclk_select_enum, TAC5X1X_CNTCLK0, 6, + pdmclk_text); + +/* Digital Volume control. From -80 to 47 dB in 0.5 dB steps */ +static DECLARE_TLV_DB_SCALE(record_dig_vol_tlv, -8000, 50, 0); + +/* Gain Calibration control. From -0.8db to 0.7db dB in 0.1 dB steps */ +static DECLARE_TLV_DB_MINMAX(record_gain_cali_tlv, -80, 70); + +/* Analog Level control. From -12 to 24 dB in 6 dB steps */ +static DECLARE_TLV_DB_SCALE(playback_analog_level_tlv, -1200, 600, 0); + +/* Digital Volume control. From -100 to 27 dB in 0.5 dB steps */ +static DECLARE_TLV_DB_SCALE(dac_dig_vol_tlv, -10000, 50, 0); // mute ? + +/* Gain Calibration control. From -0.8db to 0.7db dB in 0.1 dB steps */ +static DECLARE_TLV_DB_MINMAX(playback_gain_cali_tlv, -80, 70); + +/* Output Source Selection */ +static const char *const tac5x1x_output_source_text[] = { + "Disabled", + "DAC Input", + "Analog Bypass", + "DAC + Analog Bypass Mix", + "DAC -> OUTxP, INxP -> OUTxM", + "INxM -> OUTxP, DAC -> OUTxM", +}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_out1_source_enum, TAC5X1X_OUT1CFG0, 5, + tac5x1x_output_source_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_out2_source_enum, TAC5X1X_OUT2CFG0, 5, + tac5x1x_output_source_text); + +static const struct snd_kcontrol_new tac5x1x_dapm_out1_source_control[] = { + SOC_DAPM_ENUM("OUT1X MUX", tac5x1x_out1_source_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_dapm_out2_source_control[] = { + SOC_DAPM_ENUM("OUT2X MUX", tac5x1x_out2_source_enum), +}; + +/* Output Config Selection */ +static const char *const tac5x1x_output_config_text[] = { + "Differential", + "Stereo Single-ended", + "Mono Single-ended at OUTxP only", + "Mono Single-ended at OUTxM only", + "Pseudo differential with OUTxM as VCOM", + "Pseudo differential with OUTxM as external sensing", + "Pseudo differential with OUTxP as VCOM", +}; + +static const char *const tac5x1x_output2_config_text[] = { + "Differential", + "Stereo Single-ended", + "Mono Single-ended at OUTxP only", + "Mono Single-ended at OUTxM only", + "Pseudo differential with OUTxM as VCOM", + "Pseudo differential with OUTxP as VCOM", +}; + +static const s32 tac5x1x_output2_config_values[] = { + 0, 1, 2, 3, 4, 6 +}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_out1_config_enum, TAC5X1X_OUT1CFG0, 2, + tac5x1x_output_config_text); +static SOC_VALUE_ENUM_SINGLE_DECL(tac5x1x_out2_config_enum, + TAC5X1X_OUT2CFG0, 2, 0x7, + tac5x1x_output2_config_text, + tac5x1x_output2_config_values); + +static const struct snd_kcontrol_new tac5x1x_dapm_out1_config_control[] = { + SOC_DAPM_ENUM("OUT1X Config MUX", tac5x1x_out1_config_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_dapm_out2_config_control[] = { + SOC_DAPM_ENUM("OUT2X Config MUX", tac5x1x_out2_config_enum), +}; + +static const char *const tac5x1x_wideband_text[] = { + "Audio BW 24-kHz", + "Wide BW 96-kHz", +}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc1_wideband_enum, TAC5X1X_ADCCH1C0, 0, + tac5x1x_wideband_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc2_wideband_enum, TAC5X1X_ADCCH2C0, 0, + tac5x1x_wideband_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_dac1_wideband_enum, TAC5X1X_OUT1CFG1, 0, + tac5x1x_wideband_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_dac2_wideband_enum, TAC5X1X_OUT2CFG1, 0, + tac5x1x_wideband_text); + +static const char *const tac5x1x_tolerance_text[] = { + "AC Coupled with 100mVpp", + "AC/DC Coupled with 1Vpp", + "AC/DC Coupled with Rail-to-rail", +}; + +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc1_tolerance_enum, TAC5X1X_ADCCH1C0, 2, + tac5x1x_tolerance_text); +static SOC_ENUM_SINGLE_DECL(tac5x1x_adc2_tolerance_enum, TAC5X1X_ADCCH2C0, 2, + tac5x1x_tolerance_text); + +/* Output Drive Selection */ +static const char *const tac5x1x_output_driver_text[] = { + "Line-out", + "Headphone", + "4 ohm", + "FD Receiver/Debug", +}; + +static SOC_ENUM_SINGLE_DECL(out1p_driver_enum, TAC5X1X_OUT1CFG1, 6, + tac5x1x_output_driver_text); + +static SOC_ENUM_SINGLE_DECL(out2p_driver_enum, TAC5X1X_OUT2CFG1, 6, + tac5x1x_output_driver_text); + +static const struct snd_kcontrol_new tac5x1x_dapm_out1_driver_control[] = { + SOC_DAPM_ENUM("OUT1 driver MUX", out1p_driver_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_dapm_out2_driver_control[] = { + SOC_DAPM_ENUM("OUT2 driver MUX", out2p_driver_enum), +}; + +/* Decimation Filter Selection */ +static const char *const decimation_filter_text[] = { + "Linear Phase", "Low Latency", "Ultra-low Latency"}; + +static SOC_ENUM_SINGLE_DECL(decimation_filter_record_enum, TAC5X1X_DSP0, 6, + decimation_filter_text); +static SOC_ENUM_SINGLE_DECL(decimation_filter_playback_enum, TAC5X1X_DSP1, 6, + decimation_filter_text); + +static const struct snd_kcontrol_new tx_ch1_asi_switch = + SOC_DAPM_SINGLE("Capture Switch", TAC5X1X_PASITXCH1, 5, 1, 0); +static const struct snd_kcontrol_new tx_ch2_asi_switch = + SOC_DAPM_SINGLE("Capture Switch", TAC5X1X_PASITXCH2, 5, 1, 0); +static const struct snd_kcontrol_new tx_ch3_asi_switch = + SOC_DAPM_SINGLE("Capture Switch", TAC5X1X_PASITXCH3, 5, 1, 0); +static const struct snd_kcontrol_new tx_ch4_asi_switch = + SOC_DAPM_SINGLE("Capture Switch", TAC5X1X_PASITXCH4, 5, 1, 0); + +static const struct snd_kcontrol_new rx_ch1_asi_switch = + SOC_DAPM_SINGLE("Switch", TAC5X1X_PASIRXCH1, 5, 1, 0); +static const struct snd_kcontrol_new rx_ch2_asi_switch = + SOC_DAPM_SINGLE("Switch", TAC5X1X_PASIRXCH2, 5, 1, 0); + +static const char *const rx_ch5_asi_cfg_text[] = { + "Disable", + "DAC channel data", + "ADC channel output loopback", +}; + +static const char *const rx_ch6_asi_cfg_text[] = { + "Disable", + "DAC channel data", + "ADC channel output loopback", + "Channel Input to ICLA device", +}; + +static const char *const tx_ch5_asi_cfg_text[] = { + "Tristate", + "Input Channel Loopback data", + "Echo reference Channel data", +}; + +static const char *const tx_ch7_asi_cfg_text[] = { + "Tristate", + "Vbat_Wlby2,Temp_Wlby2", + "echo_ref_ch1,echo_ref_ch2", +}; + +static const char *const tx_ch8_asi_cfg_text[] = { + "Tristate", + "ICLA data", +}; + +static const char *const diag_cfg_text[] = { + "0mv", "30mv", "60mv", "90mv", + "120mv", "150mv", "180mv", "210mv", + "240mv", "270mv", "300mv", "330mv", + "360mv", "390mv", "420mv", "450mv", +}; + +static const char *const diag_cfg_gnd_text[] = { + "0mv", "60mv", "120mv", "180mv", + "240mv", "300mv", "360mv", "420mv", + "480mv", "540mv", "600mv", "660mv", + "720mv", "780mv", "840mv", "900mv", +}; + +static SOC_ENUM_SINGLE_DECL(tx_ch5_asi_cfg_enum, TAC5X1X_PASITXCH5, 5, + tx_ch5_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(tx_ch6_asi_cfg_enum, TAC5X1X_PASITXCH6, 5, + tx_ch5_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(tx_ch7_asi_cfg_enum, TAC5X1X_PASITXCH7, 5, + tx_ch7_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(tx_ch8_asi_cfg_enum, TAC5X1X_PASITXCH8, 5, + tx_ch8_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(rx_ch5_asi_cfg_enum, TAC5X1X_PASIRXCH5, 5, + rx_ch5_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(rx_ch6_asi_cfg_enum, TAC5X1X_PASIRXCH6, 5, + rx_ch6_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(rx_ch7_asi_cfg_enum, TAC5X1X_PASIRXCH7, 5, + rx_ch6_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(rx_ch8_asi_cfg_enum, TAC5X1X_PASIRXCH8, 5, + rx_ch6_asi_cfg_text); +static SOC_ENUM_SINGLE_DECL(diag_cfg1_sht_term_enum, TAC5X1X_DIAG_CFG1, 4, + diag_cfg_text); +static SOC_ENUM_SINGLE_DECL(diag_cfg1_vbat_in_enum, TAC5X1X_DIAG_CFG1, 0, + diag_cfg_text); +static SOC_ENUM_SINGLE_DECL(diag_cfg2_sht_gnd_enum, TAC5X1X_DIAG_CFG2, 4, + diag_cfg_gnd_text); +static SOC_ENUM_SINGLE_DECL(diag_cfg2_micbias, TAC5X1X_DIAG_CFG2, 0, + diag_cfg_text); + +static const struct snd_kcontrol_new taa5x1x_controls[] = { + SOC_ENUM("Record Decimation Filter", + decimation_filter_record_enum), + SOC_ENUM("ADC1 Audio BW", tac5x1x_adc1_wideband_enum), + + SOC_SINGLE_TLV("ADC1 Digital Capture Volume", TAC5X1X_ADCCH1C2, + 0, 0xff, 0, record_dig_vol_tlv), + + SOC_SINGLE_TLV("ADC1 Fine Capture Volume", TAC5X1X_ADCCH1C3, + 0, 0xff, 0, record_gain_cali_tlv), + + SOC_SINGLE_RANGE("ADC1 Phase Capture Volume", TAC5X1X_ADCCH1C4, + 2, 0, 63, 0), + + SOC_ENUM("ASI_TX_CH5_CFG", tx_ch5_asi_cfg_enum), + SOC_ENUM("ASI_TX_CH6_CFG", tx_ch6_asi_cfg_enum), + SOC_ENUM("ASI_TX_CH7_CFG", tx_ch7_asi_cfg_enum), + SOC_ENUM("ASI_TX_CH8_CFG", tx_ch8_asi_cfg_enum), + SOC_SINGLE("IN_CH1_EN Capture Switch", TAC5X1X_CH_EN, 7, 1, 0), + SOC_SINGLE("IN_CH2_EN Capture Switch", TAC5X1X_CH_EN, 6, 1, 0), + SOC_SINGLE("IN_CH3_EN Capture Switch", TAC5X1X_CH_EN, 5, 1, 0), + SOC_SINGLE("IN_CH4_EN Capture Switch", TAC5X1X_CH_EN, 4, 1, 0), +}; + +static const struct snd_kcontrol_new tad5x1x_controls[] = { + SOC_ENUM("Playback Decimation Filter", + decimation_filter_playback_enum), + SOC_ENUM("DAC1 Audio BW", tac5x1x_dac1_wideband_enum), + SOC_SINGLE_TLV("OUT1P Analog Level Playback Volume", TAC5X1X_OUT1CFG1, + 3, 6, 1, playback_analog_level_tlv), + SOC_SINGLE_TLV("OUT1M Analog Level Playback Volume", TAC5X1X_OUT1CFG2, + 3, 6, 1, playback_analog_level_tlv), + SOC_SINGLE_TLV("DAC1 CHA Digital Playback Volume", TAC5X1X_DACCH1A0, + 0, 0xff, 0, dac_dig_vol_tlv), + SOC_SINGLE_TLV("DAC1 CHB Digital Playback Volume", TAC5X1X_DACCH1B0, + 0, 0xff, 0, dac_dig_vol_tlv), + SOC_SINGLE_TLV("DAC1 CHA Gain Calibration Playback Volume", + TAC5X1X_DACCH1A1, 4, 0xf, 0, + playback_gain_cali_tlv), + SOC_SINGLE_TLV("DAC1 CHB Gain Calibration Playback Volume", + TAC5X1X_DACCH1B1, 4, 0xf, 0, + playback_gain_cali_tlv), + + SOC_SINGLE("ASI_RX_CH3_EN Playback Switch", + TAC5X1X_PASIRXCH3, 5, 1, 0), + SOC_SINGLE("ASI_RX_CH4_EN Playback Switch", + TAC5X1X_PASIRXCH4, 5, 1, 0), + SOC_ENUM("ASI_RX_CH5_EN Playback", rx_ch5_asi_cfg_enum), + SOC_ENUM("ASI_RX_CH6_EN Playback", rx_ch6_asi_cfg_enum), + SOC_ENUM("ASI_RX_CH7_EN Playback", rx_ch7_asi_cfg_enum), + SOC_ENUM("ASI_RX_CH8_EN Playback", rx_ch8_asi_cfg_enum), + SOC_SINGLE("OUT_CH1_EN Playback Switch", TAC5X1X_CH_EN, 3, 1, 0), + SOC_SINGLE("OUT_CH2_EN Playback Switch", TAC5X1X_CH_EN, 2, 1, 0), + SOC_SINGLE("OUT_CH3_EN Playback Switch", TAC5X1X_CH_EN, 1, 1, 0), + SOC_SINGLE("OUT_CH4_EN Playback Switch", TAC5X1X_CH_EN, 0, 1, 0), +}; + +static const struct snd_kcontrol_new tac5x11_controls[] = { + SOC_ENUM("ADC1 Common-mode Tolerance", tac5x1x_adc1_tolerance_enum), +}; + +static const struct snd_kcontrol_new tad5x12_controls[] = { + SOC_SINGLE_TLV("OUT2P Analog Level Playback Volume", TAC5X1X_OUT2CFG1, + 3, 6, 1, playback_analog_level_tlv), + SOC_SINGLE_TLV("OUT2M Analog Level Playback Volume", TAC5X1X_OUT2CFG2, + 3, 6, 1, playback_analog_level_tlv), + SOC_SINGLE_TLV("DAC2 CHA Digital Playback Volume", TAC5X1X_DACCH2A0, + 0, 0xff, 0, dac_dig_vol_tlv), + SOC_SINGLE_TLV("DAC2 CHB Digital Playback Volume", TAC5X1X_DACCH2B0, + 0, 0xff, 0, dac_dig_vol_tlv), + SOC_SINGLE_TLV("DAC2 CHA Gain Calibration Playback Volume", + TAC5X1X_DACCH2A1, 4, 0xf, 0, + playback_gain_cali_tlv), + SOC_SINGLE_TLV("DAC2 CHB Gain Calibration Playback Volume", + TAC5X1X_DACCH2B1, 4, 0xf, 0, + playback_gain_cali_tlv), + SOC_ENUM("DAC2 Audio BW", tac5x1x_dac2_wideband_enum), +}; + +static const struct snd_kcontrol_new taa5x12_controls[] = { + SOC_ENUM("ADC2 Audio BW", tac5x1x_adc2_wideband_enum), + + SOC_SINGLE_TLV("ADC2 Digital Capture Volume", TAC5X1X_ADCCH2C2, + 0, 0xff, 0, record_dig_vol_tlv), + + SOC_SINGLE_TLV("ADC2 Fine Capture Volume", TAC5X1X_ADCCH2C3, + 0, 0xff, 0, record_gain_cali_tlv), + + SOC_SINGLE_RANGE("ADC2 Phase Capture Volume", TAC5X1X_ADCCH2C4, + 2, 0, 63, 0), +}; + +static const struct snd_kcontrol_new tolerance_ctrls[] = { + SOC_ENUM("ADC1 Common-mode Tolerance", tac5x1x_adc1_tolerance_enum), + SOC_ENUM("ADC2 Common-mode Tolerance", tac5x1x_adc2_tolerance_enum), +}; + +static const struct snd_kcontrol_new tac5x1x_pdm_controls[] = { + SOC_ENUM("PDM Clk Divider", pdmclk_select_enum), + + SOC_SINGLE_TLV("PDM1 Digital Capture Volume", TAC5X1X_ADCCH1C2, + 0, 0xff, 0, record_dig_vol_tlv), + SOC_SINGLE_TLV("PDM2 Digital Capture Volume", TAC5X1X_ADCCH2C2, + 0, 0xff, 0, record_dig_vol_tlv), + SOC_SINGLE_TLV("PDM1 Fine Capture Volume", TAC5X1X_ADCCH1C3, + 0, 0xff, 0, record_gain_cali_tlv), + SOC_SINGLE_TLV("PDM2 Fine Capture Volume", TAC5X1X_ADCCH2C3, + 0, 0xff, 0, record_gain_cali_tlv), + SOC_SINGLE_RANGE("PDM1 Phase Capture Volume", TAC5X1X_ADCCH1C4, + 2, 0, 63, 0), + SOC_SINGLE_RANGE("PDM2 Phase Capture Volume", TAC5X1X_ADCCH2C4, + 2, 0, 63, 0), + SOC_SINGLE_TLV("PDM3 Digital Capture Volume", TAC5X1X_ADCCH3C2, + 0, 0xff, 0, record_dig_vol_tlv), + SOC_SINGLE_TLV("PDM4 Digital Capture Volume", TAC5X1X_ADCCH4C2, + 0, 0xff, 0, record_dig_vol_tlv), + SOC_SINGLE_TLV("PDM3 Fine Capture Volume", TAC5X1X_ADCCH3C3, + 0, 0xff, 0, record_gain_cali_tlv), + SOC_SINGLE_TLV("PDM4 Fine Capture Volume", TAC5X1X_ADCCH4C3, + 0, 0xff, 0, record_gain_cali_tlv), + SOC_SINGLE_RANGE("PDM3 Phase Capture Volume", TAC5X1X_ADCCH3C4, + 2, 0, 63, 0), + SOC_SINGLE_RANGE("PDM4 Phase Capture Volume", TAC5X1X_ADCCH4C4, + 2, 0, 63, 0), +}; + +static const struct snd_kcontrol_new taa_ip_controls[] = { + SOC_ENUM("DIAG_SHT_TERM", diag_cfg1_sht_term_enum), + SOC_ENUM("DIAG_SHT_VBAT_IN", diag_cfg1_vbat_in_enum), + SOC_ENUM("DIAG_SHT_GND", diag_cfg2_sht_gnd_enum), + SOC_ENUM("DIAG_SHT_MICBIAS", diag_cfg2_micbias), +}; + +static const struct snd_soc_dapm_widget taa5x1x_dapm_widgets[] = { + /* ADC1 */ + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_MUX("ADC1 Full-Scale", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_adc1_fscale_control), + SND_SOC_DAPM_MUX("ADC1 Config", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_adc1_config_control), + SND_SOC_DAPM_ADC("CH1_ADC_EN", "CH1 Capture", TAC5X1X_CH_EN, 7, 0), + SND_SOC_DAPM_SWITCH("ASI_TX_CH1_EN", SND_SOC_NOPM, 0, 0, + &tx_ch1_asi_switch), + SND_SOC_DAPM_MICBIAS("Mic Bias", TAC5X1X_PWR_CFG, 5, 0), + SND_SOC_DAPM_SWITCH("ASI_TX_CH2_EN", SND_SOC_NOPM, 0, 0, + &tx_ch2_asi_switch), +}; + +static const struct snd_soc_dapm_widget tad5xx_dapm_widgets[] = { + /* pdm capture */ + SND_SOC_DAPM_SWITCH("ASI_TX_CH1_EN", SND_SOC_NOPM, 0, 0, + &tx_ch1_asi_switch), + SND_SOC_DAPM_SWITCH("ASI_TX_CH2_EN", SND_SOC_NOPM, 0, 0, + &tx_ch2_asi_switch), +}; + +static const struct snd_soc_dapm_widget tad5x1x_dapm_widgets[] = { + /* DAC1 */ + SND_SOC_DAPM_AIF_IN("ASI IN1", "ASI Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("OUT1"), + SND_SOC_DAPM_MUX("OUT1x Source", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_out1_source_control), + SND_SOC_DAPM_MUX("OUT1x Config", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_out1_config_control), + SND_SOC_DAPM_MUX("OUT1x Driver", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_out1_driver_control), + SND_SOC_DAPM_DAC("Left DAC Enable", "Left Playback", TAC5X1X_CH_EN, 3, + 0), + SND_SOC_DAPM_PGA("Left DAC Power", TAC5X1X_PWR_CFG, 6, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("ASI_RX_CH1_EN", SND_SOC_NOPM, 0, 0, + &rx_ch1_asi_switch), +}; + +static const struct snd_soc_dapm_widget taa5x12_dapm_widgets[] = { + /* ADC2 */ + SND_SOC_DAPM_INPUT("AIN2"), + SND_SOC_DAPM_MUX("ADC2 Full-Scale", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_adc2_fscale_control), + SND_SOC_DAPM_MUX("ADC2 Config", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_adc2_config_control), + SND_SOC_DAPM_ADC("CH2_ADC_EN", "CH2 Capture", TAC5X1X_CH_EN, 6, 0), + +}; + +static const struct snd_soc_dapm_widget tad5x12_dapm_widgets[] = { + /* DAC2 */ + SND_SOC_DAPM_OUTPUT("OUT2"), + + SND_SOC_DAPM_AIF_IN("ASI IN2", "ASI Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_MUX("OUT2x Source", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_out2_source_control), + SND_SOC_DAPM_MUX("OUT2x Config", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_out2_config_control), + SND_SOC_DAPM_MUX("OUT2x Driver", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_out2_driver_control), + SND_SOC_DAPM_DAC("Right DAC Enable", + "Right Playback", TAC5X1X_CH_EN, 2, 0), + SND_SOC_DAPM_PGA("Right DAC Power", TAC5X1X_PWR_CFG, 6, 0, NULL, 0), + SND_SOC_DAPM_SWITCH("ASI_RX_CH2_EN", SND_SOC_NOPM, 0, 0, + &rx_ch2_asi_switch), +}; + +static const struct snd_soc_dapm_widget tac5x1x_pdm_widgets[] = { + /* PDM */ + SND_SOC_DAPM_INPUT("DIN1"), + SND_SOC_DAPM_INPUT("DIN2"), + SND_SOC_DAPM_INPUT("DIN3"), + SND_SOC_DAPM_INPUT("DIN4"), + + SND_SOC_DAPM_MUX("PDM ch1 & ch2 Datain Select", + SND_SOC_NOPM, 0, 0, pdm_12_pin_controls), + SND_SOC_DAPM_MUX("PDM ch3 & ch4 Datain Select", + SND_SOC_NOPM, 0, 0, pdm_34_pin_controls), + + SND_SOC_DAPM_ADC("CH1_PDM_EN", "PDM CH1 Capture", TAC5X1X_CH_EN, 7, 0), + SND_SOC_DAPM_ADC("CH2_PDM_EN", "PDM CH2 Capture", TAC5X1X_CH_EN, 6, 0), + SND_SOC_DAPM_ADC("CH3_PDM_EN", "PDM CH3 Capture", TAC5X1X_CH_EN, 5, 0), + SND_SOC_DAPM_ADC("CH4_PDM_EN", "PDM CH4 Capture", TAC5X1X_CH_EN, 4, 0), + + SND_SOC_DAPM_SWITCH("ASI_TX_CH3_EN", SND_SOC_NOPM, 0, 0, + &tx_ch3_asi_switch), + SND_SOC_DAPM_SWITCH("ASI_TX_CH4_EN", SND_SOC_NOPM, 0, 0, + &tx_ch4_asi_switch), +}; + +static const struct snd_soc_dapm_widget tac5x1x_common_widgets[] = { + SND_SOC_DAPM_MUX("IN1 Source Mux", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_in1_source_control), + SND_SOC_DAPM_MUX("IN2 Source Mux", SND_SOC_NOPM, 0, 0, + tac5x1x_dapm_in2_source_control), + SND_SOC_DAPM_PGA("ADC Power", TAC5X1X_PWR_CFG, 7, 0, NULL, 0), + SND_SOC_DAPM_AIF_OUT("AIF OUT", "ASI Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_widget tad_common_widgets[] = { + SND_SOC_DAPM_MUX("IN1 Source Mux", SND_SOC_NOPM, 0, 0, + tad5x1x_dapm_in1_source_control), + SND_SOC_DAPM_MUX("IN2 Source Mux", SND_SOC_NOPM, 0, 0, + tad5x1x_dapm_in2_source_control), + SND_SOC_DAPM_PGA("ADC Power", TAC5X1X_PWR_CFG, 7, 0, NULL, 0), + SND_SOC_DAPM_AIF_OUT("AIF OUT", "ASI Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route taa5x1x_dapm_routes[] = { + /* ADC channel1 */ + {"IN1 Source Mux", "Analog", "AIN1"}, + {"IN2 Source Mux", "Analog", "IN1 Source Mux"}, + {"CH1_ADC_EN", NULL, "IN2 Source Mux"}, + {"ASI_TX_CH1_EN", "Capture Switch", "CH1_ADC_EN"}, + {"ADC1 Config", "Differential", "ASI_TX_CH1_EN"}, + {"ADC1 Config", "Single-ended", "ASI_TX_CH1_EN"}, + {"ADC1 Config", "Single-ended mux INxP", + "ASI_TX_CH1_EN"}, + {"ADC1 Config", "Single-ended mux INxM", + "ASI_TX_CH1_EN"}, + + {"ADC1 Full-Scale", "2/10-VRMS", "ADC1 Config"}, + {"ADC1 Full-Scale", "4/5-VRMS", "ADC1 Config"}, + {"Mic Bias", NULL, "ADC1 Full-Scale"}, + +}; + +static const struct snd_soc_dapm_route tad5x1x_dapm_routes[] = { + /* Left Output */ + {"ASI_RX_CH1_EN", "Switch", "ASI IN1"}, + + {"OUT1x Source", "DAC + Analog Bypass Mix", "ASI_RX_CH1_EN"}, + {"OUT1x Source", "DAC -> OUTxP, INxP -> OUTxM", "ASI_RX_CH1_EN"}, + {"OUT1x Source", "INxM -> OUTxP, DAC -> OUTxM", "ASI_RX_CH1_EN"}, + + {"OUT1x Config", "Differential", "OUT1x Source"}, + // {"OUT1x Config", "Stereo Single-ended", "OUT1x Source"}, + {"OUT1x Config", "Mono Single-ended at OUTxP only", "OUT1x Source"}, + {"OUT1x Config", "Mono Single-ended at OUTxM only", "OUT1x Source"}, + {"OUT1x Config", "Pseudo differential with OUTxM as VCOM", + "OUT1x Source"}, + {"OUT1x Config", "Pseudo differential with OUTxM as external sensing", + "OUT1x Source"}, + {"OUT1x Config", "Pseudo differential with OUTxP as VCOM", + "OUT1x Source"}, + + {"OUT1x Driver", "Line-out", "OUT1x Config"}, + {"OUT1x Driver", "Headphone", "OUT1x Config"}, + + {"Left DAC Enable", NULL, "OUT1x Driver"}, + {"Left DAC Power", NULL, "Left DAC Enable"}, + + {"OUT1", NULL, "Left DAC Power"}, +}; + +static const struct snd_soc_dapm_route taa5x12_dapm_routes[] = { + /* ADC channel2 */ + {"CH2_ADC_EN", NULL, "AIN2"}, + {"ASI_TX_CH2_EN", "Capture Switch", "CH2_ADC_EN"}, + {"ADC2 Config", "Differential", "ASI_TX_CH2_EN"}, + {"ADC2 Config", "Single-ended", "ASI_TX_CH2_EN"}, + {"ADC2 Full-Scale", "2/10-VRMS", + "ADC2 Config"}, + {"ADC2 Full-Scale", "4/5-VRMS", + "ADC2 Config"}, + + {"Mic Bias", NULL, "ADC2 Full-Scale"}, +}; + +static const struct snd_soc_dapm_route tad5x12_dapm_routes[] = { + /* Right Output */ + {"ASI_RX_CH2_EN", "Switch", "ASI IN2"}, + + {"OUT2x Source", "DAC + Analog Bypass Mix", "ASI_RX_CH1_EN"}, + {"OUT2x Source", "DAC -> OUTxP, INxP -> OUTxM", "ASI_RX_CH1_EN"}, + {"OUT2x Source", "INxM -> OUTxP, DAC -> OUTxM", "ASI_RX_CH1_EN"}, + + {"OUT2x Config", "Differential", "OUT2x Source"}, + // {"OUT2x Config", "Stereo Single-ended", "OUT2x Source"}, + {"OUT2x Config", "Mono Single-ended at OUTxP only", "OUT2x Source"}, + {"OUT2x Config", "Mono Single-ended at OUTxM only", "OUT2x Source"}, + {"OUT2x Config", "Pseudo differential with OUTxM as VCOM", + "OUT2x Source"}, + {"OUT2x Config", "Pseudo differential with OUTxP as VCOM", + "OUT2x Source"}, + {"OUT2x Driver", "Line-out", "OUT2x Config"}, + {"OUT2x Driver", "Headphone", "OUT2x Config"}, + {"Right DAC Enable", NULL, "OUT2x Driver"}, + {"Right DAC Power", NULL, "Right DAC Enable"}, + {"OUT2", NULL, "Right DAC Power"}, +}; + +static const struct snd_soc_dapm_route tac5x1x_pdm_routes[] = { + /* PDM channel1 & Channel2 */ + {"IN1 Source Mux", "PDM", "DIN1"}, + {"IN2 Source Mux", "PDM", "DIN2"}, + + {"ASI_TX_CH1_EN", "Capture Switch", + "IN1 Source Mux"}, + {"ASI_TX_CH2_EN", "Capture Switch", + "IN2 Source Mux"}, + + {"CH1_PDM_EN", NULL, "ASI_TX_CH1_EN"}, + {"CH2_PDM_EN", NULL, "ASI_TX_CH2_EN"}, + + {"PDM ch1 & ch2 Datain Select", "GPIO1", "CH1_PDM_EN"}, + {"PDM ch1 & ch2 Datain Select", "GPIO2", "CH1_PDM_EN"}, + {"PDM ch1 & ch2 Datain Select", "GPI1", "CH1_PDM_EN"}, + + {"ADC Power", NULL, "PDM ch1 & ch2 Datain Select"}, + + /* PDM channel3 & Channel4 */ + {"ASI_TX_CH3_EN", "Capture Switch", "DIN3"}, + {"ASI_TX_CH4_EN", "Capture Switch", "DIN4"}, + + {"CH3_PDM_EN", NULL, "ASI_TX_CH3_EN"}, + {"CH4_PDM_EN", NULL, "ASI_TX_CH4_EN"}, + + {"PDM ch3 & ch4 Datain Select", "GPIO1", "CH3_PDM_EN"}, + {"PDM ch3 & ch4 Datain Select", "GPIO2", "CH3_PDM_EN"}, + {"PDM ch3 & ch4 Datain Select", "GPI1", "CH3_PDM_EN"}, + + {"ADC Power", NULL, "PDM ch3 & ch4 Datain Select"}, + {"AIF OUT", NULL, "ADC Power"}, +}; + +static const struct snd_soc_dapm_route tac_common_routes[] = { + {"ADC Power", NULL, "Mic Bias"}, + {"AIF OUT", NULL, "ADC Power"}, +}; + +static const struct reg_default tac5x1x_reg_defaults[] = { + {TAC5X1X_PGSEL, 0x00}, + {TAC5X1X_INT, 0x11}, + {TAC5X1X_ADCCH1C0, 0x04}, + {TAC5X1X_ADCCH2C0, 0x04}, + {TAC5X1X_OUT1CFG0, 0x20}, + {TAC5X1X_OUT2CFG0, 0x20}, + {TAC5X1X_CH_EN, 0x00}, + {TAC5X1X_PASITXCH1, 0x00}, + {TAC5X1X_PASITXCH2, 0x01}, + {TAC5X1X_PASIRXCH1, 0x00}, + {TAC5X1X_PASIRXCH2, 0x01}, + {}, +}; + +static s32 tac5x1x_pwr_ctrl(struct snd_soc_component *component, + bool power_state) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + s32 active_ctrl, ret; + s32 pwr_ctrl = 0; + + if (power_state) { + active_ctrl = TAC5X1X_VREF_SLEEP_ACTIVE_MASK; + snd_soc_component_update_bits(component, TAC5X1X_VREFCFG, + TAC5X1X_VREFCFG_MICBIAS_VAL_MASK, + tac5x1x->micbias_vg << 2); + snd_soc_component_update_bits(component, TAC5X1X_VREFCFG, + TAC5X1X_VREFCFG_VREF_FSCALE_MASK, + tac5x1x->vref_vg); + + if (tac5x1x->uad_en) + pwr_ctrl |= TAC5X1X_PWR_CFG_UAD_EN; + if (tac5x1x->vad_en) + pwr_ctrl |= TAC5X1X_PWR_CFG_VAD_EN; + if (tac5x1x->uag_en) + pwr_ctrl |= TAC5X1X_PWR_CFG_UAG_EN; + } else { + active_ctrl = 0x0; + } + + ret = snd_soc_component_update_bits(component, TAC5X1X_VREF, + TAC5X1X_VREF_SLEEP_EXIT_VREF_EN | + TAC5X1X_VREF_SLEEP_ACTIVE_MASK, + active_ctrl); + if (ret < 0) { + dev_err(tac5x1x->dev, + "%s, device active or sleep failed!, ret %d/n", + __func__, ret); + return ret; + } + + ret = snd_soc_component_update_bits(component, TAC5X1X_PWR_CFG, + TAC5X1X_PWR_CFG_UAD_EN | + TAC5X1X_PWR_CFG_UAG_EN | + TAC5X1X_PWR_CFG_VAD_EN, pwr_ctrl); + if (ret < 0) + dev_err(tac5x1x->dev, + "%s, Power control set failed!, ret %d/n", + __func__, ret); + return ret; +} + +static s32 tac5x1x_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) +{ + struct snd_soc_component *component = codec_dai->component; + s32 iface_reg_1 = 0; + s32 iface_reg_2 = 0; + s32 iface_reg_3 = 0; + + int right_slot = 1; + + dev_info(component->dev, "[tac5x1x] %s(), fmt=%d\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: + iface_reg_1 |= TAC5X1X_PASI_MODE_MASK; + break; + case SND_SOC_DAIFMT_CBC_CFC: + break; + default: + dev_err(component->dev, + "%s: invalid DAI master/slave interface\n", + __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + iface_reg_2 |= TAC5X1X_PASI_FMT_I2S; + right_slot = 16; + break; + case SND_SOC_DAIFMT_DSP_A: + iface_reg_2 |= TAC5X1X_PASI_FMT_TDM; + iface_reg_3 |= BIT(0); /* add offset 1 */ + break; + case SND_SOC_DAIFMT_DSP_B: + iface_reg_2 |= TAC5X1X_PASI_FMT_TDM; + break; + case SND_SOC_DAIFMT_LEFT_J: + iface_reg_2 |= TAC5X1X_PASI_FMT_LJ; + right_slot = 16; + break; + default: + dev_err(component->dev, + "%s: invalid DAI interface format\n", __func__); + return -EINVAL; + } + + snd_soc_component_update_bits(component, TAC5X1X_CNTCLK2, + TAC5X1X_PASI_MODE_MASK, iface_reg_1); + snd_soc_component_update_bits(component, TAC5X1X_PASI0, + TAC5X1X_PASI_FMT_MASK, iface_reg_2); + snd_soc_component_update_bits(component, TAC5X1X_PASITX1, + TAC5X1X_PASITX_OFFSET_MASK, iface_reg_3); + snd_soc_component_update_bits(component, TAC5X1X_PASIRX0, + TAC5X1X_PASIRX_OFFSET_MASK, iface_reg_3); + snd_soc_component_update_bits(component, TAC5X1X_PASIRXCH2, + TAC5X1X_PASIRX_OFFSET_MASK, right_slot); + snd_soc_component_update_bits(component, TAC5X1X_PASITXCH2, + TAC5X1X_PASITX_OFFSET_MASK, right_slot); + + return 0; +} + +static s32 tac5x1x_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + s32 sample_rate, word_length = 0; + + switch (params_rate(params)) { + case 24000: + sample_rate = 25; + break; + case 32000: + sample_rate = 23; + break; + case 44100: + case 48000: + sample_rate = 20; + break; + case 64000: + sample_rate = 18; + break; + case 96000: + sample_rate = 15; + break; + case 192000: + sample_rate = 10; + break; + default: + /* Auto detect sample rate */ + sample_rate = 0; + break; + } + + switch (params_physical_width(params)) { + case 16: + word_length |= TAC5X1X_WORD_LEN_16BITS; + break; + case 20: + word_length |= TAC5X1X_WORD_LEN_20BITS; + break; + case 24: + word_length |= TAC5X1X_WORD_LEN_24BITS; + break; + case 32: + word_length |= TAC5X1X_WORD_LEN_32BITS; + break; + default: + dev_err(tac5x1x->dev, "%s, set word length failed\n", + __func__); + return -EINVAL; + } + + snd_soc_component_update_bits(component, TAC5X1X_CLK0, + TAC5X1X_PASI_SAMP_RATE_MASK, + sample_rate << 2); + snd_soc_component_update_bits(component, TAC5X1X_PASI0, + TAC5X1X_PASI_DATALEN_MASK, word_length); + + tac5x1x_pwr_ctrl(component, true); + return 0; +} + +static s32 tac5x1x_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + s32 ret; + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + + switch (level) { + case SND_SOC_BIAS_ON: + ret = tac5x1x_pwr_ctrl(component, true); + if (ret < 0) + dev_err(tac5x1x->dev, + "%s, power up failed!/n", __func__); + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + break; + case SND_SOC_BIAS_OFF: + ret = tac5x1x_pwr_ctrl(component, false); + if (ret < 0) + dev_err(tac5x1x->dev, + "%s, power down failed!/n", __func__); + break; + } + + return ret; +} + +static const struct snd_soc_dai_ops tac5x1x_ops = { + .hw_params = tac5x1x_hw_params, + .set_fmt = tac5x1x_set_dai_fmt, + .no_capture_mute = 1, +}; + +static struct snd_soc_dai_driver tac5x1x_dai = { + .name = "tac5x1x-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5X1X_RATES, + .formats = TAC5X1X_FORMATS,}, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5X1X_RATES, + .formats = TAC5X1X_FORMATS, + }, + .ops = &tac5x1x_ops, + .symmetric_rate = 1, +}; + +static struct snd_soc_dai_driver taa5x1x_dai = { + .name = "taa5x1x-hifi", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5X1X_RATES, + .formats = TAC5X1X_FORMATS, + }, + .ops = &tac5x1x_ops, + .symmetric_rate = 1, +}; + +static struct snd_soc_dai_driver tad5x1x_dai = { + .name = "tad5x1x-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5X1X_RATES, + .formats = TAC5X1X_FORMATS, + }, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 4, + .rates = TAC5X1X_RATES, + .formats = TAC5X1X_FORMATS, + }, + .ops = &tac5x1x_ops, + .symmetric_rate = 1, +}; + +static void tac5x1x_setup_gpios(struct snd_soc_component *component) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + s32 *gpio_drive = tac5x1x->gpio_setup->gpio_drive; + s32 *gpio_func = tac5x1x->gpio_setup->gpio_func; + + /* setup GPIO functions */ + /* GPIO1 */ + if (gpio_func[0] <= TAC5X1X_GPIO_DAISY_OUT) { + snd_soc_component_update_bits(component, TAC5X1X_GPIO1, + TAC5X1X_GPIOX_CFG_MASK, + gpio_func[0] << 4); + snd_soc_component_update_bits(component, TAC5X1X_GPIO1, + TAC5X1X_GPIOX_DRV_MASK, + gpio_drive[0]); + + if (gpio_func[0] == TAC5X1X_GPIO_GPI) + snd_soc_add_component_controls(component, GPIO1_I, + ARRAY_SIZE(GPIO1_I)); + } + /* GPIO2 */ + if (gpio_func[1] <= TAC5X1X_GPIO_DAISY_OUT) { + snd_soc_component_update_bits(component, TAC5X1X_GPIO2, + TAC5X1X_GPIOX_CFG_MASK, + gpio_func[1] << 4); + snd_soc_component_update_bits(component, TAC5X1X_GPIO2, + TAC5X1X_GPIOX_DRV_MASK, + gpio_drive[1]); + + if (gpio_func[1] == TAC5X1X_GPIO_GPI) + snd_soc_add_component_controls(component, GPIO2_I, + ARRAY_SIZE(GPIO2_I)); + } + /* GPO1 */ + if (gpio_func[2] <= TAC5X1X_GPIO_DAISY_OUT) { + snd_soc_component_update_bits(component, TAC5X1X_GPO1, + TAC5X1X_GPIOX_CFG_MASK, + gpio_func[2] << 4); + snd_soc_component_update_bits(component, TAC5X1X_GPO1, + TAC5X1X_GPIOX_DRV_MASK, + gpio_drive[2]); + } + + /* GPI1 */ + if (tac5x1x->gpio_setup->gpi1_func) { + snd_soc_component_update_bits(component, TAC5X1X_GPI1, + TAC5X1X_GPI1_CFG_MASK, + TAC5X1X_GPI1_CFG_MASK); + snd_soc_add_component_controls(component, tac5x1x_GPI1, + ARRAY_SIZE(tac5x1x_GPI1)); + } + /*GPA GPIO*/ + if (tac5x1x->gpio_setup->gpa_gpio) + snd_soc_component_update_bits(component, TAC5X1X_INTF5, + TAC5X1X_GPA_CFG_MASK, + TAC5X1X_GPA_CFG_MASK); +} + +static s32 tac5x1x_reset(struct snd_soc_component *component) +{ + s32 ret, index; + + ret = snd_soc_component_write(component, TAC5X1X_RESET, 1); + if (ret < 0) + return ret; + /* Wait >= 10 ms after entering sleep mode. */ + usleep_range(10000, 100000); + + for (index = 0; index < ARRAY_SIZE(tac5x1x_reg_defaults); index++) { + ret = snd_soc_component_write(component, + tac5x1x_reg_defaults[index].reg, + tac5x1x_reg_defaults[index].def); + if (ret < 0) + return ret; + } + return ret; +} + +static s32 tac5x1x_add_controls(struct snd_soc_component *component) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + s32 *gpio_func = tac5x1x->gpio_setup->gpio_func; + s32 ret; + + switch (tac5x1x->codec_type) { + case TAA5212: + fallthrough; + case TAA5412: + ret = + snd_soc_add_component_controls(component, tolerance_ctrls, + ARRAY_SIZE(tolerance_ctrls)); + if (ret) + return ret; + ret = + snd_soc_add_component_controls(component, + taa_ip_controls, + ARRAY_SIZE(taa_ip_controls)); + if (ret) + return ret; + break; + /* For Mono */ + case TAC5111: + case TAC5211: + ret = + snd_soc_add_component_controls(component, + tac5x11_controls, + ARRAY_SIZE(tac5x11_controls)); + if (ret) + return ret; + fallthrough; + case TAC5311: + case TAC5411: + ret = + snd_soc_add_component_controls(component, tad5x1x_controls, + ARRAY_SIZE(tad5x1x_controls)); + if (ret) + return ret; + break; + /* For Stereo */ + case TAC5112: + case TAC5212: + fallthrough; + case TAC5312: + case TAC5412: + ret = + snd_soc_add_component_controls(component, tolerance_ctrls, + ARRAY_SIZE(tolerance_ctrls)); + if (ret) + return ret; + ret = + snd_soc_add_component_controls(component, tad5x1x_controls, + ARRAY_SIZE(tad5x1x_controls)); + if (ret) + return ret; + + ret = + snd_soc_add_component_controls(component, taa5x12_controls, + ARRAY_SIZE(taa5x12_controls)); + if (ret) + return ret; + + ret = + snd_soc_add_component_controls(component, tad5x12_controls, + ARRAY_SIZE(tad5x12_controls)); + if (ret) + return ret; + break; + case TAD5212: + case TAD5112: + ret = snd_soc_add_component_controls(component, tad5x12_controls, + ARRAY_SIZE(tad5x12_controls)); + if (ret) + return ret; + break; + default: + break; + } + + /* If enabled PDM GPIO*/ + if (memchr(gpio_func, TAC5X1X_GPIO_PDMCLK, + sizeof(*gpio_func) / sizeof(gpio_func[0]))) { + ret = snd_soc_add_component_controls(component, tac5x1x_pdm_controls, + ARRAY_SIZE(tac5x1x_pdm_controls)); + if (ret) + return ret; + } + + return 0; +} + +static s32 tac5x1x_add_ip_diag_controls(struct snd_soc_component *component) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + s32 ret; + + switch (tac5x1x->codec_type) { + case TAA5212: + break; + case TAA5412: + case TAC5311: + case TAC5312: + case TAC5411: + case TAC5412: + if (tac5x1x->input_diag_config.in_ch_en) { + ret = + snd_soc_add_component_controls(component, + taa_ip_controls, + ARRAY_SIZE(taa_ip_controls)); + if (ret) + return ret; + snd_soc_component_update_bits(component, + TAC5X1X_DIAG_CFG0, + TAC5X1X_IN_CH_DIAG_EN_MASK, + TAC5X1X_IN_CH_DIAG_EN_MASK); + } + if (tac5x1x->input_diag_config.out_ch_en) { + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG0, + TAC5X1X_OUT1P_DIAG_EN_MASK, + TAC5X1X_OUT1P_DIAG_EN_MASK); + } + if (tac5x1x->input_diag_config.incl_se_inm) { + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG0, + TAC5X1X_INCL_SE_INM_MASK, + TAC5X1X_INCL_SE_INM_MASK); + } + if (tac5x1x->input_diag_config.incl_ac_coup) { + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG0, + TAC5X1X_INCL_AC_COUP_MASK, + TAC5X1X_INCL_AC_COUP_MASK); + } + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG7, + 0xff, + tac5x1x->micbias_threshold[0]); + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG6, + 0xff, + tac5x1x->micbias_threshold[1]); + tac5x1x_register_interrupt(tac5x1x); + fallthrough; + case TAC5111: + case TAC5112: + case TAC5211: + case TAC5212: + case TAD5112: + case TAD5212: + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG9, + 0xff, tac5x1x->gpa_threshold[0]); + snd_soc_component_update_bits(component, TAC5X1X_DIAG_CFG8, + 0xff, tac5x1x->gpa_threshold[1]); + break; + default: + break; + } + + return ret; +}; + +static s32 tac5x1x_add_widgets(struct snd_soc_component *component) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + s32 *gpio_func = tac5x1x->gpio_setup->gpio_func; + s32 ret; + + switch (tac5x1x->codec_type) { + case TAC5111: + case TAC5211: + case TAC5311: + case TAC5411: + ret = + snd_soc_dapm_new_controls(dapm, tad5x1x_dapm_widgets, + ARRAY_SIZE(tad5x1x_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(dapm, tad5x1x_dapm_routes, + ARRAY_SIZE(tad5x1x_dapm_routes)); + if (ret) + return ret; + break; + case TAC5112: + case TAC5212: + case TAC5312: + case TAC5412: + ret = + snd_soc_dapm_new_controls(dapm, tad5x1x_dapm_widgets, + ARRAY_SIZE(tad5x1x_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(dapm, tad5x1x_dapm_routes, + ARRAY_SIZE(tad5x1x_dapm_routes)); + if (ret) + return ret; + ret = + snd_soc_dapm_new_controls(dapm, tad5x12_dapm_widgets, + ARRAY_SIZE(tad5x12_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(dapm, tad5x12_dapm_routes, + ARRAY_SIZE(tad5x12_dapm_routes)); + if (ret) + return ret; + fallthrough; + case TAA5212: + case TAA5412: + ret = + snd_soc_dapm_new_controls(dapm, taa5x12_dapm_widgets, + ARRAY_SIZE(taa5x12_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(dapm, taa5x12_dapm_routes, + ARRAY_SIZE(taa5x12_dapm_routes)); + if (ret) + return ret; + break; + case TAD5212: + case TAD5112: + ret = + snd_soc_dapm_new_controls(dapm, tad5xx_dapm_widgets, + ARRAY_SIZE(tad5xx_dapm_widgets)); + if (ret) + return ret; + + ret = + snd_soc_dapm_new_controls(dapm, tad5x12_dapm_widgets, + ARRAY_SIZE(tad5x12_dapm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(dapm, tad5x12_dapm_routes, + ARRAY_SIZE(tad5x12_dapm_routes)); + if (ret) + return ret; + + break; + default: + break; + } + + if (!(tac5x1x->codec_type == TAD5212 || + tac5x1x->codec_type == TAD5112)) { + ret = + snd_soc_dapm_new_controls(dapm, tac5x1x_common_widgets, + ARRAY_SIZE(tac5x1x_common_widgets)); + if (ret) + return ret; + + ret = snd_soc_dapm_add_routes(dapm, tac_common_routes, + ARRAY_SIZE(tac_common_routes)); + if (ret) + return ret; + } else { + ret = + snd_soc_dapm_new_controls(dapm, tad_common_widgets, + ARRAY_SIZE(tad_common_widgets)); + if (ret) + return ret; + } + /* If enabled PDM GPIO*/ + if (memchr(gpio_func, TAC5X1X_GPIO_PDMCLK, + sizeof(*gpio_func) / sizeof(gpio_func[0]))) { + ret = + snd_soc_dapm_new_controls(dapm, tac5x1x_pdm_widgets, + ARRAY_SIZE(tac5x1x_pdm_widgets)); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(dapm, tac5x1x_pdm_routes, + ARRAY_SIZE(tac5x1x_pdm_routes)); + if (ret) + return ret; + } + return 0; +} + +static int tac5x1x_setup_adc_impedance(struct device *dev, + struct tac5x1x_priv *tac5x1x) +{ + if (tac5x1x->adc_impedance[0] != -1) + snd_soc_component_update_bits(tac5x1x->component, + TAC5X1X_ADCCH1C0, + TAC5X1X_ADCCH1C0_IMPEDANCE_MASK, + tac5x1x->adc_impedance[0] << 4); + + if (tac5x1x->adc_impedance[1] != -1) + snd_soc_component_update_bits(tac5x1x->component, + TAC5X1X_ADCCH2C0, + TAC5X1X_ADCCH2C0_IMPEDANCE_MASK, + tac5x1x->adc_impedance[1] << 4); + + return 0; +} + +static s32 tac5x1x_component_probe(struct snd_soc_component *component) +{ + s32 ret; + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + + tac5x1x->component = component; + ret = tac5x1x_add_controls(component); + if (ret < 0) { + dev_err(tac5x1x->dev, + "%s, add control failed\n", __func__); + return ret; + } + + ret = tac5x1x_add_widgets(component); + if (ret < 0) { + dev_err(tac5x1x->dev, + "%s, device widget addition failed\n", __func__); + return ret; + } + + ret = tac5x1x_reset(component); + if (ret < 0) { + dev_err(tac5x1x->dev, "%s, device reset failed\n", __func__); + return ret; + } + + tac5x1x_setup_adc_impedance(tac5x1x->dev, tac5x1x); + + if (tac5x1x->gpio_setup) + tac5x1x_setup_gpios(component); + + ret = tac5x1x_add_ip_diag_controls(component); + if (ret < 0) { + dev_err(tac5x1x->dev, + "%s add diag control failed\n", __func__); + return ret; + } + return ret; +} + +static void tac5x1x_disable_regulators(struct tac5x1x_priv *tac5x1x) +{ + regulator_bulk_disable(tac5x1x_num_regulators, tac5x1x_regulators); +} + +#ifdef CONFIG_PM +static s32 tac5x1x_soc_suspend(struct snd_soc_component *component) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + + regcache_cache_only(tac5x1x->regmap, true); + regcache_mark_dirty(tac5x1x->regmap); + + tac5x1x_disable_regulators(tac5x1x); + + return 0; +} + +static s32 tac5x1x_soc_resume(struct snd_soc_component *component) +{ + struct tac5x1x_priv *tac5x1x = + snd_soc_component_get_drvdata(component); + s32 ret; + + ret = regulator_bulk_enable(tac5x1x_num_regulators, + tac5x1x_regulators); + if (ret) { + dev_err(tac5x1x->dev, "Failed to enable regulators\n"); + return ret; + } + + regcache_cache_only(tac5x1x->regmap, false); + snd_soc_component_cache_sync(component); + + return ret; +} +#else +#define tac5x1x_soc_suspend NULL +#define tac5x1x_soc_resume NULL +#endif /* CONFIG_PM */ + +static const struct snd_soc_component_driver component_tac5x1x = { + .probe = tac5x1x_component_probe, + .set_bias_level = tac5x1x_set_bias_level, + .suspend = tac5x1x_soc_suspend, + .resume = tac5x1x_soc_resume, + .controls = taa5x1x_controls, + .num_controls = ARRAY_SIZE(taa5x1x_controls), + .dapm_widgets = taa5x1x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(taa5x1x_dapm_widgets), + .dapm_routes = taa5x1x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(taa5x1x_dapm_routes), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + +static const struct snd_soc_component_driver component_taa5x1x = { + .probe = tac5x1x_component_probe, + .set_bias_level = tac5x1x_set_bias_level, + .suspend = tac5x1x_soc_suspend, + .resume = tac5x1x_soc_resume, + .controls = taa5x1x_controls, + .num_controls = ARRAY_SIZE(taa5x1x_controls), + .dapm_widgets = taa5x1x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(taa5x1x_dapm_widgets), + .dapm_routes = taa5x1x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(taa5x1x_dapm_routes), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + +static const struct snd_soc_component_driver component_tad5x1x = { + .probe = tac5x1x_component_probe, + .set_bias_level = tac5x1x_set_bias_level, + .suspend = tac5x1x_soc_suspend, + .resume = tac5x1x_soc_resume, + .controls = tad5x1x_controls, + .num_controls = ARRAY_SIZE(tad5x1x_controls), + .dapm_widgets = tad5x1x_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tad5x1x_dapm_widgets), + .dapm_routes = tad5x1x_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tad5x1x_dapm_routes), + .suspend_bias_off = 1, + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, +}; + +static s32 tac5x1x_parse_dt(struct tac5x1x_priv *tac5x1x, + struct device_node *np) +{ + struct tac5x1x_input_diag_config input_config; + struct tac5x1x_setup_gpio *tac5x1x_setup; + s32 micbias_value = TAC5X1X_MICBIAS_VREF; + s32 vref_value = TAC5X1X_VERF_2_5V; + s32 ret; + + tac5x1x_setup = devm_kzalloc(tac5x1x->dev, sizeof(*tac5x1x_setup), + GFP_KERNEL); + if (!tac5x1x_setup) + return -ENOMEM; + + ret = fwnode_property_read_u32(tac5x1x->dev->fwnode, "ti,vref", + &vref_value); + if (ret) { + dev_err(tac5x1x->dev, "Fail to get verf E:%d\n", ret); + goto out; + } + ret = fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,micbias-vg", &micbias_value); + if (ret) { + dev_err(tac5x1x->dev, "Fail to get micbias-vg E:%d\n", ret); + goto out; + } + + if (micbias_value == TAC5X1X_MICBIAS_AVDD) { + tac5x1x->micbias_vg = micbias_value; + tac5x1x->vref_vg = TAC5X1X_VERF_2_75V; + tac5x1x->micbias_en = true; + } else { + switch (vref_value) { + case TAC5X1X_VERF_2_75V: + case TAC5X1X_VERF_2_5V: + switch (micbias_value) { + case TAC5X1X_MICBIAS_VREF: + case TAC5X1X_MICBIAS_0_5VREF: + tac5x1x->micbias_vg = micbias_value; + break; + default: + dev_err(tac5x1x->dev, + "Bad tac5x1x-micbias-vg value %d\n", + micbias_value); + tac5x1x->micbias_vg = TAC5X1X_MICBIAS_AVDD; + break; + } + tac5x1x->vref_vg = vref_value; + tac5x1x->micbias_en = true; + break; + case TAC5X1X_VERF_1_375V: + if (micbias_value == TAC5X1X_MICBIAS_VREF) { + tac5x1x->micbias_vg = micbias_value; + } else { + dev_err(tac5x1x->dev, + "Bad tac5x1x-micbias-vg value %d\n", + micbias_value); + tac5x1x->micbias_vg = TAC5X1X_MICBIAS_AVDD; + } + tac5x1x->micbias_en = true; + tac5x1x->vref_vg = vref_value; + break; + default: + dev_err(tac5x1x->dev, + "Bad tac5x1x-vref-vg value %d\n", vref_value); + tac5x1x->vref_vg = TAC5X1X_VERF_2_5V; + tac5x1x->micbias_vg = TAC5X1X_MICBIAS_AVDD; + tac5x1x->micbias_en = true; + break; + } + } + + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, "ti,gpi1-func", + &tac5x1x_setup->gpi1_func)) + dev_err(tac5x1x->dev, "Fail to get gpi1-func value\n"); + + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, "ti,gpa-gpio", + &tac5x1x_setup->gpa_gpio)) + dev_err(tac5x1x->dev, "Fail to get gpa-gpio value\n"); + + if (fwnode_property_read_u32_array(tac5x1x->dev->fwnode, + "ti,gpios-func", + tac5x1x_setup->gpio_func, 3)) + dev_err(tac5x1x->dev, "Fail to get gpios-func value\n"); + if (fwnode_property_read_u32_array(tac5x1x->dev->fwnode, + "ti,gpios-drive", + tac5x1x_setup->gpio_drive, 3)) + dev_err(tac5x1x->dev, "Fail to get gpios-drive value\n"); + + tac5x1x->gpa_threshold[0] = TAC5X1X_GPA_LOW_THRESHOLD; + tac5x1x->gpa_threshold[1] = TAC5X1X_GPA_HIGH_THRESHOLD; + if (fwnode_property_read_u32_array(tac5x1x->dev->fwnode, + "ti,gpa-threshold", + tac5x1x->gpa_threshold, 2)) + dev_err(tac5x1x->dev, "Fail to get ti,gpa-threshold value\n"); + + tac5x1x->gpio_setup = tac5x1x_setup; + tac5x1x->adc_impedance[0] = -1; + tac5x1x->adc_impedance[1] = -1; + tac5x1x->out2x_vcom_cfg = -1; + + fwnode_property_read_u32(tac5x1x->dev->fwnode, "ti,out2x-vcom-cfg", + &tac5x1x->out2x_vcom_cfg); + + switch (tac5x1x->codec_type) { + case TAA5212: + case TAC5212: + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,adc2-impedance", + &tac5x1x->adc_impedance[1])) + dev_warn(tac5x1x->dev, + "Fail to get ti,adc2-impedance value\n"); + fallthrough; + case TAC5211: + case TAC5111: + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,adc1-impedance", + &tac5x1x->adc_impedance[0])) + dev_warn(tac5x1x->dev, + "Fail to get ti,adc1-impedance value\n"); + + fallthrough; + case TAC5112: + case TAD5112: + case TAD5212: + break; + case TAA5412: + case TAC5411: + case TAC5412: + case TAC5311: + case TAC5312: + tac5x1x->input_diag_config.in_ch_en = 0; + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,in-ch-en", + &input_config.in_ch_en)) + dev_err(tac5x1x->dev, + "Fail to get ti,in-ch-en value\n"); + tac5x1x->input_diag_config.out_ch_en = 0; + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,out-ch-en", + &input_config.in_ch_en)) + dev_err(tac5x1x->dev, + "Fail to get ti,out-ch-en value\n"); + tac5x1x->input_diag_config.incl_se_inm = 0; + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,incl-se-inm", + &input_config.incl_se_inm)) + dev_err(tac5x1x->dev, + "Fail to get ti,incl-se-inm value\n"); + tac5x1x->input_diag_config.incl_ac_coup = 0; + if (fwnode_property_read_u32(tac5x1x->dev->fwnode, + "ti,incl-ac-coup", + &input_config.incl_ac_coup)) + dev_err(tac5x1x->dev, + "Fail to get ti,incl-ac-coup value\n"); + tac5x1x->input_diag_config = input_config; + + tac5x1x->micbias_threshold[0] = TAC5X1X_MICBIAS_LOW_THRESHOLD; + tac5x1x->micbias_threshold[1] = TAC5X1X_MICBIAS_HIGH_THRESHOLD; + if (fwnode_property_read_u32_array(tac5x1x->dev->fwnode, + "ti,micbias-threshold", + tac5x1x->micbias_threshold, + 2)) + dev_err(tac5x1x->dev, + "Fail to get ti,micbias-threshold value\n"); + break; + } +out: + return ret; +} + +static s32 tac5x1x_setup_regulators(struct device *dev, + struct tac5x1x_priv *tac5x1x) +{ + int ret; + + ret = devm_regulator_bulk_get(dev, tac5x1x_num_regulators, + tac5x1x_regulators); + if (ret) { + dev_err(dev, "Failed to get regulators\n"); + return ret; + } + + ret = regulator_bulk_enable(tac5x1x_num_regulators, + tac5x1x_regulators); + if (ret) { + dev_err(dev, "Failed to enable regulators\n"); + regulator_bulk_disable(tac5x1x_num_regulators, + tac5x1x_regulators); + return ret; + } + + return 0; +} + +static s32 tac5x1x_probe(struct device *dev, struct regmap *regmap, + enum tac5x1x_type type) +{ + struct device_node *np = dev->of_node; + struct tac5x1x_priv *tac5x1x; + s32 ret; + + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + tac5x1x = devm_kzalloc(dev, sizeof(struct tac5x1x_priv), + GFP_KERNEL); + if (!tac5x1x) + return -ENOMEM; + + tac5x1x->dev = dev; + tac5x1x->codec_type = type; + tac5x1x->regmap = regmap; + + dev_set_drvdata(dev, tac5x1x); + if (np) { + ret = tac5x1x_parse_dt(tac5x1x, np); + if (ret) { + dev_err(dev, "Failed to parse DT node\n"); + return ret; + } + } else { + dev_err(dev, "%s: Fail to get device node\n", __func__); + } + + ret = tac5x1x_setup_regulators(dev, tac5x1x); + if (ret) { + dev_err(dev, "Failed to setup regulators\n"); + return ret; + } + + /* update if vcom property is found */ + if (tac5x1x->out2x_vcom_cfg != -1) { + snd_soc_component_update_bits(tac5x1x->component, + TAC5X1X_OUT2CFG0, + TAC5X1X_OUT2CFG0_VCOM_MASK, + tac5x1x->out2x_vcom_cfg); + } + + switch (tac5x1x->codec_type) { + case TAA5212: + case TAA5412: + ret = devm_snd_soc_register_component(dev, &component_taa5x1x, + &taa5x1x_dai, 1); + if (ret) { + dev_err(dev, "Failed to register component\n"); + goto err_disable_regulators; + } + break; + case TAC5111: + case TAC5112: + case TAC5211: + case TAC5212: + case TAC5311: + case TAC5312: + case TAC5411: + case TAC5412: + ret = devm_snd_soc_register_component(dev, &component_tac5x1x, + &tac5x1x_dai, 1); + if (ret) { + dev_err(dev, "Failed to register component\n"); + goto err_disable_regulators; + } + break; + case TAD5112: + case TAD5212: + ret = devm_snd_soc_register_component(dev, &component_tad5x1x, + &tad5x1x_dai, 1); + if (ret) { + dev_err(dev, "Failed to register component\n"); + goto err_disable_regulators; + } + break; + } + return 0; + +err_disable_regulators: + tac5x1x_disable_regulators(tac5x1x); + + return ret; +} + +static s32 tac5x1x_remove(struct device *dev) +{ + struct tac5x1x_priv *tac5x1x = dev_get_drvdata(dev); + + tac5x1x_disable_regulators(tac5x1x); + return 0; +} + +const struct of_device_id tac5x1x_of_match[] = { + { .compatible = "ti,taa5212", .data = (void *)TAA5212 }, + { .compatible = "ti,taa5412", .data = (void *)TAA5412 }, + { .compatible = "ti,tac5111", .data = (void *)TAC5111 }, + { .compatible = "ti,tac5112", .data = (void *)TAC5112 }, + { .compatible = "ti,tac5211", .data = (void *)TAC5211 }, + { .compatible = "ti,tac5212", .data = (void *)TAC5212 }, + { .compatible = "ti,tac5311", .data = (void *)TAC5311 }, + { .compatible = "ti,tac5312", .data = (void *)TAC5312 }, + { .compatible = "ti,tac5411", .data = (void *)TAC5411 }, + { .compatible = "ti,tac5412", .data = (void *)TAC5412 }, + { .compatible = "ti,tad5112", .data = (void *)TAD5112 }, + { .compatible = "ti,tad5212", .data = (void *)TAD5212 }, + {} +}; +MODULE_DEVICE_TABLE(of, tac5x1x_of_match); + +static const struct i2c_device_id tac5x1x_id[] = { + {"taa5212", TAA5212}, + {"taa5412", TAA5412}, + {"tac5111", TAC5111}, + {"tac5112", TAC5112}, + {"tac5211", TAC5211}, + {"tac5212", TAC5212}, + {"tac5311", TAC5311}, + {"tac5312", TAC5312}, + {"tac5411", TAC5411}, + {"tac5412", TAC5412}, + {"tad5112", TAD5112}, + {"tad5212", TAD5212}, + {} +}; +MODULE_DEVICE_TABLE(i2c, tac5x1x_id); + +static int tac5x1x_i2c_probe(struct i2c_client *i2c) +{ + int ret; + enum tac5x1x_type type; + struct regmap *regmap; + const struct regmap_config *config = &tac5x1x_regmap; + + regmap = devm_regmap_init_i2c(i2c, config); + type = (uintptr_t)i2c_get_match_data(i2c); + + ret = tac5x1x_probe(&i2c->dev, regmap, type); + if (ret) + dev_err(&i2c->dev, "probe failed"); + + return ret; +} + +static void tac5x1x_i2c_remove(struct i2c_client *client) +{ + tac5x1x_remove(&client->dev); +} + +static struct i2c_driver tac5x1x_i2c_driver = { + .driver = { + .name = "tac5x1x-codec", + .of_match_table = of_match_ptr(tac5x1x_of_match), + }, + .probe = tac5x1x_i2c_probe, + .remove = tac5x1x_i2c_remove, + .id_table = tac5x1x_id, +}; +module_i2c_driver(tac5x1x_i2c_driver); + +MODULE_DESCRIPTION("ASoC tac5x1x codec driver"); +MODULE_AUTHOR("Texas Instruments"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tac5x1x.h b/sound/soc/codecs/tac5x1x.h new file mode 100644 index 000000000000..f315d1dfb627 --- /dev/null +++ b/sound/soc/codecs/tac5x1x.h @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Audio Codec Driver Supporting Devices + * TAA5X1X, TAC5X1X, TAD5X1X + * + * Copyright (C) 2024-2025 Texas Instruments Incorporated - https://www.ti.com + * + * Author: Kevin Lu kevin-lu@ti.com + * Author: Kokila Karuppusamy kokila.karuppusamy@ti.com + * Author: Niranjan H Y niranjan.hy@ti.com + */ + +#ifndef _TAC5X1X_H +#define _TAC5X1X_H + +#define TAC5X1X_RATES SNDRV_PCM_RATE_8000_192000 +#define TAC5X1X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \ + | SNDRV_PCM_FMTBIT_S20_3LE \ + | SNDRV_PCM_FMTBIT_S24_LE \ + | SNDRV_PCM_FMTBIT_S24_3LE \ + | SNDRV_PCM_FMTBIT_S32_LE) + +/*PAGE Control Register (available in page0 of each book) */ +#define TAC_PAGE_SELECT 0x00 +#define TAC_PAGE_ID(reg) ((reg) / 128) +#define TAC_PAGE_REG(reg) ((reg) % 128) +#define TAC5X1X_REG(page, reg) (((page) * 128) + (reg)) + +#define TAC_PAGE1_SELECT 0x01 +#define TAC5X1X_PGSEL TAC5X1X_REG(0, 0x0) + +#define TAC5X1X_RESET TAC5X1X_REG(0, 0x1) +#define TAC5X1X_VREF TAC5X1X_REG(0, 0x2) +#define TAC5X1X_VDDSTS TAC5X1X_REG(0, 0x3) +#define TAC5X1X_MISC TAC5X1X_REG(0, 0x4) +#define TAC5X1X_MISC1 TAC5X1X_REG(0, 0x5) +#define TAC5X1X_DACA0 TAC5X1X_REG(0, 0x6) +#define TAC5X1X_MISC0 TAC5X1X_REG(0, 0x7) +#define TAC5X1X_GPIO1 TAC5X1X_REG(0, 0xa) +#define TAC5X1X_GPIO2 TAC5X1X_REG(0, 0xb) +#define TAC5X1X_GPO1 TAC5X1X_REG(0, 0xc) +#define TAC5X1X_GPI1 TAC5X1X_REG(0, 0xd) +#define TAC5X1X_GPIOVAL TAC5X1X_REG(0, 0xe) +#define TAC5X1X_INTF0 TAC5X1X_REG(0, 0xf) +#define TAC5X1X_INTF1 TAC5X1X_REG(0, 0x10) +#define TAC5X1X_INTF2 TAC5X1X_REG(0, 0x11) +#define TAC5X1X_INTF3 TAC5X1X_REG(0, 0x12) +#define TAC5X1X_INTF4 TAC5X1X_REG(0, 0x13) +#define TAC5X1X_INTF5 TAC5X1X_REG(0, 0x14) +#define TAC5X1X_INTF6 TAC5X1X_REG(0, 0x15) +#define TAC5X1X_ASI0 TAC5X1X_REG(0, 0x18) +#define TAC5X1X_ASI1 TAC5X1X_REG(0, 0x19) +#define TAC5X1X_PASI0 TAC5X1X_REG(0, 0x1a) +#define TAC5X1X_PASITX0 TAC5X1X_REG(0, 0x1b) +#define TAC5X1X_PASITX1 TAC5X1X_REG(0, 0x1c) +#define TAC5X1X_PASITX2 TAC5X1X_REG(0, 0x1d) +#define TAC5X1X_PASITXCH1 TAC5X1X_REG(0, 0x1e) +#define TAC5X1X_PASITXCH2 TAC5X1X_REG(0, 0x1f) +#define TAC5X1X_PASITXCH3 TAC5X1X_REG(0, 0x20) +#define TAC5X1X_PASITXCH4 TAC5X1X_REG(0, 0x21) +#define TAC5X1X_PASITXCH5 TAC5X1X_REG(0, 0x22) +#define TAC5X1X_PASITXCH6 TAC5X1X_REG(0, 0x23) +#define TAC5X1X_PASITXCH7 TAC5X1X_REG(0, 0x24) +#define TAC5X1X_PASITXCH8 TAC5X1X_REG(0, 0x25) +#define TAC5X1X_PASIRX0 TAC5X1X_REG(0, 0x26) +#define TAC5X1X_PASIRX1 TAC5X1X_REG(0, 0x27) +#define TAC5X1X_PASIRXCH1 TAC5X1X_REG(0, 0x28) +#define TAC5X1X_PASIRXCH2 TAC5X1X_REG(0, 0x29) +#define TAC5X1X_PASIRXCH3 TAC5X1X_REG(0, 0x2a) +#define TAC5X1X_PASIRXCH4 TAC5X1X_REG(0, 0x2b) +#define TAC5X1X_PASIRXCH5 TAC5X1X_REG(0, 0x2c) +#define TAC5X1X_PASIRXCH6 TAC5X1X_REG(0, 0x2d) +#define TAC5X1X_PASIRXCH7 TAC5X1X_REG(0, 0x2e) +#define TAC5X1X_PASIRXCH8 TAC5X1X_REG(0, 0x2f) +#define TAC5X1X_CLK0 TAC5X1X_REG(0, 0x32) +#define TAC5X1X_CLK1 TAC5X1X_REG(0, 0x33) +#define TAC5X1X_CLK2 TAC5X1X_REG(0, 0x34) +#define TAC5X1X_CNTCLK0 TAC5X1X_REG(0, 0x35) +#define TAC5X1X_CNTCLK1 TAC5X1X_REG(0, 0x36) +#define TAC5X1X_CNTCLK2 TAC5X1X_REG(0, 0x37) +#define TAC5X1X_CNTCLK3 TAC5X1X_REG(0, 0x38) +#define TAC5X1X_CNTCLK4 TAC5X1X_REG(0, 0x39) +#define TAC5X1X_CNTCLK5 TAC5X1X_REG(0, 0x3a) +#define TAC5X1X_CNTCLK6 TAC5X1X_REG(0, 0x3b) +#define TAC5X1X_CLKERRSTS0 TAC5X1X_REG(0, 0x3c) +#define TAC5X1X_CLKERRSTS1 TAC5X1X_REG(0, 0x3d) +#define TAC5X1X_CLKDETSTS0 TAC5X1X_REG(0, 0x3e) +#define TAC5X1X_CLKDETSTS1 TAC5X1X_REG(0, 0x3f) +#define TAC5X1X_CLKDETSTS2 TAC5X1X_REG(0, 0x40) +#define TAC5X1X_CLKDETSTS3 TAC5X1X_REG(0, 0x41) +#define TAC5X1X_INT TAC5X1X_REG(0, 0x42) +#define TAC5X1X_DAC_FLT TAC5X1X_REG(0, 0x43) +#define TAC5X1X_ADCDACMISC TAC5X1X_REG(0, 0x4b) +#define TAC5X1X_IADC TAC5X1X_REG(0, 0x4c) +#define TAC5X1X_VREFCFG TAC5X1X_REG(0, 0x4d) +#define TAC5X1X_PWRTUNE0 TAC5X1X_REG(0, 0x4e) +#define TAC5X1X_PWRTUNE1 TAC5X1X_REG(0, 0x4f) +#define TAC5X1X_ADCCH1C0 TAC5X1X_REG(0, 0x50) +#define TAC5X1X_ADCCH TAC5X1X_REG(0, 0x51) +#define TAC5X1X_ADCCH1C2 TAC5X1X_REG(0, 0x52) +#define TAC5X1X_ADCCH1C3 TAC5X1X_REG(0, 0x53) +#define TAC5X1X_ADCCH1C4 TAC5X1X_REG(0, 0x54) +#define TAC5X1X_ADCCH2C0 TAC5X1X_REG(0, 0x55) +#define TAC5X1X_ADCCH2C2 TAC5X1X_REG(0, 0x57) +#define TAC5X1X_ADCCH2C3 TAC5X1X_REG(0, 0x58) +#define TAC5X1X_ADCCH2C4 TAC5X1X_REG(0, 0x59) +#define TAC5X1X_ADCCH3C0 TAC5X1X_REG(0, 0x5a) +#define TAC5X1X_ADCCH3C2 TAC5X1X_REG(0, 0x5b) +#define TAC5X1X_ADCCH3C3 TAC5X1X_REG(0, 0x5c) +#define TAC5X1X_ADCCH3C4 TAC5X1X_REG(0, 0x5d) +#define TAC5X1X_ADCCH4C0 TAC5X1X_REG(0, 0x5e) +#define TAC5X1X_ADCCH4C2 TAC5X1X_REG(0, 0x5f) +#define TAC5X1X_ADCCH4C3 TAC5X1X_REG(0, 0x60) +#define TAC5X1X_ADCCH4C4 TAC5X1X_REG(0, 0x61) +#define TAC5X1X_ADCCFG1 TAC5X1X_REG(0, 0x62) +#define TAC5X1X_OUT1CFG0 TAC5X1X_REG(0, 0x64) +#define TAC5X1X_OUT1CFG1 TAC5X1X_REG(0, 0x65) +#define TAC5X1X_OUT1CFG2 TAC5X1X_REG(0, 0x66) +#define TAC5X1X_DACCH1A0 TAC5X1X_REG(0, 0x67) +#define TAC5X1X_DACCH1A1 TAC5X1X_REG(0, 0x68) +#define TAC5X1X_DACCH1B0 TAC5X1X_REG(0, 0x69) +#define TAC5X1X_DACCH1B1 TAC5X1X_REG(0, 0x6a) +#define TAC5X1X_OUT2CFG0 TAC5X1X_REG(0, 0x6b) +#define TAC5X1X_OUT2CFG1 TAC5X1X_REG(0, 0x6c) +#define TAC5X1X_OUT2CFG2 TAC5X1X_REG(0, 0x6d) +#define TAC5X1X_DACCH2A0 TAC5X1X_REG(0, 0x6e) +#define TAC5X1X_DACCH2A1 TAC5X1X_REG(0, 0x6f) +#define TAC5X1X_DACCH2B0 TAC5X1X_REG(0, 0x70) +#define TAC5X1X_DACCH2B1 TAC5X1X_REG(0, 0x71) +#define TAC5X1X_DSP0 TAC5X1X_REG(0, 0x72) +#define TAC5X1X_DSP1 TAC5X1X_REG(0, 0x73) +#define TAC5X1X_CH_EN TAC5X1X_REG(0, 0x76) +#define TAC5X1X_DYN_PUPD TAC5X1X_REG(0, 0x77) +#define TAC5X1X_PWR_CFG TAC5X1X_REG(0, 0x78) +#define TAC5X1X_DEVSTS0 TAC5X1X_REG(0, 0x79) +#define TAC5X1X_DEVSTS1 TAC5X1X_REG(0, 0x7a) + +#define TAC5X1X_CLKCFG0 TAC5X1X_REG(1, 0xd) +#define TAC5X1X_MICBIAS1 TAC5X1X_REG(1, 0x16) +#define TAC5X1X_AGC_DRC TAC5X1X_REG(1, 0x24) +#define TAC5X1X_PLIM TAC5X1X_REG(1, 0x2b) +#define TAC5X1X_MIXER TAC5X1X_REG(1, 0x2c) + +#define TAC5X1X_DIAG_CFG0 TAC5X1X_REG(1, 0x46) +#define TAC5X1X_DIAG_CFG1 TAC5X1X_REG(1, 0x47) +#define TAC5X1X_DIAG_CFG2 TAC5X1X_REG(1, 0x48) +#define TAC5X1X_DIAG_CFG8 TAC5X1X_REG(1, 0x4e) +#define TAC5X1X_DIAG_CFG9 TAC5X1X_REG(1, 0x4b) +#define TAC5X1X_DIAG_CFG6 TAC5X1X_REG(1, 0x4c) +#define TAC5X1X_DIAG_CFG7 TAC5X1X_REG(1, 0x4d) + +/* interrupt latches */ +#define TAC5X1X_REG_INT_LTCH0 TAC5X1X_REG(0x1, 0x34) +#define TAC5X1X_REG_CHX_LTCH TAC5X1X_REG(0x1, 0x35) +#define TAC5X1X_REG_IN_CH1_LTCH TAC5X1X_REG(0x1, 0x36) +#define TAC5X1X_REG_IN_CH2_LTCH TAC5X1X_REG(0x1, 0x37) +#define TAC5X1X_REG_OUT_CH1_LTCH TAC5X1X_REG(0x1, 0x38) +#define TAC5X1X_REG_OUT_CH2_LTCH TAC5X1X_REG(0x1, 0x39) +#define TAC5X1X_REG_INT_LTCH1 TAC5X1X_REG(0x1, 0x3A) +#define TAC5X1X_REG_INT_LTCH2 TAC5X1X_REG(0x1, 0x3B) + +/* Bits, masks, and shifts */ +/* TAC5X1X_CH_EN */ +#define TAC5X1X_CH_EN_ADC_MASK GENMASK(7, 4) +#define TAC5X1X_CH_EN_ADC_CH1 BIT(7) +#define TAC5X1X_CH_EN_ADC_CH2 BIT(6) +#define TAC5X1X_CH_EN_ADC_CH3 BIT(5) +#define TAC5X1X_CH_EN_ADC_CH4 BIT(4) + +#define TAC5X1X_CH_EN_DAC_MASK GENMASK(3, 0) +#define TAC5X1X_CH_EN_DAC_CH1 BIT(3) +#define TAC5X1X_CH_EN_DAC_CH2 BIT(2) +#define TAC5X1X_CH_EN_DAC_CH3 BIT(1) +#define TAC5X1X_CH_EN_DAC_CH4 BIT(0) + +/* TAC5X1X_GPIOVAL */ +#define TAC5X1X_GPIO1_VAL BIT(7) +#define TAC5X1X_GPIO2_VAL BIT(6) +#define TAC5X1X_GPO1_VAL BIT(5) +#define TAC5X1X_GPIO1_MON BIT(3) +#define TAC5X1X_GPIO2_MON BIT(2) +#define TAC5X1X_GPI1_MON BIT(1) + +/* TAC5X1X_DIAG_CFG0 */ +#define TAC5X1X_IN_CH_DIAG_EN_MASK 0xc0 +#define TAC5X1X_INCL_SE_INM_MASK 0x20 +#define TAC5X1X_INCL_AC_COUP_MASK 0x10 +#define TAC5X1X_OUT1P_DIAG_EN_MASK 0x0f +#define TAC5X1X_MICBIAS_LOW_THRESHOLD 0x48 +#define TAC5X1X_MICBIAS_HIGH_THRESHOLD 0xa2 +#define TAC5X1X_GPA_LOW_THRESHOLD 0x4b +#define TAC5X1X_GPA_HIGH_THRESHOLD 0xba + +/* TAC5X1X_PASI */ +#define TAC5X1X_PASI_SAMP_RATE_MASK GENMASK(7, 2) +#define TAC5X1X_PASI_FMT_MASK GENMASK(7, 6) +#define TAC5X1X_PASI_FMT_TDM 0x00 +#define TAC5X1X_PASI_FMT_I2S 0x40 +#define TAC5X1X_PASI_FMT_LJ 0x80 + +#define TAC5X1X_PASI_DATALEN_MASK GENMASK(5, 4) +#define TAC5X1X_WORD_LEN_16BITS 0x00 +#define TAC5X1X_WORD_LEN_20BITS 0x10 +#define TAC5X1X_WORD_LEN_24BITS 0x20 +#define TAC5X1X_WORD_LEN_32BITS 0x30 + +/* TAC5X1X_CNTCLK2 */ +#define TAC5X1X_PASI_MODE_MASK 0x10 +#define TAC5X1X_SASI_MODE_MASK 0x08 +#define TAC5X1X_ASI_RATE_MASK 0x01 + +#define TAC5X1X_PASI_RATE_48000 0x00 +#define TAC5X1X_PASI_RATE_44100 0x01 + +/* TAC5X1X_PASITX0 */ +#define TAC5X1X_PASITX_OFFSET_MASK 0x1f + +/* TAC5X1X_PASIRX0 */ +#define TAC5X1X_PASIRX_OFFSET_MASK 0x1f + +/* TAC5X1X_VREF */ +#define TAC5X1X_VREF_SLEEP_EXIT_VREF_EN 0x80 +#define TAC5X1X_VREF_SLEEP_ACTIVE_MASK 0x01 + +/* TAC5X1X_PWRCFG */ +#define TAC5X1X_PWR_CFG_ADC_PDZ BIT(7) +#define TAC5X1X_PWR_CFG_DAC_PDZ BIT(6) +#define TAC5X1X_PWR_CFG_MICBIAS BIT(5) +#define TAC5X1X_PWR_CFG_UAD_EN BIT(3) +#define TAC5X1X_PWR_CFG_VAD_EN BIT(2) +#define TAC5X1X_PWR_CFG_UAG_EN BIT(1) + +/* TAC5X1X_GPIOx */ +#define TAC5X1X_GPIO1_DEFAULT_VAL 0x32 +#define TAC5X1X_GPIO2_DEFAULT_VAL 0x00 +#define TAC5X1X_GPI1_DEFAULT_VAL 0x00 +#define TAC5X1X_GPO1_DEFAULT_VAL 0x00 + +#define TAC5X1X_GPIOX_CFG_MASK 0xf0 +#define TAC5X1X_GPIOX_DRV_MASK 0x07 + +#define TAC5X1X_GPIO_DISABLE 0 +#define TAC5X1X_GPIO_GPI 1 +#define TAC5X1X_GPIO_GPO 2 +#define TAC5X1X_GPIO_IRQ 3 +#define TAC5X1X_GPIO_PDMCLK 4 +#define TAC5X1X_GPIO_P_DOUT 5 +#define TAC5X1X_GPIO_P_DOUT2 6 +#define TAC5X1X_GPIO_S_DOUT 7 +#define TAC5X1X_GPIO_S_DOUT2 8 +#define TAC5X1X_GPIO_S_BCLK 9 +#define TAC5X1X_GPIO_S_FSYNC 10 +#define TAC5X1X_GPIO_CLKOUT 11 +#define TAC5X1X_GPIO_DOUT_MUX 12 +#define TAC5X1X_GPIO_DAISY_OUT 13 + +#define TAC5X1X_GPIO_DRV_HIZ 0 +#define TAC5X1X_GPIO_DRV_ALAH 1 +#define TAC5X1X_GPIO_DRV_ALWH 2 +#define TAC5X1X_GPIO_DRV_ALHIZ 3 +#define TAC5X1X_GPIO_DRV_WLAH 4 +#define TAC5X1X_GPIO_DRV_HIZAH 5 + +/* TAC5X1X_GPI1 */ +#define TAC5X1X_GPI1_CFG_MASK BIT(1) +#define TAC5X1X_GPA_CFG_MASK BIT(0) + +/* TAC5X1X_VREFCFG */ +#define TAC5X1X_VREFCFG_MICBIAS_VAL_MASK GENMASK(3, 2) +#define TAC5X1X_VREFCFG_VREF_FSCALE_MASK GENMASK(1, 0) + +#define TAC5X1X_ADCCH1C0_IMPEDANCE_MASK GENMASK(5, 4) +#define TAC5X1X_ADCCH2C0_IMPEDANCE_MASK GENMASK(5, 4) + +#define TAC5X1X_OUT2CFG0_VCOM_MASK BIT(1) + +#define TAC5X1X_MICBIAS_VREF 0 +#define TAC5X1X_MICBIAS_0_5VREF 1 +#define TAC5X1X_MICBIAS_AVDD 3 + +#define TAC5X1X_VERF_2_75V 0 +#define TAC5X1X_VERF_2_5V 1 +#define TAC5X1X_VERF_1_375V 2 + +enum tac5x1x_type { + TAA5212 = 0, + TAA5412, + TAC5111, + TAC5112, + TAC5211, + TAC5212, + TAC5311, + TAC5312, + TAC5411, + TAC5412, + TAD5112, + TAD5212, +}; + +#endif /* _TAC5X1X_H */

On Tue, Jun 24, 2025 at 09:07:39PM +0530, Niranjan H Y wrote:
This looks mostly good, a few issues below but none super substantial.
+static void process_one_interrupt(struct tac5x1x_priv *tac5x1x, s32 index,
s32 value)
+{
- u32 map_count, i;
- const struct mask_to_txt *map_items;
- map_count = intr_info_list[index].count;
- map_items = intr_info_list[index].mask_str_map;
- for (i = 0; i < map_count; i++) {
if (value & map_items[i].mask)
dev_err(tac5x1x->dev, "Interrupt %s detected\n",
map_items[i].name);
- }
+}
This should probably be a dev_dbg() at most if it's not for a specific interrupt.
- ret = regmap_multi_reg_read(tac5x1x->regmap,
tac5x1x->irqinfo.latch_regs,
tac5x1x->irqinfo.latch_data, latch_count);
- if (ret) {
dev_err(tac5x1x->dev,
"interrupt: latch register read failed");
return IRQ_HANDLED;
- }
IRQ_NONE is probably a better choice for a failed read, that'll mean we retry (or shut the interrupt off if it fails continually).
+static s32 tac5x1x_get_GPIO1_gpio(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
+{
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- s32 val;
- val = snd_soc_component_read(component, TAC5X1X_GPIOVAL);
- ucontrol->value.integer.value[0] = !!(val & TAC5X1X_GPIO1_MON);
- return 0;
+};
As I said on the prior version the GPIOs should be exposed via gpiolib. Please just remove this, if you want to discuss it'd be better to make it a separate incremental patch so that it doesn't hold up the rest of the driver.
+/* PDM Data input pin Selection */ +static const char *const pdm_pin_text[] = {
- "Disable",
- "GPIO1",
- "GPIO2",
- "GPI1",
+};
This looks like something that should be configured via the DT rather than from userspace, I'd expected this will be determined by the hardware design. It looks like the DT bit is already there so the controls should just be dropped.
+static s32 tac5x1x_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt) +{
- struct snd_soc_component *component = codec_dai->component;
- s32 iface_reg_1 = 0;
- s32 iface_reg_2 = 0;
- s32 iface_reg_3 = 0;
- int right_slot = 1;
- dev_info(component->dev, "[tac5x1x] %s(), fmt=%d\n", __func__, fmt);
There shouldn't be any dev_info() or higher messages in the normal playback/record flow. Error reports are fine, but when things are working the logs should be quiet so we don't obscure problems.
+static s32 tac5x1x_reset(struct snd_soc_component *component) +{
- s32 ret, index;
- ret = snd_soc_component_write(component, TAC5X1X_RESET, 1);
- if (ret < 0)
return ret;
- /* Wait >= 10 ms after entering sleep mode. */
- usleep_range(10000, 100000);
- for (index = 0; index < ARRAY_SIZE(tac5x1x_reg_defaults); index++) {
ret = snd_soc_component_write(component,
tac5x1x_reg_defaults[index].reg,
tac5x1x_reg_defaults[index].def);
if (ret < 0)
return ret;
- }
You can use regcache_drop_region() to discard the cache without having to write out all the values to the hardware, that should speed things up a lot.
- if (!(tac5x1x->codec_type == TAD5212 ||
tac5x1x->codec_type == TAD5112)) {
ret =
snd_soc_dapm_new_controls(dapm, tac5x1x_common_widgets,
ARRAY_SIZE(tac5x1x_common_widgets));
if (ret)
return ret;
ret = snd_soc_dapm_add_routes(dapm, tac_common_routes,
ARRAY_SIZE(tac_common_routes));
if (ret)
return ret;
- } else {
It's better to use switch statements for these, it's easier to extend for new chips.
+static int tac5x1x_i2c_probe(struct i2c_client *i2c) +{
- int ret;
- enum tac5x1x_type type;
- struct regmap *regmap;
- const struct regmap_config *config = &tac5x1x_regmap;
- regmap = devm_regmap_init_i2c(i2c, config);
- type = (uintptr_t)i2c_get_match_data(i2c);
- ret = tac5x1x_probe(&i2c->dev, regmap, type);
- if (ret)
dev_err(&i2c->dev, "probe failed");
- return ret;
+}
It'd be better to move the resets, regulator gets and pin configuration to the I2C probe - that means that even if the sound card doesn't start for some reason the chip will be in a known good state, and if it takes some deferred probes for the card to come up we won't be bouncing the chip on and off.

Hi Niranjan,
kernel test robot noticed the following build errors:
[auto build test ERROR on broonie-sound/for-next] [also build test ERROR on linus/master v6.16-rc3 next-20250627] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Niranjan-H-Y/ASoc-tac5x1x-add... base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next patch link: https://lore.kernel.org/r/20250624153742.1507-2-niranjan.hy%40ti.com patch subject: [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family config: x86_64-rhel-9.4 (attached as .config) compiler: gcc-12 (Debian 12.2.0-14+deb12u1) 12.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250629/202506290455.cgLfcmh1-lkp@i...)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot lkp@intel.com | Closes: https://lore.kernel.org/oe-kbuild-all/202506290455.cgLfcmh1-lkp@intel.com/
All errors (new ones prefixed by >>):
error: recursive dependency detected!
symbol REGMAP_I2C is selected by SND_SOC_TAC5X1X_I2C symbol SND_SOC_TAC5X1X_I2C depends on REGMAP_I2C For a resolution refer to Documentation/kbuild/kconfig-language.rst subsection "Kconfig recursive dependency limitations"

tac5x1x family are series of low-power and high performance mono/stereo audio codecs consists of ADC and DAC combinations. The family consist of Codecs(DAC & ADC), ADC only and DAC only configurations. The documentation explains the list of devices in the family, their power supply configurations and gpio configuration options available for various functionality.
Signed-off-by: Niranjan H Y niranjan.hy@ti.com
--- v2: - Document newly added dts entries ti,adc1-impedance, ti,adc2-impedance, ti,out2x-vcom-cfg --- .../devicetree/bindings/sound/ti,tac5x1x.yaml | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/ti,tac5x1x.yaml
diff --git a/Documentation/devicetree/bindings/sound/ti,tac5x1x.yaml b/Documentation/devicetree/bindings/sound/ti,tac5x1x.yaml new file mode 100644 index 000000000000..c1aba0632b95 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,tac5x1x.yaml @@ -0,0 +1,248 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +# Copyright (C) 2025 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,tac5x1x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments TAC5X1X Codec + +description: | + TAC5X1X are series of low-power and high performance mono or stereo + audio codecs, as well as multiple inputs and outputs programmable in + single-ended or fully differential configurations. Device supports both + Microphone and Line In input on ADC Channel. DAC Output can be configured + for either Line Out or Head Phone Load. + + The serial control bus supports SPI or I2C protocols, while the serial audio + data bus is programmable for I2S, left/right-justified, DSP, or TDM modes. + + Specification about the codecs can be found at: + https://www.ti.com/lit/gpn/taa5212 + https://www.ti.com/lit/gpn/taa5412-q1 + https://www.ti.com/lit/gpn/tac5111 + https://www.ti.com/lit/gpn/tac5112 + https://www.ti.com/lit/gpn/tac5211 + https://www.ti.com/lit/gpn/tac5212 + https://www.ti.com/lit/gpn/tac5311-q1 + https://www.ti.com/lit/gpn/tac5312-q1 + https://www.ti.com/lit/gpn/tac5411-q1 + https://www.ti.com/lit/gpn/tac5412-q1 + https://www.ti.com/lit/gpn/tad5112 + https://www.ti.com/lit/gpn/tad5212 + +maintainers: + - Niranjan H Y niranjan.hy@ti.com + - Kevin Lu kevin-lu@ti.com + +properties: + compatible: + enum: + - ti,taa5212 + - ti,taa5412 + - ti,tac5111 + - ti,tac5112 + - ti,tac5211 + - ti,tac5212 + - ti,tac5311 + - ti,tac5312 + - ti,tac5411 + - ti,tac5412 + - ti,tad5112 + - ti,tad5212 + + reg: + maxItems: 1 + + ti,vref: + description: VREF required voltage. If node is omitted then VREF is powered down. + $ref: /schemas/types.yaml#/definitions/uint32 + oneOf: + - const: 0 + description: VREF output is powered to 2.75V. + - const: 1 + description: VREF output is powered to 2.5V. + - const: 2 + description: VREF output is powered to 1.375V. + + ti,micbias-vg: + description: MicBias required voltage. If node is omitted then MicBias is powered down. + $ref: /schemas/types.yaml#/definitions/uint32 + oneOf: + - const: 0 + description: MICBIAS output is same as the VREF output + - const: 1 + description: MICBIAS output is 0.5 times the VREF output + - const: 3 + description: MICBIAS output is same as the AVDD + + avdd-supply: + description: Analog DAC voltage. + + iovdd-supply: + description: I/O voltage. + + ti,gpios-func: + description: | + Array indicating the GPIO1, GPIO2, GPO1 Functionality in the same order. + Each integer elemnent in the array represent the following + - 0 TAC5X1X_GPIO_DISABLE - GPIO is Disabled + - 1 TAC5X1X_GPIO_GPI - General Purpose Input + - 2 ADC3XXX_GPIO_GPO - General Purpose Output + - 3 TAC5X1X_GPIO_IRQ - Chip Interrupt + - 4 TAC5X1X_GPIO_PDMCLK - PDM CLK Output + - 5 TAC5X1X_GPIO_P_DOUT - Primary ASI DOUT + - 6 TAC5X1X_GPIO_P_DOUT2 - Primary ASI DOUT2 + - 7 TAC5X1X_GPIO_S_DOUT - Secondary ASI DOUT + - 8 TAC5X1X_GPIO_S_DOUT2 - Secondary ASI DOUT2 + - 9 TAC5X1X_GPIO_S_BCLK - Secondary BCLK Output + - 10 TAC5X1X_GPIO_S_FSYNC - Secondary FSYNC Output + - 11 TAC5X1X_GPIO_CLKOUT - General Purpose Output + - 12 TAC5X1X_GPIO_DOUT_MUX + - 13 TAC5X1X_GPIO_DAISY_OUT + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 3 + maxItems: 3 + + ti,gpios-drive: + description: | + Array indicating the GPIO1, GPIO2, GPO1 Driver values + Each number in the array indicate the following driver values. + - 0 # Hi-Z Output + - 1 # Drive active low and active High + - 2 # Drive active low and weak High + - 3 # Drive acive low and Hi-Z + - 4 # Drive weak low and active High + - 5 # Drive Hi-Z and active High + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 3 + maxItems: 3 + + ti,gpi1-func: + description: GPI1 Functionality + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # TAC5X1X_GPIO_DISABLE - I/O buffers powered down and not used + - 1 # TAC5X1X_GPIO_GPI - General purpose input + default: 0 + + '#sound-dai-cells': + const: 0 + + clocks: + maxItems: 1 + + ti,gpa-gpio: + description: GPA using GPIO1 configuration + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # GPA using GPIO1 is disabled + - 1 # GPA using GPIO1 + default: 0 + + ti,in-ch-en: + description: Enable Input channel diagnostics for TAC54XX and TAC53XX device. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # Disable input channel diagnostics + - 1 # Enable input channel diagnostics + + ti,out-ch-en: + description: Enable Output channel diagnostics for TAC54XX and TAC53XX device + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # Disable Output channel diagnostics + - 1 # Enable Output channel Diagnostics + + ti,incl-se-inm: + description: INxM pin Diagnostics Scan Selection for Single Ended Configuration + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # INxM pin Diagnostics Scan Selection for Single Ended excluded for diagnosis + - 1 # INxM pin Diagnostics Scan Selection for Single Ended included for diagnosis + + ti,incl-ac-coup: + description: AC coupled channels pins Scan Selection for Diagnostics + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # AC coupled channels pins Scan Selection for Diagnostics exluded for diagnosis + - 1 # AC coupled channels pins Scan Selection for Diagnostics included for diagnosis + + ti,micbias-threshold: + description: Micbias Low and High threshold values for TAC54XX and TAC53XX series + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 2 + minItems: 2 + items: + minimum: 72 + maximum: 162 + + ti,gpa-threshold: + description: GPA Low and High threshold Values + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 2 + minItems: 2 + items: + minimum: 75 + maximum: 186 + + ti,adc1-impedance: + description: Channel 1 Input Impedance Value + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # 5 kOhm + - 1 # 10 kOhm + - 2 # 40 kOhm + default: 0 + + ti,adc2-impedance: + description: Channel 2 Input Impedance Value + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # 5 kOhm + - 1 # 10 kOhm + - 2 # 40 kOhm + default: 0 + + ti,out2x-vcom-cfg: + description: Channel OUT2x VCOM configuration + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # 0.6 * Vref + - 1 # AVDD by 2 + default: 0 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/gpio/gpio.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + tac5x1x: tac5x1x@52 { + compatible = "ti,tac5212"; + reg = <0x52>; + #sound-dai-cells = <0>; + avdd-supply = <&vdd_3v3_reg>; + iovdd-supply = <&vdd_3v3_reg>; + ti,vref = <0>; + ti,micbias-vg = <3>; + ti,gpi1-func = <0>; + ti,gpios-func = <4>, <1>, <0>; + ti,gpios-drive = <0>, <0>, <0>; + ti,gpa-gpio = <0>; + ti,in-ch-en = <1>; + ti,out-ch-en = <1>; + ti,incl-ac-coup = <0>; + ti,incl-se-inm = <0>; + ti,gpa-threshold = <75>, <186>; + }; + }; +... -- 2.45.2

On Tue, Jun 24, 2025 at 09:07:40PM +0530, Niranjan H Y wrote:
tac5x1x family are series of low-power and high performance mono/stereo audio codecs consists of ADC and DAC combinations. The family consist of Codecs(DAC & ADC), ADC only and DAC only configurations. The documentation explains the list of devices in the family, their power supply configurations and gpio configuration options available for various functionality.
Signed-off-by: Niranjan H Y niranjan.hy@ti.com
Aren't DT bindings changes supposed to follow the common template in the Subject?
More important, the Cc list missed DT mailing lists and maintainers. What's going on here, please?

tac5x1x codec driver suporrts tac5x1x family which includes the following ADCs and DACs. So removed the duplicate entries in the pcm6240 i2c driver.
Signed-off-by: Niranjan H Y niranjan.hy@ti.com --- sound/soc/codecs/pcm6240.c | 124 +------------------------------------ sound/soc/codecs/pcm6240.h | 4 -- 2 files changed, 3 insertions(+), 125 deletions(-)
diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c index 75af12231d1d..bbf3eb18bf54 100644 --- a/sound/soc/codecs/pcm6240.c +++ b/sound/soc/codecs/pcm6240.c @@ -44,10 +44,6 @@ static const struct i2c_device_id pcmdevice_i2c_id[] = { { "pcmd3140", PCMD3140 }, { "pcmd3180", PCMD3180 }, { "pcmd512x", PCMD512X }, - { "taa5212", TAA5212 }, - { "taa5412", TAA5412 }, - { "tad5212", TAD5212 }, - { "tad5412", TAD5412 }, {} }; MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id); @@ -442,60 +438,6 @@ static const struct pcmdevice_mixer_control pcmd3180_fine_gain_ctl[] = { } };
-static const struct pcmdevice_mixer_control taa5412_digi_vol_ctl[] = { - { - .shift = 0, - .reg = TAA5412_REG_CH1_DIGITAL_VOLUME, - .max = 0xff, - .invert = 0, - }, - { - .shift = 0, - .reg = TAA5412_REG_CH2_DIGITAL_VOLUME, - .max = 0xff, - .invert = 0, - }, - { - .shift = 0, - .reg = TAA5412_REG_CH3_DIGITAL_VOLUME, - .max = 0xff, - .invert = 0, - }, - { - .shift = 0, - .reg = TAA5412_REG_CH4_DIGITAL_VOLUME, - .max = 0xff, - .invert = 0, - } -}; - -static const struct pcmdevice_mixer_control taa5412_fine_gain_ctl[] = { - { - .shift = 4, - .reg = TAA5412_REG_CH1_FINE_GAIN, - .max = 0xf, - .invert = 0, - }, - { - .shift = 4, - .reg = TAA5412_REG_CH2_FINE_GAIN, - .max = 0xf, - .invert = 0, - }, - { - .shift = 4, - .reg = TAA5412_REG_CH3_FINE_GAIN, - .max = 0xf, - .invert = 4, - }, - { - .shift = 0, - .reg = TAA5412_REG_CH4_FINE_GAIN, - .max = 0xf, - .invert = 4, - } -}; - static const DECLARE_TLV_DB_MINMAX_MUTE(pcmd3140_dig_gain_tlv, -10000, 2700); static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_fine_dig_gain_tlv, @@ -512,7 +454,7 @@ static const DECLARE_TLV_DB_MINMAX_MUTE(pcm6260_fgain_tlv, static const DECLARE_TLV_DB_LINEAR(pcm6260_chgain_tlv, 0, 4200); static const DECLARE_TLV_DB_MINMAX_MUTE(taa5412_dig_vol_tlv, -8050, 4700); -static const DECLARE_TLV_DB_LINEAR(taa5412_fine_gain_tlv, +static const DECLARE_TLV_DB_LINEAR(pcmd31x0_fine_gain_tlv, -80, 70);
static int pcmdev_change_dev(struct pcmdevice_priv *pcm_priv, @@ -981,7 +923,7 @@ static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = { // PCMD3140 { { - .gain = taa5412_fine_gain_tlv, + .gain = pcmd31x0_fine_gain_tlv, .pcmdev_ctrl = pcmd3140_fine_gain_ctl, .ctrl_array_size = ARRAY_SIZE(pcmd3140_fine_gain_ctl), .get = pcmdevice_get_volsw, @@ -1000,7 +942,7 @@ static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = { // PCMD3180 { { - .gain = taa5412_fine_gain_tlv, + .gain = pcmd31x0_fine_gain_tlv, .pcmdev_ctrl = pcmd3180_fine_gain_ctl, .ctrl_array_size = ARRAY_SIZE(pcmd3180_fine_gain_ctl), .get = pcmdevice_get_volsw, @@ -1025,62 +967,6 @@ static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = { .ctrl_array_size = 0, }, }, - // TAA5212 - { - { - .gain = taa5412_fine_gain_tlv, - .pcmdev_ctrl = taa5412_fine_gain_ctl, - .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl), - .get = pcmdevice_get_volsw, - .put = pcmdevice_put_volsw, - .pcmdev_ctrl_name_id = 2, - }, - { - .gain = taa5412_dig_vol_tlv, - .pcmdev_ctrl = taa5412_digi_vol_ctl, - .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl), - .get = pcmdevice_get_volsw, - .put = pcmdevice_put_volsw, - .pcmdev_ctrl_name_id = 1, - }, - }, - // TAA5412 - { - { - .gain = taa5412_fine_gain_tlv, - .pcmdev_ctrl = taa5412_fine_gain_ctl, - .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl), - .get = pcmdevice_get_volsw, - .put = pcmdevice_put_volsw, - .pcmdev_ctrl_name_id = 2, - }, - { - .gain = taa5412_dig_vol_tlv, - .pcmdev_ctrl = taa5412_digi_vol_ctl, - .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl), - .get = pcmdevice_get_volsw, - .put = pcmdevice_put_volsw, - .pcmdev_ctrl_name_id = 1, - }, - }, - // TAD5212 - { - { - .ctrl_array_size = 0, - }, - { - .ctrl_array_size = 0, - }, - }, - // TAD5412 - { - { - .ctrl_array_size = 0, - }, - { - .ctrl_array_size = 0, - }, - }, };
static int pcmdev_dev_bulk_write(struct pcmdevice_priv *pcm_dev, @@ -2002,10 +1888,6 @@ static const struct of_device_id pcmdevice_of_match[] = { { .compatible = "ti,pcmd3140" }, { .compatible = "ti,pcmd3180" }, { .compatible = "ti,pcmd512x" }, - { .compatible = "ti,taa5212" }, - { .compatible = "ti,taa5412" }, - { .compatible = "ti,tad5212" }, - { .compatible = "ti,tad5412" }, {}, }; MODULE_DEVICE_TABLE(of, pcmdevice_of_match); diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h index 2d8f9e798139..86b1ef734a3d 100644 --- a/sound/soc/codecs/pcm6240.h +++ b/sound/soc/codecs/pcm6240.h @@ -33,10 +33,6 @@ enum pcm_device { PCMD3140, PCMD3180, PCMD512X, - TAA5212, - TAA5412, - TAD5212, - TAD5412, MAX_DEVICE, };

Removed taa* and tad* device from the support list as these devices are supported by tac5x1x codec driver
Signed-off-by: Niranjan H Y niranjan.hy@ti.com --- .../devicetree/bindings/sound/ti,pcm6240.yaml | 10 ---------- 1 file changed, 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml b/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml index d89b4255b51c..b0d5f57dc0f5 100644 --- a/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml +++ b/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml @@ -29,8 +29,6 @@ description: | https://www.ti.com/lit/gpn/pcm9211 https://www.ti.com/lit/gpn/pcmd3140 https://www.ti.com/lit/gpn/pcmd3180 - https://www.ti.com/lit/gpn/taa5212 - https://www.ti.com/lit/gpn/tad5212
properties: compatible: @@ -81,10 +79,6 @@ properties: ti,pcmd3180: Eight-channel pulse-density-modulation input to TDM or I2S output converter.
- ti,taa5212: Low-power high-performance stereo audio ADC with 118-dB - dynamic range. - - ti,tad5212: Low-power stereo audio DAC with 120-dB dynamic range. oneOf: - items: - enum: @@ -98,8 +92,6 @@ properties: - enum: - ti,pcmd512x - ti,pcm9211 - - ti,taa5212 - - ti,tad5212 - const: ti,adc6120 - items: - enum: @@ -114,8 +106,6 @@ properties: - ti,pcmd3140 - ti,pcmd3180 - ti,pcm1690 - - ti,taa5412 - - ti,tad5412 - const: ti,pcm6240 - enum: - ti,adc6120

On Tue, Jun 24, 2025 at 09:07:42PM +0530, Niranjan H Y wrote:
Removed taa* and tad* device from the support list as these devices are supported by tac5x1x codec driver
Same question, why are DT mailing list and maintainers excluded from the distribution?
participants (4)
-
Andy Shevchenko
-
kernel test robot
-
Mark Brown
-
Niranjan H Y