blob: b7dbf2e7f77afcf7bde1fd53f4303f36af4a3ee4 [file] [log] [blame]
Thomas Gleixnerd0fa1172019-05-20 19:07:57 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Ian Minett95c6e9c2011-06-15 15:35:17 -07002/*
3 * HD audio interface patch for Creative CA0132 chip
4 *
5 * Copyright (c) 2011, Creative Technology Ltd.
6 *
7 * Based on patch_ca0110.c
8 * Copyright (c) 2008 Takashi Iwai <tiwai@suse.de>
Ian Minett95c6e9c2011-06-15 15:35:17 -07009 */
10
11#include <linux/init.h>
12#include <linux/delay.h>
13#include <linux/slab.h>
Ian Minett95c6e9c2011-06-15 15:35:17 -070014#include <linux/mutex.h>
Paul Gortmakerda155d52011-07-15 12:38:28 -040015#include <linux/module.h>
Ian Minett4aa3bb02012-09-20 20:29:15 -070016#include <linux/firmware.h>
Jérémy Lefaurea9291f42017-10-12 22:36:31 -040017#include <linux/kernel.h>
Connor McAdamsaa317042018-05-08 13:20:03 -040018#include <linux/types.h>
19#include <linux/io.h>
20#include <linux/pci.h>
Mark Brownd9b84a12018-09-12 12:31:32 +010021#include <asm/io.h>
Ian Minett95c6e9c2011-06-15 15:35:17 -070022#include <sound/core.h>
Pierre-Louis Bossartbe57bff2018-08-22 15:24:57 -050023#include <sound/hda_codec.h>
Ian Minett95c6e9c2011-06-15 15:35:17 -070024#include "hda_local.h"
Takashi Iwai128bc4b2012-05-07 17:42:31 +020025#include "hda_auto_parser.h"
Ian Minett5aaca442012-12-20 18:53:34 -080026#include "hda_jack.h"
Ian Minett95c6e9c2011-06-15 15:35:17 -070027
Ian Minettbcd109c2012-09-20 20:29:14 -070028#include "ca0132_regs.h"
29
Ian Minettef6b2ea2012-12-20 18:53:33 -080030/* Enable this to see controls for tuning purpose. */
31/*#define ENABLE_TUNING_CONTROLS*/
32
Takashi Sakamoto8e142e92018-05-02 22:48:16 +090033#ifdef ENABLE_TUNING_CONTROLS
34#include <sound/tlv.h>
35#endif
36
Ian Minettef6b2ea2012-12-20 18:53:33 -080037#define FLOAT_ZERO 0x00000000
38#define FLOAT_ONE 0x3f800000
39#define FLOAT_TWO 0x40000000
Connor McAdams38ba69f2018-05-08 13:20:07 -040040#define FLOAT_THREE 0x40400000
Connor McAdams7cb9d942018-05-08 13:20:10 -040041#define FLOAT_EIGHT 0x41000000
Ian Minettef6b2ea2012-12-20 18:53:33 -080042#define FLOAT_MINUS_5 0xc0a00000
43
Ian Minettef6b2ea2012-12-20 18:53:33 -080044#define UNSOL_TAG_DSP 0x16
45
Ian Minett4aa3bb02012-09-20 20:29:15 -070046#define DSP_DMA_WRITE_BUFLEN_INIT (1UL<<18)
47#define DSP_DMA_WRITE_BUFLEN_OVLY (1UL<<15)
48
49#define DMA_TRANSFER_FRAME_SIZE_NWORDS 8
50#define DMA_TRANSFER_MAX_FRAME_SIZE_NWORDS 32
51#define DMA_OVERLAY_FRAME_SIZE_NWORDS 2
52
53#define MASTERCONTROL 0x80
Ian Minettef6b2ea2012-12-20 18:53:33 -080054#define MASTERCONTROL_ALLOC_DMA_CHAN 10
55#define MASTERCONTROL_QUERY_SPEAKER_EQ_ADDRESS 60
Ian Minett4aa3bb02012-09-20 20:29:15 -070056
Ian Minett95c6e9c2011-06-15 15:35:17 -070057#define WIDGET_CHIP_CTRL 0x15
58#define WIDGET_DSP_CTRL 0x16
59
Ian Minett4aa3bb02012-09-20 20:29:15 -070060#define MEM_CONNID_MICIN1 3
61#define MEM_CONNID_MICIN2 5
62#define MEM_CONNID_MICOUT1 12
63#define MEM_CONNID_MICOUT2 14
64#define MEM_CONNID_WUH 10
65#define MEM_CONNID_DSP 16
66#define MEM_CONNID_DMIC 100
67
68#define SCP_SET 0
69#define SCP_GET 1
70
Ian Minett01ef7db2012-09-20 20:29:16 -070071#define EFX_FILE "ctefx.bin"
Connor McAdams7a928182018-09-18 14:33:36 -040072#define DESKTOP_EFX_FILE "ctefx-desktop.bin"
Connor McAdams8a19bce2018-05-08 13:20:01 -040073#define R3DI_EFX_FILE "ctefx-r3di.bin"
Ian Minett01ef7db2012-09-20 20:29:16 -070074
Takashi Iwai24f3ced2013-02-04 18:25:51 +010075#ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP
Ian Minett01ef7db2012-09-20 20:29:16 -070076MODULE_FIRMWARE(EFX_FILE);
Connor McAdams7a928182018-09-18 14:33:36 -040077MODULE_FIRMWARE(DESKTOP_EFX_FILE);
Connor McAdams8a19bce2018-05-08 13:20:01 -040078MODULE_FIRMWARE(R3DI_EFX_FILE);
Takashi Iwai7a527ed2013-01-15 17:44:20 +010079#endif
Ian Minett01ef7db2012-09-20 20:29:16 -070080
Takashi Sakamoto3a03f832018-05-15 22:12:58 +090081static const char *const dirstr[2] = { "Playback", "Capture" };
Ian Minettef6b2ea2012-12-20 18:53:33 -080082
Connor McAdams7cb9d942018-05-08 13:20:10 -040083#define NUM_OF_OUTPUTS 3
Ian Minettef6b2ea2012-12-20 18:53:33 -080084enum {
85 SPEAKER_OUT,
Connor McAdams7cb9d942018-05-08 13:20:10 -040086 HEADPHONE_OUT,
87 SURROUND_OUT
Ian Minettef6b2ea2012-12-20 18:53:33 -080088};
89
90enum {
91 DIGITAL_MIC,
92 LINE_MIC_IN
93};
94
Connor McAdams7cb9d942018-05-08 13:20:10 -040095/* Strings for Input Source Enum Control */
Takashi Sakamoto3a03f832018-05-15 22:12:58 +090096static const char *const in_src_str[3] = {"Rear Mic", "Line", "Front Mic" };
Connor McAdams7cb9d942018-05-08 13:20:10 -040097#define IN_SRC_NUM_OF_INPUTS 3
98enum {
99 REAR_MIC,
100 REAR_LINE_IN,
101 FRONT_MIC,
102};
103
Ian Minettef6b2ea2012-12-20 18:53:33 -0800104enum {
105#define VNODE_START_NID 0x80
106 VNID_SPK = VNODE_START_NID, /* Speaker vnid */
107 VNID_MIC,
108 VNID_HP_SEL,
109 VNID_AMIC1_SEL,
110 VNID_HP_ASEL,
111 VNID_AMIC1_ASEL,
112 VNODE_END_NID,
113#define VNODES_COUNT (VNODE_END_NID - VNODE_START_NID)
114
115#define EFFECT_START_NID 0x90
116#define OUT_EFFECT_START_NID EFFECT_START_NID
117 SURROUND = OUT_EFFECT_START_NID,
118 CRYSTALIZER,
119 DIALOG_PLUS,
120 SMART_VOLUME,
121 X_BASS,
122 EQUALIZER,
123 OUT_EFFECT_END_NID,
124#define OUT_EFFECTS_COUNT (OUT_EFFECT_END_NID - OUT_EFFECT_START_NID)
125
126#define IN_EFFECT_START_NID OUT_EFFECT_END_NID
127 ECHO_CANCELLATION = IN_EFFECT_START_NID,
128 VOICE_FOCUS,
129 MIC_SVM,
130 NOISE_REDUCTION,
131 IN_EFFECT_END_NID,
132#define IN_EFFECTS_COUNT (IN_EFFECT_END_NID - IN_EFFECT_START_NID)
133
134 VOICEFX = IN_EFFECT_END_NID,
135 PLAY_ENHANCEMENT,
136 CRYSTAL_VOICE,
Connor McAdams7cb9d942018-05-08 13:20:10 -0400137 EFFECT_END_NID,
138 OUTPUT_SOURCE_ENUM,
Connor McAdams47cdf762018-05-08 13:20:13 -0400139 INPUT_SOURCE_ENUM,
140 XBASS_XOVER,
141 EQ_PRESET_ENUM,
142 SMART_VOLUME_ENUM,
Connor McAdams212de2e2018-09-18 14:33:42 -0400143 MIC_BOOST_ENUM,
144 AE5_HEADPHONE_GAIN_ENUM,
Connor McAdamsd51434d2018-09-29 23:03:25 -0400145 AE5_SOUND_FILTER_ENUM,
146 ZXR_HEADPHONE_GAIN
Ian Minettef6b2ea2012-12-20 18:53:33 -0800147#define EFFECTS_COUNT (EFFECT_END_NID - EFFECT_START_NID)
148};
149
150/* Effects values size*/
151#define EFFECT_VALS_MAX_COUNT 12
152
Connor McAdams47cdf762018-05-08 13:20:13 -0400153/*
154 * Default values for the effect slider controls, they are in order of their
155 * effect NID's. Surround, Crystalizer, Dialog Plus, Smart Volume, and then
156 * X-bass.
157 */
158static const unsigned int effect_slider_defaults[] = {67, 65, 50, 74, 50};
159/* Amount of effect level sliders for ca0132_alt controls. */
160#define EFFECT_LEVEL_SLIDERS 5
161
Dylan Reide8412ca2013-04-04 13:55:09 -0700162/* Latency introduced by DSP blocks in milliseconds. */
163#define DSP_CAPTURE_INIT_LATENCY 0
164#define DSP_CRYSTAL_VOICE_LATENCY 124
165#define DSP_PLAYBACK_INIT_LATENCY 13
166#define DSP_PLAY_ENHANCEMENT_LATENCY 30
167#define DSP_SPEAKER_OUT_LATENCY 7
168
Ian Minettef6b2ea2012-12-20 18:53:33 -0800169struct ct_effect {
Takashi Iwai975cc022013-06-28 11:56:49 +0200170 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
Ian Minettef6b2ea2012-12-20 18:53:33 -0800171 hda_nid_t nid;
172 int mid; /*effect module ID*/
173 int reqs[EFFECT_VALS_MAX_COUNT]; /*effect module request*/
174 int direct; /* 0:output; 1:input*/
175 int params; /* number of default non-on/off params */
176 /*effect default values, 1st is on/off. */
177 unsigned int def_vals[EFFECT_VALS_MAX_COUNT];
178};
179
180#define EFX_DIR_OUT 0
181#define EFX_DIR_IN 1
182
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900183static const struct ct_effect ca0132_effects[EFFECTS_COUNT] = {
Ian Minettef6b2ea2012-12-20 18:53:33 -0800184 { .name = "Surround",
185 .nid = SURROUND,
186 .mid = 0x96,
187 .reqs = {0, 1},
188 .direct = EFX_DIR_OUT,
189 .params = 1,
190 .def_vals = {0x3F800000, 0x3F2B851F}
191 },
192 { .name = "Crystalizer",
193 .nid = CRYSTALIZER,
194 .mid = 0x96,
195 .reqs = {7, 8},
196 .direct = EFX_DIR_OUT,
197 .params = 1,
198 .def_vals = {0x3F800000, 0x3F266666}
199 },
200 { .name = "Dialog Plus",
201 .nid = DIALOG_PLUS,
202 .mid = 0x96,
203 .reqs = {2, 3},
204 .direct = EFX_DIR_OUT,
205 .params = 1,
206 .def_vals = {0x00000000, 0x3F000000}
207 },
208 { .name = "Smart Volume",
209 .nid = SMART_VOLUME,
210 .mid = 0x96,
211 .reqs = {4, 5, 6},
212 .direct = EFX_DIR_OUT,
213 .params = 2,
214 .def_vals = {0x3F800000, 0x3F3D70A4, 0x00000000}
215 },
216 { .name = "X-Bass",
217 .nid = X_BASS,
218 .mid = 0x96,
219 .reqs = {24, 23, 25},
220 .direct = EFX_DIR_OUT,
221 .params = 2,
222 .def_vals = {0x3F800000, 0x42A00000, 0x3F000000}
223 },
224 { .name = "Equalizer",
225 .nid = EQUALIZER,
226 .mid = 0x96,
227 .reqs = {9, 10, 11, 12, 13, 14,
228 15, 16, 17, 18, 19, 20},
229 .direct = EFX_DIR_OUT,
230 .params = 11,
231 .def_vals = {0x00000000, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 0x00000000, 0x00000000, 0x00000000,
233 0x00000000, 0x00000000, 0x00000000, 0x00000000}
234 },
235 { .name = "Echo Cancellation",
236 .nid = ECHO_CANCELLATION,
237 .mid = 0x95,
238 .reqs = {0, 1, 2, 3},
239 .direct = EFX_DIR_IN,
240 .params = 3,
241 .def_vals = {0x00000000, 0x3F3A9692, 0x00000000, 0x00000000}
242 },
243 { .name = "Voice Focus",
244 .nid = VOICE_FOCUS,
245 .mid = 0x95,
246 .reqs = {6, 7, 8, 9},
247 .direct = EFX_DIR_IN,
248 .params = 3,
249 .def_vals = {0x3F800000, 0x3D7DF3B6, 0x41F00000, 0x41F00000}
250 },
251 { .name = "Mic SVM",
252 .nid = MIC_SVM,
253 .mid = 0x95,
254 .reqs = {44, 45},
255 .direct = EFX_DIR_IN,
256 .params = 1,
257 .def_vals = {0x00000000, 0x3F3D70A4}
258 },
259 { .name = "Noise Reduction",
260 .nid = NOISE_REDUCTION,
261 .mid = 0x95,
262 .reqs = {4, 5},
263 .direct = EFX_DIR_IN,
264 .params = 1,
265 .def_vals = {0x3F800000, 0x3F000000}
266 },
267 { .name = "VoiceFX",
268 .nid = VOICEFX,
269 .mid = 0x95,
270 .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18},
271 .direct = EFX_DIR_IN,
272 .params = 8,
273 .def_vals = {0x00000000, 0x43C80000, 0x44AF0000, 0x44FA0000,
274 0x3F800000, 0x3F800000, 0x3F800000, 0x00000000,
275 0x00000000}
276 }
277};
278
279/* Tuning controls */
280#ifdef ENABLE_TUNING_CONTROLS
281
282enum {
283#define TUNING_CTL_START_NID 0xC0
284 WEDGE_ANGLE = TUNING_CTL_START_NID,
285 SVM_LEVEL,
286 EQUALIZER_BAND_0,
287 EQUALIZER_BAND_1,
288 EQUALIZER_BAND_2,
289 EQUALIZER_BAND_3,
290 EQUALIZER_BAND_4,
291 EQUALIZER_BAND_5,
292 EQUALIZER_BAND_6,
293 EQUALIZER_BAND_7,
294 EQUALIZER_BAND_8,
295 EQUALIZER_BAND_9,
296 TUNING_CTL_END_NID
297#define TUNING_CTLS_COUNT (TUNING_CTL_END_NID - TUNING_CTL_START_NID)
298};
299
300struct ct_tuning_ctl {
Takashi Iwai975cc022013-06-28 11:56:49 +0200301 char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
Ian Minettef6b2ea2012-12-20 18:53:33 -0800302 hda_nid_t parent_nid;
303 hda_nid_t nid;
304 int mid; /*effect module ID*/
305 int req; /*effect module request*/
306 int direct; /* 0:output; 1:input*/
307 unsigned int def_val;/*effect default values*/
308};
309
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900310static const struct ct_tuning_ctl ca0132_tuning_ctls[] = {
Ian Minettef6b2ea2012-12-20 18:53:33 -0800311 { .name = "Wedge Angle",
312 .parent_nid = VOICE_FOCUS,
313 .nid = WEDGE_ANGLE,
314 .mid = 0x95,
315 .req = 8,
316 .direct = EFX_DIR_IN,
317 .def_val = 0x41F00000
318 },
319 { .name = "SVM Level",
320 .parent_nid = MIC_SVM,
321 .nid = SVM_LEVEL,
322 .mid = 0x95,
323 .req = 45,
324 .direct = EFX_DIR_IN,
325 .def_val = 0x3F3D70A4
326 },
327 { .name = "EQ Band0",
328 .parent_nid = EQUALIZER,
329 .nid = EQUALIZER_BAND_0,
330 .mid = 0x96,
331 .req = 11,
332 .direct = EFX_DIR_OUT,
333 .def_val = 0x00000000
334 },
335 { .name = "EQ Band1",
336 .parent_nid = EQUALIZER,
337 .nid = EQUALIZER_BAND_1,
338 .mid = 0x96,
339 .req = 12,
340 .direct = EFX_DIR_OUT,
341 .def_val = 0x00000000
342 },
343 { .name = "EQ Band2",
344 .parent_nid = EQUALIZER,
345 .nid = EQUALIZER_BAND_2,
346 .mid = 0x96,
347 .req = 13,
348 .direct = EFX_DIR_OUT,
349 .def_val = 0x00000000
350 },
351 { .name = "EQ Band3",
352 .parent_nid = EQUALIZER,
353 .nid = EQUALIZER_BAND_3,
354 .mid = 0x96,
355 .req = 14,
356 .direct = EFX_DIR_OUT,
357 .def_val = 0x00000000
358 },
359 { .name = "EQ Band4",
360 .parent_nid = EQUALIZER,
361 .nid = EQUALIZER_BAND_4,
362 .mid = 0x96,
363 .req = 15,
364 .direct = EFX_DIR_OUT,
365 .def_val = 0x00000000
366 },
367 { .name = "EQ Band5",
368 .parent_nid = EQUALIZER,
369 .nid = EQUALIZER_BAND_5,
370 .mid = 0x96,
371 .req = 16,
372 .direct = EFX_DIR_OUT,
373 .def_val = 0x00000000
374 },
375 { .name = "EQ Band6",
376 .parent_nid = EQUALIZER,
377 .nid = EQUALIZER_BAND_6,
378 .mid = 0x96,
379 .req = 17,
380 .direct = EFX_DIR_OUT,
381 .def_val = 0x00000000
382 },
383 { .name = "EQ Band7",
384 .parent_nid = EQUALIZER,
385 .nid = EQUALIZER_BAND_7,
386 .mid = 0x96,
387 .req = 18,
388 .direct = EFX_DIR_OUT,
389 .def_val = 0x00000000
390 },
391 { .name = "EQ Band8",
392 .parent_nid = EQUALIZER,
393 .nid = EQUALIZER_BAND_8,
394 .mid = 0x96,
395 .req = 19,
396 .direct = EFX_DIR_OUT,
397 .def_val = 0x00000000
398 },
399 { .name = "EQ Band9",
400 .parent_nid = EQUALIZER,
401 .nid = EQUALIZER_BAND_9,
402 .mid = 0x96,
403 .req = 20,
404 .direct = EFX_DIR_OUT,
405 .def_val = 0x00000000
406 }
407};
408#endif
409
410/* Voice FX Presets */
411#define VOICEFX_MAX_PARAM_COUNT 9
412
413struct ct_voicefx {
414 char *name;
415 hda_nid_t nid;
416 int mid;
417 int reqs[VOICEFX_MAX_PARAM_COUNT]; /*effect module request*/
418};
419
420struct ct_voicefx_preset {
421 char *name; /*preset name*/
422 unsigned int vals[VOICEFX_MAX_PARAM_COUNT];
423};
424
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900425static const struct ct_voicefx ca0132_voicefx = {
Ian Minettef6b2ea2012-12-20 18:53:33 -0800426 .name = "VoiceFX Capture Switch",
427 .nid = VOICEFX,
428 .mid = 0x95,
429 .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18}
430};
431
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900432static const struct ct_voicefx_preset ca0132_voicefx_presets[] = {
Ian Minettef6b2ea2012-12-20 18:53:33 -0800433 { .name = "Neutral",
434 .vals = { 0x00000000, 0x43C80000, 0x44AF0000,
435 0x44FA0000, 0x3F800000, 0x3F800000,
436 0x3F800000, 0x00000000, 0x00000000 }
437 },
438 { .name = "Female2Male",
439 .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
440 0x44FA0000, 0x3F19999A, 0x3F866666,
441 0x3F800000, 0x00000000, 0x00000000 }
442 },
443 { .name = "Male2Female",
444 .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
445 0x450AC000, 0x4017AE14, 0x3F6B851F,
446 0x3F800000, 0x00000000, 0x00000000 }
447 },
448 { .name = "ScrappyKid",
449 .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
450 0x44FA0000, 0x40400000, 0x3F28F5C3,
451 0x3F800000, 0x00000000, 0x00000000 }
452 },
453 { .name = "Elderly",
454 .vals = { 0x3F800000, 0x44324000, 0x44BB8000,
455 0x44E10000, 0x3FB33333, 0x3FB9999A,
456 0x3F800000, 0x3E3A2E43, 0x00000000 }
457 },
458 { .name = "Orc",
459 .vals = { 0x3F800000, 0x43EA0000, 0x44A52000,
460 0x45098000, 0x3F266666, 0x3FC00000,
461 0x3F800000, 0x00000000, 0x00000000 }
462 },
463 { .name = "Elf",
464 .vals = { 0x3F800000, 0x43C70000, 0x44AE6000,
465 0x45193000, 0x3F8E147B, 0x3F75C28F,
466 0x3F800000, 0x00000000, 0x00000000 }
467 },
468 { .name = "Dwarf",
469 .vals = { 0x3F800000, 0x43930000, 0x44BEE000,
470 0x45007000, 0x3F451EB8, 0x3F7851EC,
471 0x3F800000, 0x00000000, 0x00000000 }
472 },
473 { .name = "AlienBrute",
474 .vals = { 0x3F800000, 0x43BFC5AC, 0x44B28FDF,
475 0x451F6000, 0x3F266666, 0x3FA7D945,
476 0x3F800000, 0x3CF5C28F, 0x00000000 }
477 },
478 { .name = "Robot",
479 .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
480 0x44FA0000, 0x3FB2718B, 0x3F800000,
481 0xBC07010E, 0x00000000, 0x00000000 }
482 },
483 { .name = "Marine",
484 .vals = { 0x3F800000, 0x43C20000, 0x44906000,
485 0x44E70000, 0x3F4CCCCD, 0x3F8A3D71,
486 0x3F0A3D71, 0x00000000, 0x00000000 }
487 },
488 { .name = "Emo",
489 .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
490 0x44FA0000, 0x3F800000, 0x3F800000,
491 0x3E4CCCCD, 0x00000000, 0x00000000 }
492 },
493 { .name = "DeepVoice",
494 .vals = { 0x3F800000, 0x43A9C5AC, 0x44AA4FDF,
495 0x44FFC000, 0x3EDBB56F, 0x3F99C4CA,
496 0x3F800000, 0x00000000, 0x00000000 }
497 },
498 { .name = "Munchkin",
499 .vals = { 0x3F800000, 0x43C80000, 0x44AF0000,
500 0x44FA0000, 0x3F800000, 0x3F1A043C,
501 0x3F800000, 0x00000000, 0x00000000 }
502 }
503};
504
Connor McAdams47cdf762018-05-08 13:20:13 -0400505/* ca0132 EQ presets, taken from Windows Sound Blaster Z Driver */
506
507#define EQ_PRESET_MAX_PARAM_COUNT 11
508
509struct ct_eq {
510 char *name;
511 hda_nid_t nid;
512 int mid;
513 int reqs[EQ_PRESET_MAX_PARAM_COUNT]; /*effect module request*/
514};
515
516struct ct_eq_preset {
517 char *name; /*preset name*/
518 unsigned int vals[EQ_PRESET_MAX_PARAM_COUNT];
519};
520
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900521static const struct ct_eq ca0132_alt_eq_enum = {
Connor McAdams47cdf762018-05-08 13:20:13 -0400522 .name = "FX: Equalizer Preset Switch",
523 .nid = EQ_PRESET_ENUM,
524 .mid = 0x96,
525 .reqs = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
526};
527
528
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900529static const struct ct_eq_preset ca0132_alt_eq_presets[] = {
Connor McAdams47cdf762018-05-08 13:20:13 -0400530 { .name = "Flat",
531 .vals = { 0x00000000, 0x00000000, 0x00000000,
532 0x00000000, 0x00000000, 0x00000000,
533 0x00000000, 0x00000000, 0x00000000,
534 0x00000000, 0x00000000 }
535 },
536 { .name = "Acoustic",
537 .vals = { 0x00000000, 0x00000000, 0x3F8CCCCD,
538 0x40000000, 0x00000000, 0x00000000,
539 0x00000000, 0x00000000, 0x40000000,
540 0x40000000, 0x40000000 }
541 },
542 { .name = "Classical",
543 .vals = { 0x00000000, 0x00000000, 0x40C00000,
544 0x40C00000, 0x40466666, 0x00000000,
545 0x00000000, 0x00000000, 0x00000000,
546 0x40466666, 0x40466666 }
547 },
548 { .name = "Country",
549 .vals = { 0x00000000, 0xBF99999A, 0x00000000,
550 0x3FA66666, 0x3FA66666, 0x3F8CCCCD,
551 0x00000000, 0x00000000, 0x40000000,
552 0x40466666, 0x40800000 }
553 },
554 { .name = "Dance",
555 .vals = { 0x00000000, 0xBF99999A, 0x40000000,
556 0x40466666, 0x40866666, 0xBF99999A,
557 0xBF99999A, 0x00000000, 0x00000000,
558 0x40800000, 0x40800000 }
559 },
560 { .name = "Jazz",
561 .vals = { 0x00000000, 0x00000000, 0x00000000,
562 0x3F8CCCCD, 0x40800000, 0x40800000,
563 0x40800000, 0x00000000, 0x3F8CCCCD,
564 0x40466666, 0x40466666 }
565 },
566 { .name = "New Age",
567 .vals = { 0x00000000, 0x00000000, 0x40000000,
568 0x40000000, 0x00000000, 0x00000000,
569 0x00000000, 0x3F8CCCCD, 0x40000000,
570 0x40000000, 0x40000000 }
571 },
572 { .name = "Pop",
573 .vals = { 0x00000000, 0xBFCCCCCD, 0x00000000,
574 0x40000000, 0x40000000, 0x00000000,
575 0xBF99999A, 0xBF99999A, 0x00000000,
576 0x40466666, 0x40C00000 }
577 },
578 { .name = "Rock",
579 .vals = { 0x00000000, 0xBF99999A, 0xBF99999A,
580 0x3F8CCCCD, 0x40000000, 0xBF99999A,
581 0xBF99999A, 0x00000000, 0x00000000,
582 0x40800000, 0x40800000 }
583 },
584 { .name = "Vocal",
585 .vals = { 0x00000000, 0xC0000000, 0xBF99999A,
586 0xBF99999A, 0x00000000, 0x40466666,
587 0x40800000, 0x40466666, 0x00000000,
588 0x00000000, 0x3F8CCCCD }
589 }
590};
591
Connor McAdams7cb9d942018-05-08 13:20:10 -0400592/* DSP command sequences for ca0132_alt_select_out */
593#define ALT_OUT_SET_MAX_COMMANDS 9 /* Max number of commands in sequence */
594struct ca0132_alt_out_set {
595 char *name; /*preset name*/
596 unsigned char commands;
597 unsigned int mids[ALT_OUT_SET_MAX_COMMANDS];
598 unsigned int reqs[ALT_OUT_SET_MAX_COMMANDS];
599 unsigned int vals[ALT_OUT_SET_MAX_COMMANDS];
600};
601
602static const struct ca0132_alt_out_set alt_out_presets[] = {
603 { .name = "Line Out",
604 .commands = 7,
605 .mids = { 0x96, 0x96, 0x96, 0x8F,
606 0x96, 0x96, 0x96 },
607 .reqs = { 0x19, 0x17, 0x18, 0x01,
608 0x1F, 0x15, 0x3A },
609 .vals = { 0x3F000000, 0x42A00000, 0x00000000,
610 0x00000000, 0x00000000, 0x00000000,
611 0x00000000 }
612 },
613 { .name = "Headphone",
614 .commands = 7,
615 .mids = { 0x96, 0x96, 0x96, 0x8F,
616 0x96, 0x96, 0x96 },
617 .reqs = { 0x19, 0x17, 0x18, 0x01,
618 0x1F, 0x15, 0x3A },
619 .vals = { 0x3F000000, 0x42A00000, 0x00000000,
620 0x00000000, 0x00000000, 0x00000000,
621 0x00000000 }
622 },
623 { .name = "Surround",
624 .commands = 8,
625 .mids = { 0x96, 0x8F, 0x96, 0x96,
626 0x96, 0x96, 0x96, 0x96 },
627 .reqs = { 0x18, 0x01, 0x1F, 0x15,
628 0x3A, 0x1A, 0x1B, 0x1C },
629 .vals = { 0x00000000, 0x00000000, 0x00000000,
630 0x00000000, 0x00000000, 0x00000000,
631 0x00000000, 0x00000000 }
632 }
633};
634
Connor McAdams017310f2018-05-08 13:20:11 -0400635/*
636 * DSP volume setting structs. Req 1 is left volume, req 2 is right volume,
637 * and I don't know what the third req is, but it's always zero. I assume it's
638 * some sort of update or set command to tell the DSP there's new volume info.
639 */
640#define DSP_VOL_OUT 0
641#define DSP_VOL_IN 1
642
643struct ct_dsp_volume_ctl {
644 hda_nid_t vnid;
645 int mid; /* module ID*/
646 unsigned int reqs[3]; /* scp req ID */
647};
648
Takashi Sakamoto862154b2018-05-15 22:13:00 +0900649static const struct ct_dsp_volume_ctl ca0132_alt_vol_ctls[] = {
Connor McAdams017310f2018-05-08 13:20:11 -0400650 { .vnid = VNID_SPK,
651 .mid = 0x32,
652 .reqs = {3, 4, 2}
653 },
654 { .vnid = VNID_MIC,
655 .mid = 0x37,
656 .reqs = {2, 3, 1}
657 }
658};
659
Connor McAdams2283c852018-09-18 14:33:40 -0400660/* Values for ca0113_mmio_command_set for selecting output. */
661#define AE5_CA0113_OUT_SET_COMMANDS 6
662struct ae5_ca0113_output_set {
663 unsigned int group[AE5_CA0113_OUT_SET_COMMANDS];
664 unsigned int target[AE5_CA0113_OUT_SET_COMMANDS];
665 unsigned int vals[AE5_CA0113_OUT_SET_COMMANDS];
666};
667
668static const struct ae5_ca0113_output_set ae5_ca0113_output_presets[] = {
669 { .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
670 .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
671 .vals = { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f }
672 },
673 { .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
674 .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
675 .vals = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 }
676 },
677 { .group = { 0x30, 0x30, 0x48, 0x48, 0x48, 0x30 },
678 .target = { 0x2e, 0x30, 0x0d, 0x17, 0x19, 0x32 },
679 .vals = { 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f }
680 }
681};
682
Connor McAdams212de2e2018-09-18 14:33:42 -0400683/* ae5 ca0113 command sequences to set headphone gain levels. */
684#define AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS 4
685struct ae5_headphone_gain_set {
686 char *name;
687 unsigned int vals[AE5_HEADPHONE_GAIN_PRESET_MAX_COMMANDS];
688};
689
690static const struct ae5_headphone_gain_set ae5_headphone_gain_presets[] = {
691 { .name = "Low (16-31",
692 .vals = { 0xff, 0x2c, 0xf5, 0x32 }
693 },
694 { .name = "Medium (32-149",
695 .vals = { 0x38, 0xa8, 0x3e, 0x4c }
696 },
697 { .name = "High (150-600",
698 .vals = { 0xff, 0xff, 0xff, 0x7f }
699 }
700};
701
702struct ae5_filter_set {
703 char *name;
704 unsigned int val;
705};
706
707static const struct ae5_filter_set ae5_filter_presets[] = {
708 { .name = "Slow Roll Off",
709 .val = 0xa0
710 },
711 { .name = "Minimum Phase",
712 .val = 0xc0
713 },
714 { .name = "Fast Roll Off",
715 .val = 0x80
716 }
717};
718
Ian Minett95c6e9c2011-06-15 15:35:17 -0700719enum hda_cmd_vendor_io {
720 /* for DspIO node */
721 VENDOR_DSPIO_SCP_WRITE_DATA_LOW = 0x000,
722 VENDOR_DSPIO_SCP_WRITE_DATA_HIGH = 0x100,
723
724 VENDOR_DSPIO_STATUS = 0xF01,
725 VENDOR_DSPIO_SCP_POST_READ_DATA = 0x702,
726 VENDOR_DSPIO_SCP_READ_DATA = 0xF02,
727 VENDOR_DSPIO_DSP_INIT = 0x703,
728 VENDOR_DSPIO_SCP_POST_COUNT_QUERY = 0x704,
729 VENDOR_DSPIO_SCP_READ_COUNT = 0xF04,
730
731 /* for ChipIO node */
732 VENDOR_CHIPIO_ADDRESS_LOW = 0x000,
733 VENDOR_CHIPIO_ADDRESS_HIGH = 0x100,
734 VENDOR_CHIPIO_STREAM_FORMAT = 0x200,
735 VENDOR_CHIPIO_DATA_LOW = 0x300,
736 VENDOR_CHIPIO_DATA_HIGH = 0x400,
737
Connor McAdamsbf85a912018-09-18 14:33:29 -0400738 VENDOR_CHIPIO_8051_WRITE_DIRECT = 0x500,
739 VENDOR_CHIPIO_8051_READ_DIRECT = 0xD00,
740
Ian Minett95c6e9c2011-06-15 15:35:17 -0700741 VENDOR_CHIPIO_GET_PARAMETER = 0xF00,
742 VENDOR_CHIPIO_STATUS = 0xF01,
743 VENDOR_CHIPIO_HIC_POST_READ = 0x702,
744 VENDOR_CHIPIO_HIC_READ_DATA = 0xF03,
745
Ian Minett4aa3bb02012-09-20 20:29:15 -0700746 VENDOR_CHIPIO_8051_DATA_WRITE = 0x707,
747 VENDOR_CHIPIO_8051_DATA_READ = 0xF07,
Connor McAdamsbf85a912018-09-18 14:33:29 -0400748 VENDOR_CHIPIO_8051_PMEM_READ = 0xF08,
749 VENDOR_CHIPIO_8051_IRAM_WRITE = 0x709,
750 VENDOR_CHIPIO_8051_IRAM_READ = 0xF09,
Ian Minett4aa3bb02012-09-20 20:29:15 -0700751
Ian Minett95c6e9c2011-06-15 15:35:17 -0700752 VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE = 0x70A,
Ian Minett4aa3bb02012-09-20 20:29:15 -0700753 VENDOR_CHIPIO_CT_EXTENSIONS_GET = 0xF0A,
Ian Minett95c6e9c2011-06-15 15:35:17 -0700754
755 VENDOR_CHIPIO_PLL_PMU_WRITE = 0x70C,
756 VENDOR_CHIPIO_PLL_PMU_READ = 0xF0C,
757 VENDOR_CHIPIO_8051_ADDRESS_LOW = 0x70D,
758 VENDOR_CHIPIO_8051_ADDRESS_HIGH = 0x70E,
759 VENDOR_CHIPIO_FLAG_SET = 0x70F,
760 VENDOR_CHIPIO_FLAGS_GET = 0xF0F,
Ian Minett4aa3bb02012-09-20 20:29:15 -0700761 VENDOR_CHIPIO_PARAM_SET = 0x710,
762 VENDOR_CHIPIO_PARAM_GET = 0xF10,
Ian Minett95c6e9c2011-06-15 15:35:17 -0700763
764 VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET = 0x711,
765 VENDOR_CHIPIO_PORT_ALLOC_SET = 0x712,
766 VENDOR_CHIPIO_PORT_ALLOC_GET = 0xF12,
767 VENDOR_CHIPIO_PORT_FREE_SET = 0x713,
768
Ian Minett4aa3bb02012-09-20 20:29:15 -0700769 VENDOR_CHIPIO_PARAM_EX_ID_GET = 0xF17,
770 VENDOR_CHIPIO_PARAM_EX_ID_SET = 0x717,
771 VENDOR_CHIPIO_PARAM_EX_VALUE_GET = 0xF18,
772 VENDOR_CHIPIO_PARAM_EX_VALUE_SET = 0x718,
773
774 VENDOR_CHIPIO_DMIC_CTL_SET = 0x788,
775 VENDOR_CHIPIO_DMIC_CTL_GET = 0xF88,
776 VENDOR_CHIPIO_DMIC_PIN_SET = 0x789,
777 VENDOR_CHIPIO_DMIC_PIN_GET = 0xF89,
778 VENDOR_CHIPIO_DMIC_MCLK_SET = 0x78A,
779 VENDOR_CHIPIO_DMIC_MCLK_GET = 0xF8A,
780
781 VENDOR_CHIPIO_EAPD_SEL_SET = 0x78D
Ian Minett95c6e9c2011-06-15 15:35:17 -0700782};
783
784/*
785 * Control flag IDs
786 */
787enum control_flag_id {
788 /* Connection manager stream setup is bypassed/enabled */
789 CONTROL_FLAG_C_MGR = 0,
790 /* DSP DMA is bypassed/enabled */
791 CONTROL_FLAG_DMA = 1,
792 /* 8051 'idle' mode is disabled/enabled */
793 CONTROL_FLAG_IDLE_ENABLE = 2,
794 /* Tracker for the SPDIF-in path is bypassed/enabled */
795 CONTROL_FLAG_TRACKER = 3,
796 /* DigitalOut to Spdif2Out connection is disabled/enabled */
797 CONTROL_FLAG_SPDIF2OUT = 4,
798 /* Digital Microphone is disabled/enabled */
799 CONTROL_FLAG_DMIC = 5,
800 /* ADC_B rate is 48 kHz/96 kHz */
801 CONTROL_FLAG_ADC_B_96KHZ = 6,
802 /* ADC_C rate is 48 kHz/96 kHz */
803 CONTROL_FLAG_ADC_C_96KHZ = 7,
804 /* DAC rate is 48 kHz/96 kHz (affects all DACs) */
805 CONTROL_FLAG_DAC_96KHZ = 8,
806 /* DSP rate is 48 kHz/96 kHz */
807 CONTROL_FLAG_DSP_96KHZ = 9,
808 /* SRC clock is 98 MHz/196 MHz (196 MHz forces rate to 96 KHz) */
809 CONTROL_FLAG_SRC_CLOCK_196MHZ = 10,
810 /* SRC rate is 48 kHz/96 kHz (48 kHz disabled when clock is 196 MHz) */
811 CONTROL_FLAG_SRC_RATE_96KHZ = 11,
812 /* Decode Loop (DSP->SRC->DSP) is disabled/enabled */
813 CONTROL_FLAG_DECODE_LOOP = 12,
814 /* De-emphasis filter on DAC-1 disabled/enabled */
815 CONTROL_FLAG_DAC1_DEEMPHASIS = 13,
816 /* De-emphasis filter on DAC-2 disabled/enabled */
817 CONTROL_FLAG_DAC2_DEEMPHASIS = 14,
818 /* De-emphasis filter on DAC-3 disabled/enabled */
819 CONTROL_FLAG_DAC3_DEEMPHASIS = 15,
820 /* High-pass filter on ADC_B disabled/enabled */
821 CONTROL_FLAG_ADC_B_HIGH_PASS = 16,
822 /* High-pass filter on ADC_C disabled/enabled */
823 CONTROL_FLAG_ADC_C_HIGH_PASS = 17,
824 /* Common mode on Port_A disabled/enabled */
825 CONTROL_FLAG_PORT_A_COMMON_MODE = 18,
826 /* Common mode on Port_D disabled/enabled */
827 CONTROL_FLAG_PORT_D_COMMON_MODE = 19,
828 /* Impedance for ramp generator on Port_A 16 Ohm/10K Ohm */
829 CONTROL_FLAG_PORT_A_10KOHM_LOAD = 20,
830 /* Impedance for ramp generator on Port_D, 16 Ohm/10K Ohm */
Ian Minett4aa3bb02012-09-20 20:29:15 -0700831 CONTROL_FLAG_PORT_D_10KOHM_LOAD = 21,
Ian Minett95c6e9c2011-06-15 15:35:17 -0700832 /* ASI rate is 48kHz/96kHz */
833 CONTROL_FLAG_ASI_96KHZ = 22,
834 /* DAC power settings able to control attached ports no/yes */
835 CONTROL_FLAG_DACS_CONTROL_PORTS = 23,
836 /* Clock Stop OK reporting is disabled/enabled */
837 CONTROL_FLAG_CONTROL_STOP_OK_ENABLE = 24,
838 /* Number of control flags */
839 CONTROL_FLAGS_MAX = (CONTROL_FLAG_CONTROL_STOP_OK_ENABLE+1)
840};
841
842/*
843 * Control parameter IDs
844 */
Ian Minett4aa3bb02012-09-20 20:29:15 -0700845enum control_param_id {
Ian Minettef6b2ea2012-12-20 18:53:33 -0800846 /* 0: None, 1: Mic1In*/
847 CONTROL_PARAM_VIP_SOURCE = 1,
Ian Minett95c6e9c2011-06-15 15:35:17 -0700848 /* 0: force HDA, 1: allow DSP if HDA Spdif1Out stream is idle */
849 CONTROL_PARAM_SPDIF1_SOURCE = 2,
Ian Minettef6b2ea2012-12-20 18:53:33 -0800850 /* Port A output stage gain setting to use when 16 Ohm output
851 * impedance is selected*/
852 CONTROL_PARAM_PORTA_160OHM_GAIN = 8,
853 /* Port D output stage gain setting to use when 16 Ohm output
854 * impedance is selected*/
855 CONTROL_PARAM_PORTD_160OHM_GAIN = 10,
Ian Minett95c6e9c2011-06-15 15:35:17 -0700856
Connor McAdamsbf85a912018-09-18 14:33:29 -0400857 /*
858 * This control param name was found in the 8051 memory, and makes
859 * sense given the fact the AE-5 uses it and has the ASI flag set.
860 */
861 CONTROL_PARAM_ASI = 23,
862
Ian Minett95c6e9c2011-06-15 15:35:17 -0700863 /* Stream Control */
864
865 /* Select stream with the given ID */
866 CONTROL_PARAM_STREAM_ID = 24,
867 /* Source connection point for the selected stream */
868 CONTROL_PARAM_STREAM_SOURCE_CONN_POINT = 25,
869 /* Destination connection point for the selected stream */
870 CONTROL_PARAM_STREAM_DEST_CONN_POINT = 26,
871 /* Number of audio channels in the selected stream */
872 CONTROL_PARAM_STREAMS_CHANNELS = 27,
873 /*Enable control for the selected stream */
874 CONTROL_PARAM_STREAM_CONTROL = 28,
875
876 /* Connection Point Control */
877
878 /* Select connection point with the given ID */
879 CONTROL_PARAM_CONN_POINT_ID = 29,
880 /* Connection point sample rate */
881 CONTROL_PARAM_CONN_POINT_SAMPLE_RATE = 30,
882
883 /* Node Control */
884
885 /* Select HDA node with the given ID */
886 CONTROL_PARAM_NODE_ID = 31
887};
888
889/*
890 * Dsp Io Status codes
891 */
892enum hda_vendor_status_dspio {
893 /* Success */
894 VENDOR_STATUS_DSPIO_OK = 0x00,
895 /* Busy, unable to accept new command, the host must retry */
896 VENDOR_STATUS_DSPIO_BUSY = 0x01,
897 /* SCP command queue is full */
898 VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL = 0x02,
899 /* SCP response queue is empty */
900 VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY = 0x03
901};
902
903/*
904 * Chip Io Status codes
905 */
906enum hda_vendor_status_chipio {
907 /* Success */
908 VENDOR_STATUS_CHIPIO_OK = 0x00,
909 /* Busy, unable to accept new command, the host must retry */
910 VENDOR_STATUS_CHIPIO_BUSY = 0x01
911};
912
913/*
914 * CA0132 sample rate
915 */
916enum ca0132_sample_rate {
917 SR_6_000 = 0x00,
918 SR_8_000 = 0x01,
919 SR_9_600 = 0x02,
920 SR_11_025 = 0x03,
921 SR_16_000 = 0x04,
922 SR_22_050 = 0x05,
923 SR_24_000 = 0x06,
924 SR_32_000 = 0x07,
925 SR_44_100 = 0x08,
926 SR_48_000 = 0x09,
927 SR_88_200 = 0x0A,
928 SR_96_000 = 0x0B,
929 SR_144_000 = 0x0C,
930 SR_176_400 = 0x0D,
931 SR_192_000 = 0x0E,
932 SR_384_000 = 0x0F,
933
934 SR_COUNT = 0x10,
935
936 SR_RATE_UNKNOWN = 0x1F
937};
938
Ian Minett01ef7db2012-09-20 20:29:16 -0700939enum dsp_download_state {
940 DSP_DOWNLOAD_FAILED = -1,
941 DSP_DOWNLOAD_INIT = 0,
942 DSP_DOWNLOADING = 1,
943 DSP_DOWNLOADED = 2
944};
945
Ian Minett01ef7db2012-09-20 20:29:16 -0700946/* retrieve parameters from hda format */
947#define get_hdafmt_chs(fmt) (fmt & 0xf)
948#define get_hdafmt_bits(fmt) ((fmt >> 4) & 0x7)
949#define get_hdafmt_rate(fmt) ((fmt >> 8) & 0x7f)
950#define get_hdafmt_type(fmt) ((fmt >> 15) & 0x1)
Ian Minett95c6e9c2011-06-15 15:35:17 -0700951
952/*
953 * CA0132 specific
954 */
955
956struct ca0132_spec {
Takashi Sakamotob0eaa072018-05-15 22:12:57 +0900957 const struct snd_kcontrol_new *mixers[5];
Ian Minetta7e76272012-12-20 18:53:35 -0800958 unsigned int num_mixers;
Ian Minett5aaca442012-12-20 18:53:34 -0800959 const struct hda_verb *base_init_verbs;
960 const struct hda_verb *base_exit_verbs;
Gabriele Martinod5c016b2015-05-18 21:15:13 +0200961 const struct hda_verb *chip_init_verbs;
Connor McAdamse42c7c72018-08-08 13:34:18 -0400962 const struct hda_verb *desktop_init_verbs;
Gabriele Martinod5c016b2015-05-18 21:15:13 +0200963 struct hda_verb *spec_init_verbs;
Ian Minett95c6e9c2011-06-15 15:35:17 -0700964 struct auto_pin_cfg autocfg;
Ian Minett5aaca442012-12-20 18:53:34 -0800965
966 /* Nodes configurations */
Ian Minett95c6e9c2011-06-15 15:35:17 -0700967 struct hda_multi_out multiout;
968 hda_nid_t out_pins[AUTO_CFG_MAX_OUTS];
969 hda_nid_t dacs[AUTO_CFG_MAX_OUTS];
Ian Minett5aaca442012-12-20 18:53:34 -0800970 unsigned int num_outputs;
Ian Minett95c6e9c2011-06-15 15:35:17 -0700971 hda_nid_t input_pins[AUTO_PIN_LAST];
972 hda_nid_t adcs[AUTO_PIN_LAST];
973 hda_nid_t dig_out;
974 hda_nid_t dig_in;
975 unsigned int num_inputs;
Ian Minetta7e76272012-12-20 18:53:35 -0800976 hda_nid_t shared_mic_nid;
977 hda_nid_t shared_out_nid;
Gabriele Martinod5c016b2015-05-18 21:15:13 +0200978 hda_nid_t unsol_tag_hp;
Connor McAdams63177af2018-05-08 13:20:02 -0400979 hda_nid_t unsol_tag_front_hp; /* for desktop ca0132 codecs */
Gabriele Martinod5c016b2015-05-18 21:15:13 +0200980 hda_nid_t unsol_tag_amic1;
Ian Minett01ef7db2012-09-20 20:29:16 -0700981
982 /* chip access */
983 struct mutex chipio_mutex; /* chip access mutex */
984 u32 curr_chip_addx;
985
986 /* DSP download related */
987 enum dsp_download_state dsp_state;
988 unsigned int dsp_stream_id;
989 unsigned int wait_scp;
990 unsigned int wait_scp_header;
991 unsigned int wait_num_data;
992 unsigned int scp_resp_header;
993 unsigned int scp_resp_data[4];
994 unsigned int scp_resp_count;
Connor McAdams38ba69f2018-05-08 13:20:07 -0400995 bool startup_check_entered;
Connor McAdamse93ac302018-05-08 13:20:05 -0400996 bool dsp_reload;
Ian Minett5aaca442012-12-20 18:53:34 -0800997
998 /* mixer and effects related */
999 unsigned char dmic_ctl;
1000 int cur_out_type;
1001 int cur_mic_type;
1002 long vnode_lvol[VNODES_COUNT];
1003 long vnode_rvol[VNODES_COUNT];
1004 long vnode_lswitch[VNODES_COUNT];
1005 long vnode_rswitch[VNODES_COUNT];
1006 long effects_switch[EFFECTS_COUNT];
1007 long voicefx_val;
1008 long cur_mic_boost;
Connor McAdams7cb9d942018-05-08 13:20:10 -04001009 /* ca0132_alt control related values */
1010 unsigned char in_enum_val;
1011 unsigned char out_enum_val;
Connor McAdams47cdf762018-05-08 13:20:13 -04001012 unsigned char mic_boost_enum_val;
1013 unsigned char smart_volume_setting;
1014 long fx_ctl_val[EFFECT_LEVEL_SLIDERS];
1015 long xbass_xover_freq;
1016 long eq_preset_val;
1017 unsigned int tlv[4];
1018 struct hda_vmaster_mute_hook vmaster_mute;
Connor McAdams212de2e2018-09-18 14:33:42 -04001019 /* AE-5 Control values */
1020 unsigned char ae5_headphone_gain_val;
1021 unsigned char ae5_filter_val;
Connor McAdamsd51434d2018-09-29 23:03:25 -04001022 /* ZxR Control Values */
1023 unsigned char zxr_gain_set;
Ian Minett44f0c972012-12-20 18:53:38 -08001024
Chih-Chung Chang993884f2013-03-25 10:39:23 -07001025 struct hda_codec *codec;
1026 struct delayed_work unsol_hp_work;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02001027 int quirk;
Chih-Chung Chang993884f2013-03-25 10:39:23 -07001028
Ian Minett44f0c972012-12-20 18:53:38 -08001029#ifdef ENABLE_TUNING_CONTROLS
1030 long cur_ctl_vals[TUNING_CTLS_COUNT];
1031#endif
Connor McAdamsaa317042018-05-08 13:20:03 -04001032 /*
Connor McAdams08eca6b2018-08-08 13:34:17 -04001033 * The Recon3D, Sound Blaster Z, Sound Blaster ZxR, and Sound Blaster
1034 * AE-5 all use PCI region 2 to toggle GPIO and other currently unknown
1035 * things.
Connor McAdamsaa317042018-05-08 13:20:03 -04001036 */
Connor McAdams08eca6b2018-08-08 13:34:17 -04001037 bool use_pci_mmio;
Connor McAdamsaa317042018-05-08 13:20:03 -04001038 void __iomem *mem_base;
Connor McAdams009b8f92018-05-08 13:20:06 -04001039
1040 /*
1041 * Whether or not to use the alt functions like alt_select_out,
1042 * alt_select_in, etc. Only used on desktop codecs for now, because of
1043 * surround sound support.
1044 */
1045 bool use_alt_functions;
Connor McAdams47cdf762018-05-08 13:20:13 -04001046
1047 /*
1048 * Whether or not to use alt controls: volume effect sliders, EQ
1049 * presets, smart volume presets, and new control names with FX prefix.
1050 * Renames PlayEnhancement and CrystalVoice too.
1051 */
1052 bool use_alt_controls;
Ian Minett95c6e9c2011-06-15 15:35:17 -07001053};
1054
Ian Minett01ef7db2012-09-20 20:29:16 -07001055/*
Gabriele Martinod5c016b2015-05-18 21:15:13 +02001056 * CA0132 quirks table
1057 */
1058enum {
1059 QUIRK_NONE,
1060 QUIRK_ALIENWARE,
Alastair Bridgewatera57a46b2018-06-15 21:56:20 -04001061 QUIRK_ALIENWARE_M17XR4,
Connor McAdams8a19bce2018-05-08 13:20:01 -04001062 QUIRK_SBZ,
Connor McAdamsb29733d2018-09-29 23:03:18 -04001063 QUIRK_ZXR,
1064 QUIRK_ZXR_DBPRO,
Connor McAdams8a19bce2018-05-08 13:20:01 -04001065 QUIRK_R3DI,
Connor McAdams8f8c5232018-08-08 13:34:15 -04001066 QUIRK_R3D,
Connor McAdamsf6276462018-09-18 14:33:30 -04001067 QUIRK_AE5,
Gabriele Martinod5c016b2015-05-18 21:15:13 +02001068};
1069
Takashi Iwai6da8f442018-11-09 14:18:32 +01001070#ifdef CONFIG_PCI
1071#define ca0132_quirk(spec) ((spec)->quirk)
1072#define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio)
1073#define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions)
1074#define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls)
1075#else
1076#define ca0132_quirk(spec) ({ (void)(spec); QUIRK_NONE; })
1077#define ca0132_use_alt_functions(spec) ({ (void)(spec); false; })
1078#define ca0132_use_pci_mmio(spec) ({ (void)(spec); false; })
1079#define ca0132_use_alt_controls(spec) ({ (void)(spec); false; })
1080#endif
1081
Takashi Iwaife14f392015-08-10 16:53:32 +02001082static const struct hda_pintbl alienware_pincfgs[] = {
1083 { 0x0b, 0x90170110 }, /* Builtin Speaker */
1084 { 0x0c, 0x411111f0 }, /* N/A */
1085 { 0x0d, 0x411111f0 }, /* N/A */
1086 { 0x0e, 0x411111f0 }, /* N/A */
1087 { 0x0f, 0x0321101f }, /* HP */
1088 { 0x10, 0x411111f0 }, /* Headset? disabled for now */
1089 { 0x11, 0x03a11021 }, /* Mic */
1090 { 0x12, 0xd5a30140 }, /* Builtin Mic */
1091 { 0x13, 0x411111f0 }, /* N/A */
1092 { 0x18, 0x411111f0 }, /* N/A */
1093 {}
1094};
1095
Connor McAdams63177af2018-05-08 13:20:02 -04001096/* Sound Blaster Z pin configs taken from Windows Driver */
1097static const struct hda_pintbl sbz_pincfgs[] = {
1098 { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */
1099 { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
1100 { 0x0d, 0x014510f0 }, /* Digital Out */
1101 { 0x0e, 0x01c510f0 }, /* SPDIF In */
1102 { 0x0f, 0x0221701f }, /* Port A -- BackPanel HP */
1103 { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */
1104 { 0x11, 0x01017014 }, /* Port B -- LineMicIn2 / Rear L/R */
1105 { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */
1106 { 0x13, 0x908700f0 }, /* What U Hear In*/
1107 { 0x18, 0x50d000f0 }, /* N/A */
1108 {}
1109};
1110
Connor McAdams6dcd7242018-09-29 23:03:19 -04001111/* Sound Blaster ZxR pin configs taken from Windows Driver */
1112static const struct hda_pintbl zxr_pincfgs[] = {
1113 { 0x0b, 0x01047110 }, /* Port G -- Lineout FRONT L/R */
1114 { 0x0c, 0x414510f0 }, /* SPDIF Out 1 - Disabled*/
1115 { 0x0d, 0x014510f0 }, /* Digital Out */
1116 { 0x0e, 0x41c520f0 }, /* SPDIF In - Disabled*/
1117 { 0x0f, 0x0122711f }, /* Port A -- BackPanel HP */
1118 { 0x10, 0x01017111 }, /* Port D -- Center/LFE */
1119 { 0x11, 0x01017114 }, /* Port B -- LineMicIn2 / Rear L/R */
1120 { 0x12, 0x01a271f0 }, /* Port C -- LineIn1 */
1121 { 0x13, 0x908700f0 }, /* What U Hear In*/
1122 { 0x18, 0x50d000f0 }, /* N/A */
1123 {}
1124};
1125
Connor McAdams7f73df92018-08-08 13:34:16 -04001126/* Recon3D pin configs taken from Windows Driver */
1127static const struct hda_pintbl r3d_pincfgs[] = {
1128 { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */
1129 { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
1130 { 0x0d, 0x014510f0 }, /* Digital Out */
1131 { 0x0e, 0x01c520f0 }, /* SPDIF In */
1132 { 0x0f, 0x0221401f }, /* Port A -- BackPanel HP */
1133 { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */
1134 { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */
1135 { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */
1136 { 0x13, 0x908700f0 }, /* What U Hear In*/
1137 { 0x18, 0x50d000f0 }, /* N/A */
1138 {}
1139};
1140
Connor McAdamsd06feaf2018-09-18 14:33:31 -04001141/* Sound Blaster AE-5 pin configs taken from Windows Driver */
1142static const struct hda_pintbl ae5_pincfgs[] = {
1143 { 0x0b, 0x01017010 }, /* Port G -- Lineout FRONT L/R */
1144 { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
1145 { 0x0d, 0x014510f0 }, /* Digital Out */
1146 { 0x0e, 0x01c510f0 }, /* SPDIF In */
1147 { 0x0f, 0x01017114 }, /* Port A -- Rear L/R. */
1148 { 0x10, 0x01017012 }, /* Port D -- Center/LFE or FP Hp */
1149 { 0x11, 0x01a170ff }, /* Port B -- LineMicIn2 / Rear Headphone */
1150 { 0x12, 0x01a170f0 }, /* Port C -- LineIn1 */
1151 { 0x13, 0x908700f0 }, /* What U Hear In*/
1152 { 0x18, 0x50d000f0 }, /* N/A */
1153 {}
1154};
1155
Connor McAdams63177af2018-05-08 13:20:02 -04001156/* Recon3D integrated pin configs taken from Windows Driver */
1157static const struct hda_pintbl r3di_pincfgs[] = {
1158 { 0x0b, 0x01014110 }, /* Port G -- Lineout FRONT L/R */
1159 { 0x0c, 0x014510f0 }, /* SPDIF Out 1 */
1160 { 0x0d, 0x014510f0 }, /* Digital Out */
1161 { 0x0e, 0x41c520f0 }, /* SPDIF In */
1162 { 0x0f, 0x0221401f }, /* Port A -- BackPanel HP */
1163 { 0x10, 0x01016011 }, /* Port D -- Center/LFE or FP Hp */
1164 { 0x11, 0x01011014 }, /* Port B -- LineMicIn2 / Rear L/R */
1165 { 0x12, 0x02a090f0 }, /* Port C -- LineIn1 */
1166 { 0x13, 0x908700f0 }, /* What U Hear In*/
1167 { 0x18, 0x500000f0 }, /* N/A */
1168 {}
1169};
1170
Gabriele Martinod5c016b2015-05-18 21:15:13 +02001171static const struct snd_pci_quirk ca0132_quirks[] = {
Alastair Bridgewatera57a46b2018-06-15 21:56:20 -04001172 SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4),
Gabriele Martino5328e1e2015-12-09 17:05:58 +01001173 SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
1174 SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
Sven Hahneb5337cf2016-11-25 14:16:43 +01001175 SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
Connor McAdams8a19bce2018-05-08 13:20:01 -04001176 SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
1177 SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
Paweł Rekowski2ca371d2019-08-19 22:40:07 +02001178 SND_PCI_QUIRK(0x1102, 0x0027, "Sound Blaster Z", QUIRK_SBZ),
Connor McAdamscce99722018-11-16 14:24:55 -05001179 SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
Connor McAdams8a19bce2018-05-08 13:20:01 -04001180 SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
Alastair Bridgewaterdad59262018-07-11 18:09:45 -04001181 SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
Alastair Bridgewaterc5a59d22018-07-11 18:09:46 -04001182 SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
Geoffrey Allotte9097e42020-03-19 14:00:48 +00001183 SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
Connor McAdams8f8c5232018-08-08 13:34:15 -04001184 SND_PCI_QUIRK(0x1102, 0x0013, "Recon3D", QUIRK_R3D),
Connor McAdamscc5edb12020-08-02 20:29:26 -04001185 SND_PCI_QUIRK(0x1102, 0x0018, "Recon3D", QUIRK_R3D),
Connor McAdamsf6276462018-09-18 14:33:30 -04001186 SND_PCI_QUIRK(0x1102, 0x0051, "Sound Blaster AE-5", QUIRK_AE5),
Gabriele Martinod5c016b2015-05-18 21:15:13 +02001187 {}
1188};
1189
1190/*
Ian Minett01ef7db2012-09-20 20:29:16 -07001191 * CA0132 codec access
1192 */
Sachin Kamat399ae722013-09-13 15:14:22 +05301193static unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid,
Ian Minett01ef7db2012-09-20 20:29:16 -07001194 unsigned int verb, unsigned int parm, unsigned int *res)
1195{
1196 unsigned int response;
1197 response = snd_hda_codec_read(codec, nid, 0, verb, parm);
1198 *res = response;
1199
1200 return ((response == -1) ? -1 : 0);
1201}
1202
1203static int codec_set_converter_format(struct hda_codec *codec, hda_nid_t nid,
1204 unsigned short converter_format, unsigned int *res)
1205{
1206 return codec_send_command(codec, nid, VENDOR_CHIPIO_STREAM_FORMAT,
1207 converter_format & 0xffff, res);
1208}
1209
1210static int codec_set_converter_stream_channel(struct hda_codec *codec,
1211 hda_nid_t nid, unsigned char stream,
1212 unsigned char channel, unsigned int *res)
1213{
1214 unsigned char converter_stream_channel = 0;
1215
1216 converter_stream_channel = (stream << 4) | (channel & 0x0f);
1217 return codec_send_command(codec, nid, AC_VERB_SET_CHANNEL_STREAMID,
1218 converter_stream_channel, res);
1219}
1220
Ian Minett95c6e9c2011-06-15 15:35:17 -07001221/* Chip access helper function */
1222static int chipio_send(struct hda_codec *codec,
1223 unsigned int reg,
1224 unsigned int data)
1225{
1226 unsigned int res;
Ian Minett6d675302013-02-08 18:31:43 -08001227 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
Ian Minett95c6e9c2011-06-15 15:35:17 -07001228
1229 /* send bits of data specified by reg */
1230 do {
1231 res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
1232 reg, data);
1233 if (res == VENDOR_STATUS_CHIPIO_OK)
1234 return 0;
Ian Minett6d675302013-02-08 18:31:43 -08001235 msleep(20);
1236 } while (time_before(jiffies, timeout));
1237
Ian Minett95c6e9c2011-06-15 15:35:17 -07001238 return -EIO;
1239}
1240
1241/*
1242 * Write chip address through the vendor widget -- NOT protected by the Mutex!
1243 */
1244static int chipio_write_address(struct hda_codec *codec,
1245 unsigned int chip_addx)
1246{
Ian Minett4861af82012-09-20 20:29:20 -07001247 struct ca0132_spec *spec = codec->spec;
Ian Minett95c6e9c2011-06-15 15:35:17 -07001248 int res;
1249
Ian Minett4861af82012-09-20 20:29:20 -07001250 if (spec->curr_chip_addx == chip_addx)
1251 return 0;
1252
Ian Minett95c6e9c2011-06-15 15:35:17 -07001253 /* send low 16 bits of the address */
1254 res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_LOW,
1255 chip_addx & 0xffff);
1256
1257 if (res != -EIO) {
1258 /* send high 16 bits of the address */
1259 res = chipio_send(codec, VENDOR_CHIPIO_ADDRESS_HIGH,
1260 chip_addx >> 16);
1261 }
1262
Matthias Kaehlcked1600402017-03-31 18:00:04 -07001263 spec->curr_chip_addx = (res < 0) ? ~0U : chip_addx;
Ian Minett4861af82012-09-20 20:29:20 -07001264
Ian Minett95c6e9c2011-06-15 15:35:17 -07001265 return res;
1266}
1267
1268/*
1269 * Write data through the vendor widget -- NOT protected by the Mutex!
1270 */
Ian Minett95c6e9c2011-06-15 15:35:17 -07001271static int chipio_write_data(struct hda_codec *codec, unsigned int data)
1272{
Ian Minett5aaca442012-12-20 18:53:34 -08001273 struct ca0132_spec *spec = codec->spec;
Ian Minett95c6e9c2011-06-15 15:35:17 -07001274 int res;
1275
1276 /* send low 16 bits of the data */
1277 res = chipio_send(codec, VENDOR_CHIPIO_DATA_LOW, data & 0xffff);
1278
1279 if (res != -EIO) {
1280 /* send high 16 bits of the data */
1281 res = chipio_send(codec, VENDOR_CHIPIO_DATA_HIGH,
1282 data >> 16);
1283 }
1284
Ian Minett5aaca442012-12-20 18:53:34 -08001285 /*If no error encountered, automatically increment the address
1286 as per chip behaviour*/
1287 spec->curr_chip_addx = (res != -EIO) ?
Matthias Kaehlcked1600402017-03-31 18:00:04 -07001288 (spec->curr_chip_addx + 4) : ~0U;
Ian Minett95c6e9c2011-06-15 15:35:17 -07001289 return res;
1290}
1291
Ian Minettd5c21b82012-09-20 20:29:18 -07001292/*
1293 * Write multiple data through the vendor widget -- NOT protected by the Mutex!
1294 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001295static int chipio_write_data_multiple(struct hda_codec *codec,
1296 const u32 *data,
1297 unsigned int count)
1298{
1299 int status = 0;
1300
1301 if (data == NULL) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01001302 codec_dbg(codec, "chipio_write_data null ptr\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07001303 return -EINVAL;
1304 }
1305
1306 while ((count-- != 0) && (status == 0))
1307 status = chipio_write_data(codec, *data++);
1308
1309 return status;
1310}
1311
1312
Ian Minett95c6e9c2011-06-15 15:35:17 -07001313/*
1314 * Read data through the vendor widget -- NOT protected by the Mutex!
1315 */
1316static int chipio_read_data(struct hda_codec *codec, unsigned int *data)
1317{
Ian Minett5aaca442012-12-20 18:53:34 -08001318 struct ca0132_spec *spec = codec->spec;
Ian Minett95c6e9c2011-06-15 15:35:17 -07001319 int res;
1320
1321 /* post read */
1322 res = chipio_send(codec, VENDOR_CHIPIO_HIC_POST_READ, 0);
1323
1324 if (res != -EIO) {
1325 /* read status */
1326 res = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
1327 }
1328
1329 if (res != -EIO) {
1330 /* read data */
1331 *data = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
1332 VENDOR_CHIPIO_HIC_READ_DATA,
1333 0);
1334 }
1335
Ian Minett5aaca442012-12-20 18:53:34 -08001336 /*If no error encountered, automatically increment the address
1337 as per chip behaviour*/
1338 spec->curr_chip_addx = (res != -EIO) ?
Matthias Kaehlcked1600402017-03-31 18:00:04 -07001339 (spec->curr_chip_addx + 4) : ~0U;
Ian Minett95c6e9c2011-06-15 15:35:17 -07001340 return res;
1341}
1342
1343/*
1344 * Write given value to the given address through the chip I/O widget.
1345 * protected by the Mutex
1346 */
1347static int chipio_write(struct hda_codec *codec,
1348 unsigned int chip_addx, const unsigned int data)
1349{
1350 struct ca0132_spec *spec = codec->spec;
1351 int err;
1352
1353 mutex_lock(&spec->chipio_mutex);
1354
1355 /* write the address, and if successful proceed to write data */
1356 err = chipio_write_address(codec, chip_addx);
1357 if (err < 0)
1358 goto exit;
1359
1360 err = chipio_write_data(codec, data);
1361 if (err < 0)
1362 goto exit;
1363
1364exit:
1365 mutex_unlock(&spec->chipio_mutex);
1366 return err;
1367}
1368
Ian Minettd5c21b82012-09-20 20:29:18 -07001369/*
Connor McAdams38ba69f2018-05-08 13:20:07 -04001370 * Write given value to the given address through the chip I/O widget.
1371 * not protected by the Mutex
1372 */
1373static int chipio_write_no_mutex(struct hda_codec *codec,
1374 unsigned int chip_addx, const unsigned int data)
1375{
1376 int err;
1377
1378
1379 /* write the address, and if successful proceed to write data */
1380 err = chipio_write_address(codec, chip_addx);
1381 if (err < 0)
1382 goto exit;
1383
1384 err = chipio_write_data(codec, data);
1385 if (err < 0)
1386 goto exit;
1387
1388exit:
1389 return err;
1390}
1391
1392/*
Ian Minettd5c21b82012-09-20 20:29:18 -07001393 * Write multiple values to the given address through the chip I/O widget.
1394 * protected by the Mutex
1395 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001396static int chipio_write_multiple(struct hda_codec *codec,
1397 u32 chip_addx,
1398 const u32 *data,
1399 unsigned int count)
1400{
1401 struct ca0132_spec *spec = codec->spec;
1402 int status;
1403
1404 mutex_lock(&spec->chipio_mutex);
Ian Minett4861af82012-09-20 20:29:20 -07001405 status = chipio_write_address(codec, chip_addx);
Ian Minett01ef7db2012-09-20 20:29:16 -07001406 if (status < 0)
1407 goto error;
1408
1409 status = chipio_write_data_multiple(codec, data, count);
1410error:
1411 mutex_unlock(&spec->chipio_mutex);
1412
1413 return status;
1414}
1415
Ian Minett95c6e9c2011-06-15 15:35:17 -07001416/*
1417 * Read the given address through the chip I/O widget
1418 * protected by the Mutex
1419 */
1420static int chipio_read(struct hda_codec *codec,
1421 unsigned int chip_addx, unsigned int *data)
1422{
1423 struct ca0132_spec *spec = codec->spec;
1424 int err;
1425
1426 mutex_lock(&spec->chipio_mutex);
1427
1428 /* write the address, and if successful proceed to write data */
1429 err = chipio_write_address(codec, chip_addx);
1430 if (err < 0)
1431 goto exit;
1432
1433 err = chipio_read_data(codec, data);
1434 if (err < 0)
1435 goto exit;
1436
1437exit:
1438 mutex_unlock(&spec->chipio_mutex);
1439 return err;
1440}
1441
Ian Minettd5c21b82012-09-20 20:29:18 -07001442/*
1443 * Set chip control flags through the chip I/O widget.
1444 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001445static void chipio_set_control_flag(struct hda_codec *codec,
1446 enum control_flag_id flag_id,
1447 bool flag_state)
1448{
1449 unsigned int val;
1450 unsigned int flag_bit;
1451
1452 flag_bit = (flag_state ? 1 : 0);
1453 val = (flag_bit << 7) | (flag_id);
1454 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1455 VENDOR_CHIPIO_FLAG_SET, val);
1456}
1457
Ian Minettd5c21b82012-09-20 20:29:18 -07001458/*
1459 * Set chip parameters through the chip I/O widget.
1460 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001461static void chipio_set_control_param(struct hda_codec *codec,
1462 enum control_param_id param_id, int param_val)
1463{
1464 struct ca0132_spec *spec = codec->spec;
1465 int val;
1466
1467 if ((param_id < 32) && (param_val < 8)) {
1468 val = (param_val << 5) | (param_id);
1469 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1470 VENDOR_CHIPIO_PARAM_SET, val);
1471 } else {
1472 mutex_lock(&spec->chipio_mutex);
1473 if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) {
1474 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1475 VENDOR_CHIPIO_PARAM_EX_ID_SET,
1476 param_id);
1477 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1478 VENDOR_CHIPIO_PARAM_EX_VALUE_SET,
1479 param_val);
1480 }
1481 mutex_unlock(&spec->chipio_mutex);
1482 }
1483}
1484
Ian Minettd5c21b82012-09-20 20:29:18 -07001485/*
Connor McAdams009b8f92018-05-08 13:20:06 -04001486 * Set chip parameters through the chip I/O widget. NO MUTEX.
1487 */
1488static void chipio_set_control_param_no_mutex(struct hda_codec *codec,
1489 enum control_param_id param_id, int param_val)
1490{
1491 int val;
1492
1493 if ((param_id < 32) && (param_val < 8)) {
1494 val = (param_val << 5) | (param_id);
1495 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1496 VENDOR_CHIPIO_PARAM_SET, val);
1497 } else {
1498 if (chipio_send(codec, VENDOR_CHIPIO_STATUS, 0) == 0) {
1499 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1500 VENDOR_CHIPIO_PARAM_EX_ID_SET,
1501 param_id);
1502 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1503 VENDOR_CHIPIO_PARAM_EX_VALUE_SET,
1504 param_val);
1505 }
1506 }
1507}
Connor McAdams38ba69f2018-05-08 13:20:07 -04001508/*
1509 * Connect stream to a source point, and then connect
1510 * that source point to a destination point.
1511 */
1512static void chipio_set_stream_source_dest(struct hda_codec *codec,
1513 int streamid, int source_point, int dest_point)
1514{
1515 chipio_set_control_param_no_mutex(codec,
1516 CONTROL_PARAM_STREAM_ID, streamid);
1517 chipio_set_control_param_no_mutex(codec,
1518 CONTROL_PARAM_STREAM_SOURCE_CONN_POINT, source_point);
1519 chipio_set_control_param_no_mutex(codec,
1520 CONTROL_PARAM_STREAM_DEST_CONN_POINT, dest_point);
1521}
1522
1523/*
1524 * Set number of channels in the selected stream.
1525 */
1526static void chipio_set_stream_channels(struct hda_codec *codec,
1527 int streamid, unsigned int channels)
1528{
1529 chipio_set_control_param_no_mutex(codec,
1530 CONTROL_PARAM_STREAM_ID, streamid);
1531 chipio_set_control_param_no_mutex(codec,
1532 CONTROL_PARAM_STREAMS_CHANNELS, channels);
1533}
Connor McAdams009b8f92018-05-08 13:20:06 -04001534
1535/*
1536 * Enable/Disable audio stream.
1537 */
1538static void chipio_set_stream_control(struct hda_codec *codec,
1539 int streamid, int enable)
1540{
1541 chipio_set_control_param_no_mutex(codec,
1542 CONTROL_PARAM_STREAM_ID, streamid);
1543 chipio_set_control_param_no_mutex(codec,
1544 CONTROL_PARAM_STREAM_CONTROL, enable);
1545}
1546
Connor McAdams38ba69f2018-05-08 13:20:07 -04001547
1548/*
1549 * Set sampling rate of the connection point. NO MUTEX.
1550 */
1551static void chipio_set_conn_rate_no_mutex(struct hda_codec *codec,
1552 int connid, enum ca0132_sample_rate rate)
1553{
1554 chipio_set_control_param_no_mutex(codec,
1555 CONTROL_PARAM_CONN_POINT_ID, connid);
1556 chipio_set_control_param_no_mutex(codec,
1557 CONTROL_PARAM_CONN_POINT_SAMPLE_RATE, rate);
1558}
1559
Connor McAdams009b8f92018-05-08 13:20:06 -04001560/*
Ian Minettd5c21b82012-09-20 20:29:18 -07001561 * Set sampling rate of the connection point.
1562 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001563static void chipio_set_conn_rate(struct hda_codec *codec,
1564 int connid, enum ca0132_sample_rate rate)
1565{
1566 chipio_set_control_param(codec, CONTROL_PARAM_CONN_POINT_ID, connid);
1567 chipio_set_control_param(codec, CONTROL_PARAM_CONN_POINT_SAMPLE_RATE,
1568 rate);
1569}
1570
Ian Minettd5c21b82012-09-20 20:29:18 -07001571/*
Connor McAdamsb9b41342018-09-18 14:33:34 -04001572 * Writes to the 8051's internal address space directly instead of indirectly,
1573 * giving access to the special function registers located at addresses
1574 * 0x80-0xFF.
1575 */
1576static void chipio_8051_write_direct(struct hda_codec *codec,
1577 unsigned int addr, unsigned int data)
1578{
1579 unsigned int verb;
1580
1581 verb = VENDOR_CHIPIO_8051_WRITE_DIRECT | data;
1582 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, verb, addr);
1583}
1584
1585/*
Ian Minettd5c21b82012-09-20 20:29:18 -07001586 * Enable clocks.
1587 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001588static void chipio_enable_clocks(struct hda_codec *codec)
1589{
1590 struct ca0132_spec *spec = codec->spec;
1591
1592 mutex_lock(&spec->chipio_mutex);
1593 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1594 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0);
1595 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1596 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xff);
1597 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1598 VENDOR_CHIPIO_8051_ADDRESS_LOW, 5);
1599 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1600 VENDOR_CHIPIO_PLL_PMU_WRITE, 0x0b);
1601 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1602 VENDOR_CHIPIO_8051_ADDRESS_LOW, 6);
1603 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
1604 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xff);
1605 mutex_unlock(&spec->chipio_mutex);
1606}
1607
1608/*
1609 * CA0132 DSP IO stuffs
1610 */
1611static int dspio_send(struct hda_codec *codec, unsigned int reg,
1612 unsigned int data)
1613{
Takashi Iwaib645d792013-01-15 17:39:29 +01001614 int res;
Ian Minett6d675302013-02-08 18:31:43 -08001615 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
Ian Minett01ef7db2012-09-20 20:29:16 -07001616
1617 /* send bits of data specified by reg to dsp */
1618 do {
1619 res = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0, reg, data);
1620 if ((res >= 0) && (res != VENDOR_STATUS_DSPIO_BUSY))
1621 return res;
Ian Minett6d675302013-02-08 18:31:43 -08001622 msleep(20);
1623 } while (time_before(jiffies, timeout));
Ian Minett01ef7db2012-09-20 20:29:16 -07001624
1625 return -EIO;
1626}
1627
Ian Minettd5c21b82012-09-20 20:29:18 -07001628/*
1629 * Wait for DSP to be ready for commands
1630 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001631static void dspio_write_wait(struct hda_codec *codec)
1632{
Ian Minett4861af82012-09-20 20:29:20 -07001633 int status;
1634 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
Ian Minett01ef7db2012-09-20 20:29:16 -07001635
Ian Minett01ef7db2012-09-20 20:29:16 -07001636 do {
Ian Minett4861af82012-09-20 20:29:20 -07001637 status = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
1638 VENDOR_DSPIO_STATUS, 0);
1639 if ((status == VENDOR_STATUS_DSPIO_OK) ||
1640 (status == VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY))
1641 break;
1642 msleep(1);
1643 } while (time_before(jiffies, timeout));
Ian Minett01ef7db2012-09-20 20:29:16 -07001644}
1645
Ian Minettd5c21b82012-09-20 20:29:18 -07001646/*
1647 * Write SCP data to DSP
1648 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001649static int dspio_write(struct hda_codec *codec, unsigned int scp_data)
1650{
1651 struct ca0132_spec *spec = codec->spec;
1652 int status;
1653
1654 dspio_write_wait(codec);
1655
1656 mutex_lock(&spec->chipio_mutex);
1657 status = dspio_send(codec, VENDOR_DSPIO_SCP_WRITE_DATA_LOW,
1658 scp_data & 0xffff);
1659 if (status < 0)
1660 goto error;
1661
1662 status = dspio_send(codec, VENDOR_DSPIO_SCP_WRITE_DATA_HIGH,
1663 scp_data >> 16);
1664 if (status < 0)
1665 goto error;
1666
1667 /* OK, now check if the write itself has executed*/
1668 status = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
1669 VENDOR_DSPIO_STATUS, 0);
1670error:
1671 mutex_unlock(&spec->chipio_mutex);
1672
1673 return (status == VENDOR_STATUS_DSPIO_SCP_COMMAND_QUEUE_FULL) ?
1674 -EIO : 0;
1675}
1676
Ian Minettd5c21b82012-09-20 20:29:18 -07001677/*
1678 * Write multiple SCP data to DSP
1679 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001680static int dspio_write_multiple(struct hda_codec *codec,
1681 unsigned int *buffer, unsigned int size)
1682{
1683 int status = 0;
1684 unsigned int count;
1685
Matthias Kaehlckea16fbb82017-03-15 15:41:23 -07001686 if (buffer == NULL)
Ian Minett01ef7db2012-09-20 20:29:16 -07001687 return -EINVAL;
1688
1689 count = 0;
1690 while (count < size) {
1691 status = dspio_write(codec, *buffer++);
1692 if (status != 0)
1693 break;
1694 count++;
1695 }
1696
1697 return status;
1698}
1699
Ian Minetta73d5112012-12-20 18:53:37 -08001700static int dspio_read(struct hda_codec *codec, unsigned int *data)
1701{
1702 int status;
1703
1704 status = dspio_send(codec, VENDOR_DSPIO_SCP_POST_READ_DATA, 0);
1705 if (status == -EIO)
1706 return status;
1707
1708 status = dspio_send(codec, VENDOR_DSPIO_STATUS, 0);
1709 if (status == -EIO ||
1710 status == VENDOR_STATUS_DSPIO_SCP_RESPONSE_QUEUE_EMPTY)
1711 return -EIO;
1712
1713 *data = snd_hda_codec_read(codec, WIDGET_DSP_CTRL, 0,
1714 VENDOR_DSPIO_SCP_READ_DATA, 0);
1715
1716 return 0;
1717}
1718
1719static int dspio_read_multiple(struct hda_codec *codec, unsigned int *buffer,
1720 unsigned int *buf_size, unsigned int size_count)
1721{
1722 int status = 0;
1723 unsigned int size = *buf_size;
1724 unsigned int count;
1725 unsigned int skip_count;
1726 unsigned int dummy;
1727
Matthias Kaehlckea16fbb82017-03-15 15:41:23 -07001728 if (buffer == NULL)
Ian Minetta73d5112012-12-20 18:53:37 -08001729 return -1;
1730
1731 count = 0;
1732 while (count < size && count < size_count) {
1733 status = dspio_read(codec, buffer++);
1734 if (status != 0)
1735 break;
1736 count++;
1737 }
1738
1739 skip_count = count;
1740 if (status == 0) {
1741 while (skip_count < size) {
1742 status = dspio_read(codec, &dummy);
1743 if (status != 0)
1744 break;
1745 skip_count++;
1746 }
1747 }
1748 *buf_size = count;
1749
1750 return status;
1751}
1752
Ian Minettd5c21b82012-09-20 20:29:18 -07001753/*
1754 * Construct the SCP header using corresponding fields
1755 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001756static inline unsigned int
1757make_scp_header(unsigned int target_id, unsigned int source_id,
1758 unsigned int get_flag, unsigned int req,
1759 unsigned int device_flag, unsigned int resp_flag,
1760 unsigned int error_flag, unsigned int data_size)
1761{
1762 unsigned int header = 0;
1763
1764 header = (data_size & 0x1f) << 27;
1765 header |= (error_flag & 0x01) << 26;
1766 header |= (resp_flag & 0x01) << 25;
1767 header |= (device_flag & 0x01) << 24;
1768 header |= (req & 0x7f) << 17;
1769 header |= (get_flag & 0x01) << 16;
1770 header |= (source_id & 0xff) << 8;
1771 header |= target_id & 0xff;
1772
1773 return header;
1774}
1775
Ian Minettd5c21b82012-09-20 20:29:18 -07001776/*
1777 * Extract corresponding fields from SCP header
1778 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001779static inline void
1780extract_scp_header(unsigned int header,
1781 unsigned int *target_id, unsigned int *source_id,
1782 unsigned int *get_flag, unsigned int *req,
1783 unsigned int *device_flag, unsigned int *resp_flag,
1784 unsigned int *error_flag, unsigned int *data_size)
1785{
1786 if (data_size)
1787 *data_size = (header >> 27) & 0x1f;
1788 if (error_flag)
1789 *error_flag = (header >> 26) & 0x01;
1790 if (resp_flag)
1791 *resp_flag = (header >> 25) & 0x01;
1792 if (device_flag)
1793 *device_flag = (header >> 24) & 0x01;
1794 if (req)
1795 *req = (header >> 17) & 0x7f;
1796 if (get_flag)
1797 *get_flag = (header >> 16) & 0x01;
1798 if (source_id)
1799 *source_id = (header >> 8) & 0xff;
1800 if (target_id)
1801 *target_id = header & 0xff;
1802}
1803
1804#define SCP_MAX_DATA_WORDS (16)
1805
1806/* Structure to contain any SCP message */
1807struct scp_msg {
1808 unsigned int hdr;
1809 unsigned int data[SCP_MAX_DATA_WORDS];
1810};
1811
Ian Minetta73d5112012-12-20 18:53:37 -08001812static void dspio_clear_response_queue(struct hda_codec *codec)
1813{
Takashi Iwaicb04fc32019-12-13 09:51:10 +01001814 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
Ian Minetta73d5112012-12-20 18:53:37 -08001815 unsigned int dummy = 0;
Takashi Iwaicb04fc32019-12-13 09:51:10 +01001816 int status;
Ian Minetta73d5112012-12-20 18:53:37 -08001817
1818 /* clear all from the response queue */
1819 do {
1820 status = dspio_read(codec, &dummy);
Takashi Iwaicb04fc32019-12-13 09:51:10 +01001821 } while (status == 0 && time_before(jiffies, timeout));
Ian Minetta73d5112012-12-20 18:53:37 -08001822}
1823
1824static int dspio_get_response_data(struct hda_codec *codec)
1825{
1826 struct ca0132_spec *spec = codec->spec;
1827 unsigned int data = 0;
1828 unsigned int count;
1829
1830 if (dspio_read(codec, &data) < 0)
1831 return -EIO;
1832
1833 if ((data & 0x00ffffff) == spec->wait_scp_header) {
1834 spec->scp_resp_header = data;
1835 spec->scp_resp_count = data >> 27;
1836 count = spec->wait_num_data;
1837 dspio_read_multiple(codec, spec->scp_resp_data,
1838 &spec->scp_resp_count, count);
1839 return 0;
1840 }
1841
1842 return -EIO;
1843}
1844
Ian Minettd5c21b82012-09-20 20:29:18 -07001845/*
1846 * Send SCP message to DSP
1847 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001848static int dspio_send_scp_message(struct hda_codec *codec,
1849 unsigned char *send_buf,
1850 unsigned int send_buf_size,
1851 unsigned char *return_buf,
1852 unsigned int return_buf_size,
1853 unsigned int *bytes_returned)
1854{
1855 struct ca0132_spec *spec = codec->spec;
Ian Minett01ef7db2012-09-20 20:29:16 -07001856 int status = -1;
1857 unsigned int scp_send_size = 0;
1858 unsigned int total_size;
1859 bool waiting_for_resp = false;
1860 unsigned int header;
1861 struct scp_msg *ret_msg;
1862 unsigned int resp_src_id, resp_target_id;
1863 unsigned int data_size, src_id, target_id, get_flag, device_flag;
1864
1865 if (bytes_returned)
1866 *bytes_returned = 0;
1867
1868 /* get scp header from buffer */
1869 header = *((unsigned int *)send_buf);
1870 extract_scp_header(header, &target_id, &src_id, &get_flag, NULL,
1871 &device_flag, NULL, NULL, &data_size);
1872 scp_send_size = data_size + 1;
1873 total_size = (scp_send_size * 4);
1874
1875 if (send_buf_size < total_size)
1876 return -EINVAL;
1877
1878 if (get_flag || device_flag) {
1879 if (!return_buf || return_buf_size < 4 || !bytes_returned)
1880 return -EINVAL;
1881
1882 spec->wait_scp_header = *((unsigned int *)send_buf);
1883
1884 /* swap source id with target id */
1885 resp_target_id = src_id;
1886 resp_src_id = target_id;
1887 spec->wait_scp_header &= 0xffff0000;
1888 spec->wait_scp_header |= (resp_src_id << 8) | (resp_target_id);
1889 spec->wait_num_data = return_buf_size/sizeof(unsigned int) - 1;
1890 spec->wait_scp = 1;
1891 waiting_for_resp = true;
1892 }
1893
1894 status = dspio_write_multiple(codec, (unsigned int *)send_buf,
1895 scp_send_size);
1896 if (status < 0) {
1897 spec->wait_scp = 0;
1898 return status;
1899 }
1900
1901 if (waiting_for_resp) {
Ian Minett6d675302013-02-08 18:31:43 -08001902 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
Ian Minett01ef7db2012-09-20 20:29:16 -07001903 memset(return_buf, 0, return_buf_size);
Ian Minett01ef7db2012-09-20 20:29:16 -07001904 do {
1905 msleep(20);
Ian Minett6d675302013-02-08 18:31:43 -08001906 } while (spec->wait_scp && time_before(jiffies, timeout));
Ian Minett01ef7db2012-09-20 20:29:16 -07001907 waiting_for_resp = false;
Ian Minett6d675302013-02-08 18:31:43 -08001908 if (!spec->wait_scp) {
Ian Minett01ef7db2012-09-20 20:29:16 -07001909 ret_msg = (struct scp_msg *)return_buf;
1910 memcpy(&ret_msg->hdr, &spec->scp_resp_header, 4);
1911 memcpy(&ret_msg->data, spec->scp_resp_data,
1912 spec->wait_num_data);
1913 *bytes_returned = (spec->scp_resp_count + 1) * 4;
1914 status = 0;
1915 } else {
1916 status = -EIO;
1917 }
1918 spec->wait_scp = 0;
1919 }
1920
1921 return status;
1922}
1923
Ian Minettd5c21b82012-09-20 20:29:18 -07001924/**
1925 * Prepare and send the SCP message to DSP
1926 * @codec: the HDA codec
1927 * @mod_id: ID of the DSP module to send the command
Pierre-Louis Bossart4f5c2652020-01-13 15:14:04 -06001928 * @src_id: ID of the source
Ian Minettd5c21b82012-09-20 20:29:18 -07001929 * @req: ID of request to send to the DSP module
1930 * @dir: SET or GET
1931 * @data: pointer to the data to send with the request, request specific
1932 * @len: length of the data, in bytes
1933 * @reply: point to the buffer to hold data returned for a reply
1934 * @reply_len: length of the reply buffer returned from GET
1935 *
1936 * Returns zero or a negative error code.
1937 */
Ian Minett01ef7db2012-09-20 20:29:16 -07001938static int dspio_scp(struct hda_codec *codec,
Connor McAdams447fd8e2018-05-08 13:20:09 -04001939 int mod_id, int src_id, int req, int dir, const void *data,
1940 unsigned int len, void *reply, unsigned int *reply_len)
Ian Minett01ef7db2012-09-20 20:29:16 -07001941{
1942 int status = 0;
1943 struct scp_msg scp_send, scp_reply;
1944 unsigned int ret_bytes, send_size, ret_size;
1945 unsigned int send_get_flag, reply_resp_flag, reply_error_flag;
1946 unsigned int reply_data_size;
1947
1948 memset(&scp_send, 0, sizeof(scp_send));
1949 memset(&scp_reply, 0, sizeof(scp_reply));
1950
1951 if ((len != 0 && data == NULL) || (len > SCP_MAX_DATA_WORDS))
1952 return -EINVAL;
1953
1954 if (dir == SCP_GET && reply == NULL) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01001955 codec_dbg(codec, "dspio_scp get but has no buffer\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07001956 return -EINVAL;
1957 }
1958
1959 if (reply != NULL && (reply_len == NULL || (*reply_len == 0))) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01001960 codec_dbg(codec, "dspio_scp bad resp buf len parms\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07001961 return -EINVAL;
1962 }
1963
Connor McAdams447fd8e2018-05-08 13:20:09 -04001964 scp_send.hdr = make_scp_header(mod_id, src_id, (dir == SCP_GET), req,
Ian Minett01ef7db2012-09-20 20:29:16 -07001965 0, 0, 0, len/sizeof(unsigned int));
1966 if (data != NULL && len > 0) {
1967 len = min((unsigned int)(sizeof(scp_send.data)), len);
1968 memcpy(scp_send.data, data, len);
1969 }
1970
1971 ret_bytes = 0;
1972 send_size = sizeof(unsigned int) + len;
1973 status = dspio_send_scp_message(codec, (unsigned char *)&scp_send,
1974 send_size, (unsigned char *)&scp_reply,
1975 sizeof(scp_reply), &ret_bytes);
1976
1977 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01001978 codec_dbg(codec, "dspio_scp: send scp msg failed\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07001979 return status;
1980 }
1981
1982 /* extract send and reply headers members */
1983 extract_scp_header(scp_send.hdr, NULL, NULL, &send_get_flag,
1984 NULL, NULL, NULL, NULL, NULL);
1985 extract_scp_header(scp_reply.hdr, NULL, NULL, NULL, NULL, NULL,
1986 &reply_resp_flag, &reply_error_flag,
1987 &reply_data_size);
1988
1989 if (!send_get_flag)
1990 return 0;
1991
1992 if (reply_resp_flag && !reply_error_flag) {
1993 ret_size = (ret_bytes - sizeof(scp_reply.hdr))
1994 / sizeof(unsigned int);
1995
1996 if (*reply_len < ret_size*sizeof(unsigned int)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01001997 codec_dbg(codec, "reply too long for buf\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07001998 return -EINVAL;
1999 } else if (ret_size != reply_data_size) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002000 codec_dbg(codec, "RetLen and HdrLen .NE.\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002001 return -EINVAL;
Arnd Bergmann46a049d2017-01-11 14:39:44 +01002002 } else if (!reply) {
2003 codec_dbg(codec, "NULL reply\n");
2004 return -EINVAL;
Ian Minett01ef7db2012-09-20 20:29:16 -07002005 } else {
2006 *reply_len = ret_size*sizeof(unsigned int);
2007 memcpy(reply, scp_reply.data, *reply_len);
2008 }
2009 } else {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002010 codec_dbg(codec, "reply ill-formed or errflag set\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002011 return -EIO;
2012 }
2013
2014 return status;
2015}
2016
Ian Minettd5c21b82012-09-20 20:29:18 -07002017/*
Ian Minett5aaca442012-12-20 18:53:34 -08002018 * Set DSP parameters
2019 */
2020static int dspio_set_param(struct hda_codec *codec, int mod_id,
Connor McAdams447fd8e2018-05-08 13:20:09 -04002021 int src_id, int req, const void *data, unsigned int len)
Ian Minett5aaca442012-12-20 18:53:34 -08002022{
Connor McAdams447fd8e2018-05-08 13:20:09 -04002023 return dspio_scp(codec, mod_id, src_id, req, SCP_SET, data, len, NULL,
2024 NULL);
Ian Minett5aaca442012-12-20 18:53:34 -08002025}
2026
2027static int dspio_set_uint_param(struct hda_codec *codec, int mod_id,
Connor McAdams447fd8e2018-05-08 13:20:09 -04002028 int req, const unsigned int data)
Ian Minett5aaca442012-12-20 18:53:34 -08002029{
Connor McAdams447fd8e2018-05-08 13:20:09 -04002030 return dspio_set_param(codec, mod_id, 0x20, req, &data,
2031 sizeof(unsigned int));
2032}
2033
2034static int dspio_set_uint_param_no_source(struct hda_codec *codec, int mod_id,
2035 int req, const unsigned int data)
2036{
2037 return dspio_set_param(codec, mod_id, 0x00, req, &data,
2038 sizeof(unsigned int));
Ian Minett5aaca442012-12-20 18:53:34 -08002039}
2040
2041/*
Ian Minettd5c21b82012-09-20 20:29:18 -07002042 * Allocate a DSP DMA channel via an SCP message
2043 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002044static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan)
2045{
2046 int status = 0;
2047 unsigned int size = sizeof(dma_chan);
2048
Takashi Iwai4e76a882014-02-25 12:21:03 +01002049 codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n");
Connor McAdams447fd8e2018-05-08 13:20:09 -04002050 status = dspio_scp(codec, MASTERCONTROL, 0x20,
2051 MASTERCONTROL_ALLOC_DMA_CHAN, SCP_GET, NULL, 0,
2052 dma_chan, &size);
Ian Minett01ef7db2012-09-20 20:29:16 -07002053
2054 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002055 codec_dbg(codec, "dspio_alloc_dma_chan: SCP Failed\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002056 return status;
2057 }
2058
2059 if ((*dma_chan + 1) == 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002060 codec_dbg(codec, "no free dma channels to allocate\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002061 return -EBUSY;
2062 }
2063
Takashi Iwai4e76a882014-02-25 12:21:03 +01002064 codec_dbg(codec, "dspio_alloc_dma_chan: chan=%d\n", *dma_chan);
2065 codec_dbg(codec, " dspio_alloc_dma_chan() -- complete\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002066
2067 return status;
2068}
2069
Ian Minettd5c21b82012-09-20 20:29:18 -07002070/*
2071 * Free a DSP DMA via an SCP message
2072 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002073static int dspio_free_dma_chan(struct hda_codec *codec, unsigned int dma_chan)
2074{
2075 int status = 0;
2076 unsigned int dummy = 0;
2077
Takashi Iwai4e76a882014-02-25 12:21:03 +01002078 codec_dbg(codec, " dspio_free_dma_chan() -- begin\n");
2079 codec_dbg(codec, "dspio_free_dma_chan: chan=%d\n", dma_chan);
Ian Minett01ef7db2012-09-20 20:29:16 -07002080
Connor McAdams447fd8e2018-05-08 13:20:09 -04002081 status = dspio_scp(codec, MASTERCONTROL, 0x20,
2082 MASTERCONTROL_ALLOC_DMA_CHAN, SCP_SET, &dma_chan,
2083 sizeof(dma_chan), NULL, &dummy);
Ian Minett01ef7db2012-09-20 20:29:16 -07002084
2085 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002086 codec_dbg(codec, "dspio_free_dma_chan: SCP Failed\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002087 return status;
2088 }
2089
Takashi Iwai4e76a882014-02-25 12:21:03 +01002090 codec_dbg(codec, " dspio_free_dma_chan() -- complete\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002091
2092 return status;
2093}
2094
2095/*
Ian Minettd5c21b82012-09-20 20:29:18 -07002096 * (Re)start the DSP
Ian Minett01ef7db2012-09-20 20:29:16 -07002097 */
2098static int dsp_set_run_state(struct hda_codec *codec)
2099{
2100 unsigned int dbg_ctrl_reg;
2101 unsigned int halt_state;
2102 int err;
2103
2104 err = chipio_read(codec, DSP_DBGCNTL_INST_OFFSET, &dbg_ctrl_reg);
2105 if (err < 0)
2106 return err;
2107
2108 halt_state = (dbg_ctrl_reg & DSP_DBGCNTL_STATE_MASK) >>
2109 DSP_DBGCNTL_STATE_LOBIT;
2110
2111 if (halt_state != 0) {
2112 dbg_ctrl_reg &= ~((halt_state << DSP_DBGCNTL_SS_LOBIT) &
2113 DSP_DBGCNTL_SS_MASK);
2114 err = chipio_write(codec, DSP_DBGCNTL_INST_OFFSET,
2115 dbg_ctrl_reg);
2116 if (err < 0)
2117 return err;
2118
2119 dbg_ctrl_reg |= (halt_state << DSP_DBGCNTL_EXEC_LOBIT) &
2120 DSP_DBGCNTL_EXEC_MASK;
2121 err = chipio_write(codec, DSP_DBGCNTL_INST_OFFSET,
2122 dbg_ctrl_reg);
2123 if (err < 0)
2124 return err;
2125 }
2126
2127 return 0;
2128}
2129
Ian Minettd5c21b82012-09-20 20:29:18 -07002130/*
2131 * Reset the DSP
2132 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002133static int dsp_reset(struct hda_codec *codec)
2134{
2135 unsigned int res;
2136 int retry = 20;
2137
Takashi Iwai4e76a882014-02-25 12:21:03 +01002138 codec_dbg(codec, "dsp_reset\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002139 do {
2140 res = dspio_send(codec, VENDOR_DSPIO_DSP_INIT, 0);
2141 retry--;
2142 } while (res == -EIO && retry);
2143
2144 if (!retry) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002145 codec_dbg(codec, "dsp_reset timeout\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002146 return -EIO;
2147 }
2148
2149 return 0;
2150}
2151
Ian Minettd5c21b82012-09-20 20:29:18 -07002152/*
2153 * Convert chip address to DSP address
2154 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002155static unsigned int dsp_chip_to_dsp_addx(unsigned int chip_addx,
2156 bool *code, bool *yram)
2157{
2158 *code = *yram = false;
2159
2160 if (UC_RANGE(chip_addx, 1)) {
2161 *code = true;
2162 return UC_OFF(chip_addx);
2163 } else if (X_RANGE_ALL(chip_addx, 1)) {
2164 return X_OFF(chip_addx);
2165 } else if (Y_RANGE_ALL(chip_addx, 1)) {
2166 *yram = true;
2167 return Y_OFF(chip_addx);
2168 }
2169
Takashi Iwai4a8b89f2013-02-12 10:15:15 +01002170 return INVALID_CHIP_ADDRESS;
Ian Minett01ef7db2012-09-20 20:29:16 -07002171}
2172
Ian Minettd5c21b82012-09-20 20:29:18 -07002173/*
2174 * Check if the DSP DMA is active
2175 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002176static bool dsp_is_dma_active(struct hda_codec *codec, unsigned int dma_chan)
2177{
2178 unsigned int dma_chnlstart_reg;
2179
2180 chipio_read(codec, DSPDMAC_CHNLSTART_INST_OFFSET, &dma_chnlstart_reg);
2181
2182 return ((dma_chnlstart_reg & (1 <<
2183 (DSPDMAC_CHNLSTART_EN_LOBIT + dma_chan))) != 0);
2184}
2185
2186static int dsp_dma_setup_common(struct hda_codec *codec,
2187 unsigned int chip_addx,
2188 unsigned int dma_chan,
2189 unsigned int port_map_mask,
2190 bool ovly)
2191{
2192 int status = 0;
2193 unsigned int chnl_prop;
2194 unsigned int dsp_addx;
2195 unsigned int active;
2196 bool code, yram;
2197
Takashi Iwai4e76a882014-02-25 12:21:03 +01002198 codec_dbg(codec, "-- dsp_dma_setup_common() -- Begin ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002199
2200 if (dma_chan >= DSPDMAC_DMA_CFG_CHANNEL_COUNT) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002201 codec_dbg(codec, "dma chan num invalid\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002202 return -EINVAL;
2203 }
2204
2205 if (dsp_is_dma_active(codec, dma_chan)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002206 codec_dbg(codec, "dma already active\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002207 return -EBUSY;
2208 }
2209
2210 dsp_addx = dsp_chip_to_dsp_addx(chip_addx, &code, &yram);
2211
2212 if (dsp_addx == INVALID_CHIP_ADDRESS) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002213 codec_dbg(codec, "invalid chip addr\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002214 return -ENXIO;
2215 }
2216
2217 chnl_prop = DSPDMAC_CHNLPROP_AC_MASK;
2218 active = 0;
2219
Takashi Iwai4e76a882014-02-25 12:21:03 +01002220 codec_dbg(codec, " dsp_dma_setup_common() start reg pgm\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002221
2222 if (ovly) {
2223 status = chipio_read(codec, DSPDMAC_CHNLPROP_INST_OFFSET,
2224 &chnl_prop);
2225
2226 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002227 codec_dbg(codec, "read CHNLPROP Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002228 return status;
2229 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002230 codec_dbg(codec, "dsp_dma_setup_common() Read CHNLPROP\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002231 }
2232
2233 if (!code)
2234 chnl_prop &= ~(1 << (DSPDMAC_CHNLPROP_MSPCE_LOBIT + dma_chan));
2235 else
2236 chnl_prop |= (1 << (DSPDMAC_CHNLPROP_MSPCE_LOBIT + dma_chan));
2237
2238 chnl_prop &= ~(1 << (DSPDMAC_CHNLPROP_DCON_LOBIT + dma_chan));
2239
2240 status = chipio_write(codec, DSPDMAC_CHNLPROP_INST_OFFSET, chnl_prop);
2241 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002242 codec_dbg(codec, "write CHNLPROP Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002243 return status;
2244 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002245 codec_dbg(codec, " dsp_dma_setup_common() Write CHNLPROP\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002246
2247 if (ovly) {
2248 status = chipio_read(codec, DSPDMAC_ACTIVE_INST_OFFSET,
2249 &active);
2250
2251 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002252 codec_dbg(codec, "read ACTIVE Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002253 return status;
2254 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002255 codec_dbg(codec, "dsp_dma_setup_common() Read ACTIVE\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002256 }
2257
2258 active &= (~(1 << (DSPDMAC_ACTIVE_AAR_LOBIT + dma_chan))) &
2259 DSPDMAC_ACTIVE_AAR_MASK;
2260
2261 status = chipio_write(codec, DSPDMAC_ACTIVE_INST_OFFSET, active);
2262 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002263 codec_dbg(codec, "write ACTIVE Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002264 return status;
2265 }
2266
Takashi Iwai4e76a882014-02-25 12:21:03 +01002267 codec_dbg(codec, " dsp_dma_setup_common() Write ACTIVE\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002268
2269 status = chipio_write(codec, DSPDMAC_AUDCHSEL_INST_OFFSET(dma_chan),
2270 port_map_mask);
2271 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002272 codec_dbg(codec, "write AUDCHSEL Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002273 return status;
2274 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002275 codec_dbg(codec, " dsp_dma_setup_common() Write AUDCHSEL\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002276
2277 status = chipio_write(codec, DSPDMAC_IRQCNT_INST_OFFSET(dma_chan),
2278 DSPDMAC_IRQCNT_BICNT_MASK | DSPDMAC_IRQCNT_CICNT_MASK);
2279 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002280 codec_dbg(codec, "write IRQCNT Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002281 return status;
2282 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002283 codec_dbg(codec, " dsp_dma_setup_common() Write IRQCNT\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002284
Takashi Iwai4e76a882014-02-25 12:21:03 +01002285 codec_dbg(codec,
Ian Minett01ef7db2012-09-20 20:29:16 -07002286 "ChipA=0x%x,DspA=0x%x,dmaCh=%u, "
2287 "CHSEL=0x%x,CHPROP=0x%x,Active=0x%x\n",
2288 chip_addx, dsp_addx, dma_chan,
2289 port_map_mask, chnl_prop, active);
2290
Takashi Iwai4e76a882014-02-25 12:21:03 +01002291 codec_dbg(codec, "-- dsp_dma_setup_common() -- Complete ------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002292
2293 return 0;
2294}
2295
Ian Minettd5c21b82012-09-20 20:29:18 -07002296/*
2297 * Setup the DSP DMA per-transfer-specific registers
2298 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002299static int dsp_dma_setup(struct hda_codec *codec,
2300 unsigned int chip_addx,
2301 unsigned int count,
2302 unsigned int dma_chan)
2303{
2304 int status = 0;
2305 bool code, yram;
2306 unsigned int dsp_addx;
2307 unsigned int addr_field;
2308 unsigned int incr_field;
2309 unsigned int base_cnt;
2310 unsigned int cur_cnt;
2311 unsigned int dma_cfg = 0;
2312 unsigned int adr_ofs = 0;
2313 unsigned int xfr_cnt = 0;
2314 const unsigned int max_dma_count = 1 << (DSPDMAC_XFRCNT_BCNT_HIBIT -
2315 DSPDMAC_XFRCNT_BCNT_LOBIT + 1);
2316
Takashi Iwai4e76a882014-02-25 12:21:03 +01002317 codec_dbg(codec, "-- dsp_dma_setup() -- Begin ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002318
2319 if (count > max_dma_count) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002320 codec_dbg(codec, "count too big\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002321 return -EINVAL;
2322 }
2323
2324 dsp_addx = dsp_chip_to_dsp_addx(chip_addx, &code, &yram);
2325 if (dsp_addx == INVALID_CHIP_ADDRESS) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002326 codec_dbg(codec, "invalid chip addr\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002327 return -ENXIO;
2328 }
2329
Takashi Iwai4e76a882014-02-25 12:21:03 +01002330 codec_dbg(codec, " dsp_dma_setup() start reg pgm\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002331
2332 addr_field = dsp_addx << DSPDMAC_DMACFG_DBADR_LOBIT;
2333 incr_field = 0;
2334
2335 if (!code) {
2336 addr_field <<= 1;
2337 if (yram)
2338 addr_field |= (1 << DSPDMAC_DMACFG_DBADR_LOBIT);
2339
2340 incr_field = (1 << DSPDMAC_DMACFG_AINCR_LOBIT);
2341 }
2342
2343 dma_cfg = addr_field + incr_field;
2344 status = chipio_write(codec, DSPDMAC_DMACFG_INST_OFFSET(dma_chan),
2345 dma_cfg);
2346 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002347 codec_dbg(codec, "write DMACFG Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002348 return status;
2349 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002350 codec_dbg(codec, " dsp_dma_setup() Write DMACFG\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002351
2352 adr_ofs = (count - 1) << (DSPDMAC_DSPADROFS_BOFS_LOBIT +
2353 (code ? 0 : 1));
2354
2355 status = chipio_write(codec, DSPDMAC_DSPADROFS_INST_OFFSET(dma_chan),
2356 adr_ofs);
2357 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002358 codec_dbg(codec, "write DSPADROFS Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002359 return status;
2360 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002361 codec_dbg(codec, " dsp_dma_setup() Write DSPADROFS\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002362
2363 base_cnt = (count - 1) << DSPDMAC_XFRCNT_BCNT_LOBIT;
2364
2365 cur_cnt = (count - 1) << DSPDMAC_XFRCNT_CCNT_LOBIT;
2366
2367 xfr_cnt = base_cnt | cur_cnt;
2368
2369 status = chipio_write(codec,
2370 DSPDMAC_XFRCNT_INST_OFFSET(dma_chan), xfr_cnt);
2371 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002372 codec_dbg(codec, "write XFRCNT Reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002373 return status;
2374 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002375 codec_dbg(codec, " dsp_dma_setup() Write XFRCNT\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002376
Takashi Iwai4e76a882014-02-25 12:21:03 +01002377 codec_dbg(codec,
Ian Minett01ef7db2012-09-20 20:29:16 -07002378 "ChipA=0x%x, cnt=0x%x, DMACFG=0x%x, "
2379 "ADROFS=0x%x, XFRCNT=0x%x\n",
2380 chip_addx, count, dma_cfg, adr_ofs, xfr_cnt);
2381
Takashi Iwai4e76a882014-02-25 12:21:03 +01002382 codec_dbg(codec, "-- dsp_dma_setup() -- Complete ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002383
2384 return 0;
2385}
2386
Ian Minettd5c21b82012-09-20 20:29:18 -07002387/*
2388 * Start the DSP DMA
2389 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002390static int dsp_dma_start(struct hda_codec *codec,
2391 unsigned int dma_chan, bool ovly)
2392{
2393 unsigned int reg = 0;
2394 int status = 0;
2395
Takashi Iwai4e76a882014-02-25 12:21:03 +01002396 codec_dbg(codec, "-- dsp_dma_start() -- Begin ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002397
2398 if (ovly) {
2399 status = chipio_read(codec,
2400 DSPDMAC_CHNLSTART_INST_OFFSET, &reg);
2401
2402 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002403 codec_dbg(codec, "read CHNLSTART reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002404 return status;
2405 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002406 codec_dbg(codec, "-- dsp_dma_start() Read CHNLSTART\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002407
2408 reg &= ~(DSPDMAC_CHNLSTART_EN_MASK |
2409 DSPDMAC_CHNLSTART_DIS_MASK);
2410 }
2411
2412 status = chipio_write(codec, DSPDMAC_CHNLSTART_INST_OFFSET,
2413 reg | (1 << (dma_chan + DSPDMAC_CHNLSTART_EN_LOBIT)));
2414 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002415 codec_dbg(codec, "write CHNLSTART reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002416 return status;
2417 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002418 codec_dbg(codec, "-- dsp_dma_start() -- Complete ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002419
2420 return status;
2421}
2422
Ian Minettd5c21b82012-09-20 20:29:18 -07002423/*
2424 * Stop the DSP DMA
2425 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002426static int dsp_dma_stop(struct hda_codec *codec,
2427 unsigned int dma_chan, bool ovly)
2428{
2429 unsigned int reg = 0;
2430 int status = 0;
2431
Takashi Iwai4e76a882014-02-25 12:21:03 +01002432 codec_dbg(codec, "-- dsp_dma_stop() -- Begin ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002433
2434 if (ovly) {
2435 status = chipio_read(codec,
2436 DSPDMAC_CHNLSTART_INST_OFFSET, &reg);
2437
2438 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002439 codec_dbg(codec, "read CHNLSTART reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002440 return status;
2441 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002442 codec_dbg(codec, "-- dsp_dma_stop() Read CHNLSTART\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002443 reg &= ~(DSPDMAC_CHNLSTART_EN_MASK |
2444 DSPDMAC_CHNLSTART_DIS_MASK);
2445 }
2446
2447 status = chipio_write(codec, DSPDMAC_CHNLSTART_INST_OFFSET,
2448 reg | (1 << (dma_chan + DSPDMAC_CHNLSTART_DIS_LOBIT)));
2449 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002450 codec_dbg(codec, "write CHNLSTART reg fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002451 return status;
2452 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002453 codec_dbg(codec, "-- dsp_dma_stop() -- Complete ---------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002454
2455 return status;
2456}
2457
Ian Minettd5c21b82012-09-20 20:29:18 -07002458/**
2459 * Allocate router ports
2460 *
2461 * @codec: the HDA codec
2462 * @num_chans: number of channels in the stream
2463 * @ports_per_channel: number of ports per channel
2464 * @start_device: start device
2465 * @port_map: pointer to the port list to hold the allocated ports
2466 *
2467 * Returns zero or a negative error code.
2468 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002469static int dsp_allocate_router_ports(struct hda_codec *codec,
2470 unsigned int num_chans,
2471 unsigned int ports_per_channel,
2472 unsigned int start_device,
2473 unsigned int *port_map)
2474{
2475 int status = 0;
2476 int res;
2477 u8 val;
2478
2479 status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
2480 if (status < 0)
2481 return status;
2482
2483 val = start_device << 6;
2484 val |= (ports_per_channel - 1) << 4;
2485 val |= num_chans - 1;
2486
2487 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
2488 VENDOR_CHIPIO_PORT_ALLOC_CONFIG_SET,
2489 val);
2490
2491 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
2492 VENDOR_CHIPIO_PORT_ALLOC_SET,
2493 MEM_CONNID_DSP);
2494
2495 status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
2496 if (status < 0)
2497 return status;
2498
2499 res = snd_hda_codec_read(codec, WIDGET_CHIP_CTRL, 0,
2500 VENDOR_CHIPIO_PORT_ALLOC_GET, 0);
2501
2502 *port_map = res;
2503
2504 return (res < 0) ? res : 0;
2505}
2506
Ian Minettd5c21b82012-09-20 20:29:18 -07002507/*
2508 * Free router ports
2509 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002510static int dsp_free_router_ports(struct hda_codec *codec)
2511{
2512 int status = 0;
2513
2514 status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
2515 if (status < 0)
2516 return status;
2517
2518 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
2519 VENDOR_CHIPIO_PORT_FREE_SET,
2520 MEM_CONNID_DSP);
2521
2522 status = chipio_send(codec, VENDOR_CHIPIO_STATUS, 0);
2523
2524 return status;
2525}
2526
Ian Minettd5c21b82012-09-20 20:29:18 -07002527/*
2528 * Allocate DSP ports for the download stream
2529 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002530static int dsp_allocate_ports(struct hda_codec *codec,
2531 unsigned int num_chans,
2532 unsigned int rate_multi, unsigned int *port_map)
2533{
2534 int status;
2535
Takashi Iwai4e76a882014-02-25 12:21:03 +01002536 codec_dbg(codec, " dsp_allocate_ports() -- begin\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002537
2538 if ((rate_multi != 1) && (rate_multi != 2) && (rate_multi != 4)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002539 codec_dbg(codec, "bad rate multiple\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002540 return -EINVAL;
2541 }
2542
2543 status = dsp_allocate_router_ports(codec, num_chans,
2544 rate_multi, 0, port_map);
2545
Takashi Iwai4e76a882014-02-25 12:21:03 +01002546 codec_dbg(codec, " dsp_allocate_ports() -- complete\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002547
2548 return status;
2549}
2550
Ian Minett01ef7db2012-09-20 20:29:16 -07002551static int dsp_allocate_ports_format(struct hda_codec *codec,
2552 const unsigned short fmt,
2553 unsigned int *port_map)
2554{
2555 int status;
2556 unsigned int num_chans;
2557
2558 unsigned int sample_rate_div = ((get_hdafmt_rate(fmt) >> 0) & 3) + 1;
2559 unsigned int sample_rate_mul = ((get_hdafmt_rate(fmt) >> 3) & 3) + 1;
2560 unsigned int rate_multi = sample_rate_mul / sample_rate_div;
2561
2562 if ((rate_multi != 1) && (rate_multi != 2) && (rate_multi != 4)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002563 codec_dbg(codec, "bad rate multiple\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002564 return -EINVAL;
2565 }
2566
2567 num_chans = get_hdafmt_chs(fmt) + 1;
2568
2569 status = dsp_allocate_ports(codec, num_chans, rate_multi, port_map);
2570
2571 return status;
2572}
2573
2574/*
Ian Minettd5c21b82012-09-20 20:29:18 -07002575 * free DSP ports
2576 */
2577static int dsp_free_ports(struct hda_codec *codec)
2578{
2579 int status;
2580
Takashi Iwai4e76a882014-02-25 12:21:03 +01002581 codec_dbg(codec, " dsp_free_ports() -- begin\n");
Ian Minettd5c21b82012-09-20 20:29:18 -07002582
2583 status = dsp_free_router_ports(codec);
2584 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002585 codec_dbg(codec, "free router ports fail\n");
Ian Minettd5c21b82012-09-20 20:29:18 -07002586 return status;
2587 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01002588 codec_dbg(codec, " dsp_free_ports() -- complete\n");
Ian Minettd5c21b82012-09-20 20:29:18 -07002589
2590 return status;
2591}
2592
2593/*
Ian Minett01ef7db2012-09-20 20:29:16 -07002594 * HDA DMA engine stuffs for DSP code download
2595 */
2596struct dma_engine {
2597 struct hda_codec *codec;
2598 unsigned short m_converter_format;
2599 struct snd_dma_buffer *dmab;
2600 unsigned int buf_size;
2601};
2602
2603
2604enum dma_state {
2605 DMA_STATE_STOP = 0,
2606 DMA_STATE_RUN = 1
2607};
2608
Takashi Iwai6194b992014-06-06 18:12:16 +02002609static int dma_convert_to_hda_format(struct hda_codec *codec,
Ian Minette97249d2012-09-20 20:29:21 -07002610 unsigned int sample_rate,
2611 unsigned short channels,
Ian Minett01ef7db2012-09-20 20:29:16 -07002612 unsigned short *hda_format)
2613{
2614 unsigned int format_val;
2615
Takashi Iwaib7d023e2015-04-16 08:19:06 +02002616 format_val = snd_hdac_calc_stream_format(sample_rate,
2617 channels, SNDRV_PCM_FORMAT_S32_LE, 32, 0);
Ian Minett01ef7db2012-09-20 20:29:16 -07002618
2619 if (hda_format)
2620 *hda_format = (unsigned short)format_val;
2621
2622 return 0;
2623}
2624
Ian Minettd5c21b82012-09-20 20:29:18 -07002625/*
2626 * Reset DMA for DSP download
2627 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002628static int dma_reset(struct dma_engine *dma)
2629{
2630 struct hda_codec *codec = dma->codec;
2631 struct ca0132_spec *spec = codec->spec;
2632 int status;
2633
Takashi Iwaib3667bd2013-02-10 11:58:40 +01002634 if (dma->dmab->area)
Ian Minett01ef7db2012-09-20 20:29:16 -07002635 snd_hda_codec_load_dsp_cleanup(codec, dma->dmab);
2636
2637 status = snd_hda_codec_load_dsp_prepare(codec,
2638 dma->m_converter_format,
2639 dma->buf_size,
2640 dma->dmab);
2641 if (status < 0)
2642 return status;
2643 spec->dsp_stream_id = status;
2644 return 0;
2645}
2646
2647static int dma_set_state(struct dma_engine *dma, enum dma_state state)
2648{
2649 bool cmd;
2650
Ian Minett01ef7db2012-09-20 20:29:16 -07002651 switch (state) {
2652 case DMA_STATE_STOP:
2653 cmd = false;
2654 break;
2655 case DMA_STATE_RUN:
2656 cmd = true;
2657 break;
2658 default:
2659 return 0;
2660 }
2661
2662 snd_hda_codec_load_dsp_trigger(dma->codec, cmd);
2663 return 0;
2664}
2665
2666static unsigned int dma_get_buffer_size(struct dma_engine *dma)
2667{
2668 return dma->dmab->bytes;
2669}
2670
2671static unsigned char *dma_get_buffer_addr(struct dma_engine *dma)
2672{
2673 return dma->dmab->area;
2674}
2675
2676static int dma_xfer(struct dma_engine *dma,
2677 const unsigned int *data,
2678 unsigned int count)
2679{
2680 memcpy(dma->dmab->area, data, count);
2681 return 0;
2682}
2683
2684static void dma_get_converter_format(
2685 struct dma_engine *dma,
2686 unsigned short *format)
2687{
2688 if (format)
2689 *format = dma->m_converter_format;
2690}
2691
2692static unsigned int dma_get_stream_id(struct dma_engine *dma)
2693{
2694 struct ca0132_spec *spec = dma->codec->spec;
2695
2696 return spec->dsp_stream_id;
2697}
2698
2699struct dsp_image_seg {
2700 u32 magic;
2701 u32 chip_addr;
2702 u32 count;
Gustavo A. R. Silva76501952020-02-11 13:44:03 -06002703 u32 data[];
Ian Minett01ef7db2012-09-20 20:29:16 -07002704};
2705
2706static const u32 g_magic_value = 0x4c46584d;
2707static const u32 g_chip_addr_magic_value = 0xFFFFFF01;
2708
2709static bool is_valid(const struct dsp_image_seg *p)
2710{
2711 return p->magic == g_magic_value;
2712}
2713
2714static bool is_hci_prog_list_seg(const struct dsp_image_seg *p)
2715{
2716 return g_chip_addr_magic_value == p->chip_addr;
2717}
2718
2719static bool is_last(const struct dsp_image_seg *p)
2720{
2721 return p->count == 0;
2722}
2723
2724static size_t dsp_sizeof(const struct dsp_image_seg *p)
2725{
Takashi Iwaie046b642019-05-31 11:47:24 +02002726 return struct_size(p, data, p->count);
Ian Minett01ef7db2012-09-20 20:29:16 -07002727}
2728
2729static const struct dsp_image_seg *get_next_seg_ptr(
2730 const struct dsp_image_seg *p)
2731{
2732 return (struct dsp_image_seg *)((unsigned char *)(p) + dsp_sizeof(p));
2733}
2734
2735/*
2736 * CA0132 chip DSP transfer stuffs. For DSP download.
2737 */
Takashi Iwai8ae3124b2013-01-15 17:43:09 +01002738#define INVALID_DMA_CHANNEL (~0U)
Ian Minett01ef7db2012-09-20 20:29:16 -07002739
Ian Minettd5c21b82012-09-20 20:29:18 -07002740/*
2741 * Program a list of address/data pairs via the ChipIO widget.
2742 * The segment data is in the format of successive pairs of words.
2743 * These are repeated as indicated by the segment's count field.
2744 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002745static int dspxfr_hci_write(struct hda_codec *codec,
2746 const struct dsp_image_seg *fls)
2747{
2748 int status;
2749 const u32 *data;
2750 unsigned int count;
2751
2752 if (fls == NULL || fls->chip_addr != g_chip_addr_magic_value) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002753 codec_dbg(codec, "hci_write invalid params\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002754 return -EINVAL;
2755 }
2756
2757 count = fls->count;
2758 data = (u32 *)(fls->data);
2759 while (count >= 2) {
2760 status = chipio_write(codec, data[0], data[1]);
2761 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002762 codec_dbg(codec, "hci_write chipio failed\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002763 return status;
2764 }
2765 count -= 2;
2766 data += 2;
2767 }
2768 return 0;
2769}
2770
Ian Minettd5c21b82012-09-20 20:29:18 -07002771/**
2772 * Write a block of data into DSP code or data RAM using pre-allocated
2773 * DMA engine.
2774 *
2775 * @codec: the HDA codec
2776 * @fls: pointer to a fast load image
2777 * @reloc: Relocation address for loading single-segment overlays, or 0 for
2778 * no relocation
2779 * @dma_engine: pointer to DMA engine to be used for DSP download
2780 * @dma_chan: The number of DMA channels used for DSP download
2781 * @port_map_mask: port mapping
2782 * @ovly: TRUE if overlay format is required
2783 *
2784 * Returns zero or a negative error code.
2785 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002786static int dspxfr_one_seg(struct hda_codec *codec,
2787 const struct dsp_image_seg *fls,
2788 unsigned int reloc,
2789 struct dma_engine *dma_engine,
2790 unsigned int dma_chan,
2791 unsigned int port_map_mask,
2792 bool ovly)
2793{
Ian Minett406261c2012-12-20 18:53:41 -08002794 int status = 0;
Ian Minett01ef7db2012-09-20 20:29:16 -07002795 bool comm_dma_setup_done = false;
2796 const unsigned int *data;
2797 unsigned int chip_addx;
2798 unsigned int words_to_write;
2799 unsigned int buffer_size_words;
2800 unsigned char *buffer_addx;
2801 unsigned short hda_format;
2802 unsigned int sample_rate_div;
2803 unsigned int sample_rate_mul;
2804 unsigned int num_chans;
2805 unsigned int hda_frame_size_words;
2806 unsigned int remainder_words;
2807 const u32 *data_remainder;
2808 u32 chip_addx_remainder;
2809 unsigned int run_size_words;
2810 const struct dsp_image_seg *hci_write = NULL;
Ian Minett6d675302013-02-08 18:31:43 -08002811 unsigned long timeout;
2812 bool dma_active;
Ian Minett01ef7db2012-09-20 20:29:16 -07002813
2814 if (fls == NULL)
2815 return -EINVAL;
2816 if (is_hci_prog_list_seg(fls)) {
2817 hci_write = fls;
2818 fls = get_next_seg_ptr(fls);
2819 }
2820
2821 if (hci_write && (!fls || is_last(fls))) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002822 codec_dbg(codec, "hci_write\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002823 return dspxfr_hci_write(codec, hci_write);
2824 }
2825
2826 if (fls == NULL || dma_engine == NULL || port_map_mask == 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002827 codec_dbg(codec, "Invalid Params\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002828 return -EINVAL;
2829 }
2830
2831 data = fls->data;
2832 chip_addx = fls->chip_addr,
2833 words_to_write = fls->count;
2834
2835 if (!words_to_write)
2836 return hci_write ? dspxfr_hci_write(codec, hci_write) : 0;
2837 if (reloc)
2838 chip_addx = (chip_addx & (0xFFFF0000 << 2)) + (reloc << 2);
2839
2840 if (!UC_RANGE(chip_addx, words_to_write) &&
2841 !X_RANGE_ALL(chip_addx, words_to_write) &&
2842 !Y_RANGE_ALL(chip_addx, words_to_write)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002843 codec_dbg(codec, "Invalid chip_addx Params\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002844 return -EINVAL;
2845 }
2846
2847 buffer_size_words = (unsigned int)dma_get_buffer_size(dma_engine) /
2848 sizeof(u32);
2849
2850 buffer_addx = dma_get_buffer_addr(dma_engine);
2851
2852 if (buffer_addx == NULL) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002853 codec_dbg(codec, "dma_engine buffer NULL\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002854 return -EINVAL;
2855 }
2856
2857 dma_get_converter_format(dma_engine, &hda_format);
2858 sample_rate_div = ((get_hdafmt_rate(hda_format) >> 0) & 3) + 1;
2859 sample_rate_mul = ((get_hdafmt_rate(hda_format) >> 3) & 3) + 1;
2860 num_chans = get_hdafmt_chs(hda_format) + 1;
2861
2862 hda_frame_size_words = ((sample_rate_div == 0) ? 0 :
2863 (num_chans * sample_rate_mul / sample_rate_div));
2864
Xi Wang3bc085a2013-03-07 00:13:51 -05002865 if (hda_frame_size_words == 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002866 codec_dbg(codec, "frmsz zero\n");
Xi Wang3bc085a2013-03-07 00:13:51 -05002867 return -EINVAL;
2868 }
2869
Ian Minett01ef7db2012-09-20 20:29:16 -07002870 buffer_size_words = min(buffer_size_words,
2871 (unsigned int)(UC_RANGE(chip_addx, 1) ?
2872 65536 : 32768));
2873 buffer_size_words -= buffer_size_words % hda_frame_size_words;
Takashi Iwai4e76a882014-02-25 12:21:03 +01002874 codec_dbg(codec,
Ian Minett01ef7db2012-09-20 20:29:16 -07002875 "chpadr=0x%08x frmsz=%u nchan=%u "
2876 "rate_mul=%u div=%u bufsz=%u\n",
2877 chip_addx, hda_frame_size_words, num_chans,
2878 sample_rate_mul, sample_rate_div, buffer_size_words);
2879
Xi Wang3bc085a2013-03-07 00:13:51 -05002880 if (buffer_size_words < hda_frame_size_words) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002881 codec_dbg(codec, "dspxfr_one_seg:failed\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002882 return -EINVAL;
2883 }
2884
2885 remainder_words = words_to_write % hda_frame_size_words;
2886 data_remainder = data;
2887 chip_addx_remainder = chip_addx;
2888
2889 data += remainder_words;
2890 chip_addx += remainder_words*sizeof(u32);
2891 words_to_write -= remainder_words;
2892
2893 while (words_to_write != 0) {
2894 run_size_words = min(buffer_size_words, words_to_write);
Takashi Iwai4e76a882014-02-25 12:21:03 +01002895 codec_dbg(codec, "dspxfr (seg loop)cnt=%u rs=%u remainder=%u\n",
Ian Minett01ef7db2012-09-20 20:29:16 -07002896 words_to_write, run_size_words, remainder_words);
2897 dma_xfer(dma_engine, data, run_size_words*sizeof(u32));
2898 if (!comm_dma_setup_done) {
2899 status = dsp_dma_stop(codec, dma_chan, ovly);
2900 if (status < 0)
Takashi Iwai425a7882013-01-15 17:41:21 +01002901 return status;
Ian Minett01ef7db2012-09-20 20:29:16 -07002902 status = dsp_dma_setup_common(codec, chip_addx,
2903 dma_chan, port_map_mask, ovly);
2904 if (status < 0)
2905 return status;
2906 comm_dma_setup_done = true;
2907 }
2908
2909 status = dsp_dma_setup(codec, chip_addx,
2910 run_size_words, dma_chan);
2911 if (status < 0)
2912 return status;
2913 status = dsp_dma_start(codec, dma_chan, ovly);
2914 if (status < 0)
2915 return status;
2916 if (!dsp_is_dma_active(codec, dma_chan)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01002917 codec_dbg(codec, "dspxfr:DMA did not start\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002918 return -EIO;
2919 }
2920 status = dma_set_state(dma_engine, DMA_STATE_RUN);
2921 if (status < 0)
2922 return status;
2923 if (remainder_words != 0) {
2924 status = chipio_write_multiple(codec,
2925 chip_addx_remainder,
2926 data_remainder,
2927 remainder_words);
Takashi Iwaib3667bd2013-02-10 11:58:40 +01002928 if (status < 0)
2929 return status;
Ian Minett01ef7db2012-09-20 20:29:16 -07002930 remainder_words = 0;
2931 }
2932 if (hci_write) {
2933 status = dspxfr_hci_write(codec, hci_write);
Takashi Iwaib3667bd2013-02-10 11:58:40 +01002934 if (status < 0)
2935 return status;
Ian Minett01ef7db2012-09-20 20:29:16 -07002936 hci_write = NULL;
2937 }
Ian Minett6d675302013-02-08 18:31:43 -08002938
2939 timeout = jiffies + msecs_to_jiffies(2000);
2940 do {
2941 dma_active = dsp_is_dma_active(codec, dma_chan);
2942 if (!dma_active)
Ian Minett01ef7db2012-09-20 20:29:16 -07002943 break;
Ian Minett6d675302013-02-08 18:31:43 -08002944 msleep(20);
2945 } while (time_before(jiffies, timeout));
2946 if (dma_active)
2947 break;
2948
Takashi Iwai4e76a882014-02-25 12:21:03 +01002949 codec_dbg(codec, "+++++ DMA complete\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07002950 dma_set_state(dma_engine, DMA_STATE_STOP);
Takashi Iwaib3667bd2013-02-10 11:58:40 +01002951 status = dma_reset(dma_engine);
Ian Minett01ef7db2012-09-20 20:29:16 -07002952
2953 if (status < 0)
2954 return status;
2955
2956 data += run_size_words;
2957 chip_addx += run_size_words*sizeof(u32);
2958 words_to_write -= run_size_words;
2959 }
2960
2961 if (remainder_words != 0) {
2962 status = chipio_write_multiple(codec, chip_addx_remainder,
2963 data_remainder, remainder_words);
2964 }
2965
2966 return status;
2967}
2968
Ian Minettd5c21b82012-09-20 20:29:18 -07002969/**
2970 * Write the entire DSP image of a DSP code/data overlay to DSP memories
2971 *
2972 * @codec: the HDA codec
2973 * @fls_data: pointer to a fast load image
2974 * @reloc: Relocation address for loading single-segment overlays, or 0 for
2975 * no relocation
Ian Minette97249d2012-09-20 20:29:21 -07002976 * @sample_rate: sampling rate of the stream used for DSP download
Takashi Iwaie60b2c72014-11-10 16:47:26 +01002977 * @channels: channels of the stream used for DSP download
Ian Minettd5c21b82012-09-20 20:29:18 -07002978 * @ovly: TRUE if overlay format is required
2979 *
2980 * Returns zero or a negative error code.
2981 */
Ian Minett01ef7db2012-09-20 20:29:16 -07002982static int dspxfr_image(struct hda_codec *codec,
2983 const struct dsp_image_seg *fls_data,
Ian Minette97249d2012-09-20 20:29:21 -07002984 unsigned int reloc,
2985 unsigned int sample_rate,
2986 unsigned short channels,
Ian Minett01ef7db2012-09-20 20:29:16 -07002987 bool ovly)
2988{
2989 struct ca0132_spec *spec = codec->spec;
2990 int status;
2991 unsigned short hda_format = 0;
2992 unsigned int response;
2993 unsigned char stream_id = 0;
2994 struct dma_engine *dma_engine;
2995 unsigned int dma_chan;
2996 unsigned int port_map_mask;
2997
2998 if (fls_data == NULL)
2999 return -EINVAL;
3000
3001 dma_engine = kzalloc(sizeof(*dma_engine), GFP_KERNEL);
Takashi Iwai549e8292013-01-15 17:42:15 +01003002 if (!dma_engine)
3003 return -ENOMEM;
Ian Minett01ef7db2012-09-20 20:29:16 -07003004
3005 dma_engine->dmab = kzalloc(sizeof(*dma_engine->dmab), GFP_KERNEL);
3006 if (!dma_engine->dmab) {
Takashi Iwai549e8292013-01-15 17:42:15 +01003007 kfree(dma_engine);
3008 return -ENOMEM;
Ian Minett01ef7db2012-09-20 20:29:16 -07003009 }
3010
3011 dma_engine->codec = codec;
Takashi Iwai6194b992014-06-06 18:12:16 +02003012 dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format);
Ian Minett01ef7db2012-09-20 20:29:16 -07003013 dma_engine->m_converter_format = hda_format;
3014 dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY :
3015 DSP_DMA_WRITE_BUFLEN_INIT) * 2;
3016
Takashi Iwai8ae3124b2013-01-15 17:43:09 +01003017 dma_chan = ovly ? INVALID_DMA_CHANNEL : 0;
Ian Minett01ef7db2012-09-20 20:29:16 -07003018
3019 status = codec_set_converter_format(codec, WIDGET_CHIP_CTRL,
3020 hda_format, &response);
3021
3022 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01003023 codec_dbg(codec, "set converter format fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003024 goto exit;
3025 }
3026
3027 status = snd_hda_codec_load_dsp_prepare(codec,
3028 dma_engine->m_converter_format,
3029 dma_engine->buf_size,
3030 dma_engine->dmab);
3031 if (status < 0)
3032 goto exit;
3033 spec->dsp_stream_id = status;
3034
3035 if (ovly) {
3036 status = dspio_alloc_dma_chan(codec, &dma_chan);
3037 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01003038 codec_dbg(codec, "alloc dmachan fail\n");
Takashi Iwai8ae3124b2013-01-15 17:43:09 +01003039 dma_chan = INVALID_DMA_CHANNEL;
Ian Minett01ef7db2012-09-20 20:29:16 -07003040 goto exit;
3041 }
3042 }
3043
3044 port_map_mask = 0;
3045 status = dsp_allocate_ports_format(codec, hda_format,
3046 &port_map_mask);
3047 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01003048 codec_dbg(codec, "alloc ports fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003049 goto exit;
3050 }
3051
3052 stream_id = dma_get_stream_id(dma_engine);
3053 status = codec_set_converter_stream_channel(codec,
3054 WIDGET_CHIP_CTRL, stream_id, 0, &response);
3055 if (status < 0) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01003056 codec_dbg(codec, "set stream chan fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003057 goto exit;
3058 }
3059
3060 while ((fls_data != NULL) && !is_last(fls_data)) {
3061 if (!is_valid(fls_data)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01003062 codec_dbg(codec, "FLS check fail\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003063 status = -EINVAL;
3064 goto exit;
3065 }
3066 status = dspxfr_one_seg(codec, fls_data, reloc,
3067 dma_engine, dma_chan,
3068 port_map_mask, ovly);
3069 if (status < 0)
3070 break;
3071
3072 if (is_hci_prog_list_seg(fls_data))
3073 fls_data = get_next_seg_ptr(fls_data);
3074
3075 if ((fls_data != NULL) && !is_last(fls_data))
3076 fls_data = get_next_seg_ptr(fls_data);
3077 }
3078
3079 if (port_map_mask != 0)
3080 status = dsp_free_ports(codec);
3081
3082 if (status < 0)
3083 goto exit;
3084
3085 status = codec_set_converter_stream_channel(codec,
3086 WIDGET_CHIP_CTRL, 0, 0, &response);
3087
3088exit:
3089 if (ovly && (dma_chan != INVALID_DMA_CHANNEL))
3090 dspio_free_dma_chan(codec, dma_chan);
3091
Takashi Iwaib3667bd2013-02-10 11:58:40 +01003092 if (dma_engine->dmab->area)
Ian Minett01ef7db2012-09-20 20:29:16 -07003093 snd_hda_codec_load_dsp_cleanup(codec, dma_engine->dmab);
3094 kfree(dma_engine->dmab);
3095 kfree(dma_engine);
3096
3097 return status;
3098}
3099
3100/*
3101 * CA0132 DSP download stuffs.
3102 */
3103static void dspload_post_setup(struct hda_codec *codec)
3104{
Connor McAdams009b8f92018-05-08 13:20:06 -04003105 struct ca0132_spec *spec = codec->spec;
Takashi Iwai4e76a882014-02-25 12:21:03 +01003106 codec_dbg(codec, "---- dspload_post_setup ------\n");
Takashi Iwai6da8f442018-11-09 14:18:32 +01003107 if (!ca0132_use_alt_functions(spec)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04003108 /*set DSP speaker to 2.0 configuration*/
3109 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080);
3110 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000);
Ian Minett01ef7db2012-09-20 20:29:16 -07003111
Connor McAdams009b8f92018-05-08 13:20:06 -04003112 /*update write pointer*/
3113 chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x29), 0x00000002);
3114 }
Ian Minett01ef7db2012-09-20 20:29:16 -07003115}
3116
Ian Minettd5c21b82012-09-20 20:29:18 -07003117/**
Takashi Iwaie60b2c72014-11-10 16:47:26 +01003118 * dspload_image - Download DSP from a DSP Image Fast Load structure.
Ian Minettd5c21b82012-09-20 20:29:18 -07003119 *
3120 * @codec: the HDA codec
3121 * @fls: pointer to a fast load image
3122 * @ovly: TRUE if overlay format is required
3123 * @reloc: Relocation address for loading single-segment overlays, or 0 for
3124 * no relocation
3125 * @autostart: TRUE if DSP starts after loading; ignored if ovly is TRUE
3126 * @router_chans: number of audio router channels to be allocated (0 means use
3127 * internal defaults; max is 32)
3128 *
Takashi Iwaie60b2c72014-11-10 16:47:26 +01003129 * Download DSP from a DSP Image Fast Load structure. This structure is a
3130 * linear, non-constant sized element array of structures, each of which
3131 * contain the count of the data to be loaded, the data itself, and the
3132 * corresponding starting chip address of the starting data location.
Ian Minettd5c21b82012-09-20 20:29:18 -07003133 * Returns zero or a negative error code.
3134 */
Ian Minett01ef7db2012-09-20 20:29:16 -07003135static int dspload_image(struct hda_codec *codec,
3136 const struct dsp_image_seg *fls,
3137 bool ovly,
3138 unsigned int reloc,
3139 bool autostart,
3140 int router_chans)
3141{
3142 int status = 0;
Ian Minette97249d2012-09-20 20:29:21 -07003143 unsigned int sample_rate;
3144 unsigned short channels;
Ian Minett01ef7db2012-09-20 20:29:16 -07003145
Takashi Iwai4e76a882014-02-25 12:21:03 +01003146 codec_dbg(codec, "---- dspload_image begin ------\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003147 if (router_chans == 0) {
3148 if (!ovly)
3149 router_chans = DMA_TRANSFER_FRAME_SIZE_NWORDS;
3150 else
3151 router_chans = DMA_OVERLAY_FRAME_SIZE_NWORDS;
3152 }
3153
Ian Minette97249d2012-09-20 20:29:21 -07003154 sample_rate = 48000;
3155 channels = (unsigned short)router_chans;
Ian Minett01ef7db2012-09-20 20:29:16 -07003156
Ian Minette97249d2012-09-20 20:29:21 -07003157 while (channels > 16) {
3158 sample_rate *= 2;
3159 channels /= 2;
Ian Minett01ef7db2012-09-20 20:29:16 -07003160 }
3161
Ian Minett01ef7db2012-09-20 20:29:16 -07003162 do {
Takashi Iwai4e76a882014-02-25 12:21:03 +01003163 codec_dbg(codec, "Ready to program DMA\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003164 if (!ovly)
3165 status = dsp_reset(codec);
3166
3167 if (status < 0)
3168 break;
3169
Takashi Iwai4e76a882014-02-25 12:21:03 +01003170 codec_dbg(codec, "dsp_reset() complete\n");
Ian Minette97249d2012-09-20 20:29:21 -07003171 status = dspxfr_image(codec, fls, reloc, sample_rate, channels,
3172 ovly);
Ian Minett01ef7db2012-09-20 20:29:16 -07003173
3174 if (status < 0)
3175 break;
3176
Takashi Iwai4e76a882014-02-25 12:21:03 +01003177 codec_dbg(codec, "dspxfr_image() complete\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003178 if (autostart && !ovly) {
3179 dspload_post_setup(codec);
3180 status = dsp_set_run_state(codec);
3181 }
3182
Takashi Iwai4e76a882014-02-25 12:21:03 +01003183 codec_dbg(codec, "LOAD FINISHED\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003184 } while (0);
3185
3186 return status;
3187}
3188
Takashi Iwaif6644172013-02-11 14:18:29 +01003189#ifdef CONFIG_SND_HDA_CODEC_CA0132_DSP
Ian Minett01ef7db2012-09-20 20:29:16 -07003190static bool dspload_is_loaded(struct hda_codec *codec)
3191{
3192 unsigned int data = 0;
3193 int status = 0;
3194
3195 status = chipio_read(codec, 0x40004, &data);
3196 if ((status < 0) || (data != 1))
3197 return false;
3198
3199 return true;
3200}
Takashi Iwaif6644172013-02-11 14:18:29 +01003201#else
3202#define dspload_is_loaded(codec) false
3203#endif
Ian Minett01ef7db2012-09-20 20:29:16 -07003204
3205static bool dspload_wait_loaded(struct hda_codec *codec)
3206{
Ian Minett6d675302013-02-08 18:31:43 -08003207 unsigned long timeout = jiffies + msecs_to_jiffies(2000);
Ian Minett01ef7db2012-09-20 20:29:16 -07003208
3209 do {
Ian Minett01ef7db2012-09-20 20:29:16 -07003210 if (dspload_is_loaded(codec)) {
Takashi Iwaid9684bb2015-10-26 16:54:16 +01003211 codec_info(codec, "ca0132 DSP downloaded and running\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003212 return true;
3213 }
Ian Minett6d675302013-02-08 18:31:43 -08003214 msleep(20);
3215 } while (time_before(jiffies, timeout));
Ian Minett01ef7db2012-09-20 20:29:16 -07003216
Takashi Iwaid9684bb2015-10-26 16:54:16 +01003217 codec_err(codec, "ca0132 failed to download DSP\n");
Ian Minett01ef7db2012-09-20 20:29:16 -07003218 return false;
3219}
3220
Ian Minett5aaca442012-12-20 18:53:34 -08003221/*
Connor McAdamsb9b41342018-09-18 14:33:34 -04003222 * ca0113 related functions. The ca0113 acts as the HDA bus for the pci-e
3223 * based cards, and has a second mmio region, region2, that's used for special
3224 * commands.
Connor McAdamse93ac302018-05-08 13:20:05 -04003225 */
3226
3227/*
Connor McAdamsa62e4732018-08-08 13:34:12 -04003228 * For cards with PCI-E region2 (Sound Blaster Z/ZxR, Recon3D, and AE-5)
3229 * the mmio address 0x320 is used to set GPIO pins. The format for the data
3230 * The first eight bits are just the number of the pin. So far, I've only seen
3231 * this number go to 7.
Connor McAdamsb9b41342018-09-18 14:33:34 -04003232 * AE-5 note: The AE-5 seems to use pins 2 and 3 to somehow set the color value
3233 * of the on-card LED. It seems to use pin 2 for data, then toggles 3 to on and
3234 * then off to send that bit.
Connor McAdamsa62e4732018-08-08 13:34:12 -04003235 */
Connor McAdamsb9b41342018-09-18 14:33:34 -04003236static void ca0113_mmio_gpio_set(struct hda_codec *codec, unsigned int gpio_pin,
Connor McAdamsa62e4732018-08-08 13:34:12 -04003237 bool enable)
3238{
3239 struct ca0132_spec *spec = codec->spec;
3240 unsigned short gpio_data;
3241
3242 gpio_data = gpio_pin & 0xF;
3243 gpio_data |= ((enable << 8) & 0x100);
3244
3245 writew(gpio_data, spec->mem_base + 0x320);
3246}
3247
3248/*
Connor McAdamsb9b41342018-09-18 14:33:34 -04003249 * Special pci region2 commands that are only used by the AE-5. They follow
3250 * a set format, and require reads at certain points to seemingly 'clear'
3251 * the response data. My first tests didn't do these reads, and would cause
3252 * the card to get locked up until the memory was read. These commands
3253 * seem to work with three distinct values that I've taken to calling group,
3254 * target-id, and value.
3255 */
3256static void ca0113_mmio_command_set(struct hda_codec *codec, unsigned int group,
3257 unsigned int target, unsigned int value)
3258{
3259 struct ca0132_spec *spec = codec->spec;
3260 unsigned int write_val;
3261
3262 writel(0x0000007e, spec->mem_base + 0x210);
3263 readl(spec->mem_base + 0x210);
3264 writel(0x0000005a, spec->mem_base + 0x210);
3265 readl(spec->mem_base + 0x210);
3266 readl(spec->mem_base + 0x210);
3267
3268 writel(0x00800005, spec->mem_base + 0x20c);
3269 writel(group, spec->mem_base + 0x804);
3270
3271 writel(0x00800005, spec->mem_base + 0x20c);
3272 write_val = (target & 0xff);
3273 write_val |= (value << 8);
3274
3275
3276 writel(write_val, spec->mem_base + 0x204);
3277 /*
3278 * Need delay here or else it goes too fast and works inconsistently.
3279 */
3280 msleep(20);
3281
3282 readl(spec->mem_base + 0x860);
3283 readl(spec->mem_base + 0x854);
3284 readl(spec->mem_base + 0x840);
3285
3286 writel(0x00800004, spec->mem_base + 0x20c);
3287 writel(0x00000000, spec->mem_base + 0x210);
3288 readl(spec->mem_base + 0x210);
3289 readl(spec->mem_base + 0x210);
3290}
3291
3292/*
Connor McAdams212de2e2018-09-18 14:33:42 -04003293 * This second type of command is used for setting the sound filter type.
3294 */
3295static void ca0113_mmio_command_set_type2(struct hda_codec *codec,
3296 unsigned int group, unsigned int target, unsigned int value)
3297{
3298 struct ca0132_spec *spec = codec->spec;
3299 unsigned int write_val;
3300
3301 writel(0x0000007e, spec->mem_base + 0x210);
3302 readl(spec->mem_base + 0x210);
3303 writel(0x0000005a, spec->mem_base + 0x210);
3304 readl(spec->mem_base + 0x210);
3305 readl(spec->mem_base + 0x210);
3306
3307 writel(0x00800003, spec->mem_base + 0x20c);
3308 writel(group, spec->mem_base + 0x804);
3309
3310 writel(0x00800005, spec->mem_base + 0x20c);
3311 write_val = (target & 0xff);
3312 write_val |= (value << 8);
3313
3314
3315 writel(write_val, spec->mem_base + 0x204);
3316 msleep(20);
3317 readl(spec->mem_base + 0x860);
3318 readl(spec->mem_base + 0x854);
3319 readl(spec->mem_base + 0x840);
3320
3321 writel(0x00800004, spec->mem_base + 0x20c);
3322 writel(0x00000000, spec->mem_base + 0x210);
3323 readl(spec->mem_base + 0x210);
3324 readl(spec->mem_base + 0x210);
3325}
3326
3327/*
Connor McAdamsb9b41342018-09-18 14:33:34 -04003328 * Setup GPIO for the other variants of Core3D.
3329 */
3330
3331/*
Connor McAdamse93ac302018-05-08 13:20:05 -04003332 * Sets up the GPIO pins so that they are discoverable. If this isn't done,
3333 * the card shows as having no GPIO pins.
3334 */
3335static void ca0132_gpio_init(struct hda_codec *codec)
3336{
3337 struct ca0132_spec *spec = codec->spec;
3338
Takashi Iwai6da8f442018-11-09 14:18:32 +01003339 switch (ca0132_quirk(spec)) {
Connor McAdamse93ac302018-05-08 13:20:05 -04003340 case QUIRK_SBZ:
Connor McAdams03c9b6b2018-09-18 14:33:35 -04003341 case QUIRK_AE5:
Connor McAdamse93ac302018-05-08 13:20:05 -04003342 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
3343 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
3344 snd_hda_codec_write(codec, 0x01, 0, 0x790, 0x23);
3345 break;
3346 case QUIRK_R3DI:
3347 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
3348 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B);
3349 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01003350 default:
3351 break;
Connor McAdamse93ac302018-05-08 13:20:05 -04003352 }
3353
3354}
3355
3356/* Sets the GPIO for audio output. */
3357static void ca0132_gpio_setup(struct hda_codec *codec)
3358{
3359 struct ca0132_spec *spec = codec->spec;
3360
Takashi Iwai6da8f442018-11-09 14:18:32 +01003361 switch (ca0132_quirk(spec)) {
Connor McAdamse93ac302018-05-08 13:20:05 -04003362 case QUIRK_SBZ:
3363 snd_hda_codec_write(codec, 0x01, 0,
3364 AC_VERB_SET_GPIO_DIRECTION, 0x07);
3365 snd_hda_codec_write(codec, 0x01, 0,
3366 AC_VERB_SET_GPIO_MASK, 0x07);
3367 snd_hda_codec_write(codec, 0x01, 0,
3368 AC_VERB_SET_GPIO_DATA, 0x04);
3369 snd_hda_codec_write(codec, 0x01, 0,
3370 AC_VERB_SET_GPIO_DATA, 0x06);
3371 break;
3372 case QUIRK_R3DI:
3373 snd_hda_codec_write(codec, 0x01, 0,
3374 AC_VERB_SET_GPIO_DIRECTION, 0x1E);
3375 snd_hda_codec_write(codec, 0x01, 0,
3376 AC_VERB_SET_GPIO_MASK, 0x1F);
3377 snd_hda_codec_write(codec, 0x01, 0,
3378 AC_VERB_SET_GPIO_DATA, 0x0C);
3379 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01003380 default:
3381 break;
Connor McAdamse93ac302018-05-08 13:20:05 -04003382 }
3383}
3384
3385/*
Connor McAdams7e6ed622018-05-08 13:20:08 -04003386 * GPIO control functions for the Recon3D integrated.
3387 */
3388
3389enum r3di_gpio_bit {
3390 /* Bit 1 - Switch between front/rear mic. 0 = rear, 1 = front */
3391 R3DI_MIC_SELECT_BIT = 1,
3392 /* Bit 2 - Switch between headphone/line out. 0 = Headphone, 1 = Line */
3393 R3DI_OUT_SELECT_BIT = 2,
3394 /*
3395 * I dunno what this actually does, but it stays on until the dsp
3396 * is downloaded.
3397 */
3398 R3DI_GPIO_DSP_DOWNLOADING = 3,
3399 /*
3400 * Same as above, no clue what it does, but it comes on after the dsp
3401 * is downloaded.
3402 */
3403 R3DI_GPIO_DSP_DOWNLOADED = 4
3404};
3405
3406enum r3di_mic_select {
3407 /* Set GPIO bit 1 to 0 for rear mic */
3408 R3DI_REAR_MIC = 0,
3409 /* Set GPIO bit 1 to 1 for front microphone*/
3410 R3DI_FRONT_MIC = 1
3411};
3412
3413enum r3di_out_select {
3414 /* Set GPIO bit 2 to 0 for headphone */
3415 R3DI_HEADPHONE_OUT = 0,
3416 /* Set GPIO bit 2 to 1 for speaker */
3417 R3DI_LINE_OUT = 1
3418};
3419enum r3di_dsp_status {
3420 /* Set GPIO bit 3 to 1 until DSP is downloaded */
3421 R3DI_DSP_DOWNLOADING = 0,
3422 /* Set GPIO bit 4 to 1 once DSP is downloaded */
3423 R3DI_DSP_DOWNLOADED = 1
3424};
3425
Connor McAdams7cb9d942018-05-08 13:20:10 -04003426
3427static void r3di_gpio_mic_set(struct hda_codec *codec,
3428 enum r3di_mic_select cur_mic)
3429{
3430 unsigned int cur_gpio;
3431
3432 /* Get the current GPIO Data setup */
3433 cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0);
3434
3435 switch (cur_mic) {
3436 case R3DI_REAR_MIC:
3437 cur_gpio &= ~(1 << R3DI_MIC_SELECT_BIT);
3438 break;
3439 case R3DI_FRONT_MIC:
3440 cur_gpio |= (1 << R3DI_MIC_SELECT_BIT);
3441 break;
3442 }
3443 snd_hda_codec_write(codec, codec->core.afg, 0,
3444 AC_VERB_SET_GPIO_DATA, cur_gpio);
3445}
3446
3447static void r3di_gpio_out_set(struct hda_codec *codec,
3448 enum r3di_out_select cur_out)
3449{
3450 unsigned int cur_gpio;
3451
3452 /* Get the current GPIO Data setup */
3453 cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0);
3454
3455 switch (cur_out) {
3456 case R3DI_HEADPHONE_OUT:
3457 cur_gpio &= ~(1 << R3DI_OUT_SELECT_BIT);
3458 break;
3459 case R3DI_LINE_OUT:
3460 cur_gpio |= (1 << R3DI_OUT_SELECT_BIT);
3461 break;
3462 }
3463 snd_hda_codec_write(codec, codec->core.afg, 0,
3464 AC_VERB_SET_GPIO_DATA, cur_gpio);
3465}
3466
Connor McAdams7e6ed622018-05-08 13:20:08 -04003467static void r3di_gpio_dsp_status_set(struct hda_codec *codec,
3468 enum r3di_dsp_status dsp_status)
3469{
3470 unsigned int cur_gpio;
3471
3472 /* Get the current GPIO Data setup */
3473 cur_gpio = snd_hda_codec_read(codec, 0x01, 0, AC_VERB_GET_GPIO_DATA, 0);
3474
3475 switch (dsp_status) {
3476 case R3DI_DSP_DOWNLOADING:
3477 cur_gpio |= (1 << R3DI_GPIO_DSP_DOWNLOADING);
3478 snd_hda_codec_write(codec, codec->core.afg, 0,
3479 AC_VERB_SET_GPIO_DATA, cur_gpio);
3480 break;
3481 case R3DI_DSP_DOWNLOADED:
3482 /* Set DOWNLOADING bit to 0. */
3483 cur_gpio &= ~(1 << R3DI_GPIO_DSP_DOWNLOADING);
3484
3485 snd_hda_codec_write(codec, codec->core.afg, 0,
3486 AC_VERB_SET_GPIO_DATA, cur_gpio);
3487
3488 cur_gpio |= (1 << R3DI_GPIO_DSP_DOWNLOADED);
3489 break;
3490 }
3491
3492 snd_hda_codec_write(codec, codec->core.afg, 0,
3493 AC_VERB_SET_GPIO_DATA, cur_gpio);
3494}
3495
3496/*
Ian Minett825315b2012-12-20 18:53:36 -08003497 * PCM callbacks
3498 */
Ian Minett95c6e9c2011-06-15 15:35:17 -07003499static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3500 struct hda_codec *codec,
3501 unsigned int stream_tag,
3502 unsigned int format,
3503 struct snd_pcm_substream *substream)
3504{
3505 struct ca0132_spec *spec = codec->spec;
Ian Minett825315b2012-12-20 18:53:36 -08003506
Hsin-Yu Chao28fba952014-02-19 14:27:07 +08003507 snd_hda_codec_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
Ian Minett825315b2012-12-20 18:53:36 -08003508
3509 return 0;
Ian Minett95c6e9c2011-06-15 15:35:17 -07003510}
3511
3512static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3513 struct hda_codec *codec,
3514 struct snd_pcm_substream *substream)
3515{
3516 struct ca0132_spec *spec = codec->spec;
Ian Minett825315b2012-12-20 18:53:36 -08003517
3518 if (spec->dsp_state == DSP_DOWNLOADING)
3519 return 0;
3520
3521 /*If Playback effects are on, allow stream some time to flush
3522 *effects tail*/
3523 if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
3524 msleep(50);
3525
Hsin-Yu Chao28fba952014-02-19 14:27:07 +08003526 snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
Ian Minett825315b2012-12-20 18:53:36 -08003527
3528 return 0;
Ian Minett95c6e9c2011-06-15 15:35:17 -07003529}
3530
Dylan Reide8412ca2013-04-04 13:55:09 -07003531static unsigned int ca0132_playback_pcm_delay(struct hda_pcm_stream *info,
3532 struct hda_codec *codec,
3533 struct snd_pcm_substream *substream)
3534{
3535 struct ca0132_spec *spec = codec->spec;
3536 unsigned int latency = DSP_PLAYBACK_INIT_LATENCY;
3537 struct snd_pcm_runtime *runtime = substream->runtime;
3538
3539 if (spec->dsp_state != DSP_DOWNLOADED)
3540 return 0;
3541
3542 /* Add latency if playback enhancement and either effect is enabled. */
3543 if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]) {
3544 if ((spec->effects_switch[SURROUND - EFFECT_START_NID]) ||
3545 (spec->effects_switch[DIALOG_PLUS - EFFECT_START_NID]))
3546 latency += DSP_PLAY_ENHANCEMENT_LATENCY;
3547 }
3548
3549 /* Applying Speaker EQ adds latency as well. */
3550 if (spec->cur_out_type == SPEAKER_OUT)
3551 latency += DSP_SPEAKER_OUT_LATENCY;
3552
3553 return (latency * runtime->rate) / 1000;
3554}
3555
Ian Minett95c6e9c2011-06-15 15:35:17 -07003556/*
3557 * Digital out
3558 */
Takashi Iwai27ebeb02012-08-08 17:20:18 +02003559static int ca0132_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3560 struct hda_codec *codec,
3561 struct snd_pcm_substream *substream)
3562{
3563 struct ca0132_spec *spec = codec->spec;
3564 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3565}
3566
Ian Minett95c6e9c2011-06-15 15:35:17 -07003567static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3568 struct hda_codec *codec,
3569 unsigned int stream_tag,
3570 unsigned int format,
3571 struct snd_pcm_substream *substream)
3572{
3573 struct ca0132_spec *spec = codec->spec;
Takashi Iwai27ebeb02012-08-08 17:20:18 +02003574 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3575 stream_tag, format, substream);
Ian Minett95c6e9c2011-06-15 15:35:17 -07003576}
3577
3578static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3579 struct hda_codec *codec,
3580 struct snd_pcm_substream *substream)
3581{
3582 struct ca0132_spec *spec = codec->spec;
Takashi Iwai27ebeb02012-08-08 17:20:18 +02003583 return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
Ian Minett95c6e9c2011-06-15 15:35:17 -07003584}
3585
Takashi Iwai27ebeb02012-08-08 17:20:18 +02003586static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3587 struct hda_codec *codec,
3588 struct snd_pcm_substream *substream)
Ian Minett95c6e9c2011-06-15 15:35:17 -07003589{
3590 struct ca0132_spec *spec = codec->spec;
Takashi Iwai27ebeb02012-08-08 17:20:18 +02003591 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
Ian Minett95c6e9c2011-06-15 15:35:17 -07003592}
3593
3594/*
Ian Minett825315b2012-12-20 18:53:36 -08003595 * Analog capture
3596 */
3597static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3598 struct hda_codec *codec,
3599 unsigned int stream_tag,
3600 unsigned int format,
3601 struct snd_pcm_substream *substream)
3602{
Hsin-Yu Chao13c12db2014-02-19 14:30:35 +08003603 snd_hda_codec_setup_stream(codec, hinfo->nid,
Hsin-Yu Chao28fba952014-02-19 14:27:07 +08003604 stream_tag, 0, format);
Ian Minett825315b2012-12-20 18:53:36 -08003605
3606 return 0;
3607}
3608
3609static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3610 struct hda_codec *codec,
3611 struct snd_pcm_substream *substream)
3612{
3613 struct ca0132_spec *spec = codec->spec;
3614
3615 if (spec->dsp_state == DSP_DOWNLOADING)
3616 return 0;
3617
Hsin-Yu Chao28fba952014-02-19 14:27:07 +08003618 snd_hda_codec_cleanup_stream(codec, hinfo->nid);
Ian Minett825315b2012-12-20 18:53:36 -08003619 return 0;
3620}
3621
Dylan Reide8412ca2013-04-04 13:55:09 -07003622static unsigned int ca0132_capture_pcm_delay(struct hda_pcm_stream *info,
3623 struct hda_codec *codec,
3624 struct snd_pcm_substream *substream)
3625{
3626 struct ca0132_spec *spec = codec->spec;
3627 unsigned int latency = DSP_CAPTURE_INIT_LATENCY;
3628 struct snd_pcm_runtime *runtime = substream->runtime;
3629
3630 if (spec->dsp_state != DSP_DOWNLOADED)
3631 return 0;
3632
3633 if (spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID])
3634 latency += DSP_CRYSTAL_VOICE_LATENCY;
3635
3636 return (latency * runtime->rate) / 1000;
3637}
3638
Ian Minette90f29e2012-12-20 18:53:39 -08003639/*
3640 * Controls stuffs.
3641 */
3642
3643/*
3644 * Mixer controls helpers.
3645 */
3646#define CA0132_CODEC_VOL_MONO(xname, nid, channel, dir) \
3647 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3648 .name = xname, \
3649 .subdevice = HDA_SUBDEV_AMP_FLAG, \
3650 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3651 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
3652 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
3653 .info = ca0132_volume_info, \
3654 .get = ca0132_volume_get, \
3655 .put = ca0132_volume_put, \
3656 .tlv = { .c = ca0132_volume_tlv }, \
3657 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
3658
Connor McAdams017310f2018-05-08 13:20:11 -04003659/*
3660 * Creates a mixer control that uses defaults of HDA_CODEC_VOL except for the
3661 * volume put, which is used for setting the DSP volume. This was done because
3662 * the ca0132 functions were taking too much time and causing lag.
3663 */
3664#define CA0132_ALT_CODEC_VOL_MONO(xname, nid, channel, dir) \
3665 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3666 .name = xname, \
3667 .subdevice = HDA_SUBDEV_AMP_FLAG, \
3668 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
3669 SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
3670 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
3671 .info = snd_hda_mixer_amp_volume_info, \
3672 .get = snd_hda_mixer_amp_volume_get, \
3673 .put = ca0132_alt_volume_put, \
3674 .tlv = { .c = snd_hda_mixer_amp_tlv }, \
3675 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
3676
Ian Minette90f29e2012-12-20 18:53:39 -08003677#define CA0132_CODEC_MUTE_MONO(xname, nid, channel, dir) \
3678 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
3679 .name = xname, \
3680 .subdevice = HDA_SUBDEV_AMP_FLAG, \
3681 .info = snd_hda_mixer_amp_switch_info, \
3682 .get = ca0132_switch_get, \
3683 .put = ca0132_switch_put, \
3684 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, 0, dir) }
3685
3686/* stereo */
3687#define CA0132_CODEC_VOL(xname, nid, dir) \
3688 CA0132_CODEC_VOL_MONO(xname, nid, 3, dir)
Connor McAdams017310f2018-05-08 13:20:11 -04003689#define CA0132_ALT_CODEC_VOL(xname, nid, dir) \
3690 CA0132_ALT_CODEC_VOL_MONO(xname, nid, 3, dir)
Ian Minette90f29e2012-12-20 18:53:39 -08003691#define CA0132_CODEC_MUTE(xname, nid, dir) \
3692 CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir)
3693
Connor McAdams017310f2018-05-08 13:20:11 -04003694/* lookup tables */
3695/*
3696 * Lookup table with decibel values for the DSP. When volume is changed in
3697 * Windows, the DSP is also sent the dB value in floating point. In Windows,
3698 * these values have decimal points, probably because the Windows driver
3699 * actually uses floating point. We can't here, so I made a lookup table of
3700 * values -90 to 9. -90 is the lowest decibel value for both the ADC's and the
3701 * DAC's, and 9 is the maximum.
3702 */
3703static const unsigned int float_vol_db_lookup[] = {
37040xC2B40000, 0xC2B20000, 0xC2B00000, 0xC2AE0000, 0xC2AC0000, 0xC2AA0000,
37050xC2A80000, 0xC2A60000, 0xC2A40000, 0xC2A20000, 0xC2A00000, 0xC29E0000,
37060xC29C0000, 0xC29A0000, 0xC2980000, 0xC2960000, 0xC2940000, 0xC2920000,
37070xC2900000, 0xC28E0000, 0xC28C0000, 0xC28A0000, 0xC2880000, 0xC2860000,
37080xC2840000, 0xC2820000, 0xC2800000, 0xC27C0000, 0xC2780000, 0xC2740000,
37090xC2700000, 0xC26C0000, 0xC2680000, 0xC2640000, 0xC2600000, 0xC25C0000,
37100xC2580000, 0xC2540000, 0xC2500000, 0xC24C0000, 0xC2480000, 0xC2440000,
37110xC2400000, 0xC23C0000, 0xC2380000, 0xC2340000, 0xC2300000, 0xC22C0000,
37120xC2280000, 0xC2240000, 0xC2200000, 0xC21C0000, 0xC2180000, 0xC2140000,
37130xC2100000, 0xC20C0000, 0xC2080000, 0xC2040000, 0xC2000000, 0xC1F80000,
37140xC1F00000, 0xC1E80000, 0xC1E00000, 0xC1D80000, 0xC1D00000, 0xC1C80000,
37150xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
37160xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
37170xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
37180xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000,
37190x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000,
37200x40C00000, 0x40E00000, 0x41000000, 0x41100000
3721};
3722
Connor McAdams47cdf762018-05-08 13:20:13 -04003723/*
3724 * This table counts from float 0 to 1 in increments of .01, which is
3725 * useful for a few different sliders.
3726 */
3727static const unsigned int float_zero_to_one_lookup[] = {
37280x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
37290x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
37300x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
37310x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F,
37320x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1,
37330x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333,
37340x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85,
37350x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7,
37360x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14,
37370x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D,
37380x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666,
37390x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F,
37400x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8,
37410x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1,
37420x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A,
37430x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333,
37440x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
3745};
3746
3747/*
3748 * This table counts from float 10 to 1000, which is the range of the x-bass
3749 * crossover slider in Windows.
3750 */
3751static const unsigned int float_xbass_xover_lookup[] = {
37520x41200000, 0x41A00000, 0x41F00000, 0x42200000, 0x42480000, 0x42700000,
37530x428C0000, 0x42A00000, 0x42B40000, 0x42C80000, 0x42DC0000, 0x42F00000,
37540x43020000, 0x430C0000, 0x43160000, 0x43200000, 0x432A0000, 0x43340000,
37550x433E0000, 0x43480000, 0x43520000, 0x435C0000, 0x43660000, 0x43700000,
37560x437A0000, 0x43820000, 0x43870000, 0x438C0000, 0x43910000, 0x43960000,
37570x439B0000, 0x43A00000, 0x43A50000, 0x43AA0000, 0x43AF0000, 0x43B40000,
37580x43B90000, 0x43BE0000, 0x43C30000, 0x43C80000, 0x43CD0000, 0x43D20000,
37590x43D70000, 0x43DC0000, 0x43E10000, 0x43E60000, 0x43EB0000, 0x43F00000,
37600x43F50000, 0x43FA0000, 0x43FF0000, 0x44020000, 0x44048000, 0x44070000,
37610x44098000, 0x440C0000, 0x440E8000, 0x44110000, 0x44138000, 0x44160000,
37620x44188000, 0x441B0000, 0x441D8000, 0x44200000, 0x44228000, 0x44250000,
37630x44278000, 0x442A0000, 0x442C8000, 0x442F0000, 0x44318000, 0x44340000,
37640x44368000, 0x44390000, 0x443B8000, 0x443E0000, 0x44408000, 0x44430000,
37650x44458000, 0x44480000, 0x444A8000, 0x444D0000, 0x444F8000, 0x44520000,
37660x44548000, 0x44570000, 0x44598000, 0x445C0000, 0x445E8000, 0x44610000,
37670x44638000, 0x44660000, 0x44688000, 0x446B0000, 0x446D8000, 0x44700000,
37680x44728000, 0x44750000, 0x44778000, 0x447A0000
3769};
3770
Masahiro Yamada4091fb92017-02-27 14:29:56 -08003771/* The following are for tuning of products */
Ian Minett44f0c972012-12-20 18:53:38 -08003772#ifdef ENABLE_TUNING_CONTROLS
3773
Takashi Iwaibf823262020-01-05 15:47:24 +01003774static const unsigned int voice_focus_vals_lookup[] = {
Ian Minett44f0c972012-12-20 18:53:38 -080037750x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000,
37760x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000,
37770x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000,
37780x42180000, 0x421C0000, 0x42200000, 0x42240000, 0x42280000, 0x422C0000,
37790x42300000, 0x42340000, 0x42380000, 0x423C0000, 0x42400000, 0x42440000,
37800x42480000, 0x424C0000, 0x42500000, 0x42540000, 0x42580000, 0x425C0000,
37810x42600000, 0x42640000, 0x42680000, 0x426C0000, 0x42700000, 0x42740000,
37820x42780000, 0x427C0000, 0x42800000, 0x42820000, 0x42840000, 0x42860000,
37830x42880000, 0x428A0000, 0x428C0000, 0x428E0000, 0x42900000, 0x42920000,
37840x42940000, 0x42960000, 0x42980000, 0x429A0000, 0x429C0000, 0x429E0000,
37850x42A00000, 0x42A20000, 0x42A40000, 0x42A60000, 0x42A80000, 0x42AA0000,
37860x42AC0000, 0x42AE0000, 0x42B00000, 0x42B20000, 0x42B40000, 0x42B60000,
37870x42B80000, 0x42BA0000, 0x42BC0000, 0x42BE0000, 0x42C00000, 0x42C20000,
37880x42C40000, 0x42C60000, 0x42C80000, 0x42CA0000, 0x42CC0000, 0x42CE0000,
37890x42D00000, 0x42D20000, 0x42D40000, 0x42D60000, 0x42D80000, 0x42DA0000,
37900x42DC0000, 0x42DE0000, 0x42E00000, 0x42E20000, 0x42E40000, 0x42E60000,
37910x42E80000, 0x42EA0000, 0x42EC0000, 0x42EE0000, 0x42F00000, 0x42F20000,
37920x42F40000, 0x42F60000, 0x42F80000, 0x42FA0000, 0x42FC0000, 0x42FE0000,
37930x43000000, 0x43010000, 0x43020000, 0x43030000, 0x43040000, 0x43050000,
37940x43060000, 0x43070000, 0x43080000, 0x43090000, 0x430A0000, 0x430B0000,
37950x430C0000, 0x430D0000, 0x430E0000, 0x430F0000, 0x43100000, 0x43110000,
37960x43120000, 0x43130000, 0x43140000, 0x43150000, 0x43160000, 0x43170000,
37970x43180000, 0x43190000, 0x431A0000, 0x431B0000, 0x431C0000, 0x431D0000,
37980x431E0000, 0x431F0000, 0x43200000, 0x43210000, 0x43220000, 0x43230000,
37990x43240000, 0x43250000, 0x43260000, 0x43270000, 0x43280000, 0x43290000,
38000x432A0000, 0x432B0000, 0x432C0000, 0x432D0000, 0x432E0000, 0x432F0000,
38010x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000
3802};
3803
Takashi Iwaibf823262020-01-05 15:47:24 +01003804static const unsigned int mic_svm_vals_lookup[] = {
Ian Minett44f0c972012-12-20 18:53:38 -080038050x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
38060x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
38070x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
38080x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F,
38090x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1,
38100x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333,
38110x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85,
38120x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7,
38130x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14,
38140x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D,
38150x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666,
38160x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F,
38170x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8,
38180x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1,
38190x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A,
38200x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333,
38210x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
3822};
3823
Takashi Iwaibf823262020-01-05 15:47:24 +01003824static const unsigned int equalizer_vals_lookup[] = {
Ian Minett44f0c972012-12-20 18:53:38 -080038250xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
38260xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
38270xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
38280xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000,
38290x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000,
38300x40C00000, 0x40E00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000,
38310x41400000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x41880000,
38320x41900000, 0x41980000, 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000,
38330x41C00000
3834};
3835
3836static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
Takashi Iwaibf823262020-01-05 15:47:24 +01003837 const unsigned int *lookup, int idx)
Ian Minett44f0c972012-12-20 18:53:38 -08003838{
3839 int i = 0;
3840
3841 for (i = 0; i < TUNING_CTLS_COUNT; i++)
3842 if (nid == ca0132_tuning_ctls[i].nid)
3843 break;
3844
3845 snd_hda_power_up(codec);
Connor McAdams447fd8e2018-05-08 13:20:09 -04003846 dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20,
Ian Minett44f0c972012-12-20 18:53:38 -08003847 ca0132_tuning_ctls[i].req,
3848 &(lookup[idx]), sizeof(unsigned int));
3849 snd_hda_power_down(codec);
3850
3851 return 1;
3852}
3853
3854static int tuning_ctl_get(struct snd_kcontrol *kcontrol,
3855 struct snd_ctl_elem_value *ucontrol)
3856{
3857 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3858 struct ca0132_spec *spec = codec->spec;
3859 hda_nid_t nid = get_amp_nid(kcontrol);
3860 long *valp = ucontrol->value.integer.value;
3861 int idx = nid - TUNING_CTL_START_NID;
3862
3863 *valp = spec->cur_ctl_vals[idx];
3864 return 0;
3865}
3866
3867static int voice_focus_ctl_info(struct snd_kcontrol *kcontrol,
3868 struct snd_ctl_elem_info *uinfo)
3869{
3870 int chs = get_amp_channels(kcontrol);
3871 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3872 uinfo->count = chs == 3 ? 2 : 1;
3873 uinfo->value.integer.min = 20;
3874 uinfo->value.integer.max = 180;
3875 uinfo->value.integer.step = 1;
3876
3877 return 0;
3878}
3879
3880static int voice_focus_ctl_put(struct snd_kcontrol *kcontrol,
3881 struct snd_ctl_elem_value *ucontrol)
3882{
3883 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3884 struct ca0132_spec *spec = codec->spec;
3885 hda_nid_t nid = get_amp_nid(kcontrol);
3886 long *valp = ucontrol->value.integer.value;
3887 int idx;
3888
3889 idx = nid - TUNING_CTL_START_NID;
3890 /* any change? */
3891 if (spec->cur_ctl_vals[idx] == *valp)
3892 return 0;
3893
3894 spec->cur_ctl_vals[idx] = *valp;
3895
3896 idx = *valp - 20;
3897 tuning_ctl_set(codec, nid, voice_focus_vals_lookup, idx);
3898
3899 return 1;
3900}
3901
3902static int mic_svm_ctl_info(struct snd_kcontrol *kcontrol,
3903 struct snd_ctl_elem_info *uinfo)
3904{
3905 int chs = get_amp_channels(kcontrol);
3906 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3907 uinfo->count = chs == 3 ? 2 : 1;
3908 uinfo->value.integer.min = 0;
3909 uinfo->value.integer.max = 100;
3910 uinfo->value.integer.step = 1;
3911
3912 return 0;
3913}
3914
3915static int mic_svm_ctl_put(struct snd_kcontrol *kcontrol,
3916 struct snd_ctl_elem_value *ucontrol)
3917{
3918 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3919 struct ca0132_spec *spec = codec->spec;
3920 hda_nid_t nid = get_amp_nid(kcontrol);
3921 long *valp = ucontrol->value.integer.value;
3922 int idx;
3923
3924 idx = nid - TUNING_CTL_START_NID;
3925 /* any change? */
3926 if (spec->cur_ctl_vals[idx] == *valp)
3927 return 0;
3928
3929 spec->cur_ctl_vals[idx] = *valp;
3930
3931 idx = *valp;
3932 tuning_ctl_set(codec, nid, mic_svm_vals_lookup, idx);
3933
3934 return 0;
3935}
3936
3937static int equalizer_ctl_info(struct snd_kcontrol *kcontrol,
3938 struct snd_ctl_elem_info *uinfo)
3939{
3940 int chs = get_amp_channels(kcontrol);
3941 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3942 uinfo->count = chs == 3 ? 2 : 1;
3943 uinfo->value.integer.min = 0;
3944 uinfo->value.integer.max = 48;
3945 uinfo->value.integer.step = 1;
3946
3947 return 0;
3948}
3949
3950static int equalizer_ctl_put(struct snd_kcontrol *kcontrol,
3951 struct snd_ctl_elem_value *ucontrol)
3952{
3953 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3954 struct ca0132_spec *spec = codec->spec;
3955 hda_nid_t nid = get_amp_nid(kcontrol);
3956 long *valp = ucontrol->value.integer.value;
3957 int idx;
3958
3959 idx = nid - TUNING_CTL_START_NID;
3960 /* any change? */
3961 if (spec->cur_ctl_vals[idx] == *valp)
3962 return 0;
3963
3964 spec->cur_ctl_vals[idx] = *valp;
3965
3966 idx = *valp;
3967 tuning_ctl_set(codec, nid, equalizer_vals_lookup, idx);
3968
3969 return 1;
3970}
3971
Takashi Sakamoto8e142e92018-05-02 22:48:16 +09003972static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(voice_focus_db_scale, 2000, 100, 0);
3973static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(eq_db_scale, -2400, 100, 0);
Ian Minett44f0c972012-12-20 18:53:38 -08003974
3975static int add_tuning_control(struct hda_codec *codec,
3976 hda_nid_t pnid, hda_nid_t nid,
3977 const char *name, int dir)
3978{
Takashi Iwai975cc022013-06-28 11:56:49 +02003979 char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
Ian Minett44f0c972012-12-20 18:53:38 -08003980 int type = dir ? HDA_INPUT : HDA_OUTPUT;
3981 struct snd_kcontrol_new knew =
3982 HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
3983
3984 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
3985 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
3986 knew.tlv.c = 0;
3987 knew.tlv.p = 0;
3988 switch (pnid) {
3989 case VOICE_FOCUS:
3990 knew.info = voice_focus_ctl_info;
3991 knew.get = tuning_ctl_get;
3992 knew.put = voice_focus_ctl_put;
3993 knew.tlv.p = voice_focus_db_scale;
3994 break;
3995 case MIC_SVM:
3996 knew.info = mic_svm_ctl_info;
3997 knew.get = tuning_ctl_get;
3998 knew.put = mic_svm_ctl_put;
3999 break;
4000 case EQUALIZER:
4001 knew.info = equalizer_ctl_info;
4002 knew.get = tuning_ctl_get;
4003 knew.put = equalizer_ctl_put;
4004 knew.tlv.p = eq_db_scale;
4005 break;
4006 default:
4007 return 0;
4008 }
4009 knew.private_value =
4010 HDA_COMPOSE_AMP_VAL(nid, 1, 0, type);
4011 sprintf(namestr, "%s %s Volume", name, dirstr[dir]);
4012 return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
4013}
4014
4015static int add_tuning_ctls(struct hda_codec *codec)
4016{
4017 int i;
4018 int err;
4019
4020 for (i = 0; i < TUNING_CTLS_COUNT; i++) {
4021 err = add_tuning_control(codec,
4022 ca0132_tuning_ctls[i].parent_nid,
4023 ca0132_tuning_ctls[i].nid,
4024 ca0132_tuning_ctls[i].name,
4025 ca0132_tuning_ctls[i].direct);
4026 if (err < 0)
4027 return err;
4028 }
4029
4030 return 0;
4031}
4032
4033static void ca0132_init_tuning_defaults(struct hda_codec *codec)
4034{
4035 struct ca0132_spec *spec = codec->spec;
4036 int i;
4037
4038 /* Wedge Angle defaults to 30. 10 below is 30 - 20. 20 is min. */
4039 spec->cur_ctl_vals[WEDGE_ANGLE - TUNING_CTL_START_NID] = 10;
4040 /* SVM level defaults to 0.74. */
4041 spec->cur_ctl_vals[SVM_LEVEL - TUNING_CTL_START_NID] = 74;
4042
4043 /* EQ defaults to 0dB. */
4044 for (i = 2; i < TUNING_CTLS_COUNT; i++)
4045 spec->cur_ctl_vals[i] = 24;
4046}
4047#endif /*ENABLE_TUNING_CONTROLS*/
4048
Ian Minett825315b2012-12-20 18:53:36 -08004049/*
Ian Minett5aaca442012-12-20 18:53:34 -08004050 * Select the active output.
4051 * If autodetect is enabled, output will be selected based on jack detection.
4052 * If jack inserted, headphone will be selected, else built-in speakers
4053 * If autodetect is disabled, output will be selected based on selection.
4054 */
4055static int ca0132_select_out(struct hda_codec *codec)
4056{
4057 struct ca0132_spec *spec = codec->spec;
4058 unsigned int pin_ctl;
4059 int jack_present;
4060 int auto_jack;
4061 unsigned int tmp;
4062 int err;
4063
Takashi Iwai4e76a882014-02-25 12:21:03 +01004064 codec_dbg(codec, "ca0132_select_out\n");
Ian Minett5aaca442012-12-20 18:53:34 -08004065
Takashi Iwai664c7152015-04-08 11:43:14 +02004066 snd_hda_power_up_pm(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08004067
4068 auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
4069
4070 if (auto_jack)
Takashi Iwaife14f392015-08-10 16:53:32 +02004071 jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_hp);
Ian Minett5aaca442012-12-20 18:53:34 -08004072 else
4073 jack_present =
4074 spec->vnode_lswitch[VNID_HP_SEL - VNODE_START_NID];
4075
4076 if (jack_present)
4077 spec->cur_out_type = HEADPHONE_OUT;
4078 else
4079 spec->cur_out_type = SPEAKER_OUT;
4080
4081 if (spec->cur_out_type == SPEAKER_OUT) {
Takashi Iwai4e76a882014-02-25 12:21:03 +01004082 codec_dbg(codec, "ca0132_select_out speaker\n");
Ian Minett5aaca442012-12-20 18:53:34 -08004083 /*speaker out config*/
4084 tmp = FLOAT_ONE;
4085 err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
4086 if (err < 0)
4087 goto exit;
4088 /*enable speaker EQ*/
4089 tmp = FLOAT_ONE;
4090 err = dspio_set_uint_param(codec, 0x8f, 0x00, tmp);
4091 if (err < 0)
4092 goto exit;
4093
4094 /* Setup EAPD */
4095 snd_hda_codec_write(codec, spec->out_pins[1], 0,
4096 VENDOR_CHIPIO_EAPD_SEL_SET, 0x02);
4097 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4098 AC_VERB_SET_EAPD_BTLENABLE, 0x00);
4099 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4100 VENDOR_CHIPIO_EAPD_SEL_SET, 0x00);
4101 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4102 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
4103
4104 /* disable headphone node */
4105 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
4106 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwaia0c041c2013-01-15 17:13:31 +01004107 snd_hda_set_pin_ctl(codec, spec->out_pins[1],
4108 pin_ctl & ~PIN_HP);
Ian Minett5aaca442012-12-20 18:53:34 -08004109 /* enable speaker node */
4110 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
Connor McAdams8a19bce2018-05-08 13:20:01 -04004111 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwaia0c041c2013-01-15 17:13:31 +01004112 snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4113 pin_ctl | PIN_OUT);
Ian Minett5aaca442012-12-20 18:53:34 -08004114 } else {
Takashi Iwai4e76a882014-02-25 12:21:03 +01004115 codec_dbg(codec, "ca0132_select_out hp\n");
Ian Minett5aaca442012-12-20 18:53:34 -08004116 /*headphone out config*/
4117 tmp = FLOAT_ZERO;
4118 err = dspio_set_uint_param(codec, 0x80, 0x04, tmp);
4119 if (err < 0)
4120 goto exit;
4121 /*disable speaker EQ*/
4122 tmp = FLOAT_ZERO;
4123 err = dspio_set_uint_param(codec, 0x8f, 0x00, tmp);
4124 if (err < 0)
4125 goto exit;
4126
4127 /* Setup EAPD */
4128 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4129 VENDOR_CHIPIO_EAPD_SEL_SET, 0x00);
4130 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4131 AC_VERB_SET_EAPD_BTLENABLE, 0x00);
4132 snd_hda_codec_write(codec, spec->out_pins[1], 0,
4133 VENDOR_CHIPIO_EAPD_SEL_SET, 0x02);
4134 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4135 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
4136
4137 /* disable speaker*/
4138 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4139 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwaia0c041c2013-01-15 17:13:31 +01004140 snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4141 pin_ctl & ~PIN_HP);
Ian Minett5aaca442012-12-20 18:53:34 -08004142 /* enable headphone*/
4143 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
4144 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
Takashi Iwaia0c041c2013-01-15 17:13:31 +01004145 snd_hda_set_pin_ctl(codec, spec->out_pins[1],
4146 pin_ctl | PIN_HP);
Ian Minett5aaca442012-12-20 18:53:34 -08004147 }
4148
4149exit:
Takashi Iwai664c7152015-04-08 11:43:14 +02004150 snd_hda_power_down_pm(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08004151
4152 return err < 0 ? err : 0;
4153}
4154
Connor McAdams212de2e2018-09-18 14:33:42 -04004155static int ae5_headphone_gain_set(struct hda_codec *codec, long val);
Connor McAdamsd51434d2018-09-29 23:03:25 -04004156static int zxr_headphone_gain_set(struct hda_codec *codec, long val);
Connor McAdams8e6bc6b2018-09-29 23:03:17 -04004157static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val);
Connor McAdams212de2e2018-09-18 14:33:42 -04004158
Connor McAdams2283c852018-09-18 14:33:40 -04004159static void ae5_mmio_select_out(struct hda_codec *codec)
4160{
4161 struct ca0132_spec *spec = codec->spec;
4162 unsigned int i;
4163
4164 for (i = 0; i < AE5_CA0113_OUT_SET_COMMANDS; i++)
4165 ca0113_mmio_command_set(codec,
4166 ae5_ca0113_output_presets[spec->cur_out_type].group[i],
4167 ae5_ca0113_output_presets[spec->cur_out_type].target[i],
4168 ae5_ca0113_output_presets[spec->cur_out_type].vals[i]);
4169}
4170
Connor McAdams7cb9d942018-05-08 13:20:10 -04004171/*
Connor McAdams746fc9d2018-09-18 14:33:39 -04004172 * These are the commands needed to setup output on each of the different card
4173 * types.
4174 */
4175static void ca0132_alt_select_out_quirk_handler(struct hda_codec *codec)
4176{
4177 struct ca0132_spec *spec = codec->spec;
Connor McAdams2283c852018-09-18 14:33:40 -04004178 unsigned int tmp;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004179
4180 switch (spec->cur_out_type) {
4181 case SPEAKER_OUT:
Takashi Iwai6da8f442018-11-09 14:18:32 +01004182 switch (ca0132_quirk(spec)) {
Connor McAdams746fc9d2018-09-18 14:33:39 -04004183 case QUIRK_SBZ:
4184 ca0113_mmio_gpio_set(codec, 7, false);
4185 ca0113_mmio_gpio_set(codec, 4, true);
4186 ca0113_mmio_gpio_set(codec, 1, true);
Connor McAdams2283c852018-09-18 14:33:40 -04004187 chipio_set_control_param(codec, 0x0d, 0x18);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004188 break;
Connor McAdams55845942018-09-29 23:03:23 -04004189 case QUIRK_ZXR:
4190 ca0113_mmio_gpio_set(codec, 2, true);
4191 ca0113_mmio_gpio_set(codec, 3, true);
4192 ca0113_mmio_gpio_set(codec, 5, false);
Connor McAdamsd51434d2018-09-29 23:03:25 -04004193 zxr_headphone_gain_set(codec, 0);
Connor McAdams55845942018-09-29 23:03:23 -04004194 chipio_set_control_param(codec, 0x0d, 0x24);
4195 break;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004196 case QUIRK_R3DI:
Connor McAdams2283c852018-09-18 14:33:40 -04004197 chipio_set_control_param(codec, 0x0d, 0x24);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004198 r3di_gpio_out_set(codec, R3DI_LINE_OUT);
4199 break;
4200 case QUIRK_R3D:
Connor McAdams2283c852018-09-18 14:33:40 -04004201 chipio_set_control_param(codec, 0x0d, 0x24);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004202 ca0113_mmio_gpio_set(codec, 1, true);
4203 break;
Connor McAdams2283c852018-09-18 14:33:40 -04004204 case QUIRK_AE5:
4205 ae5_mmio_select_out(codec);
Connor McAdams212de2e2018-09-18 14:33:42 -04004206 ae5_headphone_gain_set(codec, 2);
Connor McAdams2283c852018-09-18 14:33:40 -04004207 tmp = FLOAT_ZERO;
4208 dspio_set_uint_param(codec, 0x96, 0x29, tmp);
4209 dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
4210 chipio_set_control_param(codec, 0x0d, 0xa4);
4211 chipio_write(codec, 0x18b03c, 0x00000012);
4212 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004213 default:
4214 break;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004215 }
4216 break;
4217 case HEADPHONE_OUT:
Takashi Iwai6da8f442018-11-09 14:18:32 +01004218 switch (ca0132_quirk(spec)) {
Connor McAdams746fc9d2018-09-18 14:33:39 -04004219 case QUIRK_SBZ:
4220 ca0113_mmio_gpio_set(codec, 7, true);
4221 ca0113_mmio_gpio_set(codec, 4, true);
4222 ca0113_mmio_gpio_set(codec, 1, false);
Connor McAdams2283c852018-09-18 14:33:40 -04004223 chipio_set_control_param(codec, 0x0d, 0x12);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004224 break;
Connor McAdams55845942018-09-29 23:03:23 -04004225 case QUIRK_ZXR:
4226 ca0113_mmio_gpio_set(codec, 2, false);
4227 ca0113_mmio_gpio_set(codec, 3, false);
4228 ca0113_mmio_gpio_set(codec, 5, true);
Connor McAdamsd51434d2018-09-29 23:03:25 -04004229 zxr_headphone_gain_set(codec, spec->zxr_gain_set);
Connor McAdams55845942018-09-29 23:03:23 -04004230 chipio_set_control_param(codec, 0x0d, 0x21);
4231 break;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004232 case QUIRK_R3DI:
Connor McAdams2283c852018-09-18 14:33:40 -04004233 chipio_set_control_param(codec, 0x0d, 0x21);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004234 r3di_gpio_out_set(codec, R3DI_HEADPHONE_OUT);
4235 break;
4236 case QUIRK_R3D:
Connor McAdams2283c852018-09-18 14:33:40 -04004237 chipio_set_control_param(codec, 0x0d, 0x21);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004238 ca0113_mmio_gpio_set(codec, 0x1, false);
4239 break;
Connor McAdams2283c852018-09-18 14:33:40 -04004240 case QUIRK_AE5:
4241 ae5_mmio_select_out(codec);
Connor McAdams212de2e2018-09-18 14:33:42 -04004242 ae5_headphone_gain_set(codec,
4243 spec->ae5_headphone_gain_val);
Connor McAdams2283c852018-09-18 14:33:40 -04004244 tmp = FLOAT_ONE;
4245 dspio_set_uint_param(codec, 0x96, 0x29, tmp);
4246 dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
4247 chipio_set_control_param(codec, 0x0d, 0xa1);
4248 chipio_write(codec, 0x18b03c, 0x00000012);
4249 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004250 default:
4251 break;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004252 }
4253 break;
4254 case SURROUND_OUT:
Takashi Iwai6da8f442018-11-09 14:18:32 +01004255 switch (ca0132_quirk(spec)) {
Connor McAdams746fc9d2018-09-18 14:33:39 -04004256 case QUIRK_SBZ:
4257 ca0113_mmio_gpio_set(codec, 7, false);
4258 ca0113_mmio_gpio_set(codec, 4, true);
4259 ca0113_mmio_gpio_set(codec, 1, true);
Connor McAdams2283c852018-09-18 14:33:40 -04004260 chipio_set_control_param(codec, 0x0d, 0x18);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004261 break;
Connor McAdams55845942018-09-29 23:03:23 -04004262 case QUIRK_ZXR:
4263 ca0113_mmio_gpio_set(codec, 2, true);
4264 ca0113_mmio_gpio_set(codec, 3, true);
4265 ca0113_mmio_gpio_set(codec, 5, false);
Connor McAdamsd51434d2018-09-29 23:03:25 -04004266 zxr_headphone_gain_set(codec, 0);
Connor McAdams55845942018-09-29 23:03:23 -04004267 chipio_set_control_param(codec, 0x0d, 0x24);
4268 break;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004269 case QUIRK_R3DI:
Connor McAdams2283c852018-09-18 14:33:40 -04004270 chipio_set_control_param(codec, 0x0d, 0x24);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004271 r3di_gpio_out_set(codec, R3DI_LINE_OUT);
4272 break;
4273 case QUIRK_R3D:
4274 ca0113_mmio_gpio_set(codec, 1, true);
Connor McAdams2283c852018-09-18 14:33:40 -04004275 chipio_set_control_param(codec, 0x0d, 0x24);
4276 break;
4277 case QUIRK_AE5:
4278 ae5_mmio_select_out(codec);
Connor McAdams212de2e2018-09-18 14:33:42 -04004279 ae5_headphone_gain_set(codec, 2);
Connor McAdams2283c852018-09-18 14:33:40 -04004280 tmp = FLOAT_ZERO;
4281 dspio_set_uint_param(codec, 0x96, 0x29, tmp);
4282 dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
4283 chipio_set_control_param(codec, 0x0d, 0xa4);
4284 chipio_write(codec, 0x18b03c, 0x00000012);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004285 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004286 default:
4287 break;
Connor McAdams746fc9d2018-09-18 14:33:39 -04004288 }
4289 break;
4290 }
4291}
4292
4293/*
Connor McAdams7cb9d942018-05-08 13:20:10 -04004294 * This function behaves similarly to the ca0132_select_out funciton above,
4295 * except with a few differences. It adds the ability to select the current
4296 * output with an enumerated control "output source" if the auto detect
4297 * mute switch is set to off. If the auto detect mute switch is enabled, it
4298 * will detect either headphone or lineout(SPEAKER_OUT) from jack detection.
4299 * It also adds the ability to auto-detect the front headphone port. The only
4300 * way to select surround is to disable auto detect, and set Surround with the
4301 * enumerated control.
4302 */
4303static int ca0132_alt_select_out(struct hda_codec *codec)
4304{
4305 struct ca0132_spec *spec = codec->spec;
4306 unsigned int pin_ctl;
4307 int jack_present;
4308 int auto_jack;
4309 unsigned int i;
4310 unsigned int tmp;
4311 int err;
4312 /* Default Headphone is rear headphone */
4313 hda_nid_t headphone_nid = spec->out_pins[1];
4314
4315 codec_dbg(codec, "%s\n", __func__);
4316
4317 snd_hda_power_up_pm(codec);
4318
4319 auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
4320
4321 /*
4322 * If headphone rear or front is plugged in, set to headphone.
4323 * If neither is plugged in, set to rear line out. Only if
4324 * hp/speaker auto detect is enabled.
4325 */
4326 if (auto_jack) {
4327 jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_hp) ||
4328 snd_hda_jack_detect(codec, spec->unsol_tag_front_hp);
4329
4330 if (jack_present)
4331 spec->cur_out_type = HEADPHONE_OUT;
4332 else
4333 spec->cur_out_type = SPEAKER_OUT;
4334 } else
4335 spec->cur_out_type = spec->out_enum_val;
4336
4337 /* Begin DSP output switch */
4338 tmp = FLOAT_ONE;
4339 err = dspio_set_uint_param(codec, 0x96, 0x3A, tmp);
4340 if (err < 0)
4341 goto exit;
4342
Connor McAdams746fc9d2018-09-18 14:33:39 -04004343 ca0132_alt_select_out_quirk_handler(codec);
4344
Connor McAdams7cb9d942018-05-08 13:20:10 -04004345 switch (spec->cur_out_type) {
4346 case SPEAKER_OUT:
4347 codec_dbg(codec, "%s speaker\n", __func__);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004348
4349 /* disable headphone node */
4350 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
4351 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4352 snd_hda_set_pin_ctl(codec, spec->out_pins[1],
4353 pin_ctl & ~PIN_HP);
4354 /* enable line-out node */
4355 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4356 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4357 snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4358 pin_ctl | PIN_OUT);
4359 /* Enable EAPD */
4360 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4361 AC_VERB_SET_EAPD_BTLENABLE, 0x01);
4362
4363 /* If PlayEnhancement is enabled, set different source */
4364 if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4365 dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
4366 else
4367 dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT);
4368 break;
4369 case HEADPHONE_OUT:
4370 codec_dbg(codec, "%s hp\n", __func__);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004371
4372 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4373 AC_VERB_SET_EAPD_BTLENABLE, 0x00);
4374
4375 /* disable speaker*/
4376 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4377 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4378 snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4379 pin_ctl & ~PIN_HP);
4380
4381 /* enable headphone, either front or rear */
4382
4383 if (snd_hda_jack_detect(codec, spec->unsol_tag_front_hp))
4384 headphone_nid = spec->out_pins[2];
4385 else if (snd_hda_jack_detect(codec, spec->unsol_tag_hp))
4386 headphone_nid = spec->out_pins[1];
4387
4388 pin_ctl = snd_hda_codec_read(codec, headphone_nid, 0,
4389 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4390 snd_hda_set_pin_ctl(codec, headphone_nid,
4391 pin_ctl | PIN_HP);
4392
4393 if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4394 dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ONE);
4395 else
4396 dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_ZERO);
4397 break;
4398 case SURROUND_OUT:
4399 codec_dbg(codec, "%s surround\n", __func__);
Connor McAdams746fc9d2018-09-18 14:33:39 -04004400
Connor McAdams7cb9d942018-05-08 13:20:10 -04004401 /* enable line out node */
4402 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[0], 0,
4403 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4404 snd_hda_set_pin_ctl(codec, spec->out_pins[0],
4405 pin_ctl | PIN_OUT);
4406 /* Disable headphone out */
4407 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[1], 0,
4408 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4409 snd_hda_set_pin_ctl(codec, spec->out_pins[1],
4410 pin_ctl & ~PIN_HP);
4411 /* Enable EAPD on line out */
4412 snd_hda_codec_write(codec, spec->out_pins[0], 0,
4413 AC_VERB_SET_EAPD_BTLENABLE, 0x01);
4414 /* enable center/lfe out node */
4415 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[2], 0,
4416 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4417 snd_hda_set_pin_ctl(codec, spec->out_pins[2],
4418 pin_ctl | PIN_OUT);
4419 /* Now set rear surround node as out. */
4420 pin_ctl = snd_hda_codec_read(codec, spec->out_pins[3], 0,
4421 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4422 snd_hda_set_pin_ctl(codec, spec->out_pins[3],
4423 pin_ctl | PIN_OUT);
4424
Connor McAdams8e6bc6b2018-09-29 23:03:17 -04004425 dspio_set_uint_param(codec, 0x80, 0x04, FLOAT_EIGHT);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004426 break;
4427 }
Connor McAdams8e6bc6b2018-09-29 23:03:17 -04004428 /*
4429 * Surround always sets it's scp command to req 0x04 to FLOAT_EIGHT.
4430 * With this set though, X_BASS cannot be enabled. So, if we have OutFX
4431 * enabled, we need to make sure X_BASS is off, otherwise everything
4432 * sounds all muffled. Running ca0132_effects_set with X_BASS as the
4433 * effect should sort this out.
4434 */
4435 if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4436 ca0132_effects_set(codec, X_BASS,
4437 spec->effects_switch[X_BASS - EFFECT_START_NID]);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004438
Connor McAdams2283c852018-09-18 14:33:40 -04004439 /* run through the output dsp commands for the selected output. */
Connor McAdams7cb9d942018-05-08 13:20:10 -04004440 for (i = 0; i < alt_out_presets[spec->cur_out_type].commands; i++) {
4441 err = dspio_set_uint_param(codec,
4442 alt_out_presets[spec->cur_out_type].mids[i],
4443 alt_out_presets[spec->cur_out_type].reqs[i],
4444 alt_out_presets[spec->cur_out_type].vals[i]);
4445
4446 if (err < 0)
4447 goto exit;
4448 }
4449
4450exit:
4451 snd_hda_power_down_pm(codec);
4452
4453 return err < 0 ? err : 0;
4454}
4455
Chih-Chung Chang993884f2013-03-25 10:39:23 -07004456static void ca0132_unsol_hp_delayed(struct work_struct *work)
4457{
4458 struct ca0132_spec *spec = container_of(
4459 to_delayed_work(work), struct ca0132_spec, unsol_hp_work);
Takashi Iwaif8fb1172014-09-11 15:53:26 +02004460 struct hda_jack_tbl *jack;
4461
Takashi Iwai6da8f442018-11-09 14:18:32 +01004462 if (ca0132_use_alt_functions(spec))
Connor McAdams7cb9d942018-05-08 13:20:10 -04004463 ca0132_alt_select_out(spec->codec);
4464 else
4465 ca0132_select_out(spec->codec);
4466
Gabriele Martinod5c016b2015-05-18 21:15:13 +02004467 jack = snd_hda_jack_tbl_get(spec->codec, spec->unsol_tag_hp);
Takashi Iwaif8fb1172014-09-11 15:53:26 +02004468 if (jack) {
4469 jack->block_report = 0;
4470 snd_hda_jack_report_sync(spec->codec);
4471 }
Chih-Chung Chang993884f2013-03-25 10:39:23 -07004472}
4473
Ian Minett5aaca442012-12-20 18:53:34 -08004474static void ca0132_set_dmic(struct hda_codec *codec, int enable);
4475static int ca0132_mic_boost_set(struct hda_codec *codec, long val);
Connor McAdamse0026d02018-05-08 13:20:12 -04004476static void resume_mic1(struct hda_codec *codec, unsigned int oldval);
4477static int stop_mic1(struct hda_codec *codec);
4478static int ca0132_cvoice_switch_set(struct hda_codec *codec);
Connor McAdams47cdf762018-05-08 13:20:13 -04004479static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val);
Ian Minett5aaca442012-12-20 18:53:34 -08004480
4481/*
4482 * Select the active VIP source
4483 */
4484static int ca0132_set_vipsource(struct hda_codec *codec, int val)
4485{
4486 struct ca0132_spec *spec = codec->spec;
4487 unsigned int tmp;
4488
Dylan Reide8f1bd52013-03-14 17:27:45 -07004489 if (spec->dsp_state != DSP_DOWNLOADED)
Ian Minett5aaca442012-12-20 18:53:34 -08004490 return 0;
4491
4492 /* if CrystalVoice if off, vipsource should be 0 */
4493 if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ||
4494 (val == 0)) {
4495 chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
4496 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
4497 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
4498 if (spec->cur_mic_type == DIGITAL_MIC)
4499 tmp = FLOAT_TWO;
4500 else
4501 tmp = FLOAT_ONE;
4502 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4503 tmp = FLOAT_ZERO;
4504 dspio_set_uint_param(codec, 0x80, 0x05, tmp);
4505 } else {
4506 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000);
4507 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000);
4508 if (spec->cur_mic_type == DIGITAL_MIC)
4509 tmp = FLOAT_TWO;
4510 else
4511 tmp = FLOAT_ONE;
4512 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4513 tmp = FLOAT_ONE;
4514 dspio_set_uint_param(codec, 0x80, 0x05, tmp);
4515 msleep(20);
4516 chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, val);
4517 }
4518
4519 return 1;
4520}
4521
Connor McAdamse0026d02018-05-08 13:20:12 -04004522static int ca0132_alt_set_vipsource(struct hda_codec *codec, int val)
4523{
4524 struct ca0132_spec *spec = codec->spec;
4525 unsigned int tmp;
4526
4527 if (spec->dsp_state != DSP_DOWNLOADED)
4528 return 0;
4529
4530 codec_dbg(codec, "%s\n", __func__);
4531
4532 chipio_set_stream_control(codec, 0x03, 0);
4533 chipio_set_stream_control(codec, 0x04, 0);
4534
4535 /* if CrystalVoice is off, vipsource should be 0 */
4536 if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ||
4537 (val == 0) || spec->in_enum_val == REAR_LINE_IN) {
4538 codec_dbg(codec, "%s: off.", __func__);
4539 chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
4540
4541 tmp = FLOAT_ZERO;
4542 dspio_set_uint_param(codec, 0x80, 0x05, tmp);
4543
4544 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
4545 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004546 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdamse0026d02018-05-08 13:20:12 -04004547 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
4548
4549
4550 if (spec->in_enum_val == REAR_LINE_IN)
4551 tmp = FLOAT_ZERO;
4552 else {
Takashi Iwai6da8f442018-11-09 14:18:32 +01004553 if (ca0132_quirk(spec) == QUIRK_SBZ)
Connor McAdamse0026d02018-05-08 13:20:12 -04004554 tmp = FLOAT_THREE;
4555 else
4556 tmp = FLOAT_ONE;
4557 }
4558
4559 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4560
4561 } else {
4562 codec_dbg(codec, "%s: on.", __func__);
4563 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000);
4564 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004565 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdamse0026d02018-05-08 13:20:12 -04004566 chipio_set_conn_rate(codec, 0x0F, SR_16_000);
4567
4568 if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID])
4569 tmp = FLOAT_TWO;
4570 else
4571 tmp = FLOAT_ONE;
4572 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4573
4574 tmp = FLOAT_ONE;
4575 dspio_set_uint_param(codec, 0x80, 0x05, tmp);
4576
4577 msleep(20);
4578 chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, val);
4579 }
4580
4581 chipio_set_stream_control(codec, 0x03, 1);
4582 chipio_set_stream_control(codec, 0x04, 1);
4583
4584 return 1;
4585}
4586
Ian Minett5aaca442012-12-20 18:53:34 -08004587/*
4588 * Select the active microphone.
4589 * If autodetect is enabled, mic will be selected based on jack detection.
4590 * If jack inserted, ext.mic will be selected, else built-in mic
4591 * If autodetect is disabled, mic will be selected based on selection.
4592 */
4593static int ca0132_select_mic(struct hda_codec *codec)
4594{
4595 struct ca0132_spec *spec = codec->spec;
4596 int jack_present;
4597 int auto_jack;
4598
Takashi Iwai4e76a882014-02-25 12:21:03 +01004599 codec_dbg(codec, "ca0132_select_mic\n");
Ian Minett5aaca442012-12-20 18:53:34 -08004600
Takashi Iwai664c7152015-04-08 11:43:14 +02004601 snd_hda_power_up_pm(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08004602
4603 auto_jack = spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID];
4604
4605 if (auto_jack)
Takashi Iwaife14f392015-08-10 16:53:32 +02004606 jack_present = snd_hda_jack_detect(codec, spec->unsol_tag_amic1);
Ian Minett5aaca442012-12-20 18:53:34 -08004607 else
4608 jack_present =
4609 spec->vnode_lswitch[VNID_AMIC1_SEL - VNODE_START_NID];
4610
4611 if (jack_present)
4612 spec->cur_mic_type = LINE_MIC_IN;
4613 else
4614 spec->cur_mic_type = DIGITAL_MIC;
4615
4616 if (spec->cur_mic_type == DIGITAL_MIC) {
4617 /* enable digital Mic */
4618 chipio_set_conn_rate(codec, MEM_CONNID_DMIC, SR_32_000);
4619 ca0132_set_dmic(codec, 1);
4620 ca0132_mic_boost_set(codec, 0);
4621 /* set voice focus */
4622 ca0132_effects_set(codec, VOICE_FOCUS,
4623 spec->effects_switch
4624 [VOICE_FOCUS - EFFECT_START_NID]);
4625 } else {
4626 /* disable digital Mic */
4627 chipio_set_conn_rate(codec, MEM_CONNID_DMIC, SR_96_000);
4628 ca0132_set_dmic(codec, 0);
4629 ca0132_mic_boost_set(codec, spec->cur_mic_boost);
4630 /* disable voice focus */
4631 ca0132_effects_set(codec, VOICE_FOCUS, 0);
4632 }
4633
Takashi Iwai664c7152015-04-08 11:43:14 +02004634 snd_hda_power_down_pm(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08004635
4636 return 0;
4637}
4638
4639/*
Connor McAdams7cb9d942018-05-08 13:20:10 -04004640 * Select the active input.
4641 * Mic detection isn't used, because it's kind of pointless on the SBZ.
4642 * The front mic has no jack-detection, so the only way to switch to it
4643 * is to do it manually in alsamixer.
4644 */
4645static int ca0132_alt_select_in(struct hda_codec *codec)
4646{
4647 struct ca0132_spec *spec = codec->spec;
4648 unsigned int tmp;
4649
4650 codec_dbg(codec, "%s\n", __func__);
4651
4652 snd_hda_power_up_pm(codec);
4653
4654 chipio_set_stream_control(codec, 0x03, 0);
4655 chipio_set_stream_control(codec, 0x04, 0);
4656
4657 spec->cur_mic_type = spec->in_enum_val;
4658
4659 switch (spec->cur_mic_type) {
4660 case REAR_MIC:
Takashi Iwai6da8f442018-11-09 14:18:32 +01004661 switch (ca0132_quirk(spec)) {
Connor McAdams7cb9d942018-05-08 13:20:10 -04004662 case QUIRK_SBZ:
Connor McAdams42aa3a12018-08-08 13:34:20 -04004663 case QUIRK_R3D:
Connor McAdamsb9b41342018-09-18 14:33:34 -04004664 ca0113_mmio_gpio_set(codec, 0, false);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004665 tmp = FLOAT_THREE;
4666 break;
Connor McAdams55845942018-09-29 23:03:23 -04004667 case QUIRK_ZXR:
4668 tmp = FLOAT_THREE;
4669 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004670 case QUIRK_R3DI:
4671 r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
4672 tmp = FLOAT_ONE;
4673 break;
Connor McAdamsf231daa2018-09-18 14:33:41 -04004674 case QUIRK_AE5:
Connor McAdams7fe35302020-08-02 20:29:27 -04004675 ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
Connor McAdamsf231daa2018-09-18 14:33:41 -04004676 tmp = FLOAT_THREE;
4677 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004678 default:
4679 tmp = FLOAT_ONE;
4680 break;
4681 }
4682
4683 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
4684 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004685 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdams7cb9d942018-05-08 13:20:10 -04004686 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
4687
4688 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4689
4690 chipio_set_stream_control(codec, 0x03, 1);
4691 chipio_set_stream_control(codec, 0x04, 1);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004692 switch (ca0132_quirk(spec)) {
Connor McAdamsf231daa2018-09-18 14:33:41 -04004693 case QUIRK_SBZ:
Connor McAdams7cb9d942018-05-08 13:20:10 -04004694 chipio_write(codec, 0x18B098, 0x0000000C);
4695 chipio_write(codec, 0x18B09C, 0x0000000C);
Connor McAdamsf231daa2018-09-18 14:33:41 -04004696 break;
Connor McAdams55845942018-09-29 23:03:23 -04004697 case QUIRK_ZXR:
4698 chipio_write(codec, 0x18B098, 0x0000000C);
4699 chipio_write(codec, 0x18B09C, 0x000000CC);
4700 break;
Connor McAdamsf231daa2018-09-18 14:33:41 -04004701 case QUIRK_AE5:
4702 chipio_write(codec, 0x18B098, 0x0000000C);
4703 chipio_write(codec, 0x18B09C, 0x0000004C);
4704 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004705 default:
4706 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004707 }
Connor McAdams47cdf762018-05-08 13:20:13 -04004708 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004709 break;
4710 case REAR_LINE_IN:
4711 ca0132_mic_boost_set(codec, 0);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004712 switch (ca0132_quirk(spec)) {
Connor McAdams7cb9d942018-05-08 13:20:10 -04004713 case QUIRK_SBZ:
Connor McAdams42aa3a12018-08-08 13:34:20 -04004714 case QUIRK_R3D:
Connor McAdamsb9b41342018-09-18 14:33:34 -04004715 ca0113_mmio_gpio_set(codec, 0, false);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004716 break;
4717 case QUIRK_R3DI:
4718 r3di_gpio_mic_set(codec, R3DI_REAR_MIC);
4719 break;
Connor McAdamsf231daa2018-09-18 14:33:41 -04004720 case QUIRK_AE5:
Connor McAdams7fe35302020-08-02 20:29:27 -04004721 ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
Connor McAdamsf231daa2018-09-18 14:33:41 -04004722 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004723 default:
4724 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004725 }
4726
4727 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
4728 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004729 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdams7cb9d942018-05-08 13:20:10 -04004730 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
4731
4732 tmp = FLOAT_ZERO;
4733 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4734
Takashi Iwai6da8f442018-11-09 14:18:32 +01004735 switch (ca0132_quirk(spec)) {
Connor McAdamsf231daa2018-09-18 14:33:41 -04004736 case QUIRK_SBZ:
4737 case QUIRK_AE5:
Connor McAdams7cb9d942018-05-08 13:20:10 -04004738 chipio_write(codec, 0x18B098, 0x00000000);
4739 chipio_write(codec, 0x18B09C, 0x00000000);
Connor McAdamsf231daa2018-09-18 14:33:41 -04004740 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004741 default:
4742 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004743 }
Connor McAdams7cb9d942018-05-08 13:20:10 -04004744 chipio_set_stream_control(codec, 0x03, 1);
4745 chipio_set_stream_control(codec, 0x04, 1);
4746 break;
4747 case FRONT_MIC:
Takashi Iwai6da8f442018-11-09 14:18:32 +01004748 switch (ca0132_quirk(spec)) {
Connor McAdams7cb9d942018-05-08 13:20:10 -04004749 case QUIRK_SBZ:
Connor McAdams42aa3a12018-08-08 13:34:20 -04004750 case QUIRK_R3D:
Connor McAdamsb9b41342018-09-18 14:33:34 -04004751 ca0113_mmio_gpio_set(codec, 0, true);
4752 ca0113_mmio_gpio_set(codec, 5, false);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004753 tmp = FLOAT_THREE;
4754 break;
4755 case QUIRK_R3DI:
4756 r3di_gpio_mic_set(codec, R3DI_FRONT_MIC);
4757 tmp = FLOAT_ONE;
4758 break;
Connor McAdamsf231daa2018-09-18 14:33:41 -04004759 case QUIRK_AE5:
Connor McAdams7fe35302020-08-02 20:29:27 -04004760 ca0113_mmio_command_set(codec, 0x30, 0x28, 0x3f);
Connor McAdamsf231daa2018-09-18 14:33:41 -04004761 tmp = FLOAT_THREE;
4762 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004763 default:
4764 tmp = FLOAT_ONE;
4765 break;
4766 }
4767
4768 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
4769 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01004770 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdams7cb9d942018-05-08 13:20:10 -04004771 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
4772
4773 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4774
4775 chipio_set_stream_control(codec, 0x03, 1);
4776 chipio_set_stream_control(codec, 0x04, 1);
4777
Takashi Iwai6da8f442018-11-09 14:18:32 +01004778 switch (ca0132_quirk(spec)) {
Connor McAdamsf231daa2018-09-18 14:33:41 -04004779 case QUIRK_SBZ:
Connor McAdams7cb9d942018-05-08 13:20:10 -04004780 chipio_write(codec, 0x18B098, 0x0000000C);
4781 chipio_write(codec, 0x18B09C, 0x000000CC);
Connor McAdamsf231daa2018-09-18 14:33:41 -04004782 break;
4783 case QUIRK_AE5:
4784 chipio_write(codec, 0x18B098, 0x0000000C);
4785 chipio_write(codec, 0x18B09C, 0x0000004C);
4786 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01004787 default:
4788 break;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004789 }
Connor McAdams47cdf762018-05-08 13:20:13 -04004790 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004791 break;
4792 }
Connor McAdamse0026d02018-05-08 13:20:12 -04004793 ca0132_cvoice_switch_set(codec);
Connor McAdams7cb9d942018-05-08 13:20:10 -04004794
4795 snd_hda_power_down_pm(codec);
4796 return 0;
Connor McAdams7cb9d942018-05-08 13:20:10 -04004797}
4798
4799/*
Ian Minetta7e76272012-12-20 18:53:35 -08004800 * Check if VNODE settings take effect immediately.
4801 */
4802static bool ca0132_is_vnode_effective(struct hda_codec *codec,
4803 hda_nid_t vnid,
4804 hda_nid_t *shared_nid)
4805{
4806 struct ca0132_spec *spec = codec->spec;
4807 hda_nid_t nid;
Ian Minetta7e76272012-12-20 18:53:35 -08004808
4809 switch (vnid) {
4810 case VNID_SPK:
4811 nid = spec->shared_out_nid;
Ian Minetta7e76272012-12-20 18:53:35 -08004812 break;
4813 case VNID_MIC:
4814 nid = spec->shared_mic_nid;
Ian Minetta7e76272012-12-20 18:53:35 -08004815 break;
4816 default:
Takashi Iwai9a0869f2013-02-07 12:41:40 +01004817 return false;
Ian Minetta7e76272012-12-20 18:53:35 -08004818 }
4819
Takashi Iwai9a0869f2013-02-07 12:41:40 +01004820 if (shared_nid)
Ian Minetta7e76272012-12-20 18:53:35 -08004821 *shared_nid = nid;
4822
Takashi Iwai9a0869f2013-02-07 12:41:40 +01004823 return true;
Ian Minetta7e76272012-12-20 18:53:35 -08004824}
4825
4826/*
4827* The following functions are control change helpers.
4828* They return 0 if no changed. Return 1 if changed.
4829*/
4830static int ca0132_voicefx_set(struct hda_codec *codec, int enable)
4831{
4832 struct ca0132_spec *spec = codec->spec;
4833 unsigned int tmp;
4834
4835 /* based on CrystalVoice state to enable VoiceFX. */
4836 if (enable) {
4837 tmp = spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ?
4838 FLOAT_ONE : FLOAT_ZERO;
4839 } else {
4840 tmp = FLOAT_ZERO;
4841 }
4842
4843 dspio_set_uint_param(codec, ca0132_voicefx.mid,
4844 ca0132_voicefx.reqs[0], tmp);
4845
4846 return 1;
4847}
4848
4849/*
Ian Minett5aaca442012-12-20 18:53:34 -08004850 * Set the effects parameters
4851 */
4852static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val)
4853{
4854 struct ca0132_spec *spec = codec->spec;
Connor McAdams009b8f92018-05-08 13:20:06 -04004855 unsigned int on, tmp;
Ian Minett5aaca442012-12-20 18:53:34 -08004856 int num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
4857 int err = 0;
4858 int idx = nid - EFFECT_START_NID;
4859
4860 if ((idx < 0) || (idx >= num_fx))
4861 return 0; /* no changed */
4862
4863 /* for out effect, qualify with PE */
4864 if ((nid >= OUT_EFFECT_START_NID) && (nid < OUT_EFFECT_END_NID)) {
4865 /* if PE if off, turn off out effects. */
4866 if (!spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
4867 val = 0;
Connor McAdams8e6bc6b2018-09-29 23:03:17 -04004868 if (spec->cur_out_type == SURROUND_OUT && nid == X_BASS)
4869 val = 0;
Ian Minett5aaca442012-12-20 18:53:34 -08004870 }
4871
4872 /* for in effect, qualify with CrystalVoice */
4873 if ((nid >= IN_EFFECT_START_NID) && (nid < IN_EFFECT_END_NID)) {
4874 /* if CrystalVoice if off, turn off in effects. */
4875 if (!spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID])
4876 val = 0;
4877
4878 /* Voice Focus applies to 2-ch Mic, Digital Mic */
4879 if ((nid == VOICE_FOCUS) && (spec->cur_mic_type != DIGITAL_MIC))
4880 val = 0;
Connor McAdams009b8f92018-05-08 13:20:06 -04004881
4882 /* If Voice Focus on SBZ, set to two channel. */
Takashi Iwai6da8f442018-11-09 14:18:32 +01004883 if ((nid == VOICE_FOCUS) && ca0132_use_pci_mmio(spec)
Connor McAdams7cb9d942018-05-08 13:20:10 -04004884 && (spec->cur_mic_type != REAR_LINE_IN)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04004885 if (spec->effects_switch[CRYSTAL_VOICE -
4886 EFFECT_START_NID]) {
4887
4888 if (spec->effects_switch[VOICE_FOCUS -
4889 EFFECT_START_NID]) {
4890 tmp = FLOAT_TWO;
4891 val = 1;
4892 } else
4893 tmp = FLOAT_ONE;
4894
4895 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
4896 }
4897 }
4898 /*
4899 * For SBZ noise reduction, there's an extra command
4900 * to module ID 0x47. No clue why.
4901 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01004902 if ((nid == NOISE_REDUCTION) && ca0132_use_pci_mmio(spec)
Connor McAdams7cb9d942018-05-08 13:20:10 -04004903 && (spec->cur_mic_type != REAR_LINE_IN)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04004904 if (spec->effects_switch[CRYSTAL_VOICE -
4905 EFFECT_START_NID]) {
4906 if (spec->effects_switch[NOISE_REDUCTION -
4907 EFFECT_START_NID])
4908 tmp = FLOAT_ONE;
4909 else
4910 tmp = FLOAT_ZERO;
4911 } else
4912 tmp = FLOAT_ZERO;
4913
4914 dspio_set_uint_param(codec, 0x47, 0x00, tmp);
4915 }
Connor McAdams7cb9d942018-05-08 13:20:10 -04004916
4917 /* If rear line in disable effects. */
Takashi Iwai6da8f442018-11-09 14:18:32 +01004918 if (ca0132_use_alt_functions(spec) &&
Connor McAdams7cb9d942018-05-08 13:20:10 -04004919 spec->in_enum_val == REAR_LINE_IN)
4920 val = 0;
Ian Minett5aaca442012-12-20 18:53:34 -08004921 }
4922
Takashi Iwai4e76a882014-02-25 12:21:03 +01004923 codec_dbg(codec, "ca0132_effect_set: nid=0x%x, val=%ld\n",
Ian Minett5aaca442012-12-20 18:53:34 -08004924 nid, val);
4925
4926 on = (val == 0) ? FLOAT_ZERO : FLOAT_ONE;
4927 err = dspio_set_uint_param(codec, ca0132_effects[idx].mid,
4928 ca0132_effects[idx].reqs[0], on);
4929
4930 if (err < 0)
4931 return 0; /* no changed */
4932
4933 return 1;
4934}
4935
Ian Minetta7e76272012-12-20 18:53:35 -08004936/*
4937 * Turn on/off Playback Enhancements
4938 */
4939static int ca0132_pe_switch_set(struct hda_codec *codec)
4940{
4941 struct ca0132_spec *spec = codec->spec;
4942 hda_nid_t nid;
4943 int i, ret = 0;
4944
Takashi Iwai4e76a882014-02-25 12:21:03 +01004945 codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n",
Ian Minetta7e76272012-12-20 18:53:35 -08004946 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]);
4947
Takashi Iwai6da8f442018-11-09 14:18:32 +01004948 if (ca0132_use_alt_functions(spec))
Connor McAdams7cb9d942018-05-08 13:20:10 -04004949 ca0132_alt_select_out(codec);
4950
Ian Minetta7e76272012-12-20 18:53:35 -08004951 i = OUT_EFFECT_START_NID - EFFECT_START_NID;
4952 nid = OUT_EFFECT_START_NID;
4953 /* PE affects all out effects */
4954 for (; nid < OUT_EFFECT_END_NID; nid++, i++)
4955 ret |= ca0132_effects_set(codec, nid, spec->effects_switch[i]);
4956
4957 return ret;
4958}
4959
Ian Minett5aaca442012-12-20 18:53:34 -08004960/* Check if Mic1 is streaming, if so, stop streaming */
4961static int stop_mic1(struct hda_codec *codec)
4962{
4963 struct ca0132_spec *spec = codec->spec;
4964 unsigned int oldval = snd_hda_codec_read(codec, spec->adcs[0], 0,
4965 AC_VERB_GET_CONV, 0);
4966 if (oldval != 0)
4967 snd_hda_codec_write(codec, spec->adcs[0], 0,
4968 AC_VERB_SET_CHANNEL_STREAMID,
4969 0);
4970 return oldval;
4971}
4972
4973/* Resume Mic1 streaming if it was stopped. */
4974static void resume_mic1(struct hda_codec *codec, unsigned int oldval)
4975{
4976 struct ca0132_spec *spec = codec->spec;
4977 /* Restore the previous stream and channel */
4978 if (oldval != 0)
4979 snd_hda_codec_write(codec, spec->adcs[0], 0,
4980 AC_VERB_SET_CHANNEL_STREAMID,
4981 oldval);
4982}
4983
4984/*
Ian Minetta7e76272012-12-20 18:53:35 -08004985 * Turn on/off CrystalVoice
Ian Minett5aaca442012-12-20 18:53:34 -08004986 */
Ian Minetta7e76272012-12-20 18:53:35 -08004987static int ca0132_cvoice_switch_set(struct hda_codec *codec)
4988{
4989 struct ca0132_spec *spec = codec->spec;
4990 hda_nid_t nid;
4991 int i, ret = 0;
4992 unsigned int oldval;
4993
Takashi Iwai4e76a882014-02-25 12:21:03 +01004994 codec_dbg(codec, "ca0132_cvoice_switch_set: val=%ld\n",
Ian Minetta7e76272012-12-20 18:53:35 -08004995 spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]);
4996
4997 i = IN_EFFECT_START_NID - EFFECT_START_NID;
4998 nid = IN_EFFECT_START_NID;
4999 /* CrystalVoice affects all in effects */
5000 for (; nid < IN_EFFECT_END_NID; nid++, i++)
5001 ret |= ca0132_effects_set(codec, nid, spec->effects_switch[i]);
5002
5003 /* including VoiceFX */
5004 ret |= ca0132_voicefx_set(codec, (spec->voicefx_val ? 1 : 0));
5005
5006 /* set correct vipsource */
5007 oldval = stop_mic1(codec);
Takashi Iwai6da8f442018-11-09 14:18:32 +01005008 if (ca0132_use_alt_functions(spec))
Connor McAdamse0026d02018-05-08 13:20:12 -04005009 ret |= ca0132_alt_set_vipsource(codec, 1);
5010 else
5011 ret |= ca0132_set_vipsource(codec, 1);
Ian Minetta7e76272012-12-20 18:53:35 -08005012 resume_mic1(codec, oldval);
5013 return ret;
5014}
5015
Ian Minett5aaca442012-12-20 18:53:34 -08005016static int ca0132_mic_boost_set(struct hda_codec *codec, long val)
5017{
5018 struct ca0132_spec *spec = codec->spec;
5019 int ret = 0;
5020
5021 if (val) /* on */
5022 ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0,
5023 HDA_INPUT, 0, HDA_AMP_VOLMASK, 3);
5024 else /* off */
5025 ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0,
5026 HDA_INPUT, 0, HDA_AMP_VOLMASK, 0);
5027
5028 return ret;
5029}
5030
Connor McAdams47cdf762018-05-08 13:20:13 -04005031static int ca0132_alt_mic_boost_set(struct hda_codec *codec, long val)
5032{
5033 struct ca0132_spec *spec = codec->spec;
5034 int ret = 0;
5035
5036 ret = snd_hda_codec_amp_update(codec, spec->input_pins[0], 0,
5037 HDA_INPUT, 0, HDA_AMP_VOLMASK, val);
5038 return ret;
5039}
5040
Connor McAdams212de2e2018-09-18 14:33:42 -04005041static int ae5_headphone_gain_set(struct hda_codec *codec, long val)
5042{
5043 unsigned int i;
5044
5045 for (i = 0; i < 4; i++)
5046 ca0113_mmio_command_set(codec, 0x48, 0x11 + i,
5047 ae5_headphone_gain_presets[val].vals[i]);
5048 return 0;
5049}
5050
Connor McAdamsd51434d2018-09-29 23:03:25 -04005051/*
5052 * gpio pin 1 is a relay that switches on/off, apparently setting the headphone
5053 * amplifier to handle a 600 ohm load.
5054 */
5055static int zxr_headphone_gain_set(struct hda_codec *codec, long val)
5056{
5057 ca0113_mmio_gpio_set(codec, 1, val);
5058
5059 return 0;
5060}
5061
Ian Minetta7e76272012-12-20 18:53:35 -08005062static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
5063 struct snd_ctl_elem_value *ucontrol)
5064{
5065 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5066 hda_nid_t nid = get_amp_nid(kcontrol);
5067 hda_nid_t shared_nid = 0;
5068 bool effective;
5069 int ret = 0;
5070 struct ca0132_spec *spec = codec->spec;
5071 int auto_jack;
5072
5073 if (nid == VNID_HP_SEL) {
5074 auto_jack =
5075 spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
Connor McAdams7cb9d942018-05-08 13:20:10 -04005076 if (!auto_jack) {
Takashi Iwai6da8f442018-11-09 14:18:32 +01005077 if (ca0132_use_alt_functions(spec))
Connor McAdams7cb9d942018-05-08 13:20:10 -04005078 ca0132_alt_select_out(codec);
5079 else
5080 ca0132_select_out(codec);
5081 }
Ian Minetta7e76272012-12-20 18:53:35 -08005082 return 1;
5083 }
5084
5085 if (nid == VNID_AMIC1_SEL) {
5086 auto_jack =
5087 spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID];
5088 if (!auto_jack)
5089 ca0132_select_mic(codec);
5090 return 1;
5091 }
5092
5093 if (nid == VNID_HP_ASEL) {
Takashi Iwai6da8f442018-11-09 14:18:32 +01005094 if (ca0132_use_alt_functions(spec))
Connor McAdams7cb9d942018-05-08 13:20:10 -04005095 ca0132_alt_select_out(codec);
5096 else
5097 ca0132_select_out(codec);
Ian Minetta7e76272012-12-20 18:53:35 -08005098 return 1;
5099 }
5100
5101 if (nid == VNID_AMIC1_ASEL) {
5102 ca0132_select_mic(codec);
5103 return 1;
5104 }
5105
5106 /* if effective conditions, then update hw immediately. */
5107 effective = ca0132_is_vnode_effective(codec, nid, &shared_nid);
5108 if (effective) {
5109 int dir = get_amp_direction(kcontrol);
5110 int ch = get_amp_channels(kcontrol);
5111 unsigned long pval;
5112
5113 mutex_lock(&codec->control_mutex);
5114 pval = kcontrol->private_value;
5115 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch,
5116 0, dir);
5117 ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
5118 kcontrol->private_value = pval;
5119 mutex_unlock(&codec->control_mutex);
5120 }
5121
5122 return ret;
5123}
5124/* End of control change helpers. */
Connor McAdams47cdf762018-05-08 13:20:13 -04005125/*
5126 * Below I've added controls to mess with the effect levels, I've only enabled
5127 * them on the Sound Blaster Z, but they would probably also work on the
5128 * Chromebook. I figured they were probably tuned specifically for it, and left
5129 * out for a reason.
5130 */
5131
5132/* Sets DSP effect level from the sliders above the controls */
5133static int ca0132_alt_slider_ctl_set(struct hda_codec *codec, hda_nid_t nid,
5134 const unsigned int *lookup, int idx)
5135{
5136 int i = 0;
5137 unsigned int y;
5138 /*
5139 * For X_BASS, req 2 is actually crossover freq instead of
5140 * effect level
5141 */
5142 if (nid == X_BASS)
5143 y = 2;
5144 else
5145 y = 1;
5146
5147 snd_hda_power_up(codec);
5148 if (nid == XBASS_XOVER) {
5149 for (i = 0; i < OUT_EFFECTS_COUNT; i++)
5150 if (ca0132_effects[i].nid == X_BASS)
5151 break;
5152
5153 dspio_set_param(codec, ca0132_effects[i].mid, 0x20,
5154 ca0132_effects[i].reqs[1],
5155 &(lookup[idx - 1]), sizeof(unsigned int));
5156 } else {
5157 /* Find the actual effect structure */
5158 for (i = 0; i < OUT_EFFECTS_COUNT; i++)
5159 if (nid == ca0132_effects[i].nid)
5160 break;
5161
5162 dspio_set_param(codec, ca0132_effects[i].mid, 0x20,
5163 ca0132_effects[i].reqs[y],
5164 &(lookup[idx]), sizeof(unsigned int));
5165 }
5166
5167 snd_hda_power_down(codec);
5168
5169 return 0;
5170}
5171
5172static int ca0132_alt_xbass_xover_slider_ctl_get(struct snd_kcontrol *kcontrol,
5173 struct snd_ctl_elem_value *ucontrol)
5174{
5175 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5176 struct ca0132_spec *spec = codec->spec;
5177 long *valp = ucontrol->value.integer.value;
5178
5179 *valp = spec->xbass_xover_freq;
5180 return 0;
5181}
5182
5183static int ca0132_alt_slider_ctl_get(struct snd_kcontrol *kcontrol,
5184 struct snd_ctl_elem_value *ucontrol)
5185{
5186 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5187 struct ca0132_spec *spec = codec->spec;
5188 hda_nid_t nid = get_amp_nid(kcontrol);
5189 long *valp = ucontrol->value.integer.value;
5190 int idx = nid - OUT_EFFECT_START_NID;
5191
5192 *valp = spec->fx_ctl_val[idx];
5193 return 0;
5194}
5195
5196/*
5197 * The X-bass crossover starts at 10hz, so the min is 1. The
5198 * frequency is set in multiples of 10.
5199 */
5200static int ca0132_alt_xbass_xover_slider_info(struct snd_kcontrol *kcontrol,
5201 struct snd_ctl_elem_info *uinfo)
5202{
5203 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5204 uinfo->count = 1;
5205 uinfo->value.integer.min = 1;
5206 uinfo->value.integer.max = 100;
5207 uinfo->value.integer.step = 1;
5208
5209 return 0;
5210}
5211
5212static int ca0132_alt_effect_slider_info(struct snd_kcontrol *kcontrol,
5213 struct snd_ctl_elem_info *uinfo)
5214{
5215 int chs = get_amp_channels(kcontrol);
5216
5217 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
5218 uinfo->count = chs == 3 ? 2 : 1;
5219 uinfo->value.integer.min = 0;
5220 uinfo->value.integer.max = 100;
5221 uinfo->value.integer.step = 1;
5222
5223 return 0;
5224}
5225
5226static int ca0132_alt_xbass_xover_slider_put(struct snd_kcontrol *kcontrol,
5227 struct snd_ctl_elem_value *ucontrol)
5228{
5229 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5230 struct ca0132_spec *spec = codec->spec;
5231 hda_nid_t nid = get_amp_nid(kcontrol);
5232 long *valp = ucontrol->value.integer.value;
5233 int idx;
5234
5235 /* any change? */
5236 if (spec->xbass_xover_freq == *valp)
5237 return 0;
5238
5239 spec->xbass_xover_freq = *valp;
5240
5241 idx = *valp;
5242 ca0132_alt_slider_ctl_set(codec, nid, float_xbass_xover_lookup, idx);
5243
5244 return 0;
5245}
5246
5247static int ca0132_alt_effect_slider_put(struct snd_kcontrol *kcontrol,
5248 struct snd_ctl_elem_value *ucontrol)
5249{
5250 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5251 struct ca0132_spec *spec = codec->spec;
5252 hda_nid_t nid = get_amp_nid(kcontrol);
5253 long *valp = ucontrol->value.integer.value;
5254 int idx;
5255
5256 idx = nid - EFFECT_START_NID;
5257 /* any change? */
5258 if (spec->fx_ctl_val[idx] == *valp)
5259 return 0;
5260
5261 spec->fx_ctl_val[idx] = *valp;
5262
5263 idx = *valp;
5264 ca0132_alt_slider_ctl_set(codec, nid, float_zero_to_one_lookup, idx);
5265
5266 return 0;
5267}
5268
5269
5270/*
5271 * Mic Boost Enum for alternative ca0132 codecs. I didn't like that the original
5272 * only has off or full 30 dB, and didn't like making a volume slider that has
5273 * traditional 0-100 in alsamixer that goes in big steps. I like enum better.
5274 */
5275#define MIC_BOOST_NUM_OF_STEPS 4
5276#define MIC_BOOST_ENUM_MAX_STRLEN 10
5277
5278static int ca0132_alt_mic_boost_info(struct snd_kcontrol *kcontrol,
5279 struct snd_ctl_elem_info *uinfo)
5280{
5281 char *sfx = "dB";
5282 char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5283
5284 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5285 uinfo->count = 1;
5286 uinfo->value.enumerated.items = MIC_BOOST_NUM_OF_STEPS;
5287 if (uinfo->value.enumerated.item >= MIC_BOOST_NUM_OF_STEPS)
5288 uinfo->value.enumerated.item = MIC_BOOST_NUM_OF_STEPS - 1;
5289 sprintf(namestr, "%d %s", (uinfo->value.enumerated.item * 10), sfx);
5290 strcpy(uinfo->value.enumerated.name, namestr);
5291 return 0;
5292}
5293
5294static int ca0132_alt_mic_boost_get(struct snd_kcontrol *kcontrol,
5295 struct snd_ctl_elem_value *ucontrol)
5296{
5297 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5298 struct ca0132_spec *spec = codec->spec;
5299
5300 ucontrol->value.enumerated.item[0] = spec->mic_boost_enum_val;
5301 return 0;
5302}
5303
5304static int ca0132_alt_mic_boost_put(struct snd_kcontrol *kcontrol,
5305 struct snd_ctl_elem_value *ucontrol)
5306{
5307 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5308 struct ca0132_spec *spec = codec->spec;
5309 int sel = ucontrol->value.enumerated.item[0];
5310 unsigned int items = MIC_BOOST_NUM_OF_STEPS;
5311
5312 if (sel >= items)
5313 return 0;
5314
5315 codec_dbg(codec, "ca0132_alt_mic_boost: boost=%d\n",
5316 sel);
5317
5318 spec->mic_boost_enum_val = sel;
5319
5320 if (spec->in_enum_val != REAR_LINE_IN)
5321 ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val);
5322
5323 return 1;
5324}
5325
Connor McAdams212de2e2018-09-18 14:33:42 -04005326/*
5327 * Sound BlasterX AE-5 Headphone Gain Controls.
5328 */
5329#define AE5_HEADPHONE_GAIN_MAX 3
5330static int ae5_headphone_gain_info(struct snd_kcontrol *kcontrol,
5331 struct snd_ctl_elem_info *uinfo)
5332{
5333 char *sfx = " Ohms)";
5334 char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5335
5336 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5337 uinfo->count = 1;
5338 uinfo->value.enumerated.items = AE5_HEADPHONE_GAIN_MAX;
5339 if (uinfo->value.enumerated.item >= AE5_HEADPHONE_GAIN_MAX)
5340 uinfo->value.enumerated.item = AE5_HEADPHONE_GAIN_MAX - 1;
5341 sprintf(namestr, "%s %s",
5342 ae5_headphone_gain_presets[uinfo->value.enumerated.item].name,
5343 sfx);
5344 strcpy(uinfo->value.enumerated.name, namestr);
5345 return 0;
5346}
5347
5348static int ae5_headphone_gain_get(struct snd_kcontrol *kcontrol,
5349 struct snd_ctl_elem_value *ucontrol)
5350{
5351 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5352 struct ca0132_spec *spec = codec->spec;
5353
5354 ucontrol->value.enumerated.item[0] = spec->ae5_headphone_gain_val;
5355 return 0;
5356}
5357
5358static int ae5_headphone_gain_put(struct snd_kcontrol *kcontrol,
5359 struct snd_ctl_elem_value *ucontrol)
5360{
5361 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5362 struct ca0132_spec *spec = codec->spec;
5363 int sel = ucontrol->value.enumerated.item[0];
5364 unsigned int items = AE5_HEADPHONE_GAIN_MAX;
5365
5366 if (sel >= items)
5367 return 0;
5368
5369 codec_dbg(codec, "ae5_headphone_gain: boost=%d\n",
5370 sel);
5371
5372 spec->ae5_headphone_gain_val = sel;
5373
5374 if (spec->out_enum_val == HEADPHONE_OUT)
5375 ae5_headphone_gain_set(codec, spec->ae5_headphone_gain_val);
5376
5377 return 1;
5378}
5379
5380/*
5381 * Sound BlasterX AE-5 sound filter enumerated control.
5382 */
5383#define AE5_SOUND_FILTER_MAX 3
5384
5385static int ae5_sound_filter_info(struct snd_kcontrol *kcontrol,
5386 struct snd_ctl_elem_info *uinfo)
5387{
5388 char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
5389
5390 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5391 uinfo->count = 1;
5392 uinfo->value.enumerated.items = AE5_SOUND_FILTER_MAX;
5393 if (uinfo->value.enumerated.item >= AE5_SOUND_FILTER_MAX)
5394 uinfo->value.enumerated.item = AE5_SOUND_FILTER_MAX - 1;
5395 sprintf(namestr, "%s",
5396 ae5_filter_presets[uinfo->value.enumerated.item].name);
5397 strcpy(uinfo->value.enumerated.name, namestr);
5398 return 0;
5399}
5400
5401static int ae5_sound_filter_get(struct snd_kcontrol *kcontrol,
5402 struct snd_ctl_elem_value *ucontrol)
5403{
5404 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5405 struct ca0132_spec *spec = codec->spec;
5406
5407 ucontrol->value.enumerated.item[0] = spec->ae5_filter_val;
5408 return 0;
5409}
5410
5411static int ae5_sound_filter_put(struct snd_kcontrol *kcontrol,
5412 struct snd_ctl_elem_value *ucontrol)
5413{
5414 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5415 struct ca0132_spec *spec = codec->spec;
5416 int sel = ucontrol->value.enumerated.item[0];
5417 unsigned int items = AE5_SOUND_FILTER_MAX;
5418
5419 if (sel >= items)
5420 return 0;
5421
5422 codec_dbg(codec, "ae5_sound_filter: %s\n",
5423 ae5_filter_presets[sel].name);
5424
5425 spec->ae5_filter_val = sel;
5426
5427 ca0113_mmio_command_set_type2(codec, 0x48, 0x07,
5428 ae5_filter_presets[sel].val);
5429
5430 return 1;
5431}
Ian Minetta7e76272012-12-20 18:53:35 -08005432
Connor McAdams7cb9d942018-05-08 13:20:10 -04005433/*
5434 * Input Select Control for alternative ca0132 codecs. This exists because
5435 * front microphone has no auto-detect, and we need a way to set the rear
5436 * as line-in
5437 */
5438static int ca0132_alt_input_source_info(struct snd_kcontrol *kcontrol,
5439 struct snd_ctl_elem_info *uinfo)
5440{
5441 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5442 uinfo->count = 1;
5443 uinfo->value.enumerated.items = IN_SRC_NUM_OF_INPUTS;
5444 if (uinfo->value.enumerated.item >= IN_SRC_NUM_OF_INPUTS)
5445 uinfo->value.enumerated.item = IN_SRC_NUM_OF_INPUTS - 1;
5446 strcpy(uinfo->value.enumerated.name,
5447 in_src_str[uinfo->value.enumerated.item]);
5448 return 0;
5449}
5450
5451static int ca0132_alt_input_source_get(struct snd_kcontrol *kcontrol,
5452 struct snd_ctl_elem_value *ucontrol)
5453{
5454 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5455 struct ca0132_spec *spec = codec->spec;
5456
5457 ucontrol->value.enumerated.item[0] = spec->in_enum_val;
5458 return 0;
5459}
5460
5461static int ca0132_alt_input_source_put(struct snd_kcontrol *kcontrol,
5462 struct snd_ctl_elem_value *ucontrol)
5463{
5464 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5465 struct ca0132_spec *spec = codec->spec;
5466 int sel = ucontrol->value.enumerated.item[0];
5467 unsigned int items = IN_SRC_NUM_OF_INPUTS;
5468
5469 if (sel >= items)
5470 return 0;
5471
5472 codec_dbg(codec, "ca0132_alt_input_select: sel=%d, preset=%s\n",
5473 sel, in_src_str[sel]);
5474
5475 spec->in_enum_val = sel;
5476
5477 ca0132_alt_select_in(codec);
5478
5479 return 1;
5480}
5481
5482/* Sound Blaster Z Output Select Control */
5483static int ca0132_alt_output_select_get_info(struct snd_kcontrol *kcontrol,
5484 struct snd_ctl_elem_info *uinfo)
5485{
5486 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5487 uinfo->count = 1;
5488 uinfo->value.enumerated.items = NUM_OF_OUTPUTS;
5489 if (uinfo->value.enumerated.item >= NUM_OF_OUTPUTS)
5490 uinfo->value.enumerated.item = NUM_OF_OUTPUTS - 1;
5491 strcpy(uinfo->value.enumerated.name,
5492 alt_out_presets[uinfo->value.enumerated.item].name);
5493 return 0;
5494}
5495
5496static int ca0132_alt_output_select_get(struct snd_kcontrol *kcontrol,
5497 struct snd_ctl_elem_value *ucontrol)
5498{
5499 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5500 struct ca0132_spec *spec = codec->spec;
5501
5502 ucontrol->value.enumerated.item[0] = spec->out_enum_val;
5503 return 0;
5504}
5505
5506static int ca0132_alt_output_select_put(struct snd_kcontrol *kcontrol,
5507 struct snd_ctl_elem_value *ucontrol)
5508{
5509 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5510 struct ca0132_spec *spec = codec->spec;
5511 int sel = ucontrol->value.enumerated.item[0];
5512 unsigned int items = NUM_OF_OUTPUTS;
5513 unsigned int auto_jack;
5514
5515 if (sel >= items)
5516 return 0;
5517
5518 codec_dbg(codec, "ca0132_alt_output_select: sel=%d, preset=%s\n",
5519 sel, alt_out_presets[sel].name);
5520
5521 spec->out_enum_val = sel;
5522
5523 auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
5524
5525 if (!auto_jack)
5526 ca0132_alt_select_out(codec);
5527
5528 return 1;
5529}
5530
Connor McAdams47cdf762018-05-08 13:20:13 -04005531/*
5532 * Smart Volume output setting control. Three different settings, Normal,
5533 * which takes the value from the smart volume slider. The two others, loud
5534 * and night, disregard the slider value and have uneditable values.
5535 */
5536#define NUM_OF_SVM_SETTINGS 3
Takashi Sakamoto3a03f832018-05-15 22:12:58 +09005537static const char *const out_svm_set_enum_str[3] = {"Normal", "Loud", "Night" };
Connor McAdams47cdf762018-05-08 13:20:13 -04005538
5539static int ca0132_alt_svm_setting_info(struct snd_kcontrol *kcontrol,
5540 struct snd_ctl_elem_info *uinfo)
5541{
5542 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5543 uinfo->count = 1;
5544 uinfo->value.enumerated.items = NUM_OF_SVM_SETTINGS;
5545 if (uinfo->value.enumerated.item >= NUM_OF_SVM_SETTINGS)
5546 uinfo->value.enumerated.item = NUM_OF_SVM_SETTINGS - 1;
5547 strcpy(uinfo->value.enumerated.name,
5548 out_svm_set_enum_str[uinfo->value.enumerated.item]);
5549 return 0;
5550}
5551
5552static int ca0132_alt_svm_setting_get(struct snd_kcontrol *kcontrol,
5553 struct snd_ctl_elem_value *ucontrol)
5554{
5555 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5556 struct ca0132_spec *spec = codec->spec;
5557
5558 ucontrol->value.enumerated.item[0] = spec->smart_volume_setting;
5559 return 0;
5560}
5561
5562static int ca0132_alt_svm_setting_put(struct snd_kcontrol *kcontrol,
5563 struct snd_ctl_elem_value *ucontrol)
5564{
5565 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5566 struct ca0132_spec *spec = codec->spec;
5567 int sel = ucontrol->value.enumerated.item[0];
5568 unsigned int items = NUM_OF_SVM_SETTINGS;
5569 unsigned int idx = SMART_VOLUME - EFFECT_START_NID;
5570 unsigned int tmp;
5571
5572 if (sel >= items)
5573 return 0;
5574
5575 codec_dbg(codec, "ca0132_alt_svm_setting: sel=%d, preset=%s\n",
5576 sel, out_svm_set_enum_str[sel]);
5577
5578 spec->smart_volume_setting = sel;
5579
5580 switch (sel) {
5581 case 0:
5582 tmp = FLOAT_ZERO;
5583 break;
5584 case 1:
5585 tmp = FLOAT_ONE;
5586 break;
5587 case 2:
5588 tmp = FLOAT_TWO;
5589 break;
5590 default:
5591 tmp = FLOAT_ZERO;
5592 break;
5593 }
5594 /* Req 2 is the Smart Volume Setting req. */
5595 dspio_set_uint_param(codec, ca0132_effects[idx].mid,
5596 ca0132_effects[idx].reqs[2], tmp);
5597 return 1;
5598}
5599
5600/* Sound Blaster Z EQ preset controls */
5601static int ca0132_alt_eq_preset_info(struct snd_kcontrol *kcontrol,
5602 struct snd_ctl_elem_info *uinfo)
5603{
Fengguang Wuc5f13d72018-05-15 03:02:14 +08005604 unsigned int items = ARRAY_SIZE(ca0132_alt_eq_presets);
Connor McAdams47cdf762018-05-08 13:20:13 -04005605
5606 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5607 uinfo->count = 1;
5608 uinfo->value.enumerated.items = items;
5609 if (uinfo->value.enumerated.item >= items)
5610 uinfo->value.enumerated.item = items - 1;
5611 strcpy(uinfo->value.enumerated.name,
5612 ca0132_alt_eq_presets[uinfo->value.enumerated.item].name);
5613 return 0;
5614}
5615
5616static int ca0132_alt_eq_preset_get(struct snd_kcontrol *kcontrol,
5617 struct snd_ctl_elem_value *ucontrol)
5618{
5619 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5620 struct ca0132_spec *spec = codec->spec;
5621
5622 ucontrol->value.enumerated.item[0] = spec->eq_preset_val;
5623 return 0;
5624}
5625
5626static int ca0132_alt_eq_preset_put(struct snd_kcontrol *kcontrol,
5627 struct snd_ctl_elem_value *ucontrol)
5628{
5629 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5630 struct ca0132_spec *spec = codec->spec;
5631 int i, err = 0;
5632 int sel = ucontrol->value.enumerated.item[0];
Fengguang Wuc5f13d72018-05-15 03:02:14 +08005633 unsigned int items = ARRAY_SIZE(ca0132_alt_eq_presets);
Connor McAdams47cdf762018-05-08 13:20:13 -04005634
5635 if (sel >= items)
5636 return 0;
5637
5638 codec_dbg(codec, "%s: sel=%d, preset=%s\n", __func__, sel,
5639 ca0132_alt_eq_presets[sel].name);
5640 /*
5641 * Idx 0 is default.
5642 * Default needs to qualify with CrystalVoice state.
5643 */
5644 for (i = 0; i < EQ_PRESET_MAX_PARAM_COUNT; i++) {
5645 err = dspio_set_uint_param(codec, ca0132_alt_eq_enum.mid,
5646 ca0132_alt_eq_enum.reqs[i],
5647 ca0132_alt_eq_presets[sel].vals[i]);
5648 if (err < 0)
5649 break;
5650 }
5651
5652 if (err >= 0)
5653 spec->eq_preset_val = sel;
5654
5655 return 1;
5656}
5657
Ian Minetta7e76272012-12-20 18:53:35 -08005658static int ca0132_voicefx_info(struct snd_kcontrol *kcontrol,
5659 struct snd_ctl_elem_info *uinfo)
5660{
Jérémy Lefaurea9291f42017-10-12 22:36:31 -04005661 unsigned int items = ARRAY_SIZE(ca0132_voicefx_presets);
Ian Minetta7e76272012-12-20 18:53:35 -08005662
5663 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
5664 uinfo->count = 1;
5665 uinfo->value.enumerated.items = items;
5666 if (uinfo->value.enumerated.item >= items)
5667 uinfo->value.enumerated.item = items - 1;
5668 strcpy(uinfo->value.enumerated.name,
5669 ca0132_voicefx_presets[uinfo->value.enumerated.item].name);
5670 return 0;
5671}
5672
5673static int ca0132_voicefx_get(struct snd_kcontrol *kcontrol,
5674 struct snd_ctl_elem_value *ucontrol)
5675{
5676 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5677 struct ca0132_spec *spec = codec->spec;
5678
5679 ucontrol->value.enumerated.item[0] = spec->voicefx_val;
5680 return 0;
5681}
5682
5683static int ca0132_voicefx_put(struct snd_kcontrol *kcontrol,
5684 struct snd_ctl_elem_value *ucontrol)
5685{
5686 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5687 struct ca0132_spec *spec = codec->spec;
5688 int i, err = 0;
5689 int sel = ucontrol->value.enumerated.item[0];
Ian Minetta7e76272012-12-20 18:53:35 -08005690
Jérémy Lefaurea9291f42017-10-12 22:36:31 -04005691 if (sel >= ARRAY_SIZE(ca0132_voicefx_presets))
Ian Minetta7e76272012-12-20 18:53:35 -08005692 return 0;
5693
Takashi Iwai4e76a882014-02-25 12:21:03 +01005694 codec_dbg(codec, "ca0132_voicefx_put: sel=%d, preset=%s\n",
Ian Minetta7e76272012-12-20 18:53:35 -08005695 sel, ca0132_voicefx_presets[sel].name);
5696
5697 /*
5698 * Idx 0 is default.
5699 * Default needs to qualify with CrystalVoice state.
5700 */
5701 for (i = 0; i < VOICEFX_MAX_PARAM_COUNT; i++) {
5702 err = dspio_set_uint_param(codec, ca0132_voicefx.mid,
5703 ca0132_voicefx.reqs[i],
5704 ca0132_voicefx_presets[sel].vals[i]);
5705 if (err < 0)
5706 break;
5707 }
5708
5709 if (err >= 0) {
5710 spec->voicefx_val = sel;
5711 /* enable voice fx */
5712 ca0132_voicefx_set(codec, (sel ? 1 : 0));
5713 }
5714
5715 return 1;
5716}
5717
5718static int ca0132_switch_get(struct snd_kcontrol *kcontrol,
5719 struct snd_ctl_elem_value *ucontrol)
5720{
5721 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5722 struct ca0132_spec *spec = codec->spec;
5723 hda_nid_t nid = get_amp_nid(kcontrol);
5724 int ch = get_amp_channels(kcontrol);
5725 long *valp = ucontrol->value.integer.value;
5726
5727 /* vnode */
5728 if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) {
5729 if (ch & 1) {
5730 *valp = spec->vnode_lswitch[nid - VNODE_START_NID];
5731 valp++;
5732 }
5733 if (ch & 2) {
5734 *valp = spec->vnode_rswitch[nid - VNODE_START_NID];
5735 valp++;
5736 }
5737 return 0;
5738 }
5739
5740 /* effects, include PE and CrystalVoice */
5741 if ((nid >= EFFECT_START_NID) && (nid < EFFECT_END_NID)) {
5742 *valp = spec->effects_switch[nid - EFFECT_START_NID];
5743 return 0;
5744 }
5745
5746 /* mic boost */
5747 if (nid == spec->input_pins[0]) {
5748 *valp = spec->cur_mic_boost;
5749 return 0;
5750 }
5751
Connor McAdamsa00dc402020-08-02 20:29:25 -04005752 if (nid == ZXR_HEADPHONE_GAIN) {
5753 *valp = spec->zxr_gain_set;
5754 return 0;
5755 }
5756
Ian Minetta7e76272012-12-20 18:53:35 -08005757 return 0;
5758}
5759
5760static int ca0132_switch_put(struct snd_kcontrol *kcontrol,
5761 struct snd_ctl_elem_value *ucontrol)
5762{
5763 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5764 struct ca0132_spec *spec = codec->spec;
5765 hda_nid_t nid = get_amp_nid(kcontrol);
5766 int ch = get_amp_channels(kcontrol);
5767 long *valp = ucontrol->value.integer.value;
5768 int changed = 1;
5769
Takashi Iwai4e76a882014-02-25 12:21:03 +01005770 codec_dbg(codec, "ca0132_switch_put: nid=0x%x, val=%ld\n",
Ian Minetta7e76272012-12-20 18:53:35 -08005771 nid, *valp);
5772
5773 snd_hda_power_up(codec);
5774 /* vnode */
5775 if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) {
5776 if (ch & 1) {
5777 spec->vnode_lswitch[nid - VNODE_START_NID] = *valp;
5778 valp++;
5779 }
5780 if (ch & 2) {
5781 spec->vnode_rswitch[nid - VNODE_START_NID] = *valp;
5782 valp++;
5783 }
5784 changed = ca0132_vnode_switch_set(kcontrol, ucontrol);
5785 goto exit;
5786 }
5787
5788 /* PE */
5789 if (nid == PLAY_ENHANCEMENT) {
5790 spec->effects_switch[nid - EFFECT_START_NID] = *valp;
5791 changed = ca0132_pe_switch_set(codec);
5792 goto exit;
5793 }
5794
5795 /* CrystalVoice */
5796 if (nid == CRYSTAL_VOICE) {
5797 spec->effects_switch[nid - EFFECT_START_NID] = *valp;
5798 changed = ca0132_cvoice_switch_set(codec);
5799 goto exit;
5800 }
5801
5802 /* out and in effects */
5803 if (((nid >= OUT_EFFECT_START_NID) && (nid < OUT_EFFECT_END_NID)) ||
5804 ((nid >= IN_EFFECT_START_NID) && (nid < IN_EFFECT_END_NID))) {
5805 spec->effects_switch[nid - EFFECT_START_NID] = *valp;
5806 changed = ca0132_effects_set(codec, nid, *valp);
5807 goto exit;
5808 }
5809
5810 /* mic boost */
5811 if (nid == spec->input_pins[0]) {
5812 spec->cur_mic_boost = *valp;
Takashi Iwai6da8f442018-11-09 14:18:32 +01005813 if (ca0132_use_alt_functions(spec)) {
Connor McAdams7cb9d942018-05-08 13:20:10 -04005814 if (spec->in_enum_val != REAR_LINE_IN)
5815 changed = ca0132_mic_boost_set(codec, *valp);
5816 } else {
5817 /* Mic boost does not apply to Digital Mic */
5818 if (spec->cur_mic_type != DIGITAL_MIC)
5819 changed = ca0132_mic_boost_set(codec, *valp);
5820 }
Ian Minetta7e76272012-12-20 18:53:35 -08005821
Ian Minetta7e76272012-12-20 18:53:35 -08005822 goto exit;
5823 }
5824
Connor McAdamsd51434d2018-09-29 23:03:25 -04005825 if (nid == ZXR_HEADPHONE_GAIN) {
5826 spec->zxr_gain_set = *valp;
5827 if (spec->cur_out_type == HEADPHONE_OUT)
5828 changed = zxr_headphone_gain_set(codec, *valp);
5829 else
5830 changed = 0;
5831
5832 goto exit;
5833 }
5834
Ian Minetta7e76272012-12-20 18:53:35 -08005835exit:
5836 snd_hda_power_down(codec);
5837 return changed;
5838}
5839
5840/*
5841 * Volume related
5842 */
Connor McAdams017310f2018-05-08 13:20:11 -04005843/*
5844 * Sets the internal DSP decibel level to match the DAC for output, and the
5845 * ADC for input. Currently only the SBZ sets dsp capture volume level, and
5846 * all alternative codecs set DSP playback volume.
5847 */
5848static void ca0132_alt_dsp_volume_put(struct hda_codec *codec, hda_nid_t nid)
5849{
5850 struct ca0132_spec *spec = codec->spec;
5851 unsigned int dsp_dir;
5852 unsigned int lookup_val;
5853
5854 if (nid == VNID_SPK)
5855 dsp_dir = DSP_VOL_OUT;
5856 else
5857 dsp_dir = DSP_VOL_IN;
5858
5859 lookup_val = spec->vnode_lvol[nid - VNODE_START_NID];
5860
5861 dspio_set_uint_param(codec,
5862 ca0132_alt_vol_ctls[dsp_dir].mid,
5863 ca0132_alt_vol_ctls[dsp_dir].reqs[0],
5864 float_vol_db_lookup[lookup_val]);
5865
5866 lookup_val = spec->vnode_rvol[nid - VNODE_START_NID];
5867
5868 dspio_set_uint_param(codec,
5869 ca0132_alt_vol_ctls[dsp_dir].mid,
5870 ca0132_alt_vol_ctls[dsp_dir].reqs[1],
5871 float_vol_db_lookup[lookup_val]);
5872
5873 dspio_set_uint_param(codec,
5874 ca0132_alt_vol_ctls[dsp_dir].mid,
5875 ca0132_alt_vol_ctls[dsp_dir].reqs[2], FLOAT_ZERO);
5876}
5877
Ian Minetta7e76272012-12-20 18:53:35 -08005878static int ca0132_volume_info(struct snd_kcontrol *kcontrol,
5879 struct snd_ctl_elem_info *uinfo)
5880{
5881 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5882 struct ca0132_spec *spec = codec->spec;
5883 hda_nid_t nid = get_amp_nid(kcontrol);
5884 int ch = get_amp_channels(kcontrol);
5885 int dir = get_amp_direction(kcontrol);
5886 unsigned long pval;
5887 int err;
5888
5889 switch (nid) {
5890 case VNID_SPK:
5891 /* follow shared_out info */
5892 nid = spec->shared_out_nid;
5893 mutex_lock(&codec->control_mutex);
5894 pval = kcontrol->private_value;
5895 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
5896 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
5897 kcontrol->private_value = pval;
5898 mutex_unlock(&codec->control_mutex);
5899 break;
5900 case VNID_MIC:
5901 /* follow shared_mic info */
5902 nid = spec->shared_mic_nid;
5903 mutex_lock(&codec->control_mutex);
5904 pval = kcontrol->private_value;
5905 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
5906 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
5907 kcontrol->private_value = pval;
5908 mutex_unlock(&codec->control_mutex);
5909 break;
5910 default:
5911 err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
5912 }
5913 return err;
5914}
5915
5916static int ca0132_volume_get(struct snd_kcontrol *kcontrol,
5917 struct snd_ctl_elem_value *ucontrol)
5918{
5919 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5920 struct ca0132_spec *spec = codec->spec;
5921 hda_nid_t nid = get_amp_nid(kcontrol);
5922 int ch = get_amp_channels(kcontrol);
5923 long *valp = ucontrol->value.integer.value;
5924
5925 /* store the left and right volume */
5926 if (ch & 1) {
5927 *valp = spec->vnode_lvol[nid - VNODE_START_NID];
5928 valp++;
5929 }
5930 if (ch & 2) {
5931 *valp = spec->vnode_rvol[nid - VNODE_START_NID];
5932 valp++;
5933 }
5934 return 0;
5935}
5936
5937static int ca0132_volume_put(struct snd_kcontrol *kcontrol,
5938 struct snd_ctl_elem_value *ucontrol)
5939{
5940 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5941 struct ca0132_spec *spec = codec->spec;
5942 hda_nid_t nid = get_amp_nid(kcontrol);
5943 int ch = get_amp_channels(kcontrol);
5944 long *valp = ucontrol->value.integer.value;
5945 hda_nid_t shared_nid = 0;
5946 bool effective;
5947 int changed = 1;
5948
5949 /* store the left and right volume */
5950 if (ch & 1) {
5951 spec->vnode_lvol[nid - VNODE_START_NID] = *valp;
5952 valp++;
5953 }
5954 if (ch & 2) {
5955 spec->vnode_rvol[nid - VNODE_START_NID] = *valp;
5956 valp++;
5957 }
5958
5959 /* if effective conditions, then update hw immediately. */
5960 effective = ca0132_is_vnode_effective(codec, nid, &shared_nid);
5961 if (effective) {
5962 int dir = get_amp_direction(kcontrol);
5963 unsigned long pval;
5964
5965 snd_hda_power_up(codec);
5966 mutex_lock(&codec->control_mutex);
5967 pval = kcontrol->private_value;
5968 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch,
5969 0, dir);
5970 changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
5971 kcontrol->private_value = pval;
5972 mutex_unlock(&codec->control_mutex);
5973 snd_hda_power_down(codec);
5974 }
5975
5976 return changed;
5977}
5978
Connor McAdams017310f2018-05-08 13:20:11 -04005979/*
5980 * This function is the same as the one above, because using an if statement
5981 * inside of the above volume control for the DSP volume would cause too much
5982 * lag. This is a lot more smooth.
5983 */
5984static int ca0132_alt_volume_put(struct snd_kcontrol *kcontrol,
5985 struct snd_ctl_elem_value *ucontrol)
5986{
5987 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
5988 struct ca0132_spec *spec = codec->spec;
5989 hda_nid_t nid = get_amp_nid(kcontrol);
5990 int ch = get_amp_channels(kcontrol);
5991 long *valp = ucontrol->value.integer.value;
5992 hda_nid_t vnid = 0;
Colin Ian King33539932019-07-04 13:44:25 +01005993 int changed;
Connor McAdams017310f2018-05-08 13:20:11 -04005994
5995 switch (nid) {
5996 case 0x02:
5997 vnid = VNID_SPK;
5998 break;
5999 case 0x07:
6000 vnid = VNID_MIC;
6001 break;
6002 }
6003
6004 /* store the left and right volume */
6005 if (ch & 1) {
6006 spec->vnode_lvol[vnid - VNODE_START_NID] = *valp;
6007 valp++;
6008 }
6009 if (ch & 2) {
6010 spec->vnode_rvol[vnid - VNODE_START_NID] = *valp;
6011 valp++;
6012 }
6013
6014 snd_hda_power_up(codec);
6015 ca0132_alt_dsp_volume_put(codec, vnid);
6016 mutex_lock(&codec->control_mutex);
6017 changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
6018 mutex_unlock(&codec->control_mutex);
6019 snd_hda_power_down(codec);
6020
6021 return changed;
6022}
6023
Ian Minetta7e76272012-12-20 18:53:35 -08006024static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag,
6025 unsigned int size, unsigned int __user *tlv)
6026{
6027 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
6028 struct ca0132_spec *spec = codec->spec;
6029 hda_nid_t nid = get_amp_nid(kcontrol);
6030 int ch = get_amp_channels(kcontrol);
6031 int dir = get_amp_direction(kcontrol);
6032 unsigned long pval;
6033 int err;
6034
6035 switch (nid) {
6036 case VNID_SPK:
6037 /* follow shared_out tlv */
6038 nid = spec->shared_out_nid;
6039 mutex_lock(&codec->control_mutex);
6040 pval = kcontrol->private_value;
6041 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
6042 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
6043 kcontrol->private_value = pval;
6044 mutex_unlock(&codec->control_mutex);
6045 break;
6046 case VNID_MIC:
6047 /* follow shared_mic tlv */
6048 nid = spec->shared_mic_nid;
6049 mutex_lock(&codec->control_mutex);
6050 pval = kcontrol->private_value;
6051 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir);
6052 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
6053 kcontrol->private_value = pval;
6054 mutex_unlock(&codec->control_mutex);
6055 break;
6056 default:
6057 err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
6058 }
6059 return err;
6060}
6061
Connor McAdams47cdf762018-05-08 13:20:13 -04006062/* Add volume slider control for effect level */
6063static int ca0132_alt_add_effect_slider(struct hda_codec *codec, hda_nid_t nid,
6064 const char *pfx, int dir)
6065{
Connor McAdams47cdf762018-05-08 13:20:13 -04006066 char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
6067 int type = dir ? HDA_INPUT : HDA_OUTPUT;
6068 struct snd_kcontrol_new knew =
6069 HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
6070
Takashi Sakamoto0cc1aa72018-05-15 22:12:59 +09006071 sprintf(namestr, "FX: %s %s Volume", pfx, dirstr[dir]);
Connor McAdams47cdf762018-05-08 13:20:13 -04006072
Takashi Iwaibb86124c2018-07-25 23:00:49 +02006073 knew.tlv.c = NULL;
Connor McAdams47cdf762018-05-08 13:20:13 -04006074
6075 switch (nid) {
6076 case XBASS_XOVER:
6077 knew.info = ca0132_alt_xbass_xover_slider_info;
6078 knew.get = ca0132_alt_xbass_xover_slider_ctl_get;
6079 knew.put = ca0132_alt_xbass_xover_slider_put;
6080 break;
6081 default:
6082 knew.info = ca0132_alt_effect_slider_info;
6083 knew.get = ca0132_alt_slider_ctl_get;
6084 knew.put = ca0132_alt_effect_slider_put;
6085 knew.private_value =
6086 HDA_COMPOSE_AMP_VAL(nid, 1, 0, type);
6087 break;
6088 }
6089
6090 return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
6091}
6092
6093/*
6094 * Added FX: prefix for the alternative codecs, because otherwise the surround
6095 * effect would conflict with the Surround sound volume control. Also seems more
6096 * clear as to what the switches do. Left alone for others.
6097 */
Ian Minetta7e76272012-12-20 18:53:35 -08006098static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid,
6099 const char *pfx, int dir)
6100{
Connor McAdams47cdf762018-05-08 13:20:13 -04006101 struct ca0132_spec *spec = codec->spec;
Takashi Iwai975cc022013-06-28 11:56:49 +02006102 char namestr[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
Ian Minetta7e76272012-12-20 18:53:35 -08006103 int type = dir ? HDA_INPUT : HDA_OUTPUT;
6104 struct snd_kcontrol_new knew =
6105 CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type);
Connor McAdams47cdf762018-05-08 13:20:13 -04006106 /* If using alt_controls, add FX: prefix. But, don't add FX:
6107 * prefix to OutFX or InFX enable controls.
6108 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006109 if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID))
Takashi Sakamoto0cc1aa72018-05-15 22:12:59 +09006110 sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]);
Connor McAdams47cdf762018-05-08 13:20:13 -04006111 else
6112 sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);
6113
Ian Minetta7e76272012-12-20 18:53:35 -08006114 return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
6115}
6116
6117static int add_voicefx(struct hda_codec *codec)
6118{
6119 struct snd_kcontrol_new knew =
6120 HDA_CODEC_MUTE_MONO(ca0132_voicefx.name,
6121 VOICEFX, 1, 0, HDA_INPUT);
6122 knew.info = ca0132_voicefx_info;
6123 knew.get = ca0132_voicefx_get;
6124 knew.put = ca0132_voicefx_put;
6125 return snd_hda_ctl_add(codec, VOICEFX, snd_ctl_new1(&knew, codec));
6126}
6127
Connor McAdams47cdf762018-05-08 13:20:13 -04006128/* Create the EQ Preset control */
6129static int add_ca0132_alt_eq_presets(struct hda_codec *codec)
6130{
6131 struct snd_kcontrol_new knew =
6132 HDA_CODEC_MUTE_MONO(ca0132_alt_eq_enum.name,
6133 EQ_PRESET_ENUM, 1, 0, HDA_OUTPUT);
6134 knew.info = ca0132_alt_eq_preset_info;
6135 knew.get = ca0132_alt_eq_preset_get;
6136 knew.put = ca0132_alt_eq_preset_put;
6137 return snd_hda_ctl_add(codec, EQ_PRESET_ENUM,
6138 snd_ctl_new1(&knew, codec));
6139}
6140
6141/*
6142 * Add enumerated control for the three different settings of the smart volume
6143 * output effect. Normal just uses the slider value, and loud and night are
6144 * their own things that ignore that value.
6145 */
6146static int ca0132_alt_add_svm_enum(struct hda_codec *codec)
6147{
6148 struct snd_kcontrol_new knew =
6149 HDA_CODEC_MUTE_MONO("FX: Smart Volume Setting",
6150 SMART_VOLUME_ENUM, 1, 0, HDA_OUTPUT);
6151 knew.info = ca0132_alt_svm_setting_info;
6152 knew.get = ca0132_alt_svm_setting_get;
6153 knew.put = ca0132_alt_svm_setting_put;
6154 return snd_hda_ctl_add(codec, SMART_VOLUME_ENUM,
6155 snd_ctl_new1(&knew, codec));
6156
6157}
6158
Ian Minetta7e76272012-12-20 18:53:35 -08006159/*
Connor McAdams7cb9d942018-05-08 13:20:10 -04006160 * Create an Output Select enumerated control for codecs with surround
6161 * out capabilities.
6162 */
6163static int ca0132_alt_add_output_enum(struct hda_codec *codec)
6164{
6165 struct snd_kcontrol_new knew =
6166 HDA_CODEC_MUTE_MONO("Output Select",
6167 OUTPUT_SOURCE_ENUM, 1, 0, HDA_OUTPUT);
6168 knew.info = ca0132_alt_output_select_get_info;
6169 knew.get = ca0132_alt_output_select_get;
6170 knew.put = ca0132_alt_output_select_put;
6171 return snd_hda_ctl_add(codec, OUTPUT_SOURCE_ENUM,
6172 snd_ctl_new1(&knew, codec));
6173}
6174
6175/*
6176 * Create an Input Source enumerated control for the alternate ca0132 codecs
6177 * because the front microphone has no auto-detect, and Line-in has to be set
6178 * somehow.
6179 */
6180static int ca0132_alt_add_input_enum(struct hda_codec *codec)
6181{
6182 struct snd_kcontrol_new knew =
6183 HDA_CODEC_MUTE_MONO("Input Source",
6184 INPUT_SOURCE_ENUM, 1, 0, HDA_INPUT);
6185 knew.info = ca0132_alt_input_source_info;
6186 knew.get = ca0132_alt_input_source_get;
6187 knew.put = ca0132_alt_input_source_put;
6188 return snd_hda_ctl_add(codec, INPUT_SOURCE_ENUM,
6189 snd_ctl_new1(&knew, codec));
6190}
6191
6192/*
Connor McAdams47cdf762018-05-08 13:20:13 -04006193 * Add mic boost enumerated control. Switches through 0dB to 30dB. This adds
6194 * more control than the original mic boost, which is either full 30dB or off.
6195 */
6196static int ca0132_alt_add_mic_boost_enum(struct hda_codec *codec)
6197{
6198 struct snd_kcontrol_new knew =
6199 HDA_CODEC_MUTE_MONO("Mic Boost Capture Switch",
6200 MIC_BOOST_ENUM, 1, 0, HDA_INPUT);
6201 knew.info = ca0132_alt_mic_boost_info;
6202 knew.get = ca0132_alt_mic_boost_get;
6203 knew.put = ca0132_alt_mic_boost_put;
6204 return snd_hda_ctl_add(codec, MIC_BOOST_ENUM,
6205 snd_ctl_new1(&knew, codec));
6206
6207}
6208
6209/*
Connor McAdams212de2e2018-09-18 14:33:42 -04006210 * Add headphone gain enumerated control for the AE-5. This switches between
6211 * three modes, low, medium, and high. When non-headphone outputs are selected,
6212 * it is automatically set to high. This is the same behavior as Windows.
6213 */
6214static int ae5_add_headphone_gain_enum(struct hda_codec *codec)
6215{
6216 struct snd_kcontrol_new knew =
6217 HDA_CODEC_MUTE_MONO("AE-5: Headphone Gain",
Connor McAdams4b432ad2018-09-29 23:03:16 -04006218 AE5_HEADPHONE_GAIN_ENUM, 1, 0, HDA_OUTPUT);
Connor McAdams212de2e2018-09-18 14:33:42 -04006219 knew.info = ae5_headphone_gain_info;
6220 knew.get = ae5_headphone_gain_get;
6221 knew.put = ae5_headphone_gain_put;
6222 return snd_hda_ctl_add(codec, AE5_HEADPHONE_GAIN_ENUM,
6223 snd_ctl_new1(&knew, codec));
6224}
6225
6226/*
6227 * Add sound filter enumerated control for the AE-5. This adds three different
6228 * settings: Slow Roll Off, Minimum Phase, and Fast Roll Off. From what I've
6229 * read into it, it changes the DAC's interpolation filter.
6230 */
6231static int ae5_add_sound_filter_enum(struct hda_codec *codec)
6232{
6233 struct snd_kcontrol_new knew =
6234 HDA_CODEC_MUTE_MONO("AE-5: Sound Filter",
Connor McAdams4b432ad2018-09-29 23:03:16 -04006235 AE5_SOUND_FILTER_ENUM, 1, 0, HDA_OUTPUT);
Connor McAdams212de2e2018-09-18 14:33:42 -04006236 knew.info = ae5_sound_filter_info;
6237 knew.get = ae5_sound_filter_get;
6238 knew.put = ae5_sound_filter_put;
6239 return snd_hda_ctl_add(codec, AE5_SOUND_FILTER_ENUM,
6240 snd_ctl_new1(&knew, codec));
6241}
6242
Connor McAdamsd51434d2018-09-29 23:03:25 -04006243static int zxr_add_headphone_gain_switch(struct hda_codec *codec)
6244{
6245 struct snd_kcontrol_new knew =
6246 CA0132_CODEC_MUTE_MONO("ZxR: 600 Ohm Gain",
6247 ZXR_HEADPHONE_GAIN, 1, HDA_OUTPUT);
6248
6249 return snd_hda_ctl_add(codec, ZXR_HEADPHONE_GAIN,
6250 snd_ctl_new1(&knew, codec));
6251}
6252
Connor McAdams212de2e2018-09-18 14:33:42 -04006253/*
Takashi Iwai9ab0cb32020-07-17 17:45:17 +02006254 * Need to create follower controls for the alternate codecs that have surround
Connor McAdams47cdf762018-05-08 13:20:13 -04006255 * capabilities.
6256 */
Takashi Iwai9ab0cb32020-07-17 17:45:17 +02006257static const char * const ca0132_alt_follower_pfxs[] = {
Connor McAdams47cdf762018-05-08 13:20:13 -04006258 "Front", "Surround", "Center", "LFE", NULL,
6259};
6260
6261/*
6262 * Also need special channel map, because the default one is incorrect.
6263 * I think this has to do with the pin for rear surround being 0x11,
6264 * and the center/lfe being 0x10. Usually the pin order is the opposite.
6265 */
Colin Ian King9c4a6652018-06-21 19:34:57 +01006266static const struct snd_pcm_chmap_elem ca0132_alt_chmaps[] = {
Connor McAdams47cdf762018-05-08 13:20:13 -04006267 { .channels = 2,
6268 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
6269 { .channels = 4,
6270 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
6271 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
6272 { .channels = 6,
6273 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
6274 SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE,
6275 SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },
6276 { }
6277};
6278
6279/* Add the correct chmap for streams with 6 channels. */
6280static void ca0132_alt_add_chmap_ctls(struct hda_codec *codec)
6281{
6282 int err = 0;
6283 struct hda_pcm *pcm;
6284
6285 list_for_each_entry(pcm, &codec->pcm_list_head, list) {
6286 struct hda_pcm_stream *hinfo =
6287 &pcm->stream[SNDRV_PCM_STREAM_PLAYBACK];
6288 struct snd_pcm_chmap *chmap;
6289 const struct snd_pcm_chmap_elem *elem;
6290
6291 elem = ca0132_alt_chmaps;
6292 if (hinfo->channels_max == 6) {
6293 err = snd_pcm_add_chmap_ctls(pcm->pcm,
6294 SNDRV_PCM_STREAM_PLAYBACK,
6295 elem, hinfo->channels_max, 0, &chmap);
6296 if (err < 0)
6297 codec_dbg(codec, "snd_pcm_add_chmap_ctls failed!");
6298 }
6299 }
6300}
6301
6302/*
Ian Minetta7e76272012-12-20 18:53:35 -08006303 * When changing Node IDs for Mixer Controls below, make sure to update
6304 * Node IDs in ca0132_config() as well.
6305 */
Takashi Sakamotob0eaa072018-05-15 22:12:57 +09006306static const struct snd_kcontrol_new ca0132_mixer[] = {
Ian Minetta7e76272012-12-20 18:53:35 -08006307 CA0132_CODEC_VOL("Master Playback Volume", VNID_SPK, HDA_OUTPUT),
6308 CA0132_CODEC_MUTE("Master Playback Switch", VNID_SPK, HDA_OUTPUT),
6309 CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT),
6310 CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT),
6311 HDA_CODEC_VOLUME("Analog-Mic2 Capture Volume", 0x08, 0, HDA_INPUT),
6312 HDA_CODEC_MUTE("Analog-Mic2 Capture Switch", 0x08, 0, HDA_INPUT),
6313 HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT),
6314 HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT),
6315 CA0132_CODEC_MUTE_MONO("Mic1-Boost (30dB) Capture Switch",
6316 0x12, 1, HDA_INPUT),
6317 CA0132_CODEC_MUTE_MONO("HP/Speaker Playback Switch",
6318 VNID_HP_SEL, 1, HDA_OUTPUT),
6319 CA0132_CODEC_MUTE_MONO("AMic1/DMic Capture Switch",
6320 VNID_AMIC1_SEL, 1, HDA_INPUT),
6321 CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch",
6322 VNID_HP_ASEL, 1, HDA_OUTPUT),
6323 CA0132_CODEC_MUTE_MONO("AMic1/DMic Auto Detect Capture Switch",
6324 VNID_AMIC1_ASEL, 1, HDA_INPUT),
6325 { } /* end */
6326};
6327
Connor McAdams017310f2018-05-08 13:20:11 -04006328/*
Connor McAdamse25e3442018-08-08 13:34:21 -04006329 * Desktop specific control mixer. Removes auto-detect for mic, and adds
6330 * surround controls. Also sets both the Front Playback and Capture Volume
6331 * controls to alt so they set the DSP's decibel level.
Connor McAdams017310f2018-05-08 13:20:11 -04006332 */
Connor McAdamse25e3442018-08-08 13:34:21 -04006333static const struct snd_kcontrol_new desktop_mixer[] = {
Connor McAdams017310f2018-05-08 13:20:11 -04006334 CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT),
6335 CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT),
Connor McAdams47cdf762018-05-08 13:20:13 -04006336 HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT),
6337 HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0, HDA_OUTPUT),
6338 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x03, 1, 0, HDA_OUTPUT),
6339 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x03, 1, 0, HDA_OUTPUT),
6340 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x03, 2, 0, HDA_OUTPUT),
6341 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x03, 2, 0, HDA_OUTPUT),
Connor McAdams017310f2018-05-08 13:20:11 -04006342 CA0132_ALT_CODEC_VOL("Capture Volume", 0x07, HDA_INPUT),
6343 CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT),
6344 HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT),
6345 HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT),
6346 CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch",
6347 VNID_HP_ASEL, 1, HDA_OUTPUT),
6348 { } /* end */
6349};
6350
6351/*
6352 * Same as the Sound Blaster Z, except doesn't use the alt volume for capture
6353 * because it doesn't set decibel levels for the DSP for capture.
6354 */
Takashi Sakamotob0eaa072018-05-15 22:12:57 +09006355static const struct snd_kcontrol_new r3di_mixer[] = {
Connor McAdams017310f2018-05-08 13:20:11 -04006356 CA0132_ALT_CODEC_VOL("Front Playback Volume", 0x02, HDA_OUTPUT),
6357 CA0132_CODEC_MUTE("Front Playback Switch", VNID_SPK, HDA_OUTPUT),
Connor McAdams47cdf762018-05-08 13:20:13 -04006358 HDA_CODEC_VOLUME("Surround Playback Volume", 0x04, 0, HDA_OUTPUT),
6359 HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0, HDA_OUTPUT),
6360 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x03, 1, 0, HDA_OUTPUT),
6361 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x03, 1, 0, HDA_OUTPUT),
6362 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x03, 2, 0, HDA_OUTPUT),
6363 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x03, 2, 0, HDA_OUTPUT),
Connor McAdams017310f2018-05-08 13:20:11 -04006364 CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT),
6365 CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT),
6366 HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT),
6367 HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT),
6368 CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch",
6369 VNID_HP_ASEL, 1, HDA_OUTPUT),
6370 { } /* end */
6371};
6372
Ian Minette90f29e2012-12-20 18:53:39 -08006373static int ca0132_build_controls(struct hda_codec *codec)
6374{
6375 struct ca0132_spec *spec = codec->spec;
Connor McAdams47cdf762018-05-08 13:20:13 -04006376 int i, num_fx, num_sliders;
Ian Minette90f29e2012-12-20 18:53:39 -08006377 int err = 0;
6378
6379 /* Add Mixer controls */
6380 for (i = 0; i < spec->num_mixers; i++) {
6381 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
6382 if (err < 0)
6383 return err;
6384 }
Takashi Iwai9ab0cb32020-07-17 17:45:17 +02006385 /* Setup vmaster with surround followers for desktop ca0132 devices */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006386 if (ca0132_use_alt_functions(spec)) {
Connor McAdams47cdf762018-05-08 13:20:13 -04006387 snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT,
6388 spec->tlv);
6389 snd_hda_add_vmaster(codec, "Master Playback Volume",
Takashi Iwai9ab0cb32020-07-17 17:45:17 +02006390 spec->tlv, ca0132_alt_follower_pfxs,
Connor McAdams47cdf762018-05-08 13:20:13 -04006391 "Playback Volume");
6392 err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
Takashi Iwai9ab0cb32020-07-17 17:45:17 +02006393 NULL, ca0132_alt_follower_pfxs,
Connor McAdams47cdf762018-05-08 13:20:13 -04006394 "Playback Switch",
6395 true, &spec->vmaster_mute.sw_kctl);
Connor McAdams1502b432018-10-08 15:39:59 -04006396 if (err < 0)
6397 return err;
Connor McAdams47cdf762018-05-08 13:20:13 -04006398 }
Ian Minette90f29e2012-12-20 18:53:39 -08006399
6400 /* Add in and out effects controls.
6401 * VoiceFX, PE and CrystalVoice are added separately.
6402 */
6403 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
6404 for (i = 0; i < num_fx; i++) {
Connor McAdams7a2dc842018-10-08 15:40:00 -04006405 /* Desktop cards break if Echo Cancellation is used. */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006406 if (ca0132_use_pci_mmio(spec)) {
Connor McAdams47cdf762018-05-08 13:20:13 -04006407 if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID +
6408 OUT_EFFECTS_COUNT))
6409 continue;
6410 }
6411
Ian Minette90f29e2012-12-20 18:53:39 -08006412 err = add_fx_switch(codec, ca0132_effects[i].nid,
6413 ca0132_effects[i].name,
6414 ca0132_effects[i].direct);
6415 if (err < 0)
6416 return err;
6417 }
Connor McAdams47cdf762018-05-08 13:20:13 -04006418 /*
6419 * If codec has use_alt_controls set to true, add effect level sliders,
6420 * EQ presets, and Smart Volume presets. Also, change names to add FX
6421 * prefix, and change PlayEnhancement and CrystalVoice to match.
6422 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006423 if (ca0132_use_alt_controls(spec)) {
Connor McAdams1502b432018-10-08 15:39:59 -04006424 err = ca0132_alt_add_svm_enum(codec);
6425 if (err < 0)
6426 return err;
6427
6428 err = add_ca0132_alt_eq_presets(codec);
6429 if (err < 0)
6430 return err;
6431
Connor McAdams47cdf762018-05-08 13:20:13 -04006432 err = add_fx_switch(codec, PLAY_ENHANCEMENT,
6433 "Enable OutFX", 0);
6434 if (err < 0)
6435 return err;
Ian Minette90f29e2012-12-20 18:53:39 -08006436
Connor McAdams47cdf762018-05-08 13:20:13 -04006437 err = add_fx_switch(codec, CRYSTAL_VOICE,
6438 "Enable InFX", 1);
6439 if (err < 0)
6440 return err;
Ian Minette90f29e2012-12-20 18:53:39 -08006441
Connor McAdams47cdf762018-05-08 13:20:13 -04006442 num_sliders = OUT_EFFECTS_COUNT - 1;
6443 for (i = 0; i < num_sliders; i++) {
6444 err = ca0132_alt_add_effect_slider(codec,
6445 ca0132_effects[i].nid,
6446 ca0132_effects[i].name,
6447 ca0132_effects[i].direct);
6448 if (err < 0)
6449 return err;
6450 }
Ian Minette90f29e2012-12-20 18:53:39 -08006451
Connor McAdams47cdf762018-05-08 13:20:13 -04006452 err = ca0132_alt_add_effect_slider(codec, XBASS_XOVER,
6453 "X-Bass Crossover", EFX_DIR_OUT);
6454
6455 if (err < 0)
6456 return err;
6457 } else {
6458 err = add_fx_switch(codec, PLAY_ENHANCEMENT,
6459 "PlayEnhancement", 0);
6460 if (err < 0)
6461 return err;
6462
6463 err = add_fx_switch(codec, CRYSTAL_VOICE,
6464 "CrystalVoice", 1);
6465 if (err < 0)
6466 return err;
6467 }
Connor McAdams1502b432018-10-08 15:39:59 -04006468 err = add_voicefx(codec);
6469 if (err < 0)
6470 return err;
Ian Minette90f29e2012-12-20 18:53:39 -08006471
Connor McAdams7cb9d942018-05-08 13:20:10 -04006472 /*
6473 * If the codec uses alt_functions, you need the enumerated controls
6474 * to select the new outputs and inputs, plus add the new mic boost
6475 * setting control.
6476 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006477 if (ca0132_use_alt_functions(spec)) {
Connor McAdams1502b432018-10-08 15:39:59 -04006478 err = ca0132_alt_add_output_enum(codec);
6479 if (err < 0)
6480 return err;
6481 err = ca0132_alt_add_mic_boost_enum(codec);
6482 if (err < 0)
6483 return err;
Connor McAdams76dea4d2018-09-29 23:03:24 -04006484 /*
6485 * ZxR only has microphone input, there is no front panel
6486 * header on the card, and aux-in is handled by the DBPro board.
6487 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006488 if (ca0132_quirk(spec) != QUIRK_ZXR) {
Connor McAdams1502b432018-10-08 15:39:59 -04006489 err = ca0132_alt_add_input_enum(codec);
6490 if (err < 0)
6491 return err;
6492 }
Connor McAdams7cb9d942018-05-08 13:20:10 -04006493 }
Connor McAdams212de2e2018-09-18 14:33:42 -04006494
Takashi Iwai6da8f442018-11-09 14:18:32 +01006495 if (ca0132_quirk(spec) == QUIRK_AE5) {
Connor McAdams1502b432018-10-08 15:39:59 -04006496 err = ae5_add_headphone_gain_enum(codec);
6497 if (err < 0)
6498 return err;
6499 err = ae5_add_sound_filter_enum(codec);
6500 if (err < 0)
6501 return err;
Connor McAdams212de2e2018-09-18 14:33:42 -04006502 }
Connor McAdamsd51434d2018-09-29 23:03:25 -04006503
Takashi Iwai6da8f442018-11-09 14:18:32 +01006504 if (ca0132_quirk(spec) == QUIRK_ZXR) {
Connor McAdams1502b432018-10-08 15:39:59 -04006505 err = zxr_add_headphone_gain_switch(codec);
6506 if (err < 0)
6507 return err;
6508 }
Ian Minette90f29e2012-12-20 18:53:39 -08006509#ifdef ENABLE_TUNING_CONTROLS
6510 add_tuning_ctls(codec);
6511#endif
6512
6513 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
6514 if (err < 0)
6515 return err;
6516
6517 if (spec->dig_out) {
6518 err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
6519 spec->dig_out);
6520 if (err < 0)
6521 return err;
6522 err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);
6523 if (err < 0)
6524 return err;
6525 /* spec->multiout.share_spdif = 1; */
6526 }
6527
6528 if (spec->dig_in) {
6529 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
6530 if (err < 0)
6531 return err;
6532 }
Connor McAdams47cdf762018-05-08 13:20:13 -04006533
Takashi Iwai6da8f442018-11-09 14:18:32 +01006534 if (ca0132_use_alt_functions(spec))
Connor McAdams47cdf762018-05-08 13:20:13 -04006535 ca0132_alt_add_chmap_ctls(codec);
6536
Ian Minette90f29e2012-12-20 18:53:39 -08006537 return 0;
6538}
6539
Connor McAdams7675a2a2018-09-29 23:03:20 -04006540static int dbpro_build_controls(struct hda_codec *codec)
6541{
6542 struct ca0132_spec *spec = codec->spec;
6543 int err = 0;
6544
6545 if (spec->dig_out) {
6546 err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out,
6547 spec->dig_out);
6548 if (err < 0)
6549 return err;
6550 }
6551
6552 if (spec->dig_in) {
6553 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);
6554 if (err < 0)
6555 return err;
6556 }
6557
6558 return 0;
6559}
6560
Ian Minett5aaca442012-12-20 18:53:34 -08006561/*
Ian Minette90f29e2012-12-20 18:53:39 -08006562 * PCM
Ian Minett95c6e9c2011-06-15 15:35:17 -07006563 */
Julia Lawall071f1342016-09-11 15:05:43 +02006564static const struct hda_pcm_stream ca0132_pcm_analog_playback = {
Ian Minett95c6e9c2011-06-15 15:35:17 -07006565 .substreams = 1,
6566 .channels_min = 2,
Ian Minett825315b2012-12-20 18:53:36 -08006567 .channels_max = 6,
Ian Minett95c6e9c2011-06-15 15:35:17 -07006568 .ops = {
6569 .prepare = ca0132_playback_pcm_prepare,
Dylan Reide8412ca2013-04-04 13:55:09 -07006570 .cleanup = ca0132_playback_pcm_cleanup,
6571 .get_delay = ca0132_playback_pcm_delay,
Ian Minett95c6e9c2011-06-15 15:35:17 -07006572 },
6573};
6574
Julia Lawall071f1342016-09-11 15:05:43 +02006575static const struct hda_pcm_stream ca0132_pcm_analog_capture = {
Ian Minett95c6e9c2011-06-15 15:35:17 -07006576 .substreams = 1,
6577 .channels_min = 2,
6578 .channels_max = 2,
Ian Minett825315b2012-12-20 18:53:36 -08006579 .ops = {
6580 .prepare = ca0132_capture_pcm_prepare,
Dylan Reide8412ca2013-04-04 13:55:09 -07006581 .cleanup = ca0132_capture_pcm_cleanup,
6582 .get_delay = ca0132_capture_pcm_delay,
Ian Minett825315b2012-12-20 18:53:36 -08006583 },
Ian Minett95c6e9c2011-06-15 15:35:17 -07006584};
6585
Julia Lawall071f1342016-09-11 15:05:43 +02006586static const struct hda_pcm_stream ca0132_pcm_digital_playback = {
Ian Minett95c6e9c2011-06-15 15:35:17 -07006587 .substreams = 1,
6588 .channels_min = 2,
6589 .channels_max = 2,
6590 .ops = {
Takashi Iwai27ebeb02012-08-08 17:20:18 +02006591 .open = ca0132_dig_playback_pcm_open,
6592 .close = ca0132_dig_playback_pcm_close,
Ian Minett95c6e9c2011-06-15 15:35:17 -07006593 .prepare = ca0132_dig_playback_pcm_prepare,
6594 .cleanup = ca0132_dig_playback_pcm_cleanup
6595 },
6596};
6597
Julia Lawall071f1342016-09-11 15:05:43 +02006598static const struct hda_pcm_stream ca0132_pcm_digital_capture = {
Ian Minett95c6e9c2011-06-15 15:35:17 -07006599 .substreams = 1,
6600 .channels_min = 2,
6601 .channels_max = 2,
Ian Minett95c6e9c2011-06-15 15:35:17 -07006602};
6603
6604static int ca0132_build_pcms(struct hda_codec *codec)
6605{
6606 struct ca0132_spec *spec = codec->spec;
Takashi Iwaibbbc7e82015-02-27 17:43:19 +01006607 struct hda_pcm *info;
Ian Minett95c6e9c2011-06-15 15:35:17 -07006608
Takashi Iwaibbbc7e82015-02-27 17:43:19 +01006609 info = snd_hda_codec_pcm_new(codec, "CA0132 Analog");
6610 if (!info)
6611 return -ENOMEM;
Takashi Iwai6da8f442018-11-09 14:18:32 +01006612 if (ca0132_use_alt_functions(spec)) {
Connor McAdams47cdf762018-05-08 13:20:13 -04006613 info->own_chmap = true;
6614 info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap
6615 = ca0132_alt_chmaps;
6616 }
Ian Minett95c6e9c2011-06-15 15:35:17 -07006617 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback;
6618 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0];
6619 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
6620 spec->multiout.max_channels;
6621 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
Ian Minett825315b2012-12-20 18:53:36 -08006622 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
Ian Minett95c6e9c2011-06-15 15:35:17 -07006623 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
Ian Minett95c6e9c2011-06-15 15:35:17 -07006624
Connor McAdams009b8f92018-05-08 13:20:06 -04006625 /* With the DSP enabled, desktops don't use this ADC. */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006626 if (!ca0132_use_alt_functions(spec)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04006627 info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
6628 if (!info)
6629 return -ENOMEM;
6630 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
6631 ca0132_pcm_analog_capture;
6632 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
6633 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
6634 }
Ian Minett825315b2012-12-20 18:53:36 -08006635
Takashi Iwaibbbc7e82015-02-27 17:43:19 +01006636 info = snd_hda_codec_pcm_new(codec, "CA0132 What U Hear");
6637 if (!info)
6638 return -ENOMEM;
Ian Minett825315b2012-12-20 18:53:36 -08006639 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
6640 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
6641 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2];
Ian Minett825315b2012-12-20 18:53:36 -08006642
Ian Minett95c6e9c2011-06-15 15:35:17 -07006643 if (!spec->dig_out && !spec->dig_in)
6644 return 0;
6645
Takashi Iwaibbbc7e82015-02-27 17:43:19 +01006646 info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
6647 if (!info)
6648 return -ENOMEM;
Ian Minett95c6e9c2011-06-15 15:35:17 -07006649 info->pcm_type = HDA_PCM_TYPE_SPDIF;
6650 if (spec->dig_out) {
6651 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
6652 ca0132_pcm_digital_playback;
6653 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
6654 }
6655 if (spec->dig_in) {
6656 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
6657 ca0132_pcm_digital_capture;
6658 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
6659 }
Ian Minett95c6e9c2011-06-15 15:35:17 -07006660
6661 return 0;
6662}
6663
Connor McAdams7675a2a2018-09-29 23:03:20 -04006664static int dbpro_build_pcms(struct hda_codec *codec)
6665{
6666 struct ca0132_spec *spec = codec->spec;
6667 struct hda_pcm *info;
6668
6669 info = snd_hda_codec_pcm_new(codec, "CA0132 Alt Analog");
6670 if (!info)
6671 return -ENOMEM;
6672 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
6673 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
6674 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
6675
6676
6677 if (!spec->dig_out && !spec->dig_in)
6678 return 0;
6679
6680 info = snd_hda_codec_pcm_new(codec, "CA0132 Digital");
6681 if (!info)
6682 return -ENOMEM;
6683 info->pcm_type = HDA_PCM_TYPE_SPDIF;
6684 if (spec->dig_out) {
6685 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
6686 ca0132_pcm_digital_playback;
6687 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out;
6688 }
6689 if (spec->dig_in) {
6690 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
6691 ca0132_pcm_digital_capture;
6692 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in;
6693 }
6694
6695 return 0;
6696}
6697
Ian Minett441aa6a2012-12-20 18:53:40 -08006698static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
6699{
6700 if (pin) {
Takashi Iwaia0c041c2013-01-15 17:13:31 +01006701 snd_hda_set_pin_ctl(codec, pin, PIN_HP);
Ian Minett441aa6a2012-12-20 18:53:40 -08006702 if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
6703 snd_hda_codec_write(codec, pin, 0,
6704 AC_VERB_SET_AMP_GAIN_MUTE,
6705 AMP_OUT_UNMUTE);
6706 }
6707 if (dac && (get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))
6708 snd_hda_codec_write(codec, dac, 0,
6709 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO);
6710}
6711
6712static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
6713{
6714 if (pin) {
Takashi Iwaia0c041c2013-01-15 17:13:31 +01006715 snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
Ian Minett441aa6a2012-12-20 18:53:40 -08006716 if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
6717 snd_hda_codec_write(codec, pin, 0,
6718 AC_VERB_SET_AMP_GAIN_MUTE,
6719 AMP_IN_UNMUTE(0));
6720 }
6721 if (adc && (get_wcaps(codec, adc) & AC_WCAP_IN_AMP)) {
6722 snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE,
6723 AMP_IN_UNMUTE(0));
6724
6725 /* init to 0 dB and unmute. */
6726 snd_hda_codec_amp_stereo(codec, adc, HDA_INPUT, 0,
6727 HDA_AMP_VOLMASK, 0x5a);
6728 snd_hda_codec_amp_stereo(codec, adc, HDA_INPUT, 0,
6729 HDA_AMP_MUTE, 0);
6730 }
6731}
6732
Ian Minett5aaca442012-12-20 18:53:34 -08006733static void refresh_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir)
6734{
6735 unsigned int caps;
6736
6737 caps = snd_hda_param_read(codec, nid, dir == HDA_OUTPUT ?
6738 AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
6739 snd_hda_override_amp_caps(codec, nid, dir, caps);
6740}
6741
6742/*
6743 * Switch between Digital built-in mic and analog mic.
6744 */
6745static void ca0132_set_dmic(struct hda_codec *codec, int enable)
6746{
6747 struct ca0132_spec *spec = codec->spec;
6748 unsigned int tmp;
6749 u8 val;
6750 unsigned int oldval;
6751
Takashi Iwai4e76a882014-02-25 12:21:03 +01006752 codec_dbg(codec, "ca0132_set_dmic: enable=%d\n", enable);
Ian Minett5aaca442012-12-20 18:53:34 -08006753
6754 oldval = stop_mic1(codec);
6755 ca0132_set_vipsource(codec, 0);
6756 if (enable) {
6757 /* set DMic input as 2-ch */
6758 tmp = FLOAT_TWO;
6759 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
6760
6761 val = spec->dmic_ctl;
6762 val |= 0x80;
6763 snd_hda_codec_write(codec, spec->input_pins[0], 0,
6764 VENDOR_CHIPIO_DMIC_CTL_SET, val);
6765
6766 if (!(spec->dmic_ctl & 0x20))
6767 chipio_set_control_flag(codec, CONTROL_FLAG_DMIC, 1);
6768 } else {
6769 /* set AMic input as mono */
6770 tmp = FLOAT_ONE;
6771 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
6772
6773 val = spec->dmic_ctl;
6774 /* clear bit7 and bit5 to disable dmic */
6775 val &= 0x5f;
6776 snd_hda_codec_write(codec, spec->input_pins[0], 0,
6777 VENDOR_CHIPIO_DMIC_CTL_SET, val);
6778
6779 if (!(spec->dmic_ctl & 0x20))
6780 chipio_set_control_flag(codec, CONTROL_FLAG_DMIC, 0);
6781 }
6782 ca0132_set_vipsource(codec, 1);
6783 resume_mic1(codec, oldval);
6784}
6785
6786/*
6787 * Initialization for Digital Mic.
6788 */
6789static void ca0132_init_dmic(struct hda_codec *codec)
6790{
6791 struct ca0132_spec *spec = codec->spec;
6792 u8 val;
6793
6794 /* Setup Digital Mic here, but don't enable.
6795 * Enable based on jack detect.
6796 */
6797
6798 /* MCLK uses MPIO1, set to enable.
6799 * Bit 2-0: MPIO select
6800 * Bit 3: set to disable
6801 * Bit 7-4: reserved
6802 */
6803 val = 0x01;
6804 snd_hda_codec_write(codec, spec->input_pins[0], 0,
6805 VENDOR_CHIPIO_DMIC_MCLK_SET, val);
6806
6807 /* Data1 uses MPIO3. Data2 not use
6808 * Bit 2-0: Data1 MPIO select
6809 * Bit 3: set disable Data1
6810 * Bit 6-4: Data2 MPIO select
6811 * Bit 7: set disable Data2
6812 */
6813 val = 0x83;
6814 snd_hda_codec_write(codec, spec->input_pins[0], 0,
6815 VENDOR_CHIPIO_DMIC_PIN_SET, val);
6816
6817 /* Use Ch-0 and Ch-1. Rate is 48K, mode 1. Disable DMic first.
6818 * Bit 3-0: Channel mask
6819 * Bit 4: set for 48KHz, clear for 32KHz
6820 * Bit 5: mode
6821 * Bit 6: set to select Data2, clear for Data1
6822 * Bit 7: set to enable DMic, clear for AMic
6823 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006824 if (ca0132_quirk(spec) == QUIRK_ALIENWARE_M17XR4)
Alastair Bridgewatera57a46b2018-06-15 21:56:20 -04006825 val = 0x33;
6826 else
6827 val = 0x23;
Ian Minett5aaca442012-12-20 18:53:34 -08006828 /* keep a copy of dmic ctl val for enable/disable dmic purpuse */
6829 spec->dmic_ctl = val;
6830 snd_hda_codec_write(codec, spec->input_pins[0], 0,
6831 VENDOR_CHIPIO_DMIC_CTL_SET, val);
6832}
6833
6834/*
6835 * Initialization for Analog Mic 2
6836 */
6837static void ca0132_init_analog_mic2(struct hda_codec *codec)
6838{
6839 struct ca0132_spec *spec = codec->spec;
6840
6841 mutex_lock(&spec->chipio_mutex);
6842 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
6843 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20);
6844 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
6845 VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19);
6846 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
6847 VENDOR_CHIPIO_8051_DATA_WRITE, 0x00);
6848 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
6849 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x2D);
6850 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
6851 VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19);
6852 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
6853 VENDOR_CHIPIO_8051_DATA_WRITE, 0x00);
6854 mutex_unlock(&spec->chipio_mutex);
6855}
6856
6857static void ca0132_refresh_widget_caps(struct hda_codec *codec)
6858{
6859 struct ca0132_spec *spec = codec->spec;
6860 int i;
Ian Minett5aaca442012-12-20 18:53:34 -08006861
Takashi Iwai4e76a882014-02-25 12:21:03 +01006862 codec_dbg(codec, "ca0132_refresh_widget_caps.\n");
Takashi Iwai7639a062015-03-03 10:07:24 +01006863 snd_hda_codec_update_widgets(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08006864
6865 for (i = 0; i < spec->multiout.num_dacs; i++)
6866 refresh_amp_caps(codec, spec->dacs[i], HDA_OUTPUT);
6867
6868 for (i = 0; i < spec->num_outputs; i++)
6869 refresh_amp_caps(codec, spec->out_pins[i], HDA_OUTPUT);
6870
6871 for (i = 0; i < spec->num_inputs; i++) {
6872 refresh_amp_caps(codec, spec->adcs[i], HDA_INPUT);
6873 refresh_amp_caps(codec, spec->input_pins[i], HDA_INPUT);
6874 }
6875}
6876
6877/*
Connor McAdams6ef0e912018-09-18 14:33:37 -04006878 * Creates a dummy stream to bind the output to. This seems to have to be done
6879 * after changing the main outputs source and destination streams.
Connor McAdams7e6ed622018-05-08 13:20:08 -04006880 */
Connor McAdams6ef0e912018-09-18 14:33:37 -04006881static void ca0132_alt_create_dummy_stream(struct hda_codec *codec)
Connor McAdams447fd8e2018-05-08 13:20:09 -04006882{
Connor McAdams6ef0e912018-09-18 14:33:37 -04006883 struct ca0132_spec *spec = codec->spec;
6884 unsigned int stream_format;
Connor McAdams447fd8e2018-05-08 13:20:09 -04006885
Connor McAdams6ef0e912018-09-18 14:33:37 -04006886 stream_format = snd_hdac_calc_stream_format(48000, 2,
6887 SNDRV_PCM_FORMAT_S32_LE, 32, 0);
Connor McAdams447fd8e2018-05-08 13:20:09 -04006888
Connor McAdams6ef0e912018-09-18 14:33:37 -04006889 snd_hda_codec_setup_stream(codec, spec->dacs[0], spec->dsp_stream_id,
6890 0, stream_format);
Connor McAdams447fd8e2018-05-08 13:20:09 -04006891
Connor McAdams6ef0e912018-09-18 14:33:37 -04006892 snd_hda_codec_cleanup_stream(codec, spec->dacs[0]);
Connor McAdams7e6ed622018-05-08 13:20:08 -04006893}
6894
6895/*
Connor McAdams6ef0e912018-09-18 14:33:37 -04006896 * Initialize mic for non-chromebook ca0132 implementations.
Connor McAdams38ba69f2018-05-08 13:20:07 -04006897 */
Connor McAdams6ef0e912018-09-18 14:33:37 -04006898static void ca0132_alt_init_analog_mics(struct hda_codec *codec)
Connor McAdams38ba69f2018-05-08 13:20:07 -04006899{
Connor McAdams6ef0e912018-09-18 14:33:37 -04006900 struct ca0132_spec *spec = codec->spec;
Connor McAdams38ba69f2018-05-08 13:20:07 -04006901 unsigned int tmp;
6902
6903 /* Mic 1 Setup */
6904 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
6905 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01006906 if (ca0132_quirk(spec) == QUIRK_R3DI) {
Connor McAdams6ef0e912018-09-18 14:33:37 -04006907 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
6908 tmp = FLOAT_ONE;
6909 } else
6910 tmp = FLOAT_THREE;
Connor McAdams38ba69f2018-05-08 13:20:07 -04006911 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
6912
Connor McAdams6ef0e912018-09-18 14:33:37 -04006913 /* Mic 2 setup (not present on desktop cards) */
Connor McAdams38ba69f2018-05-08 13:20:07 -04006914 chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000);
6915 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000);
Takashi Iwai6da8f442018-11-09 14:18:32 +01006916 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdams6ef0e912018-09-18 14:33:37 -04006917 chipio_set_conn_rate(codec, 0x0F, SR_96_000);
Connor McAdams38ba69f2018-05-08 13:20:07 -04006918 tmp = FLOAT_ZERO;
6919 dspio_set_uint_param(codec, 0x80, 0x01, tmp);
Connor McAdams38ba69f2018-05-08 13:20:07 -04006920}
6921
6922/*
6923 * Sets the source of stream 0x14 to connpointID 0x48, and the destination
6924 * connpointID to 0x91. If this isn't done, the destination is 0x71, and
6925 * you get no sound. I'm guessing this has to do with the Sound Blaster Z
6926 * having an updated DAC, which changes the destination to that DAC.
6927 */
6928static void sbz_connect_streams(struct hda_codec *codec)
6929{
6930 struct ca0132_spec *spec = codec->spec;
6931
6932 mutex_lock(&spec->chipio_mutex);
6933
6934 codec_dbg(codec, "Connect Streams entered, mutex locked and loaded.\n");
6935
6936 chipio_set_stream_channels(codec, 0x0C, 6);
6937 chipio_set_stream_control(codec, 0x0C, 1);
6938
6939 /* This value is 0x43 for 96khz, and 0x83 for 192khz. */
6940 chipio_write_no_mutex(codec, 0x18a020, 0x00000043);
6941
6942 /* Setup stream 0x14 with it's source and destination points */
6943 chipio_set_stream_source_dest(codec, 0x14, 0x48, 0x91);
6944 chipio_set_conn_rate_no_mutex(codec, 0x48, SR_96_000);
6945 chipio_set_conn_rate_no_mutex(codec, 0x91, SR_96_000);
6946 chipio_set_stream_channels(codec, 0x14, 2);
6947 chipio_set_stream_control(codec, 0x14, 1);
6948
6949 codec_dbg(codec, "Connect Streams exited, mutex released.\n");
6950
6951 mutex_unlock(&spec->chipio_mutex);
Connor McAdams38ba69f2018-05-08 13:20:07 -04006952}
6953
6954/*
6955 * Write data through ChipIO to setup proper stream destinations.
6956 * Not sure how it exactly works, but it seems to direct data
6957 * to different destinations. Example is f8 to c0, e0 to c0.
6958 * All I know is, if you don't set these, you get no sound.
6959 */
6960static void sbz_chipio_startup_data(struct hda_codec *codec)
6961{
6962 struct ca0132_spec *spec = codec->spec;
6963
6964 mutex_lock(&spec->chipio_mutex);
6965 codec_dbg(codec, "Startup Data entered, mutex locked and loaded.\n");
6966
6967 /* These control audio output */
6968 chipio_write_no_mutex(codec, 0x190060, 0x0001f8c0);
6969 chipio_write_no_mutex(codec, 0x190064, 0x0001f9c1);
6970 chipio_write_no_mutex(codec, 0x190068, 0x0001fac6);
6971 chipio_write_no_mutex(codec, 0x19006c, 0x0001fbc7);
6972 /* Signal to update I think */
6973 chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
6974
6975 chipio_set_stream_channels(codec, 0x0C, 6);
6976 chipio_set_stream_control(codec, 0x0C, 1);
6977 /* No clue what these control */
Takashi Iwai6da8f442018-11-09 14:18:32 +01006978 if (ca0132_quirk(spec) == QUIRK_SBZ) {
Connor McAdamsc25c73e2018-09-29 23:03:22 -04006979 chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0);
6980 chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1);
6981 chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2);
6982 chipio_write_no_mutex(codec, 0x19003c, 0x0001e5c3);
6983 chipio_write_no_mutex(codec, 0x190040, 0x0001e2c4);
6984 chipio_write_no_mutex(codec, 0x190044, 0x0001e3c5);
6985 chipio_write_no_mutex(codec, 0x190048, 0x0001e8c6);
6986 chipio_write_no_mutex(codec, 0x19004c, 0x0001e9c7);
6987 chipio_write_no_mutex(codec, 0x190050, 0x0001ecc8);
6988 chipio_write_no_mutex(codec, 0x190054, 0x0001edc9);
6989 chipio_write_no_mutex(codec, 0x190058, 0x0001eaca);
6990 chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb);
Takashi Iwai6da8f442018-11-09 14:18:32 +01006991 } else if (ca0132_quirk(spec) == QUIRK_ZXR) {
Connor McAdamsc25c73e2018-09-29 23:03:22 -04006992 chipio_write_no_mutex(codec, 0x190038, 0x000140c2);
6993 chipio_write_no_mutex(codec, 0x19003c, 0x000141c3);
6994 chipio_write_no_mutex(codec, 0x190040, 0x000150c4);
6995 chipio_write_no_mutex(codec, 0x190044, 0x000151c5);
6996 chipio_write_no_mutex(codec, 0x190050, 0x000142c8);
6997 chipio_write_no_mutex(codec, 0x190054, 0x000143c9);
6998 chipio_write_no_mutex(codec, 0x190058, 0x000152ca);
6999 chipio_write_no_mutex(codec, 0x19005c, 0x000153cb);
7000 }
Connor McAdams38ba69f2018-05-08 13:20:07 -04007001 chipio_write_no_mutex(codec, 0x19042c, 0x00000001);
7002
7003 codec_dbg(codec, "Startup Data exited, mutex released.\n");
7004 mutex_unlock(&spec->chipio_mutex);
7005}
7006
Connor McAdams447fd8e2018-05-08 13:20:09 -04007007/*
Connor McAdams6ef0e912018-09-18 14:33:37 -04007008 * Custom DSP SCP commands where the src value is 0x00 instead of 0x20. This is
7009 * done after the DSP is loaded.
Connor McAdams447fd8e2018-05-08 13:20:09 -04007010 */
Connor McAdams6ef0e912018-09-18 14:33:37 -04007011static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec)
Connor McAdams447fd8e2018-05-08 13:20:09 -04007012{
Connor McAdams6ef0e912018-09-18 14:33:37 -04007013 struct ca0132_spec *spec = codec->spec;
Connor McAdamsb5a22932018-10-21 13:53:03 -04007014 unsigned int tmp, i;
Connor McAdams447fd8e2018-05-08 13:20:09 -04007015
Connor McAdamsb5a22932018-10-21 13:53:03 -04007016 /*
7017 * Gotta run these twice, or else mic works inconsistently. Not clear
7018 * why this is, but multiple tests have confirmed it.
7019 */
7020 for (i = 0; i < 2; i++) {
Takashi Iwai6da8f442018-11-09 14:18:32 +01007021 switch (ca0132_quirk(spec)) {
Connor McAdamsb5a22932018-10-21 13:53:03 -04007022 case QUIRK_SBZ:
7023 case QUIRK_AE5:
7024 tmp = 0x00000003;
7025 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7026 tmp = 0x00000000;
7027 dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7028 tmp = 0x00000001;
7029 dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
7030 tmp = 0x00000004;
7031 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7032 tmp = 0x00000005;
7033 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7034 tmp = 0x00000000;
7035 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7036 break;
7037 case QUIRK_R3D:
7038 case QUIRK_R3DI:
7039 tmp = 0x00000000;
7040 dspio_set_uint_param_no_source(codec, 0x80, 0x0A, tmp);
7041 tmp = 0x00000001;
7042 dspio_set_uint_param_no_source(codec, 0x80, 0x0B, tmp);
7043 tmp = 0x00000004;
7044 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7045 tmp = 0x00000005;
7046 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7047 tmp = 0x00000000;
7048 dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp);
7049 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01007050 default:
7051 break;
Connor McAdamsb5a22932018-10-21 13:53:03 -04007052 }
7053 msleep(100);
Connor McAdams6ef0e912018-09-18 14:33:37 -04007054 }
Connor McAdams447fd8e2018-05-08 13:20:09 -04007055}
7056
Connor McAdams6ef0e912018-09-18 14:33:37 -04007057static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec)
Connor McAdams38ba69f2018-05-08 13:20:07 -04007058{
Connor McAdams6ef0e912018-09-18 14:33:37 -04007059 struct ca0132_spec *spec = codec->spec;
Connor McAdams38ba69f2018-05-08 13:20:07 -04007060 unsigned int tmp;
7061
7062 chipio_set_stream_control(codec, 0x03, 0);
7063 chipio_set_stream_control(codec, 0x04, 0);
7064
7065 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
7066 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
7067
7068 tmp = FLOAT_THREE;
7069 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
7070
7071 chipio_set_stream_control(codec, 0x03, 1);
7072 chipio_set_stream_control(codec, 0x04, 1);
7073
Takashi Iwai6da8f442018-11-09 14:18:32 +01007074 switch (ca0132_quirk(spec)) {
Connor McAdams6ef0e912018-09-18 14:33:37 -04007075 case QUIRK_SBZ:
7076 chipio_write(codec, 0x18b098, 0x0000000c);
7077 chipio_write(codec, 0x18b09C, 0x0000000c);
7078 break;
7079 case QUIRK_AE5:
7080 chipio_write(codec, 0x18b098, 0x0000000c);
7081 chipio_write(codec, 0x18b09c, 0x0000004c);
7082 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01007083 default:
7084 break;
Connor McAdams6ef0e912018-09-18 14:33:37 -04007085 }
Connor McAdams38ba69f2018-05-08 13:20:07 -04007086}
7087
Connor McAdams415cd842018-09-18 14:33:38 -04007088static void ae5_post_dsp_register_set(struct hda_codec *codec)
7089{
7090 struct ca0132_spec *spec = codec->spec;
7091
7092 chipio_8051_write_direct(codec, 0x93, 0x10);
7093 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7094 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
7095 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7096 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
7097
7098 writeb(0xff, spec->mem_base + 0x304);
7099 writeb(0xff, spec->mem_base + 0x304);
7100 writeb(0xff, spec->mem_base + 0x304);
7101 writeb(0xff, spec->mem_base + 0x304);
7102 writeb(0x00, spec->mem_base + 0x100);
7103 writeb(0xff, spec->mem_base + 0x304);
7104 writeb(0x00, spec->mem_base + 0x100);
7105 writeb(0xff, spec->mem_base + 0x304);
7106 writeb(0x00, spec->mem_base + 0x100);
7107 writeb(0xff, spec->mem_base + 0x304);
7108 writeb(0x00, spec->mem_base + 0x100);
7109 writeb(0xff, spec->mem_base + 0x304);
7110
7111 ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x3f);
7112 ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
7113 ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7114}
7115
7116static void ae5_post_dsp_param_setup(struct hda_codec *codec)
7117{
7118 /*
7119 * Param3 in the 8051's memory is represented by the ascii string 'mch'
7120 * which seems to be 'multichannel'. This is also mentioned in the
7121 * AE-5's registry values in Windows.
7122 */
7123 chipio_set_control_param(codec, 3, 0);
7124 /*
7125 * I believe ASI is 'audio serial interface' and that it's used to
7126 * change colors on the external LED strip connected to the AE-5.
7127 */
7128 chipio_set_control_flag(codec, CONTROL_FLAG_ASI_96KHZ, 1);
7129
7130 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x724, 0x83);
7131 chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
7132
7133 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7134 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x92);
7135 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7136 VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0xfa);
7137 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7138 VENDOR_CHIPIO_8051_DATA_WRITE, 0x22);
7139}
7140
7141static void ae5_post_dsp_pll_setup(struct hda_codec *codec)
7142{
7143 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7144 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x41);
7145 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7146 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc8);
7147
7148 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7149 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x45);
7150 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7151 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcc);
7152
7153 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7154 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x40);
7155 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7156 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xcb);
7157
7158 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7159 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7160 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7161 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7162
7163 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7164 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x51);
7165 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7166 VENDOR_CHIPIO_PLL_PMU_WRITE, 0x8d);
7167}
7168
7169static void ae5_post_dsp_stream_setup(struct hda_codec *codec)
7170{
7171 struct ca0132_spec *spec = codec->spec;
7172
7173 mutex_lock(&spec->chipio_mutex);
7174
7175 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x725, 0x81);
7176
7177 chipio_set_conn_rate_no_mutex(codec, 0x70, SR_96_000);
7178
7179 chipio_set_stream_channels(codec, 0x0C, 6);
7180 chipio_set_stream_control(codec, 0x0C, 1);
7181
7182 chipio_set_stream_source_dest(codec, 0x5, 0x43, 0x0);
7183
7184 chipio_set_stream_source_dest(codec, 0x18, 0x9, 0xd0);
7185 chipio_set_conn_rate_no_mutex(codec, 0xd0, SR_96_000);
7186 chipio_set_stream_channels(codec, 0x18, 6);
7187 chipio_set_stream_control(codec, 0x18, 1);
7188
7189 chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 4);
7190
7191 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7192 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x43);
7193 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
7194 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc7);
7195
7196 ca0113_mmio_command_set(codec, 0x48, 0x01, 0x80);
7197
7198 mutex_unlock(&spec->chipio_mutex);
7199}
7200
7201static void ae5_post_dsp_startup_data(struct hda_codec *codec)
7202{
7203 struct ca0132_spec *spec = codec->spec;
7204
7205 mutex_lock(&spec->chipio_mutex);
7206
7207 chipio_write_no_mutex(codec, 0x189000, 0x0001f101);
7208 chipio_write_no_mutex(codec, 0x189004, 0x0001f101);
7209 chipio_write_no_mutex(codec, 0x189024, 0x00014004);
7210 chipio_write_no_mutex(codec, 0x189028, 0x0002000f);
7211
7212 ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
7213 chipio_set_control_param_no_mutex(codec, CONTROL_PARAM_ASI, 7);
7214 ca0113_mmio_command_set(codec, 0x48, 0x0b, 0x12);
7215 ca0113_mmio_command_set(codec, 0x48, 0x04, 0x00);
7216 ca0113_mmio_command_set(codec, 0x48, 0x06, 0x48);
7217 ca0113_mmio_command_set(codec, 0x48, 0x0a, 0x05);
7218 ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7219 ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7220 ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7221 ca0113_mmio_gpio_set(codec, 0, true);
7222 ca0113_mmio_gpio_set(codec, 1, true);
7223 ca0113_mmio_command_set(codec, 0x48, 0x07, 0x80);
7224
7225 chipio_write_no_mutex(codec, 0x18b03c, 0x00000012);
7226
7227 ca0113_mmio_command_set(codec, 0x48, 0x0f, 0x00);
7228 ca0113_mmio_command_set(codec, 0x48, 0x10, 0x00);
7229
7230 mutex_unlock(&spec->chipio_mutex);
7231}
7232
Connor McAdams38ba69f2018-05-08 13:20:07 -04007233/*
Ian Minett5aaca442012-12-20 18:53:34 -08007234 * Setup default parameters for DSP
7235 */
7236static void ca0132_setup_defaults(struct hda_codec *codec)
7237{
Dylan Reide8f1bd52013-03-14 17:27:45 -07007238 struct ca0132_spec *spec = codec->spec;
Ian Minett5aaca442012-12-20 18:53:34 -08007239 unsigned int tmp;
7240 int num_fx;
7241 int idx, i;
7242
Dylan Reide8f1bd52013-03-14 17:27:45 -07007243 if (spec->dsp_state != DSP_DOWNLOADED)
Ian Minett5aaca442012-12-20 18:53:34 -08007244 return;
7245
7246 /* out, in effects + voicefx */
7247 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
7248 for (idx = 0; idx < num_fx; idx++) {
7249 for (i = 0; i <= ca0132_effects[idx].params; i++) {
7250 dspio_set_uint_param(codec, ca0132_effects[idx].mid,
7251 ca0132_effects[idx].reqs[i],
7252 ca0132_effects[idx].def_vals[i]);
7253 }
7254 }
7255
7256 /*remove DSP headroom*/
7257 tmp = FLOAT_ZERO;
7258 dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
7259
7260 /*set speaker EQ bypass attenuation*/
7261 dspio_set_uint_param(codec, 0x8f, 0x01, tmp);
7262
7263 /* set AMic1 and AMic2 as mono mic */
7264 tmp = FLOAT_ONE;
7265 dspio_set_uint_param(codec, 0x80, 0x00, tmp);
7266 dspio_set_uint_param(codec, 0x80, 0x01, tmp);
7267
7268 /* set AMic1 as CrystalVoice input */
7269 tmp = FLOAT_ONE;
7270 dspio_set_uint_param(codec, 0x80, 0x05, tmp);
7271
7272 /* set WUH source */
7273 tmp = FLOAT_TWO;
7274 dspio_set_uint_param(codec, 0x31, 0x00, tmp);
7275}
7276
7277/*
Connor McAdamsc986f502018-08-08 13:34:19 -04007278 * Setup default parameters for Recon3D/Recon3Di DSP.
Connor McAdams7e6ed622018-05-08 13:20:08 -04007279 */
7280
Connor McAdamsc986f502018-08-08 13:34:19 -04007281static void r3d_setup_defaults(struct hda_codec *codec)
Connor McAdams7e6ed622018-05-08 13:20:08 -04007282{
7283 struct ca0132_spec *spec = codec->spec;
7284 unsigned int tmp;
7285 int num_fx;
7286 int idx, i;
7287
7288 if (spec->dsp_state != DSP_DOWNLOADED)
7289 return;
7290
Connor McAdams6ef0e912018-09-18 14:33:37 -04007291 ca0132_alt_dsp_scp_startup(codec);
7292 ca0132_alt_init_analog_mics(codec);
Connor McAdams7e6ed622018-05-08 13:20:08 -04007293
7294 /*remove DSP headroom*/
7295 tmp = FLOAT_ZERO;
7296 dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
7297
7298 /* set WUH source */
7299 tmp = FLOAT_TWO;
7300 dspio_set_uint_param(codec, 0x31, 0x00, tmp);
7301 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
7302
7303 /* Set speaker source? */
7304 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
7305
Takashi Iwai6da8f442018-11-09 14:18:32 +01007306 if (ca0132_quirk(spec) == QUIRK_R3DI)
Connor McAdamsc986f502018-08-08 13:34:19 -04007307 r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED);
Connor McAdams7e6ed622018-05-08 13:20:08 -04007308
7309 /* Setup effect defaults */
7310 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
7311 for (idx = 0; idx < num_fx; idx++) {
7312 for (i = 0; i <= ca0132_effects[idx].params; i++) {
7313 dspio_set_uint_param(codec,
7314 ca0132_effects[idx].mid,
7315 ca0132_effects[idx].reqs[i],
7316 ca0132_effects[idx].def_vals[i]);
7317 }
7318 }
Connor McAdams7e6ed622018-05-08 13:20:08 -04007319}
7320
7321/*
Connor McAdams38ba69f2018-05-08 13:20:07 -04007322 * Setup default parameters for the Sound Blaster Z DSP. A lot more going on
7323 * than the Chromebook setup.
7324 */
7325static void sbz_setup_defaults(struct hda_codec *codec)
7326{
7327 struct ca0132_spec *spec = codec->spec;
Connor McAdams6ef0e912018-09-18 14:33:37 -04007328 unsigned int tmp;
Connor McAdams38ba69f2018-05-08 13:20:07 -04007329 int num_fx;
7330 int idx, i;
7331
7332 if (spec->dsp_state != DSP_DOWNLOADED)
7333 return;
7334
Connor McAdams6ef0e912018-09-18 14:33:37 -04007335 ca0132_alt_dsp_scp_startup(codec);
7336 ca0132_alt_init_analog_mics(codec);
Connor McAdams38ba69f2018-05-08 13:20:07 -04007337 sbz_connect_streams(codec);
Connor McAdams38ba69f2018-05-08 13:20:07 -04007338 sbz_chipio_startup_data(codec);
7339
7340 chipio_set_stream_control(codec, 0x03, 1);
7341 chipio_set_stream_control(codec, 0x04, 1);
7342
7343 /*
7344 * Sets internal input loopback to off, used to have a switch to
7345 * enable input loopback, but turned out to be way too buggy.
7346 */
7347 tmp = FLOAT_ONE;
7348 dspio_set_uint_param(codec, 0x37, 0x08, tmp);
7349 dspio_set_uint_param(codec, 0x37, 0x10, tmp);
7350
7351 /*remove DSP headroom*/
7352 tmp = FLOAT_ZERO;
7353 dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
7354
7355 /* set WUH source */
7356 tmp = FLOAT_TWO;
7357 dspio_set_uint_param(codec, 0x31, 0x00, tmp);
7358 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
7359
7360 /* Set speaker source? */
7361 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
7362
Connor McAdams6ef0e912018-09-18 14:33:37 -04007363 ca0132_alt_dsp_initial_mic_setup(codec);
Connor McAdams38ba69f2018-05-08 13:20:07 -04007364
7365 /* out, in effects + voicefx */
7366 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
7367 for (idx = 0; idx < num_fx; idx++) {
7368 for (i = 0; i <= ca0132_effects[idx].params; i++) {
7369 dspio_set_uint_param(codec,
7370 ca0132_effects[idx].mid,
7371 ca0132_effects[idx].reqs[i],
7372 ca0132_effects[idx].def_vals[i]);
7373 }
7374 }
7375
Connor McAdams6ef0e912018-09-18 14:33:37 -04007376 ca0132_alt_create_dummy_stream(codec);
Connor McAdams38ba69f2018-05-08 13:20:07 -04007377}
7378
7379/*
Connor McAdams415cd842018-09-18 14:33:38 -04007380 * Setup default parameters for the Sound BlasterX AE-5 DSP.
7381 */
7382static void ae5_setup_defaults(struct hda_codec *codec)
7383{
7384 struct ca0132_spec *spec = codec->spec;
7385 unsigned int tmp;
7386 int num_fx;
7387 int idx, i;
7388
7389 if (spec->dsp_state != DSP_DOWNLOADED)
7390 return;
7391
7392 ca0132_alt_dsp_scp_startup(codec);
7393 ca0132_alt_init_analog_mics(codec);
7394 chipio_set_stream_control(codec, 0x03, 1);
7395 chipio_set_stream_control(codec, 0x04, 1);
7396
7397 /* New, unknown SCP req's */
7398 tmp = FLOAT_ZERO;
7399 dspio_set_uint_param(codec, 0x96, 0x29, tmp);
7400 dspio_set_uint_param(codec, 0x96, 0x2a, tmp);
7401 dspio_set_uint_param(codec, 0x80, 0x0d, tmp);
7402 dspio_set_uint_param(codec, 0x80, 0x0e, tmp);
7403
7404 ca0113_mmio_command_set(codec, 0x30, 0x2e, 0x3f);
7405 ca0113_mmio_gpio_set(codec, 0, false);
7406 ca0113_mmio_command_set(codec, 0x30, 0x28, 0x00);
7407
7408 /* Internal loopback off */
7409 tmp = FLOAT_ONE;
7410 dspio_set_uint_param(codec, 0x37, 0x08, tmp);
7411 dspio_set_uint_param(codec, 0x37, 0x10, tmp);
7412
7413 /*remove DSP headroom*/
7414 tmp = FLOAT_ZERO;
7415 dspio_set_uint_param(codec, 0x96, 0x3C, tmp);
7416
7417 /* set WUH source */
7418 tmp = FLOAT_TWO;
7419 dspio_set_uint_param(codec, 0x31, 0x00, tmp);
7420 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
7421
7422 /* Set speaker source? */
7423 dspio_set_uint_param(codec, 0x32, 0x00, tmp);
7424
7425 ca0132_alt_dsp_initial_mic_setup(codec);
7426 ae5_post_dsp_register_set(codec);
7427 ae5_post_dsp_param_setup(codec);
7428 ae5_post_dsp_pll_setup(codec);
7429 ae5_post_dsp_stream_setup(codec);
7430 ae5_post_dsp_startup_data(codec);
7431
7432 /* out, in effects + voicefx */
7433 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT + 1;
7434 for (idx = 0; idx < num_fx; idx++) {
7435 for (i = 0; i <= ca0132_effects[idx].params; i++) {
7436 dspio_set_uint_param(codec,
7437 ca0132_effects[idx].mid,
7438 ca0132_effects[idx].reqs[i],
7439 ca0132_effects[idx].def_vals[i]);
7440 }
7441 }
7442
7443 ca0132_alt_create_dummy_stream(codec);
7444}
7445
7446/*
Ian Minett5aaca442012-12-20 18:53:34 -08007447 * Initialization of flags in chip
7448 */
7449static void ca0132_init_flags(struct hda_codec *codec)
7450{
Connor McAdams009b8f92018-05-08 13:20:06 -04007451 struct ca0132_spec *spec = codec->spec;
7452
Takashi Iwai6da8f442018-11-09 14:18:32 +01007453 if (ca0132_use_alt_functions(spec)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04007454 chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1);
7455 chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1);
7456 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1);
7457 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_96KHZ, 1);
7458 chipio_set_control_flag(codec, CONTROL_FLAG_SRC_RATE_96KHZ, 1);
7459 chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
7460 chipio_set_control_flag(codec, CONTROL_FLAG_SPDIF2OUT, 0);
7461 chipio_set_control_flag(codec,
7462 CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
7463 chipio_set_control_flag(codec,
7464 CONTROL_FLAG_PORT_A_10KOHM_LOAD, 1);
7465 } else {
7466 chipio_set_control_flag(codec, CONTROL_FLAG_IDLE_ENABLE, 0);
7467 chipio_set_control_flag(codec,
7468 CONTROL_FLAG_PORT_A_COMMON_MODE, 0);
7469 chipio_set_control_flag(codec,
7470 CONTROL_FLAG_PORT_D_COMMON_MODE, 0);
7471 chipio_set_control_flag(codec,
7472 CONTROL_FLAG_PORT_A_10KOHM_LOAD, 0);
7473 chipio_set_control_flag(codec,
7474 CONTROL_FLAG_PORT_D_10KOHM_LOAD, 0);
7475 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_HIGH_PASS, 1);
7476 }
Ian Minett5aaca442012-12-20 18:53:34 -08007477}
7478
7479/*
7480 * Initialization of parameters in chip
7481 */
7482static void ca0132_init_params(struct hda_codec *codec)
7483{
Connor McAdams009b8f92018-05-08 13:20:06 -04007484 struct ca0132_spec *spec = codec->spec;
7485
Takashi Iwai6da8f442018-11-09 14:18:32 +01007486 if (ca0132_use_alt_functions(spec)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04007487 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
7488 chipio_set_conn_rate(codec, 0x0B, SR_48_000);
7489 chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0);
7490 chipio_set_control_param(codec, 0, 0);
7491 chipio_set_control_param(codec, CONTROL_PARAM_VIP_SOURCE, 0);
7492 }
7493
Ian Minett5aaca442012-12-20 18:53:34 -08007494 chipio_set_control_param(codec, CONTROL_PARAM_PORTA_160OHM_GAIN, 6);
7495 chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6);
7496}
Ian Minett95c6e9c2011-06-15 15:35:17 -07007497
Ian Minette90f29e2012-12-20 18:53:39 -08007498static void ca0132_set_dsp_msr(struct hda_codec *codec, bool is96k)
7499{
7500 chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, is96k);
7501 chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, is96k);
7502 chipio_set_control_flag(codec, CONTROL_FLAG_SRC_RATE_96KHZ, is96k);
7503 chipio_set_control_flag(codec, CONTROL_FLAG_SRC_CLOCK_196MHZ, is96k);
7504 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, is96k);
7505 chipio_set_control_flag(codec, CONTROL_FLAG_ADC_C_96KHZ, is96k);
7506
Ian Minett406261c2012-12-20 18:53:41 -08007507 chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000);
7508 chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000);
Ian Minette90f29e2012-12-20 18:53:39 -08007509 chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000);
7510}
7511
7512static bool ca0132_download_dsp_images(struct hda_codec *codec)
7513{
7514 bool dsp_loaded = false;
Connor McAdams8a19bce2018-05-08 13:20:01 -04007515 struct ca0132_spec *spec = codec->spec;
Ian Minette90f29e2012-12-20 18:53:39 -08007516 const struct dsp_image_seg *dsp_os_image;
Takashi Iwai4fc90fb2019-03-22 15:51:36 +01007517 const struct firmware *fw_entry = NULL;
Connor McAdams8a19bce2018-05-08 13:20:01 -04007518 /*
7519 * Alternate firmwares for different variants. The Recon3Di apparently
7520 * can use the default firmware, but I'll leave the option in case
7521 * it needs it again.
7522 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01007523 switch (ca0132_quirk(spec)) {
Connor McAdams8a19bce2018-05-08 13:20:01 -04007524 case QUIRK_SBZ:
Connor McAdams7a928182018-09-18 14:33:36 -04007525 case QUIRK_R3D:
7526 case QUIRK_AE5:
7527 if (request_firmware(&fw_entry, DESKTOP_EFX_FILE,
Takashi Iwai4fc90fb2019-03-22 15:51:36 +01007528 codec->card->dev) != 0)
Connor McAdams6ef0e912018-09-18 14:33:37 -04007529 codec_dbg(codec, "Desktop firmware not found.");
Takashi Iwai4fc90fb2019-03-22 15:51:36 +01007530 else
Connor McAdams7a928182018-09-18 14:33:36 -04007531 codec_dbg(codec, "Desktop firmware selected.");
Connor McAdams8a19bce2018-05-08 13:20:01 -04007532 break;
7533 case QUIRK_R3DI:
7534 if (request_firmware(&fw_entry, R3DI_EFX_FILE,
Takashi Iwai4fc90fb2019-03-22 15:51:36 +01007535 codec->card->dev) != 0)
Connor McAdams8a19bce2018-05-08 13:20:01 -04007536 codec_dbg(codec, "Recon3Di alt firmware not detected.");
Takashi Iwai4fc90fb2019-03-22 15:51:36 +01007537 else
Connor McAdams8a19bce2018-05-08 13:20:01 -04007538 codec_dbg(codec, "Recon3Di firmware selected.");
Connor McAdams8a19bce2018-05-08 13:20:01 -04007539 break;
7540 default:
Connor McAdams8a19bce2018-05-08 13:20:01 -04007541 break;
7542 }
7543 /*
7544 * Use default ctefx.bin if no alt firmware is detected, or if none
7545 * exists for your particular codec.
7546 */
Takashi Iwai4fc90fb2019-03-22 15:51:36 +01007547 if (!fw_entry) {
Connor McAdams8a19bce2018-05-08 13:20:01 -04007548 codec_dbg(codec, "Default firmware selected.");
7549 if (request_firmware(&fw_entry, EFX_FILE,
7550 codec->card->dev) != 0)
7551 return false;
7552 }
Ian Minette90f29e2012-12-20 18:53:39 -08007553
Takashi Iwai15e4ba62013-01-15 17:08:38 +01007554 dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
Dylan Reidd1d28502013-03-14 17:27:44 -07007555 if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) {
Takashi Iwaid9684bb2015-10-26 16:54:16 +01007556 codec_err(codec, "ca0132 DSP load image failed\n");
Dylan Reidd1d28502013-03-14 17:27:44 -07007557 goto exit_download;
7558 }
7559
Ian Minette90f29e2012-12-20 18:53:39 -08007560 dsp_loaded = dspload_wait_loaded(codec);
7561
Dylan Reidd1d28502013-03-14 17:27:44 -07007562exit_download:
Takashi Iwai15e4ba62013-01-15 17:08:38 +01007563 release_firmware(fw_entry);
7564
Ian Minette90f29e2012-12-20 18:53:39 -08007565 return dsp_loaded;
7566}
7567
7568static void ca0132_download_dsp(struct hda_codec *codec)
7569{
7570 struct ca0132_spec *spec = codec->spec;
7571
Takashi Iwai9a0869f2013-02-07 12:41:40 +01007572#ifndef CONFIG_SND_HDA_CODEC_CA0132_DSP
7573 return; /* NOP */
7574#endif
Ian Minette90f29e2012-12-20 18:53:39 -08007575
Takashi Iwaie24aa0a2014-08-10 13:30:08 +02007576 if (spec->dsp_state == DSP_DOWNLOAD_FAILED)
7577 return; /* don't retry failures */
7578
Dylan Reidb714a712013-03-14 17:27:46 -07007579 chipio_enable_clocks(codec);
Connor McAdamse93ac302018-05-08 13:20:05 -04007580 if (spec->dsp_state != DSP_DOWNLOADED) {
7581 spec->dsp_state = DSP_DOWNLOADING;
7582
7583 if (!ca0132_download_dsp_images(codec))
7584 spec->dsp_state = DSP_DOWNLOAD_FAILED;
7585 else
7586 spec->dsp_state = DSP_DOWNLOADED;
7587 }
Ian Minette90f29e2012-12-20 18:53:39 -08007588
Connor McAdams009b8f92018-05-08 13:20:06 -04007589 /* For codecs using alt functions, this is already done earlier */
Takashi Iwai6da8f442018-11-09 14:18:32 +01007590 if (spec->dsp_state == DSP_DOWNLOADED && !ca0132_use_alt_functions(spec))
Ian Minette90f29e2012-12-20 18:53:39 -08007591 ca0132_set_dsp_msr(codec, true);
7592}
7593
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007594static void ca0132_process_dsp_response(struct hda_codec *codec,
7595 struct hda_jack_callback *callback)
Ian Minette90f29e2012-12-20 18:53:39 -08007596{
7597 struct ca0132_spec *spec = codec->spec;
7598
Takashi Iwai4e76a882014-02-25 12:21:03 +01007599 codec_dbg(codec, "ca0132_process_dsp_response\n");
Takashi Iwai377bc0c2019-12-13 09:51:09 +01007600 snd_hda_power_up_pm(codec);
Ian Minette90f29e2012-12-20 18:53:39 -08007601 if (spec->wait_scp) {
7602 if (dspio_get_response_data(codec) >= 0)
7603 spec->wait_scp = 0;
7604 }
7605
7606 dspio_clear_response_queue(codec);
Takashi Iwai377bc0c2019-12-13 09:51:09 +01007607 snd_hda_power_down_pm(codec);
Ian Minette90f29e2012-12-20 18:53:39 -08007608}
7609
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007610static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
Ian Minette90f29e2012-12-20 18:53:39 -08007611{
Chih-Chung Chang993884f2013-03-25 10:39:23 -07007612 struct ca0132_spec *spec = codec->spec;
Takashi Iwai2ebab402016-02-09 10:23:52 +01007613 struct hda_jack_tbl *tbl;
Ian Minette90f29e2012-12-20 18:53:39 -08007614
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007615 /* Delay enabling the HP amp, to let the mic-detection
7616 * state machine run.
7617 */
Takashi Iwai2ebab402016-02-09 10:23:52 +01007618 tbl = snd_hda_jack_tbl_get(codec, cb->nid);
7619 if (tbl)
7620 tbl->block_report = 1;
Takashi Iwai42fb6b12019-12-13 09:51:11 +01007621 schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007622}
Ian Minette90f29e2012-12-20 18:53:39 -08007623
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007624static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
7625{
Connor McAdamsa1b7f012018-08-08 13:34:14 -04007626 struct ca0132_spec *spec = codec->spec;
7627
Takashi Iwai6da8f442018-11-09 14:18:32 +01007628 if (ca0132_use_alt_functions(spec))
Connor McAdamsa1b7f012018-08-08 13:34:14 -04007629 ca0132_alt_select_in(codec);
7630 else
7631 ca0132_select_mic(codec);
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007632}
7633
7634static void ca0132_init_unsol(struct hda_codec *codec)
7635{
Gabriele Martinod5c016b2015-05-18 21:15:13 +02007636 struct ca0132_spec *spec = codec->spec;
7637 snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_hp, hp_callback);
7638 snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_amic1,
Takashi Iwaif8fb1172014-09-11 15:53:26 +02007639 amic_callback);
7640 snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP,
7641 ca0132_process_dsp_response);
Connor McAdams63177af2018-05-08 13:20:02 -04007642 /* Front headphone jack detection */
Takashi Iwai6da8f442018-11-09 14:18:32 +01007643 if (ca0132_use_alt_functions(spec))
Connor McAdams63177af2018-05-08 13:20:02 -04007644 snd_hda_jack_detect_enable_callback(codec,
7645 spec->unsol_tag_front_hp, hp_callback);
Ian Minette90f29e2012-12-20 18:53:39 -08007646}
7647
Ian Minett5aaca442012-12-20 18:53:34 -08007648/*
7649 * Verbs tables.
7650 */
7651
7652/* Sends before DSP download. */
Takashi Iwaibf823262020-01-05 15:47:24 +01007653static const struct hda_verb ca0132_base_init_verbs[] = {
Ian Minett5aaca442012-12-20 18:53:34 -08007654 /*enable ct extension*/
7655 {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1},
Ian Minett5aaca442012-12-20 18:53:34 -08007656 {}
7657};
7658
7659/* Send at exit. */
Takashi Iwaibf823262020-01-05 15:47:24 +01007660static const struct hda_verb ca0132_base_exit_verbs[] = {
Ian Minett5aaca442012-12-20 18:53:34 -08007661 /*set afg to D3*/
7662 {0x01, AC_VERB_SET_POWER_STATE, 0x03},
7663 /*disable ct extension*/
7664 {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0},
7665 {}
7666};
7667
Connor McAdams8a19bce2018-05-08 13:20:01 -04007668/* Other verbs tables. Sends after DSP download. */
Connor McAdamse93ac302018-05-08 13:20:05 -04007669
Takashi Iwaibf823262020-01-05 15:47:24 +01007670static const struct hda_verb ca0132_init_verbs0[] = {
Ian Minett5aaca442012-12-20 18:53:34 -08007671 /* chip init verbs */
7672 {0x15, 0x70D, 0xF0},
7673 {0x15, 0x70E, 0xFE},
7674 {0x15, 0x707, 0x75},
7675 {0x15, 0x707, 0xD3},
7676 {0x15, 0x707, 0x09},
7677 {0x15, 0x707, 0x53},
7678 {0x15, 0x707, 0xD4},
7679 {0x15, 0x707, 0xEF},
7680 {0x15, 0x707, 0x75},
7681 {0x15, 0x707, 0xD3},
7682 {0x15, 0x707, 0x09},
7683 {0x15, 0x707, 0x02},
7684 {0x15, 0x707, 0x37},
7685 {0x15, 0x707, 0x78},
7686 {0x15, 0x53C, 0xCE},
7687 {0x15, 0x575, 0xC9},
7688 {0x15, 0x53D, 0xCE},
7689 {0x15, 0x5B7, 0xC9},
7690 {0x15, 0x70D, 0xE8},
7691 {0x15, 0x70E, 0xFE},
7692 {0x15, 0x707, 0x02},
7693 {0x15, 0x707, 0x68},
7694 {0x15, 0x707, 0x62},
7695 {0x15, 0x53A, 0xCE},
7696 {0x15, 0x546, 0xC9},
7697 {0x15, 0x53B, 0xCE},
7698 {0x15, 0x5E8, 0xC9},
Connor McAdamse93ac302018-05-08 13:20:05 -04007699 {}
7700};
7701
Connor McAdamse42c7c72018-08-08 13:34:18 -04007702/* Extra init verbs for desktop cards. */
Takashi Iwaibf823262020-01-05 15:47:24 +01007703static const struct hda_verb ca0132_init_verbs1[] = {
Connor McAdamse93ac302018-05-08 13:20:05 -04007704 {0x15, 0x70D, 0x20},
7705 {0x15, 0x70E, 0x19},
7706 {0x15, 0x707, 0x00},
7707 {0x15, 0x539, 0xCE},
7708 {0x15, 0x546, 0xC9},
7709 {0x15, 0x70D, 0xB7},
7710 {0x15, 0x70E, 0x09},
7711 {0x15, 0x707, 0x10},
7712 {0x15, 0x70D, 0xAF},
7713 {0x15, 0x70E, 0x09},
7714 {0x15, 0x707, 0x01},
7715 {0x15, 0x707, 0x05},
7716 {0x15, 0x70D, 0x73},
7717 {0x15, 0x70E, 0x09},
7718 {0x15, 0x707, 0x14},
7719 {0x15, 0x6FF, 0xC4},
Ian Minett5aaca442012-12-20 18:53:34 -08007720 {}
7721};
7722
Ian Minett95c6e9c2011-06-15 15:35:17 -07007723static void ca0132_init_chip(struct hda_codec *codec)
7724{
7725 struct ca0132_spec *spec = codec->spec;
Ian Minett5aaca442012-12-20 18:53:34 -08007726 int num_fx;
7727 int i;
7728 unsigned int on;
Ian Minett95c6e9c2011-06-15 15:35:17 -07007729
7730 mutex_init(&spec->chipio_mutex);
Ian Minett5aaca442012-12-20 18:53:34 -08007731
7732 spec->cur_out_type = SPEAKER_OUT;
Takashi Iwai6da8f442018-11-09 14:18:32 +01007733 if (!ca0132_use_alt_functions(spec))
Connor McAdams7cb9d942018-05-08 13:20:10 -04007734 spec->cur_mic_type = DIGITAL_MIC;
7735 else
7736 spec->cur_mic_type = REAR_MIC;
7737
Ian Minett5aaca442012-12-20 18:53:34 -08007738 spec->cur_mic_boost = 0;
7739
7740 for (i = 0; i < VNODES_COUNT; i++) {
7741 spec->vnode_lvol[i] = 0x5a;
7742 spec->vnode_rvol[i] = 0x5a;
7743 spec->vnode_lswitch[i] = 0;
7744 spec->vnode_rswitch[i] = 0;
7745 }
7746
7747 /*
7748 * Default states for effects are in ca0132_effects[].
7749 */
7750 num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT;
7751 for (i = 0; i < num_fx; i++) {
7752 on = (unsigned int)ca0132_effects[i].reqs[0];
7753 spec->effects_switch[i] = on ? 1 : 0;
7754 }
Connor McAdams47cdf762018-05-08 13:20:13 -04007755 /*
7756 * Sets defaults for the effect slider controls, only for alternative
7757 * ca0132 codecs. Also sets x-bass crossover frequency to 80hz.
7758 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01007759 if (ca0132_use_alt_controls(spec)) {
Connor McAdams47cdf762018-05-08 13:20:13 -04007760 spec->xbass_xover_freq = 8;
7761 for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++)
7762 spec->fx_ctl_val[i] = effect_slider_defaults[i];
7763 }
Ian Minett5aaca442012-12-20 18:53:34 -08007764
7765 spec->voicefx_val = 0;
7766 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1;
7767 spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0;
7768
Connor McAdams76dea4d2018-09-29 23:03:24 -04007769 /*
7770 * The ZxR doesn't have a front panel header, and it's line-in is on
7771 * the daughter board. So, there is no input enum control, and we need
7772 * to make sure that spec->in_enum_val is set properly.
7773 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01007774 if (ca0132_quirk(spec) == QUIRK_ZXR)
Connor McAdams76dea4d2018-09-29 23:03:24 -04007775 spec->in_enum_val = REAR_MIC;
7776
Ian Minett44f0c972012-12-20 18:53:38 -08007777#ifdef ENABLE_TUNING_CONTROLS
7778 ca0132_init_tuning_defaults(codec);
7779#endif
Ian Minett95c6e9c2011-06-15 15:35:17 -07007780}
7781
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007782/*
7783 * Recon3Di exit specific commands.
7784 */
7785/* prevents popping noise on shutdown */
7786static void r3di_gpio_shutdown(struct hda_codec *codec)
7787{
7788 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0x00);
7789}
7790
7791/*
7792 * Sound Blaster Z exit specific commands.
7793 */
7794static void sbz_region2_exit(struct hda_codec *codec)
7795{
7796 struct ca0132_spec *spec = codec->spec;
7797 unsigned int i;
7798
7799 for (i = 0; i < 4; i++)
7800 writeb(0x0, spec->mem_base + 0x100);
7801 for (i = 0; i < 8; i++)
7802 writeb(0xb3, spec->mem_base + 0x304);
Connor McAdamsa62e4732018-08-08 13:34:12 -04007803
Connor McAdamsb9b41342018-09-18 14:33:34 -04007804 ca0113_mmio_gpio_set(codec, 0, false);
7805 ca0113_mmio_gpio_set(codec, 1, false);
7806 ca0113_mmio_gpio_set(codec, 4, true);
7807 ca0113_mmio_gpio_set(codec, 5, false);
7808 ca0113_mmio_gpio_set(codec, 7, false);
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007809}
7810
7811static void sbz_set_pin_ctl_default(struct hda_codec *codec)
7812{
Michał Mirosławcaf3c042020-01-03 10:23:48 +01007813 static const hda_nid_t pins[] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007814 unsigned int i;
7815
7816 snd_hda_codec_write(codec, 0x11, 0,
7817 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
7818
Michał Mirosławcaf3c042020-01-03 10:23:48 +01007819 for (i = 0; i < ARRAY_SIZE(pins); i++)
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007820 snd_hda_codec_write(codec, pins[i], 0,
7821 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00);
7822}
7823
Connor McAdams2f295f92018-08-08 13:34:22 -04007824static void ca0132_clear_unsolicited(struct hda_codec *codec)
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007825{
Michał Mirosławcaf3c042020-01-03 10:23:48 +01007826 static const hda_nid_t pins[] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007827 unsigned int i;
7828
Michał Mirosławcaf3c042020-01-03 10:23:48 +01007829 for (i = 0; i < ARRAY_SIZE(pins); i++) {
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007830 snd_hda_codec_write(codec, pins[i], 0,
7831 AC_VERB_SET_UNSOLICITED_ENABLE, 0x00);
7832 }
7833}
7834
7835/* On shutdown, sends commands in sets of three */
7836static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir,
7837 int mask, int data)
7838{
7839 if (dir >= 0)
7840 snd_hda_codec_write(codec, 0x01, 0,
7841 AC_VERB_SET_GPIO_DIRECTION, dir);
7842 if (mask >= 0)
7843 snd_hda_codec_write(codec, 0x01, 0,
7844 AC_VERB_SET_GPIO_MASK, mask);
7845
7846 if (data >= 0)
7847 snd_hda_codec_write(codec, 0x01, 0,
7848 AC_VERB_SET_GPIO_DATA, data);
7849}
7850
Connor McAdams7675a2a2018-09-29 23:03:20 -04007851static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec)
7852{
Michał Mirosławcaf3c042020-01-03 10:23:48 +01007853 static const hda_nid_t pins[] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01};
Connor McAdams7675a2a2018-09-29 23:03:20 -04007854 unsigned int i;
7855
Michał Mirosławcaf3c042020-01-03 10:23:48 +01007856 for (i = 0; i < ARRAY_SIZE(pins); i++)
Connor McAdams7675a2a2018-09-29 23:03:20 -04007857 snd_hda_codec_write(codec, pins[i], 0,
7858 AC_VERB_SET_POWER_STATE, 0x03);
7859}
7860
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007861static void sbz_exit_chip(struct hda_codec *codec)
7862{
Connor McAdams009b8f92018-05-08 13:20:06 -04007863 chipio_set_stream_control(codec, 0x03, 0);
7864 chipio_set_stream_control(codec, 0x04, 0);
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007865
7866 /* Mess with GPIO */
7867 sbz_gpio_shutdown_commands(codec, 0x07, 0x07, -1);
7868 sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x05);
7869 sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x01);
7870
Connor McAdams009b8f92018-05-08 13:20:06 -04007871 chipio_set_stream_control(codec, 0x14, 0);
7872 chipio_set_stream_control(codec, 0x0C, 0);
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007873
7874 chipio_set_conn_rate(codec, 0x41, SR_192_000);
7875 chipio_set_conn_rate(codec, 0x91, SR_192_000);
7876
7877 chipio_write(codec, 0x18a020, 0x00000083);
7878
7879 sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x03);
7880 sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x07);
7881 sbz_gpio_shutdown_commands(codec, 0x07, 0x07, 0x06);
7882
Connor McAdams009b8f92018-05-08 13:20:06 -04007883 chipio_set_stream_control(codec, 0x0C, 0);
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007884
7885 chipio_set_control_param(codec, 0x0D, 0x24);
7886
Connor McAdams2f295f92018-08-08 13:34:22 -04007887 ca0132_clear_unsolicited(codec);
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007888 sbz_set_pin_ctl_default(codec);
7889
7890 snd_hda_codec_write(codec, 0x0B, 0,
7891 AC_VERB_SET_EAPD_BTLENABLE, 0x00);
7892
Connor McAdams2e48b2b2018-05-08 13:20:04 -04007893 sbz_region2_exit(codec);
7894}
7895
Connor McAdams2f295f92018-08-08 13:34:22 -04007896static void r3d_exit_chip(struct hda_codec *codec)
7897{
7898 ca0132_clear_unsolicited(codec);
7899 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
7900 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5b);
7901}
7902
Connor McAdamsedb1b3a2018-09-18 14:33:43 -04007903static void ae5_exit_chip(struct hda_codec *codec)
7904{
7905 chipio_set_stream_control(codec, 0x03, 0);
7906 chipio_set_stream_control(codec, 0x04, 0);
7907
7908 ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
7909 ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7910 ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
7911 ca0113_mmio_command_set(codec, 0x30, 0x30, 0x00);
7912 ca0113_mmio_command_set(codec, 0x30, 0x2b, 0x00);
7913 ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x00);
7914 ca0113_mmio_gpio_set(codec, 0, false);
7915 ca0113_mmio_gpio_set(codec, 1, false);
7916
7917 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
7918 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
7919
7920 chipio_set_control_param(codec, CONTROL_PARAM_ASI, 0);
7921
7922 chipio_set_stream_control(codec, 0x18, 0);
7923 chipio_set_stream_control(codec, 0x0c, 0);
7924
7925 snd_hda_codec_write(codec, 0x01, 0, 0x724, 0x83);
7926}
7927
Connor McAdams96395e82018-09-29 23:03:26 -04007928static void zxr_exit_chip(struct hda_codec *codec)
7929{
7930 chipio_set_stream_control(codec, 0x03, 0);
7931 chipio_set_stream_control(codec, 0x04, 0);
7932 chipio_set_stream_control(codec, 0x14, 0);
7933 chipio_set_stream_control(codec, 0x0C, 0);
7934
7935 chipio_set_conn_rate(codec, 0x41, SR_192_000);
7936 chipio_set_conn_rate(codec, 0x91, SR_192_000);
7937
7938 chipio_write(codec, 0x18a020, 0x00000083);
7939
7940 snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00);
7941 snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x53);
7942
7943 ca0132_clear_unsolicited(codec);
7944 sbz_set_pin_ctl_default(codec);
7945 snd_hda_codec_write(codec, 0x0B, 0, AC_VERB_SET_EAPD_BTLENABLE, 0x00);
7946
7947 ca0113_mmio_gpio_set(codec, 5, false);
7948 ca0113_mmio_gpio_set(codec, 2, false);
7949 ca0113_mmio_gpio_set(codec, 3, false);
7950 ca0113_mmio_gpio_set(codec, 0, false);
7951 ca0113_mmio_gpio_set(codec, 4, true);
7952 ca0113_mmio_gpio_set(codec, 0, true);
7953 ca0113_mmio_gpio_set(codec, 5, true);
7954 ca0113_mmio_gpio_set(codec, 2, false);
7955 ca0113_mmio_gpio_set(codec, 3, false);
7956}
7957
Ian Minett95c6e9c2011-06-15 15:35:17 -07007958static void ca0132_exit_chip(struct hda_codec *codec)
7959{
7960 /* put any chip cleanup stuffs here. */
Ian Minett5aaca442012-12-20 18:53:34 -08007961
7962 if (dspload_is_loaded(codec))
7963 dsp_reset(codec);
Ian Minett95c6e9c2011-06-15 15:35:17 -07007964}
7965
Connor McAdamse93ac302018-05-08 13:20:05 -04007966/*
Connor McAdams38ba69f2018-05-08 13:20:07 -04007967 * This fixes a problem that was hard to reproduce. Very rarely, I would
7968 * boot up, and there would be no sound, but the DSP indicated it had loaded
7969 * properly. I did a few memory dumps to see if anything was different, and
7970 * there were a few areas of memory uninitialized with a1a2a3a4. This function
7971 * checks if those areas are uninitialized, and if they are, it'll attempt to
7972 * reload the card 3 times. Usually it fixes by the second.
7973 */
7974static void sbz_dsp_startup_check(struct hda_codec *codec)
7975{
7976 struct ca0132_spec *spec = codec->spec;
7977 unsigned int dsp_data_check[4];
7978 unsigned int cur_address = 0x390;
7979 unsigned int i;
7980 unsigned int failure = 0;
7981 unsigned int reload = 3;
7982
7983 if (spec->startup_check_entered)
7984 return;
7985
7986 spec->startup_check_entered = true;
7987
7988 for (i = 0; i < 4; i++) {
7989 chipio_read(codec, cur_address, &dsp_data_check[i]);
7990 cur_address += 0x4;
7991 }
7992 for (i = 0; i < 4; i++) {
7993 if (dsp_data_check[i] == 0xa1a2a3a4)
7994 failure = 1;
7995 }
7996
7997 codec_dbg(codec, "Startup Check: %d ", failure);
7998 if (failure)
7999 codec_info(codec, "DSP not initialized properly. Attempting to fix.");
8000 /*
8001 * While the failure condition is true, and we haven't reached our
8002 * three reload limit, continue trying to reload the driver and
8003 * fix the issue.
8004 */
8005 while (failure && (reload != 0)) {
8006 codec_info(codec, "Reloading... Tries left: %d", reload);
8007 sbz_exit_chip(codec);
8008 spec->dsp_state = DSP_DOWNLOAD_INIT;
8009 codec->patch_ops.init(codec);
8010 failure = 0;
8011 for (i = 0; i < 4; i++) {
8012 chipio_read(codec, cur_address, &dsp_data_check[i]);
8013 cur_address += 0x4;
8014 }
8015 for (i = 0; i < 4; i++) {
8016 if (dsp_data_check[i] == 0xa1a2a3a4)
8017 failure = 1;
8018 }
8019 reload--;
8020 }
8021
8022 if (!failure && reload < 3)
8023 codec_info(codec, "DSP fixed.");
8024
8025 if (!failure)
8026 return;
8027
8028 codec_info(codec, "DSP failed to initialize properly. Either try a full shutdown or a suspend to clear the internal memory.");
8029}
8030
8031/*
Connor McAdamse93ac302018-05-08 13:20:05 -04008032 * This is for the extra volume verbs 0x797 (left) and 0x798 (right). These add
8033 * extra precision for decibel values. If you had the dB value in floating point
8034 * you would take the value after the decimal point, multiply by 64, and divide
8035 * by 2. So for 8.59, it's (59 * 64) / 100. Useful if someone wanted to
8036 * implement fixed point or floating point dB volumes. For now, I'll set them
8037 * to 0 just incase a value has lingered from a boot into Windows.
8038 */
8039static void ca0132_alt_vol_setup(struct hda_codec *codec)
8040{
8041 snd_hda_codec_write(codec, 0x02, 0, 0x797, 0x00);
8042 snd_hda_codec_write(codec, 0x02, 0, 0x798, 0x00);
8043 snd_hda_codec_write(codec, 0x03, 0, 0x797, 0x00);
8044 snd_hda_codec_write(codec, 0x03, 0, 0x798, 0x00);
8045 snd_hda_codec_write(codec, 0x04, 0, 0x797, 0x00);
8046 snd_hda_codec_write(codec, 0x04, 0, 0x798, 0x00);
8047 snd_hda_codec_write(codec, 0x07, 0, 0x797, 0x00);
8048 snd_hda_codec_write(codec, 0x07, 0, 0x798, 0x00);
8049}
8050
8051/*
8052 * Extra commands that don't really fit anywhere else.
8053 */
8054static void sbz_pre_dsp_setup(struct hda_codec *codec)
8055{
8056 struct ca0132_spec *spec = codec->spec;
8057
8058 writel(0x00820680, spec->mem_base + 0x01C);
8059 writel(0x00820680, spec->mem_base + 0x01C);
8060
Connor McAdamse93ac302018-05-08 13:20:05 -04008061 chipio_write(codec, 0x18b0a4, 0x000000c2);
8062
8063 snd_hda_codec_write(codec, 0x11, 0,
8064 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44);
8065}
8066
Connor McAdamse42c7c72018-08-08 13:34:18 -04008067static void r3d_pre_dsp_setup(struct hda_codec *codec)
8068{
Connor McAdamse42c7c72018-08-08 13:34:18 -04008069 chipio_write(codec, 0x18b0a4, 0x000000c2);
8070
8071 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8072 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x1E);
8073 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8074 VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x1C);
8075 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8076 VENDOR_CHIPIO_8051_DATA_WRITE, 0x5B);
8077
8078 snd_hda_codec_write(codec, 0x11, 0,
8079 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x44);
8080}
8081
Connor McAdamse93ac302018-05-08 13:20:05 -04008082static void r3di_pre_dsp_setup(struct hda_codec *codec)
8083{
8084 chipio_write(codec, 0x18b0a4, 0x000000c2);
8085
8086 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8087 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x1E);
8088 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8089 VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x1C);
8090 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8091 VENDOR_CHIPIO_8051_DATA_WRITE, 0x5B);
8092
8093 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8094 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x20);
8095 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8096 VENDOR_CHIPIO_8051_ADDRESS_HIGH, 0x19);
8097 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8098 VENDOR_CHIPIO_8051_DATA_WRITE, 0x00);
8099 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8100 VENDOR_CHIPIO_8051_DATA_WRITE, 0x40);
8101
8102 snd_hda_codec_write(codec, 0x11, 0,
8103 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x04);
8104}
8105
Connor McAdamse93ac302018-05-08 13:20:05 -04008106/*
8107 * These are sent before the DSP is downloaded. Not sure
8108 * what they do, or if they're necessary. Could possibly
8109 * be removed. Figure they're better to leave in.
8110 */
Connor McAdamse42c7c72018-08-08 13:34:18 -04008111static void ca0132_mmio_init(struct hda_codec *codec)
Connor McAdamse93ac302018-05-08 13:20:05 -04008112{
8113 struct ca0132_spec *spec = codec->spec;
8114
Takashi Iwai6da8f442018-11-09 14:18:32 +01008115 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsce715442018-09-18 14:33:33 -04008116 writel(0x00000001, spec->mem_base + 0x400);
8117 else
8118 writel(0x00000000, spec->mem_base + 0x400);
8119
Takashi Iwai6da8f442018-11-09 14:18:32 +01008120 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsce715442018-09-18 14:33:33 -04008121 writel(0x00000001, spec->mem_base + 0x408);
8122 else
8123 writel(0x00000000, spec->mem_base + 0x408);
8124
Takashi Iwai6da8f442018-11-09 14:18:32 +01008125 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsce715442018-09-18 14:33:33 -04008126 writel(0x00000001, spec->mem_base + 0x40c);
8127 else
8128 writel(0x00000000, spec->mem_base + 0x40C);
8129
Takashi Iwai6da8f442018-11-09 14:18:32 +01008130 if (ca0132_quirk(spec) == QUIRK_ZXR)
Connor McAdams2e492b82018-09-29 23:03:21 -04008131 writel(0x00880640, spec->mem_base + 0x01C);
8132 else
8133 writel(0x00880680, spec->mem_base + 0x01C);
Connor McAdamsce715442018-09-18 14:33:33 -04008134
Takashi Iwai6da8f442018-11-09 14:18:32 +01008135 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsce715442018-09-18 14:33:33 -04008136 writel(0x00000080, spec->mem_base + 0xC0C);
8137 else
8138 writel(0x00000083, spec->mem_base + 0xC0C);
8139
Connor McAdamse93ac302018-05-08 13:20:05 -04008140 writel(0x00000030, spec->mem_base + 0xC00);
8141 writel(0x00000000, spec->mem_base + 0xC04);
Connor McAdamsce715442018-09-18 14:33:33 -04008142
Takashi Iwai6da8f442018-11-09 14:18:32 +01008143 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsce715442018-09-18 14:33:33 -04008144 writel(0x00000000, spec->mem_base + 0xC0C);
8145 else
8146 writel(0x00000003, spec->mem_base + 0xC0C);
8147
Connor McAdamse93ac302018-05-08 13:20:05 -04008148 writel(0x00000003, spec->mem_base + 0xC0C);
8149 writel(0x00000003, spec->mem_base + 0xC0C);
8150 writel(0x00000003, spec->mem_base + 0xC0C);
Connor McAdamsce715442018-09-18 14:33:33 -04008151
Takashi Iwai6da8f442018-11-09 14:18:32 +01008152 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsce715442018-09-18 14:33:33 -04008153 writel(0x00000001, spec->mem_base + 0xC08);
8154 else
8155 writel(0x000000C1, spec->mem_base + 0xC08);
8156
Connor McAdamse93ac302018-05-08 13:20:05 -04008157 writel(0x000000F1, spec->mem_base + 0xC08);
8158 writel(0x00000001, spec->mem_base + 0xC08);
8159 writel(0x000000C7, spec->mem_base + 0xC08);
8160 writel(0x000000C1, spec->mem_base + 0xC08);
8161 writel(0x00000080, spec->mem_base + 0xC04);
Connor McAdamsce715442018-09-18 14:33:33 -04008162
Takashi Iwai6da8f442018-11-09 14:18:32 +01008163 if (ca0132_quirk(spec) == QUIRK_AE5) {
Connor McAdamsce715442018-09-18 14:33:33 -04008164 writel(0x00000000, spec->mem_base + 0x42c);
8165 writel(0x00000000, spec->mem_base + 0x46c);
8166 writel(0x00000000, spec->mem_base + 0x4ac);
8167 writel(0x00000000, spec->mem_base + 0x4ec);
8168 writel(0x00000000, spec->mem_base + 0x43c);
8169 writel(0x00000000, spec->mem_base + 0x47c);
8170 writel(0x00000000, spec->mem_base + 0x4bc);
8171 writel(0x00000000, spec->mem_base + 0x4fc);
8172 writel(0x00000600, spec->mem_base + 0x100);
8173 writel(0x00000014, spec->mem_base + 0x410);
8174 writel(0x0000060f, spec->mem_base + 0x100);
8175 writel(0x0000070f, spec->mem_base + 0x100);
8176 writel(0x00000aff, spec->mem_base + 0x830);
8177 writel(0x00000000, spec->mem_base + 0x86c);
8178 writel(0x0000006b, spec->mem_base + 0x800);
8179 writel(0x00000001, spec->mem_base + 0x86c);
8180 writel(0x0000006b, spec->mem_base + 0x800);
8181 writel(0x00000057, spec->mem_base + 0x804);
8182 writel(0x00800000, spec->mem_base + 0x20c);
8183 }
Connor McAdamse93ac302018-05-08 13:20:05 -04008184}
8185
8186/*
Connor McAdamsb9b41342018-09-18 14:33:34 -04008187 * This function writes to some SFR's, does some region2 writes, and then
8188 * eventually resets the codec with the 0x7ff verb. Not quite sure why it does
8189 * what it does.
8190 */
8191static void ae5_register_set(struct hda_codec *codec)
8192{
8193 struct ca0132_spec *spec = codec->spec;
8194
8195 chipio_8051_write_direct(codec, 0x93, 0x10);
8196 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8197 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x44);
8198 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8199 VENDOR_CHIPIO_PLL_PMU_WRITE, 0xc2);
8200
8201 writeb(0x0f, spec->mem_base + 0x304);
8202 writeb(0x0f, spec->mem_base + 0x304);
8203 writeb(0x0f, spec->mem_base + 0x304);
8204 writeb(0x0f, spec->mem_base + 0x304);
8205 writeb(0x0e, spec->mem_base + 0x100);
8206 writeb(0x1f, spec->mem_base + 0x304);
8207 writeb(0x0c, spec->mem_base + 0x100);
8208 writeb(0x3f, spec->mem_base + 0x304);
8209 writeb(0x08, spec->mem_base + 0x100);
8210 writeb(0x7f, spec->mem_base + 0x304);
8211 writeb(0x00, spec->mem_base + 0x100);
8212 writeb(0xff, spec->mem_base + 0x304);
8213
8214 ca0113_mmio_command_set(codec, 0x30, 0x2d, 0x3f);
8215
8216 chipio_8051_write_direct(codec, 0x90, 0x00);
8217 chipio_8051_write_direct(codec, 0x90, 0x10);
8218
8219 ca0113_mmio_command_set(codec, 0x48, 0x07, 0x83);
8220
8221 chipio_write(codec, 0x18b0a4, 0x000000c2);
8222
8223 snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00);
8224 snd_hda_codec_write(codec, 0x01, 0, 0x7ff, 0x00);
8225}
8226
8227/*
Connor McAdamse93ac302018-05-08 13:20:05 -04008228 * Extra init functions for alternative ca0132 codecs. Done
8229 * here so they don't clutter up the main ca0132_init function
8230 * anymore than they have to.
8231 */
8232static void ca0132_alt_init(struct hda_codec *codec)
8233{
8234 struct ca0132_spec *spec = codec->spec;
8235
8236 ca0132_alt_vol_setup(codec);
8237
Takashi Iwai6da8f442018-11-09 14:18:32 +01008238 switch (ca0132_quirk(spec)) {
Connor McAdamse93ac302018-05-08 13:20:05 -04008239 case QUIRK_SBZ:
8240 codec_dbg(codec, "SBZ alt_init");
8241 ca0132_gpio_init(codec);
8242 sbz_pre_dsp_setup(codec);
8243 snd_hda_sequence_write(codec, spec->chip_init_verbs);
Connor McAdamse42c7c72018-08-08 13:34:18 -04008244 snd_hda_sequence_write(codec, spec->desktop_init_verbs);
Connor McAdamse93ac302018-05-08 13:20:05 -04008245 break;
8246 case QUIRK_R3DI:
8247 codec_dbg(codec, "R3DI alt_init");
8248 ca0132_gpio_init(codec);
8249 ca0132_gpio_setup(codec);
Connor McAdams7e6ed622018-05-08 13:20:08 -04008250 r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADING);
Connor McAdamse93ac302018-05-08 13:20:05 -04008251 r3di_pre_dsp_setup(codec);
8252 snd_hda_sequence_write(codec, spec->chip_init_verbs);
8253 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, 0x6FF, 0xC4);
8254 break;
Connor McAdamse42c7c72018-08-08 13:34:18 -04008255 case QUIRK_R3D:
8256 r3d_pre_dsp_setup(codec);
8257 snd_hda_sequence_write(codec, spec->chip_init_verbs);
8258 snd_hda_sequence_write(codec, spec->desktop_init_verbs);
8259 break;
Connor McAdams03c9b6b2018-09-18 14:33:35 -04008260 case QUIRK_AE5:
8261 ca0132_gpio_init(codec);
8262 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8263 VENDOR_CHIPIO_8051_ADDRESS_LOW, 0x49);
8264 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8265 VENDOR_CHIPIO_PLL_PMU_WRITE, 0x88);
8266 chipio_write(codec, 0x18b030, 0x00000020);
8267 snd_hda_sequence_write(codec, spec->chip_init_verbs);
8268 snd_hda_sequence_write(codec, spec->desktop_init_verbs);
8269 ca0113_mmio_command_set(codec, 0x30, 0x32, 0x3f);
8270 break;
Connor McAdams2e492b82018-09-29 23:03:21 -04008271 case QUIRK_ZXR:
8272 snd_hda_sequence_write(codec, spec->chip_init_verbs);
8273 snd_hda_sequence_write(codec, spec->desktop_init_verbs);
8274 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01008275 default:
8276 break;
Connor McAdamse93ac302018-05-08 13:20:05 -04008277 }
8278}
8279
Ian Minett95c6e9c2011-06-15 15:35:17 -07008280static int ca0132_init(struct hda_codec *codec)
8281{
8282 struct ca0132_spec *spec = codec->spec;
8283 struct auto_pin_cfg *cfg = &spec->autocfg;
8284 int i;
Connor McAdamse93ac302018-05-08 13:20:05 -04008285 bool dsp_loaded;
8286
8287 /*
8288 * If the DSP is already downloaded, and init has been entered again,
8289 * there's only two reasons for it. One, the codec has awaken from a
8290 * suspended state, and in that case dspload_is_loaded will return
8291 * false, and the init will be ran again. The other reason it gets
8292 * re entered is on startup for some reason it triggers a suspend and
8293 * resume state. In this case, it will check if the DSP is downloaded,
8294 * and not run the init function again. For codecs using alt_functions,
8295 * it will check if the DSP is loaded properly.
8296 */
8297 if (spec->dsp_state == DSP_DOWNLOADED) {
8298 dsp_loaded = dspload_is_loaded(codec);
8299 if (!dsp_loaded) {
8300 spec->dsp_reload = true;
8301 spec->dsp_state = DSP_DOWNLOAD_INIT;
Connor McAdams38ba69f2018-05-08 13:20:07 -04008302 } else {
Takashi Iwai6da8f442018-11-09 14:18:32 +01008303 if (ca0132_quirk(spec) == QUIRK_SBZ)
Connor McAdams38ba69f2018-05-08 13:20:07 -04008304 sbz_dsp_startup_check(codec);
Connor McAdamse93ac302018-05-08 13:20:05 -04008305 return 0;
Connor McAdams38ba69f2018-05-08 13:20:07 -04008306 }
Connor McAdamse93ac302018-05-08 13:20:05 -04008307 }
Ian Minett95c6e9c2011-06-15 15:35:17 -07008308
Takashi Iwaie24aa0a2014-08-10 13:30:08 +02008309 if (spec->dsp_state != DSP_DOWNLOAD_FAILED)
8310 spec->dsp_state = DSP_DOWNLOAD_INIT;
Takashi Iwai4a8b89f2013-02-12 10:15:15 +01008311 spec->curr_chip_addx = INVALID_CHIP_ADDRESS;
Ian Minett5aaca442012-12-20 18:53:34 -08008312
Takashi Iwai6da8f442018-11-09 14:18:32 +01008313 if (ca0132_use_pci_mmio(spec))
Connor McAdamse42c7c72018-08-08 13:34:18 -04008314 ca0132_mmio_init(codec);
Connor McAdamse93ac302018-05-08 13:20:05 -04008315
Takashi Iwai664c7152015-04-08 11:43:14 +02008316 snd_hda_power_up_pm(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08008317
Takashi Iwai6da8f442018-11-09 14:18:32 +01008318 if (ca0132_quirk(spec) == QUIRK_AE5)
Connor McAdamsb9b41342018-09-18 14:33:34 -04008319 ae5_register_set(codec);
8320
Takashi Iwaif8fb1172014-09-11 15:53:26 +02008321 ca0132_init_unsol(codec);
Ian Minett5aaca442012-12-20 18:53:34 -08008322 ca0132_init_params(codec);
8323 ca0132_init_flags(codec);
Connor McAdams7e6ed622018-05-08 13:20:08 -04008324
Ian Minett5aaca442012-12-20 18:53:34 -08008325 snd_hda_sequence_write(codec, spec->base_init_verbs);
Connor McAdamse93ac302018-05-08 13:20:05 -04008326
Takashi Iwai6da8f442018-11-09 14:18:32 +01008327 if (ca0132_use_alt_functions(spec))
Connor McAdamse93ac302018-05-08 13:20:05 -04008328 ca0132_alt_init(codec);
8329
Ian Minett01ef7db2012-09-20 20:29:16 -07008330 ca0132_download_dsp(codec);
Connor McAdams7e6ed622018-05-08 13:20:08 -04008331
Ian Minett5aaca442012-12-20 18:53:34 -08008332 ca0132_refresh_widget_caps(codec);
Connor McAdamse93ac302018-05-08 13:20:05 -04008333
Takashi Iwai6da8f442018-11-09 14:18:32 +01008334 switch (ca0132_quirk(spec)) {
Connor McAdams7e6ed622018-05-08 13:20:08 -04008335 case QUIRK_R3DI:
Connor McAdamsc986f502018-08-08 13:34:19 -04008336 case QUIRK_R3D:
8337 r3d_setup_defaults(codec);
Connor McAdams7e6ed622018-05-08 13:20:08 -04008338 break;
Alastair Bridgewater126b75e2018-06-15 21:56:18 -04008339 case QUIRK_SBZ:
Connor McAdamsc25c73e2018-09-29 23:03:22 -04008340 case QUIRK_ZXR:
Connor McAdamsd97420d2018-08-08 13:34:13 -04008341 sbz_setup_defaults(codec);
Alastair Bridgewater126b75e2018-06-15 21:56:18 -04008342 break;
Connor McAdams415cd842018-09-18 14:33:38 -04008343 case QUIRK_AE5:
8344 ae5_setup_defaults(codec);
8345 break;
Alastair Bridgewater126b75e2018-06-15 21:56:18 -04008346 default:
Connor McAdams38ba69f2018-05-08 13:20:07 -04008347 ca0132_setup_defaults(codec);
8348 ca0132_init_analog_mic2(codec);
8349 ca0132_init_dmic(codec);
Connor McAdams7e6ed622018-05-08 13:20:08 -04008350 break;
Connor McAdams38ba69f2018-05-08 13:20:07 -04008351 }
Ian Minett01ef7db2012-09-20 20:29:16 -07008352
Ian Minett5aaca442012-12-20 18:53:34 -08008353 for (i = 0; i < spec->num_outputs; i++)
8354 init_output(codec, spec->out_pins[i], spec->dacs[0]);
8355
Ian Minett95c6e9c2011-06-15 15:35:17 -07008356 init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
8357
8358 for (i = 0; i < spec->num_inputs; i++)
8359 init_input(codec, spec->input_pins[i], spec->adcs[i]);
8360
8361 init_input(codec, cfg->dig_in_pin, spec->dig_in);
8362
Takashi Iwai6da8f442018-11-09 14:18:32 +01008363 if (!ca0132_use_alt_functions(spec)) {
Connor McAdamse93ac302018-05-08 13:20:05 -04008364 snd_hda_sequence_write(codec, spec->chip_init_verbs);
8365 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8366 VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D);
8367 snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0,
8368 VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20);
8369 }
8370
Takashi Iwai6da8f442018-11-09 14:18:32 +01008371 if (ca0132_quirk(spec) == QUIRK_SBZ)
Connor McAdamse93ac302018-05-08 13:20:05 -04008372 ca0132_gpio_setup(codec);
8373
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008374 snd_hda_sequence_write(codec, spec->spec_init_verbs);
Takashi Iwai6da8f442018-11-09 14:18:32 +01008375 if (ca0132_use_alt_functions(spec)) {
Connor McAdams7cb9d942018-05-08 13:20:10 -04008376 ca0132_alt_select_out(codec);
8377 ca0132_alt_select_in(codec);
Connor McAdamsd97420d2018-08-08 13:34:13 -04008378 } else {
Connor McAdams7cb9d942018-05-08 13:20:10 -04008379 ca0132_select_out(codec);
8380 ca0132_select_mic(codec);
Connor McAdams7cb9d942018-05-08 13:20:10 -04008381 }
Ian Minett5aaca442012-12-20 18:53:34 -08008382
Ian Minetta73d5112012-12-20 18:53:37 -08008383 snd_hda_jack_report_sync(codec);
8384
Connor McAdamse93ac302018-05-08 13:20:05 -04008385 /*
8386 * Re set the PlayEnhancement switch on a resume event, because the
8387 * controls will not be reloaded.
8388 */
8389 if (spec->dsp_reload) {
8390 spec->dsp_reload = false;
8391 ca0132_pe_switch_set(codec);
8392 }
8393
Takashi Iwai664c7152015-04-08 11:43:14 +02008394 snd_hda_power_down_pm(codec);
Ian Minett95c6e9c2011-06-15 15:35:17 -07008395
8396 return 0;
8397}
8398
Connor McAdams7675a2a2018-09-29 23:03:20 -04008399static int dbpro_init(struct hda_codec *codec)
8400{
8401 struct ca0132_spec *spec = codec->spec;
8402 struct auto_pin_cfg *cfg = &spec->autocfg;
8403 unsigned int i;
8404
8405 init_output(codec, cfg->dig_out_pins[0], spec->dig_out);
8406 init_input(codec, cfg->dig_in_pin, spec->dig_in);
8407
8408 for (i = 0; i < spec->num_inputs; i++)
8409 init_input(codec, spec->input_pins[i], spec->adcs[i]);
8410
8411 return 0;
8412}
8413
Ian Minett95c6e9c2011-06-15 15:35:17 -07008414static void ca0132_free(struct hda_codec *codec)
8415{
Ian Minett5aaca442012-12-20 18:53:34 -08008416 struct ca0132_spec *spec = codec->spec;
8417
Chih-Chung Chang993884f2013-03-25 10:39:23 -07008418 cancel_delayed_work_sync(&spec->unsol_hp_work);
Ian Minett5aaca442012-12-20 18:53:34 -08008419 snd_hda_power_up(codec);
Takashi Iwai6da8f442018-11-09 14:18:32 +01008420 switch (ca0132_quirk(spec)) {
Connor McAdams2e48b2b2018-05-08 13:20:04 -04008421 case QUIRK_SBZ:
8422 sbz_exit_chip(codec);
8423 break;
Connor McAdams96395e82018-09-29 23:03:26 -04008424 case QUIRK_ZXR:
8425 zxr_exit_chip(codec);
8426 break;
Connor McAdams2f295f92018-08-08 13:34:22 -04008427 case QUIRK_R3D:
8428 r3d_exit_chip(codec);
8429 break;
Connor McAdamsedb1b3a2018-09-18 14:33:43 -04008430 case QUIRK_AE5:
8431 ae5_exit_chip(codec);
8432 break;
Connor McAdams2e48b2b2018-05-08 13:20:04 -04008433 case QUIRK_R3DI:
8434 r3di_gpio_shutdown(codec);
Connor McAdams2e48b2b2018-05-08 13:20:04 -04008435 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01008436 default:
8437 break;
Connor McAdams2e48b2b2018-05-08 13:20:04 -04008438 }
Connor McAdams2f295f92018-08-08 13:34:22 -04008439
8440 snd_hda_sequence_write(codec, spec->base_exit_verbs);
8441 ca0132_exit_chip(codec);
8442
Ian Minett5aaca442012-12-20 18:53:34 -08008443 snd_hda_power_down(codec);
Takashi Iwaic97617a2019-02-05 17:57:27 +01008444#ifdef CONFIG_PCI
8445 if (spec->mem_base)
Takashi Iwaid99501b2018-11-12 12:26:57 +01008446 pci_iounmap(codec->bus->pci, spec->mem_base);
Takashi Iwaic97617a2019-02-05 17:57:27 +01008447#endif
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008448 kfree(spec->spec_init_verbs);
Ian Minett95c6e9c2011-06-15 15:35:17 -07008449 kfree(codec->spec);
8450}
8451
Connor McAdams7675a2a2018-09-29 23:03:20 -04008452static void dbpro_free(struct hda_codec *codec)
8453{
8454 struct ca0132_spec *spec = codec->spec;
8455
8456 zxr_dbpro_power_state_shutdown(codec);
8457
8458 kfree(spec->spec_init_verbs);
8459 kfree(codec->spec);
8460}
8461
Connor McAdams2e48b2b2018-05-08 13:20:04 -04008462static void ca0132_reboot_notify(struct hda_codec *codec)
8463{
8464 codec->patch_ops.free(codec);
8465}
8466
Takashi Iwai42fb6b12019-12-13 09:51:11 +01008467#ifdef CONFIG_PM
8468static int ca0132_suspend(struct hda_codec *codec)
8469{
8470 struct ca0132_spec *spec = codec->spec;
8471
8472 cancel_delayed_work_sync(&spec->unsol_hp_work);
8473 return 0;
8474}
8475#endif
8476
Julia Lawall071f1342016-09-11 15:05:43 +02008477static const struct hda_codec_ops ca0132_patch_ops = {
Ian Minett95c6e9c2011-06-15 15:35:17 -07008478 .build_controls = ca0132_build_controls,
8479 .build_pcms = ca0132_build_pcms,
8480 .init = ca0132_init,
8481 .free = ca0132_free,
Takashi Iwaif8fb1172014-09-11 15:53:26 +02008482 .unsol_event = snd_hda_jack_unsol_event,
Takashi Iwai42fb6b12019-12-13 09:51:11 +01008483#ifdef CONFIG_PM
8484 .suspend = ca0132_suspend,
8485#endif
Connor McAdams2e48b2b2018-05-08 13:20:04 -04008486 .reboot_notify = ca0132_reboot_notify,
Ian Minett95c6e9c2011-06-15 15:35:17 -07008487};
8488
Connor McAdams7675a2a2018-09-29 23:03:20 -04008489static const struct hda_codec_ops dbpro_patch_ops = {
8490 .build_controls = dbpro_build_controls,
8491 .build_pcms = dbpro_build_pcms,
8492 .init = dbpro_init,
8493 .free = dbpro_free,
8494};
8495
Ian Minett441aa6a2012-12-20 18:53:40 -08008496static void ca0132_config(struct hda_codec *codec)
8497{
8498 struct ca0132_spec *spec = codec->spec;
Ian Minett441aa6a2012-12-20 18:53:40 -08008499
8500 spec->dacs[0] = 0x2;
8501 spec->dacs[1] = 0x3;
8502 spec->dacs[2] = 0x4;
8503
8504 spec->multiout.dac_nids = spec->dacs;
8505 spec->multiout.num_dacs = 3;
Ian Minett441aa6a2012-12-20 18:53:40 -08008506
Takashi Iwai6da8f442018-11-09 14:18:32 +01008507 if (!ca0132_use_alt_functions(spec))
Connor McAdams63177af2018-05-08 13:20:02 -04008508 spec->multiout.max_channels = 2;
8509 else
8510 spec->multiout.max_channels = 6;
8511
Takashi Iwai6da8f442018-11-09 14:18:32 +01008512 switch (ca0132_quirk(spec)) {
Connor McAdams63177af2018-05-08 13:20:02 -04008513 case QUIRK_ALIENWARE:
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008514 codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__);
Takashi Iwaife14f392015-08-10 16:53:32 +02008515 snd_hda_apply_pincfgs(codec, alienware_pincfgs);
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008516 break;
8517 case QUIRK_SBZ:
8518 codec_dbg(codec, "%s: QUIRK_SBZ applied.\n", __func__);
8519 snd_hda_apply_pincfgs(codec, sbz_pincfgs);
8520 break;
Connor McAdams6dcd7242018-09-29 23:03:19 -04008521 case QUIRK_ZXR:
8522 codec_dbg(codec, "%s: QUIRK_ZXR applied.\n", __func__);
8523 snd_hda_apply_pincfgs(codec, zxr_pincfgs);
8524 break;
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008525 case QUIRK_R3D:
8526 codec_dbg(codec, "%s: QUIRK_R3D applied.\n", __func__);
8527 snd_hda_apply_pincfgs(codec, r3d_pincfgs);
8528 break;
8529 case QUIRK_R3DI:
8530 codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
8531 snd_hda_apply_pincfgs(codec, r3di_pincfgs);
8532 break;
8533 case QUIRK_AE5:
8534 codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__);
Connor McAdamsa6b0961b2018-11-16 14:24:56 -05008535 snd_hda_apply_pincfgs(codec, ae5_pincfgs);
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008536 break;
Takashi Iwai6da8f442018-11-09 14:18:32 +01008537 default:
8538 break;
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008539 }
Takashi Iwaife14f392015-08-10 16:53:32 +02008540
Takashi Iwai6da8f442018-11-09 14:18:32 +01008541 switch (ca0132_quirk(spec)) {
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008542 case QUIRK_ALIENWARE:
Takashi Iwaife14f392015-08-10 16:53:32 +02008543 spec->num_outputs = 2;
8544 spec->out_pins[0] = 0x0b; /* speaker out */
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008545 spec->out_pins[1] = 0x0f;
Takashi Iwaife14f392015-08-10 16:53:32 +02008546 spec->shared_out_nid = 0x2;
8547 spec->unsol_tag_hp = 0x0f;
8548
8549 spec->adcs[0] = 0x7; /* digital mic / analog mic1 */
8550 spec->adcs[1] = 0x8; /* analog mic2 */
8551 spec->adcs[2] = 0xa; /* what u hear */
8552
8553 spec->num_inputs = 3;
8554 spec->input_pins[0] = 0x12;
8555 spec->input_pins[1] = 0x11;
8556 spec->input_pins[2] = 0x13;
8557 spec->shared_mic_nid = 0x7;
8558 spec->unsol_tag_amic1 = 0x11;
Connor McAdams63177af2018-05-08 13:20:02 -04008559 break;
8560 case QUIRK_SBZ:
Connor McAdams7f73df92018-08-08 13:34:16 -04008561 case QUIRK_R3D:
Connor McAdams63177af2018-05-08 13:20:02 -04008562 spec->num_outputs = 2;
8563 spec->out_pins[0] = 0x0B; /* Line out */
8564 spec->out_pins[1] = 0x0F; /* Rear headphone out */
8565 spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
8566 spec->out_pins[3] = 0x11; /* Rear surround */
8567 spec->shared_out_nid = 0x2;
8568 spec->unsol_tag_hp = spec->out_pins[1];
8569 spec->unsol_tag_front_hp = spec->out_pins[2];
8570
8571 spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
8572 spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */
8573 spec->adcs[2] = 0xa; /* what u hear */
8574
8575 spec->num_inputs = 2;
8576 spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
8577 spec->input_pins[1] = 0x13; /* What U Hear */
8578 spec->shared_mic_nid = 0x7;
8579 spec->unsol_tag_amic1 = spec->input_pins[0];
8580
8581 /* SPDIF I/O */
8582 spec->dig_out = 0x05;
8583 spec->multiout.dig_out_nid = spec->dig_out;
Connor McAdams63177af2018-05-08 13:20:02 -04008584 spec->dig_in = 0x09;
Connor McAdams63177af2018-05-08 13:20:02 -04008585 break;
Connor McAdams6dcd7242018-09-29 23:03:19 -04008586 case QUIRK_ZXR:
8587 spec->num_outputs = 2;
8588 spec->out_pins[0] = 0x0B; /* Line out */
8589 spec->out_pins[1] = 0x0F; /* Rear headphone out */
8590 spec->out_pins[2] = 0x10; /* Center/LFE */
8591 spec->out_pins[3] = 0x11; /* Rear surround */
8592 spec->shared_out_nid = 0x2;
8593 spec->unsol_tag_hp = spec->out_pins[1];
8594 spec->unsol_tag_front_hp = spec->out_pins[2];
8595
8596 spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
8597 spec->adcs[1] = 0x8; /* Not connected, no front mic */
8598 spec->adcs[2] = 0xa; /* what u hear */
8599
8600 spec->num_inputs = 2;
8601 spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
8602 spec->input_pins[1] = 0x13; /* What U Hear */
8603 spec->shared_mic_nid = 0x7;
8604 spec->unsol_tag_amic1 = spec->input_pins[0];
8605 break;
8606 case QUIRK_ZXR_DBPRO:
8607 spec->adcs[0] = 0x8; /* ZxR DBPro Aux In */
8608
8609 spec->num_inputs = 1;
8610 spec->input_pins[0] = 0x11; /* RCA Line-in */
8611
8612 spec->dig_out = 0x05;
8613 spec->multiout.dig_out_nid = spec->dig_out;
8614
8615 spec->dig_in = 0x09;
8616 break;
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008617 case QUIRK_AE5:
8618 spec->num_outputs = 2;
8619 spec->out_pins[0] = 0x0B; /* Line out */
8620 spec->out_pins[1] = 0x11; /* Rear headphone out */
8621 spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
8622 spec->out_pins[3] = 0x0F; /* Rear surround */
8623 spec->shared_out_nid = 0x2;
8624 spec->unsol_tag_hp = spec->out_pins[1];
8625 spec->unsol_tag_front_hp = spec->out_pins[2];
Connor McAdams63177af2018-05-08 13:20:02 -04008626
Connor McAdamsd06feaf2018-09-18 14:33:31 -04008627 spec->adcs[0] = 0x7; /* Rear Mic / Line-in */
8628 spec->adcs[1] = 0x8; /* Front Mic, but only if no DSP */
8629 spec->adcs[2] = 0xa; /* what u hear */
8630
8631 spec->num_inputs = 2;
8632 spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
8633 spec->input_pins[1] = 0x13; /* What U Hear */
8634 spec->shared_mic_nid = 0x7;
8635 spec->unsol_tag_amic1 = spec->input_pins[0];
8636
8637 /* SPDIF I/O */
8638 spec->dig_out = 0x05;
8639 spec->multiout.dig_out_nid = spec->dig_out;
8640 break;
8641 case QUIRK_R3DI:
Connor McAdams63177af2018-05-08 13:20:02 -04008642 spec->num_outputs = 2;
8643 spec->out_pins[0] = 0x0B; /* Line out */
8644 spec->out_pins[1] = 0x0F; /* Rear headphone out */
8645 spec->out_pins[2] = 0x10; /* Front Headphone / Center/LFE*/
8646 spec->out_pins[3] = 0x11; /* Rear surround */
8647 spec->shared_out_nid = 0x2;
8648 spec->unsol_tag_hp = spec->out_pins[1];
8649 spec->unsol_tag_front_hp = spec->out_pins[2];
8650
8651 spec->adcs[0] = 0x07; /* Rear Mic / Line-in */
8652 spec->adcs[1] = 0x08; /* Front Mic, but only if no DSP */
8653 spec->adcs[2] = 0x0a; /* what u hear */
8654
8655 spec->num_inputs = 2;
8656 spec->input_pins[0] = 0x12; /* Rear Mic / Line-in */
8657 spec->input_pins[1] = 0x13; /* What U Hear */
8658 spec->shared_mic_nid = 0x7;
8659 spec->unsol_tag_amic1 = spec->input_pins[0];
8660
8661 /* SPDIF I/O */
8662 spec->dig_out = 0x05;
8663 spec->multiout.dig_out_nid = spec->dig_out;
Connor McAdams63177af2018-05-08 13:20:02 -04008664 break;
8665 default:
Takashi Iwaife14f392015-08-10 16:53:32 +02008666 spec->num_outputs = 2;
8667 spec->out_pins[0] = 0x0b; /* speaker out */
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008668 spec->out_pins[1] = 0x10; /* headphone out */
Takashi Iwaife14f392015-08-10 16:53:32 +02008669 spec->shared_out_nid = 0x2;
8670 spec->unsol_tag_hp = spec->out_pins[1];
8671
8672 spec->adcs[0] = 0x7; /* digital mic / analog mic1 */
8673 spec->adcs[1] = 0x8; /* analog mic2 */
8674 spec->adcs[2] = 0xa; /* what u hear */
8675
8676 spec->num_inputs = 3;
8677 spec->input_pins[0] = 0x12;
8678 spec->input_pins[1] = 0x11;
8679 spec->input_pins[2] = 0x13;
8680 spec->shared_mic_nid = 0x7;
8681 spec->unsol_tag_amic1 = spec->input_pins[0];
8682
8683 /* SPDIF I/O */
8684 spec->dig_out = 0x05;
8685 spec->multiout.dig_out_nid = spec->dig_out;
Takashi Iwaife14f392015-08-10 16:53:32 +02008686 spec->dig_in = 0x09;
Connor McAdams63177af2018-05-08 13:20:02 -04008687 break;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008688 }
Ian Minett441aa6a2012-12-20 18:53:40 -08008689}
8690
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008691static int ca0132_prepare_verbs(struct hda_codec *codec)
8692{
8693/* Verbs + terminator (an empty element) */
Alastair Bridgewatera3d90d62018-06-15 21:56:16 -04008694#define NUM_SPEC_VERBS 2
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008695 struct ca0132_spec *spec = codec->spec;
8696
8697 spec->chip_init_verbs = ca0132_init_verbs0;
Connor McAdams88268ce2018-09-18 14:33:32 -04008698 /*
8699 * Since desktop cards use pci_mmio, this can be used to determine
8700 * whether or not to use these verbs instead of a separate bool.
8701 */
Takashi Iwai6da8f442018-11-09 14:18:32 +01008702 if (ca0132_use_pci_mmio(spec))
Connor McAdamse42c7c72018-08-08 13:34:18 -04008703 spec->desktop_init_verbs = ca0132_init_verbs1;
Kees Cook6396bb22018-06-12 14:03:40 -07008704 spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS,
8705 sizeof(struct hda_verb),
8706 GFP_KERNEL);
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008707 if (!spec->spec_init_verbs)
8708 return -ENOMEM;
8709
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008710 /* config EAPD */
Alastair Bridgewatera3d90d62018-06-15 21:56:16 -04008711 spec->spec_init_verbs[0].nid = 0x0b;
8712 spec->spec_init_verbs[0].param = 0x78D;
8713 spec->spec_init_verbs[0].verb = 0x00;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008714
8715 /* Previously commented configuration */
8716 /*
Alastair Bridgewatera3d90d62018-06-15 21:56:16 -04008717 spec->spec_init_verbs[2].nid = 0x0b;
8718 spec->spec_init_verbs[2].param = AC_VERB_SET_EAPD_BTLENABLE;
8719 spec->spec_init_verbs[2].verb = 0x02;
8720
8721 spec->spec_init_verbs[3].nid = 0x10;
8722 spec->spec_init_verbs[3].param = 0x78D;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008723 spec->spec_init_verbs[3].verb = 0x02;
8724
8725 spec->spec_init_verbs[4].nid = 0x10;
Alastair Bridgewatera3d90d62018-06-15 21:56:16 -04008726 spec->spec_init_verbs[4].param = AC_VERB_SET_EAPD_BTLENABLE;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008727 spec->spec_init_verbs[4].verb = 0x02;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008728 */
8729
8730 /* Terminator: spec->spec_init_verbs[NUM_SPEC_VERBS-1] */
8731 return 0;
8732}
8733
Connor McAdamsb29733d2018-09-29 23:03:18 -04008734/*
8735 * The Sound Blaster ZxR shares the same PCI subsystem ID as some regular
8736 * Sound Blaster Z cards. However, they have different HDA codec subsystem
8737 * ID's. So, we check for the ZxR's subsystem ID, as well as the DBPro
8738 * daughter boards ID.
8739 */
8740static void sbz_detect_quirk(struct hda_codec *codec)
8741{
8742 struct ca0132_spec *spec = codec->spec;
8743
8744 switch (codec->core.subsystem_id) {
8745 case 0x11020033:
8746 spec->quirk = QUIRK_ZXR;
8747 break;
8748 case 0x1102003f:
8749 spec->quirk = QUIRK_ZXR_DBPRO;
8750 break;
8751 default:
8752 spec->quirk = QUIRK_SBZ;
8753 break;
8754 }
8755}
8756
Ian Minett95c6e9c2011-06-15 15:35:17 -07008757static int patch_ca0132(struct hda_codec *codec)
8758{
8759 struct ca0132_spec *spec;
Ian Minetta73d5112012-12-20 18:53:37 -08008760 int err;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008761 const struct snd_pci_quirk *quirk;
Ian Minett95c6e9c2011-06-15 15:35:17 -07008762
Takashi Iwai4e76a882014-02-25 12:21:03 +01008763 codec_dbg(codec, "patch_ca0132\n");
Ian Minett95c6e9c2011-06-15 15:35:17 -07008764
8765 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
8766 if (!spec)
8767 return -ENOMEM;
8768 codec->spec = spec;
Chih-Chung Chang993884f2013-03-25 10:39:23 -07008769 spec->codec = codec;
Ian Minett95c6e9c2011-06-15 15:35:17 -07008770
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008771 /* Detect codec quirk */
8772 quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
8773 if (quirk)
8774 spec->quirk = quirk->value;
8775 else
8776 spec->quirk = QUIRK_NONE;
Takashi Iwai6da8f442018-11-09 14:18:32 +01008777 if (ca0132_quirk(spec) == QUIRK_SBZ)
Connor McAdamsb29733d2018-09-29 23:03:18 -04008778 sbz_detect_quirk(codec);
8779
Takashi Iwai6da8f442018-11-09 14:18:32 +01008780 if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
Connor McAdamsebabde12018-10-08 15:39:58 -04008781 codec->patch_ops = dbpro_patch_ops;
8782 else
8783 codec->patch_ops = ca0132_patch_ops;
8784
8785 codec->pcm_format_first = 1;
8786 codec->no_sticky_stream = 1;
8787
8788
Takashi Iwaie24aa0a2014-08-10 13:30:08 +02008789 spec->dsp_state = DSP_DOWNLOAD_INIT;
Ian Minetta7e76272012-12-20 18:53:35 -08008790 spec->num_mixers = 1;
Connor McAdams017310f2018-05-08 13:20:11 -04008791
8792 /* Set which mixers each quirk uses. */
Takashi Iwai6da8f442018-11-09 14:18:32 +01008793 switch (ca0132_quirk(spec)) {
Connor McAdams017310f2018-05-08 13:20:11 -04008794 case QUIRK_SBZ:
Connor McAdamse25e3442018-08-08 13:34:21 -04008795 spec->mixers[0] = desktop_mixer;
Connor McAdams017310f2018-05-08 13:20:11 -04008796 snd_hda_codec_set_name(codec, "Sound Blaster Z");
8797 break;
Connor McAdams2e492b82018-09-29 23:03:21 -04008798 case QUIRK_ZXR:
8799 spec->mixers[0] = desktop_mixer;
8800 snd_hda_codec_set_name(codec, "Sound Blaster ZxR");
8801 break;
Connor McAdams7675a2a2018-09-29 23:03:20 -04008802 case QUIRK_ZXR_DBPRO:
Connor McAdams7675a2a2018-09-29 23:03:20 -04008803 break;
Connor McAdamse25e3442018-08-08 13:34:21 -04008804 case QUIRK_R3D:
8805 spec->mixers[0] = desktop_mixer;
8806 snd_hda_codec_set_name(codec, "Recon3D");
8807 break;
Connor McAdams017310f2018-05-08 13:20:11 -04008808 case QUIRK_R3DI:
8809 spec->mixers[0] = r3di_mixer;
8810 snd_hda_codec_set_name(codec, "Recon3Di");
8811 break;
Connor McAdams88268ce2018-09-18 14:33:32 -04008812 case QUIRK_AE5:
8813 spec->mixers[0] = desktop_mixer;
8814 snd_hda_codec_set_name(codec, "Sound BlasterX AE-5");
8815 break;
Connor McAdams017310f2018-05-08 13:20:11 -04008816 default:
8817 spec->mixers[0] = ca0132_mixer;
8818 break;
8819 }
Ian Minetta7e76272012-12-20 18:53:35 -08008820
Connor McAdams08eca6b2018-08-08 13:34:17 -04008821 /* Setup whether or not to use alt functions/controls/pci_mmio */
Takashi Iwai6da8f442018-11-09 14:18:32 +01008822 switch (ca0132_quirk(spec)) {
Connor McAdams009b8f92018-05-08 13:20:06 -04008823 case QUIRK_SBZ:
Connor McAdamse42c7c72018-08-08 13:34:18 -04008824 case QUIRK_R3D:
Connor McAdams88268ce2018-09-18 14:33:32 -04008825 case QUIRK_AE5:
Connor McAdams2e492b82018-09-29 23:03:21 -04008826 case QUIRK_ZXR:
Connor McAdams08eca6b2018-08-08 13:34:17 -04008827 spec->use_alt_controls = true;
8828 spec->use_alt_functions = true;
8829 spec->use_pci_mmio = true;
8830 break;
Connor McAdams009b8f92018-05-08 13:20:06 -04008831 case QUIRK_R3DI:
Connor McAdams47cdf762018-05-08 13:20:13 -04008832 spec->use_alt_controls = true;
Connor McAdams009b8f92018-05-08 13:20:06 -04008833 spec->use_alt_functions = true;
Connor McAdams08eca6b2018-08-08 13:34:17 -04008834 spec->use_pci_mmio = false;
Connor McAdams009b8f92018-05-08 13:20:06 -04008835 break;
8836 default:
Connor McAdams47cdf762018-05-08 13:20:13 -04008837 spec->use_alt_controls = false;
Connor McAdams009b8f92018-05-08 13:20:06 -04008838 spec->use_alt_functions = false;
Connor McAdams08eca6b2018-08-08 13:34:17 -04008839 spec->use_pci_mmio = false;
Connor McAdams009b8f92018-05-08 13:20:06 -04008840 break;
8841 }
8842
Takashi Iwai6da8f442018-11-09 14:18:32 +01008843#ifdef CONFIG_PCI
Connor McAdams08eca6b2018-08-08 13:34:17 -04008844 if (spec->use_pci_mmio) {
8845 spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20);
8846 if (spec->mem_base == NULL) {
8847 codec_warn(codec, "pci_iomap failed! Setting quirk to QUIRK_NONE.");
8848 spec->quirk = QUIRK_NONE;
8849 }
8850 }
Takashi Iwai6da8f442018-11-09 14:18:32 +01008851#endif
Connor McAdams08eca6b2018-08-08 13:34:17 -04008852
Ian Minett5aaca442012-12-20 18:53:34 -08008853 spec->base_init_verbs = ca0132_base_init_verbs;
8854 spec->base_exit_verbs = ca0132_base_exit_verbs;
Ian Minett5aaca442012-12-20 18:53:34 -08008855
Chih-Chung Chang993884f2013-03-25 10:39:23 -07008856 INIT_DELAYED_WORK(&spec->unsol_hp_work, ca0132_unsol_hp_delayed);
8857
Ian Minett95c6e9c2011-06-15 15:35:17 -07008858 ca0132_init_chip(codec);
8859
8860 ca0132_config(codec);
8861
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008862 err = ca0132_prepare_verbs(codec);
8863 if (err < 0)
Takashi Iwaicc91cea2017-09-04 17:38:36 +02008864 goto error;
Gabriele Martinod5c016b2015-05-18 21:15:13 +02008865
Ian Minetta73d5112012-12-20 18:53:37 -08008866 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
8867 if (err < 0)
Takashi Iwaicc91cea2017-09-04 17:38:36 +02008868 goto error;
Ian Minetta73d5112012-12-20 18:53:37 -08008869
Ian Minett95c6e9c2011-06-15 15:35:17 -07008870 return 0;
Takashi Iwaicc91cea2017-09-04 17:38:36 +02008871
8872 error:
8873 ca0132_free(codec);
8874 return err;
Ian Minett95c6e9c2011-06-15 15:35:17 -07008875}
8876
8877/*
8878 * patch entries
8879 */
Takashi Iwaibf823262020-01-05 15:47:24 +01008880static const struct hda_device_id snd_hda_id_ca0132[] = {
Takashi Iwaib9a94a92015-10-01 16:20:04 +02008881 HDA_CODEC_ENTRY(0x11020011, "CA0132", patch_ca0132),
Ian Minett95c6e9c2011-06-15 15:35:17 -07008882 {} /* terminator */
8883};
Takashi Iwaib9a94a92015-10-01 16:20:04 +02008884MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_ca0132);
Ian Minett95c6e9c2011-06-15 15:35:17 -07008885
8886MODULE_LICENSE("GPL");
Ian Minett406261c2012-12-20 18:53:41 -08008887MODULE_DESCRIPTION("Creative Sound Core3D codec");
Ian Minett95c6e9c2011-06-15 15:35:17 -07008888
Takashi Iwaid8a766a2015-02-17 15:25:37 +01008889static struct hda_codec_driver ca0132_driver = {
Takashi Iwaib9a94a92015-10-01 16:20:04 +02008890 .id = snd_hda_id_ca0132,
Ian Minett95c6e9c2011-06-15 15:35:17 -07008891};
8892
Takashi Iwaid8a766a2015-02-17 15:25:37 +01008893module_hda_codec_driver(ca0132_driver);