All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] ASoc: tac5x1x: mixer-test report
@ 2025-06-24 15:37 Niranjan H Y
  2025-06-24 15:37 ` [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family Niranjan H Y
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Niranjan H Y @ 2025-06-24 15:37 UTC (permalink / raw)
  To: broonie
  Cc: andriy.shevchenko, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi, niranjan.hy

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


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family
  2025-06-24 15:37 [PATCH v2 0/4] ASoc: tac5x1x: mixer-test report Niranjan H Y
@ 2025-06-24 15:37 ` Niranjan H Y
  2025-06-25 12:03   ` Mark Brown
  2025-06-28 20:42   ` kernel test robot
  2025-06-24 15:37 ` [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec Niranjan H Y
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 11+ messages in thread
From: Niranjan H Y @ 2025-06-24 15:37 UTC (permalink / raw)
  To: broonie
  Cc: andriy.shevchenko, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi, niranjan.hy

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 */
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec
  2025-06-24 15:37 [PATCH v2 0/4] ASoc: tac5x1x: mixer-test report Niranjan H Y
  2025-06-24 15:37 ` [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family Niranjan H Y
@ 2025-06-24 15:37 ` Niranjan H Y
  2025-06-25 14:30   ` Andy Shevchenko
  2025-06-24 15:37 ` [PATCH v2 3/4] Asoc: pcm6240: remove support for taac5x1x family Niranjan H Y
  2025-06-24 15:37 ` [PATCH v2 4/4] ASoc: pcm6240: dt-bindings device support list update Niranjan H Y
  3 siblings, 1 reply; 11+ messages in thread
From: Niranjan H Y @ 2025-06-24 15:37 UTC (permalink / raw)
  To: broonie
  Cc: andriy.shevchenko, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi, niranjan.hy

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


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 3/4] Asoc: pcm6240: remove support for taac5x1x family
  2025-06-24 15:37 [PATCH v2 0/4] ASoc: tac5x1x: mixer-test report Niranjan H Y
  2025-06-24 15:37 ` [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family Niranjan H Y
  2025-06-24 15:37 ` [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec Niranjan H Y
@ 2025-06-24 15:37 ` Niranjan H Y
  2025-06-24 15:37 ` [PATCH v2 4/4] ASoc: pcm6240: dt-bindings device support list update Niranjan H Y
  3 siblings, 0 replies; 11+ messages in thread
From: Niranjan H Y @ 2025-06-24 15:37 UTC (permalink / raw)
  To: broonie
  Cc: andriy.shevchenko, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi, niranjan.hy

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,
 };
 
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v2 4/4] ASoc: pcm6240: dt-bindings device support list update
  2025-06-24 15:37 [PATCH v2 0/4] ASoc: tac5x1x: mixer-test report Niranjan H Y
                   ` (2 preceding siblings ...)
  2025-06-24 15:37 ` [PATCH v2 3/4] Asoc: pcm6240: remove support for taac5x1x family Niranjan H Y
@ 2025-06-24 15:37 ` Niranjan H Y
  2025-06-25 14:32   ` Andy Shevchenko
  3 siblings, 1 reply; 11+ messages in thread
From: Niranjan H Y @ 2025-06-24 15:37 UTC (permalink / raw)
  To: broonie
  Cc: andriy.shevchenko, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi, niranjan.hy

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
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family
  2025-06-24 15:37 ` [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family Niranjan H Y
@ 2025-06-25 12:03   ` Mark Brown
  2025-06-28 20:42   ` kernel test robot
  1 sibling, 0 replies; 11+ messages in thread
From: Mark Brown @ 2025-06-25 12:03 UTC (permalink / raw)
  To: Niranjan H Y
  Cc: andriy.shevchenko, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi

[-- Attachment #1: Type: text/plain, Size: 4442 bytes --]

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.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec
  2025-06-24 15:37 ` [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec Niranjan H Y
@ 2025-06-25 14:30   ` Andy Shevchenko
  0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-06-25 14:30 UTC (permalink / raw)
  To: Niranjan H Y
  Cc: broonie, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi

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?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 4/4] ASoc: pcm6240: dt-bindings device support list update
  2025-06-24 15:37 ` [PATCH v2 4/4] ASoc: pcm6240: dt-bindings device support list update Niranjan H Y
@ 2025-06-25 14:32   ` Andy Shevchenko
  0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-06-25 14:32 UTC (permalink / raw)
  To: Niranjan H Y
  Cc: broonie, tiwai, alsa-devel, baojun.xu, shenghao-ding,
	liam.r.girdwood, navada, v-hampiholi

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?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec
@ 2025-06-26 14:23 Holalu Yogendra, Niranjan
  2025-06-26 14:51 ` Andy Shevchenko
  0 siblings, 1 reply; 11+ messages in thread
From: Holalu Yogendra, Niranjan @ 2025-06-26 14:23 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: broonie@kernel.org, tiwai@suse.de, alsa-devel@alsa-project.org,
	Xu, Baojun, Ding, Shenghao, liam.r.girdwood@intel.com,
	Navada Kanyana, Mukund, Hampiholi, Vallabha

Thank you for the time and review comment.

> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Sent: Wednesday, June 25, 2025 8:01 PM
> Subject: Re: [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec
> 
> 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.
> 
> Aren't DT bindings changes supposed to follow the common template in the
> Subject?
Is it okay to change the subject in the next patch or keep using the 
same subject tracking?  please suggest.
> 
> More important, the Cc list missed DT mailing lists and maintainers.
> What's going on here, please?
Pardon my ignorance. 
I will address in the next patch.

Regards
Niranjan

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec
  2025-06-26 14:23 [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec Holalu Yogendra, Niranjan
@ 2025-06-26 14:51 ` Andy Shevchenko
  0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-06-26 14:51 UTC (permalink / raw)
  To: Holalu Yogendra, Niranjan
  Cc: broonie@kernel.org, tiwai@suse.de, alsa-devel@alsa-project.org,
	Xu, Baojun, Ding, Shenghao, liam.r.girdwood@intel.com,
	Navada Kanyana, Mukund, Hampiholi, Vallabha

On Thu, Jun 26, 2025 at 02:23:43PM +0000, Holalu Yogendra, Niranjan wrote:
> > From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Sent: Wednesday, June 25, 2025 8:01 PM
> > 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.
> > 
> > Aren't DT bindings changes supposed to follow the common template in the
> > Subject?
> Is it okay to change the subject in the next patch or keep using the 
> same subject tracking?  please suggest.

I think you need to play their rules.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family
  2025-06-24 15:37 ` [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family Niranjan H Y
  2025-06-25 12:03   ` Mark Brown
@ 2025-06-28 20:42   ` kernel test robot
  1 sibling, 0 replies; 11+ messages in thread
From: kernel test robot @ 2025-06-28 20:42 UTC (permalink / raw)
  To: Niranjan H Y, broonie
  Cc: oe-kbuild-all, andriy.shevchenko, tiwai, alsa-devel, baojun.xu,
	shenghao-ding, liam.r.girdwood, navada, v-hampiholi, niranjan.hy

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-codec-driver-tac5x1x-family/20250628-012714
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@intel.com/reproduce)

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"

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-06-28 20:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-24 15:37 [PATCH v2 0/4] ASoc: tac5x1x: mixer-test report Niranjan H Y
2025-06-24 15:37 ` [PATCH v2 1/4] ASoc: tac5x1x: add codec driver tac5x1x family Niranjan H Y
2025-06-25 12:03   ` Mark Brown
2025-06-28 20:42   ` kernel test robot
2025-06-24 15:37 ` [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec Niranjan H Y
2025-06-25 14:30   ` Andy Shevchenko
2025-06-24 15:37 ` [PATCH v2 3/4] Asoc: pcm6240: remove support for taac5x1x family Niranjan H Y
2025-06-24 15:37 ` [PATCH v2 4/4] ASoc: pcm6240: dt-bindings device support list update Niranjan H Y
2025-06-25 14:32   ` Andy Shevchenko
  -- strict thread matches above, loose matches on Subject: below --
2025-06-26 14:23 [PATCH v2 2/4] Asoc: tac5x1x: document tac5x1x codec Holalu Yogendra, Niranjan
2025-06-26 14:51 ` Andy Shevchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.