-
Notifications
You must be signed in to change notification settings - Fork 8
/
patch_cirrus_real84.h
5954 lines (4122 loc) · 270 KB
/
patch_cirrus_real84.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
static int tdm_in_use(struct hda_codec *codec, int where_flag)
{
int coef_ret = 0;
int coef_idx = 0;
// re-implementation of AppleHDATDMBusManagerCS8409::tdmInUse
mycodec_info(codec, "command tdmInUse start %d\n", where_flag);
// note on OSX the coef get functions returns a status value with read value stored in passed address
// on linux it seems -1 is an error return
coef_ret = cs_8409_vendor_coef_get(codec, 0x19);
//if (coef_ret == -1) error;
coef_idx = 0x1a;
do {
if ((short)coef_ret >= 0) {
mycodec_info(codec, "command tdmInUse 1 end %d\n", where_flag);
return 1;
}
coef_ret = cs_8409_vendor_coef_get(codec, coef_idx);
//if (coef_ret == -1) error;
coef_idx++;
} while (coef_idx <= 0x57);
mycodec_info(codec, "command tdmInUse 0 end %d\n", where_flag);
return 0;
}
static int cs42l83_headphone_sense(struct hda_codec *codec)
{
int retval = 0;
// AppleHDATDM_Codec::getHeadphonePinSense(bool*, unsigned int*)
// register 0x1b77 - Detect Status 1
// value 0x96 0x80 HP plugged bias 0x16
// snd_hda i2cPagedRead i2c address 0x90 i2c reg hi 0x1b lo 0x7700 i2c data 0x7796
retval = cs_8409_vendor_i2cRead(codec, 0x90, 0x1b77, 1); // snd_hda
mycodec_info(codec, "cs42l83_headphone_sense - 0x%04x\n", retval);
return retval;
}
static int read_gpio_status_check(struct hda_codec *codec)
{
int retval;
// should these be done powered down??
// lets check power state here
retval = snd_hda_codec_read(codec, codec->core.afg, 0, AC_VERB_GET_GPIO_DATA, 0x00000000); // 0x001f1500
mycodec_info(codec, "command read_gpio_status_check %x\n", retval);
return retval;
}
static void cs_8409_intmike_format_setup_format33_nouse(struct hda_codec *codec)
{
int retval;
int ret_coef9 = 0;
int new_coef9 = 0;
struct cs8409_apple_spec *spec = codec->spec;
// 0x44 -> 0x22 is internal (I think) mike input (macbook pro)
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004033); // 0x02224033
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004033); // 0x02224033
// snd_hda: stream format 34 [('CHAN', 4), ('RATE', 44100), ('BITS', 24), ('RATE_MUL', 1), ('RATE_DIV', 1)]
}
static void cs_8409_intmike_format_setup_format_nouse(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004031); // 0x02224031
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004031); // 0x02224031
// snd_hda: stream format 34 [('CHAN', 2), ('RATE', 44100), ('BITS', 24), ('RATE_MUL', 1), ('RATE_DIV', 1)]
}
static void cs_8409_intmike_format_setup_enable(struct hda_codec *codec, int hda_format, int powered_down)
{
int retval;
int ret_coef9 = 0;
int new_coef9 = 0;
struct cs8409_apple_spec *spec = codec->spec;
// 0x44 -> 0x22 is internal (I think) mike input (macbook pro)
// now updated to not write the Apple format but use my format setting routines
// (remember we have limited the allowed formats to acceptable ones)
// note that apparently we can set the format with the nid powered down but for setting the
// stream id the nid has to be powered up
// this seems to be used a lot in plugin/unplug headset in a powered down state
// - but when capturing no power changes done
// for some very strange reason we setup a 4 channel format after unplug of headset with mike
// - otherwise its 2 channel - pass the format to allow for this
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004033); // 0x02224033
// snd_hda: stream format 34 [('CHAN', 4), ('RATE', 44100), ('BITS', 24), ('RATE_MUL', 1), ('RATE_DIV', 1)]
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_STREAM_FORMAT, hda_format); // 0x02224033
// now assuming have saved the stream info prior to calling this function
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 10515); // 0x022f0500
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02270500
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 10518); // 0x022f0500
//if (powered_down) hda_set_node_power_state(codec, 0x22, AC_PWRST_D0);
if (powered_down) hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D0);
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000010); // 0x02270610
// snd_hda: conv stream channel map 34 [('CHAN', 0), ('STREAMID', 1)]
// using the stored stream parameters update nid 0x22 stream parameters
// we have limited the allowed formats so should only have working formats here
//cs_8409_really_update_stream_format(codec, 0x22, 1, 1, 0);
cs_8409_really_update_stream_format(codec, spec->intmike_adc_nid, 1, 1, 0);
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02270503
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 10521); // 0x022f0500
//if (powered_down) hda_set_node_power_state(codec, 0x22, AC_PWRST_D3);
if (powered_down) hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D3);
// snd_hda: # AppleHDAWidgetCS8409::setConnectionSelect:
ret_coef9 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0009, 0x0000, 0x000000b3, 0 ); // AppleHDAWidgetCS8409::setConnectionSelect coef read 10523
//new_coef9 = (ret_coef9 | 0x20); // note most of the time it just seems to copy the value because bit 0x20 already set on input
// // only on boot does this get set
new_coef9 = (ret_coef9 | spec->reg9_intmike_dmic_mo); // note most of the time it just seems to copy the value because bit 0x20 already set on input
// only on boot does this get set
myprintk_dbg("snd_hda_intel: masked cs_8409_intmike_format_setup_enable coef 0x09 update 0x%04x 0x%04x \n", ret_coef9, new_coef9);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0009, 0x00b3, 0x00000000, 10527 ); // AppleHDAWidgetCS8409::setConnectionSelect coef write 10527
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0009, new_coef9, 0x00000000, 0 ); // AppleHDAWidgetCS8409::setConnectionSelect coef write 10527
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_CONNECT_SEL, 0x00000000); // 0x02270100
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_CONNECT_SEL, 0x00000000); // 0x02270100
}
static void cs_8409_volume_set(struct hda_codec *codec, hda_nid_t nid, int volume)
{
int retgain;
int newgain;
retgain = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000); // 0x022b2000
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x6000;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02236027
retgain = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000); // 0x022b0000
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x5000;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02235027
}
static void cs_8409_volume_mute(struct hda_codec *codec, hda_nid_t nid)
{
int retgain;
int newgain;
retgain = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000); // 0x022b2000
newgain = (retgain & 0x7f) | 0x80 | 0x6000;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02236000
retgain = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000); // 0x022b0000
newgain = (retgain & 0x7f) | 0x80 | 0x5000;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02235027
}
static void cs_8409_volume_unmute(struct hda_codec *codec, hda_nid_t nid)
{
int retgain;
int newgain;
retgain = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000); // 0x022b2000
newgain = (retgain & 0x7f) | 0x6000;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02236000
retgain = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000); // 0x022b0000
newgain = (retgain & 0x7f) | 0x5000;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02235027
}
static void cs_8409_intmike_volume_set(struct hda_codec *codec, int volume)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_set(codec, spec->intmike_adc_nid, volume);
}
static void cs_8409_linein_volume_set(struct hda_codec *codec, int volume)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_set(codec, spec->linein_amp_nid, volume);
}
static void cs_8409_intmike_volume_unmute(struct hda_codec *codec)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_unmute(codec, spec->intmike_adc_nid);
}
static void cs_8409_linein_volume_unmute(struct hda_codec *codec)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_unmute(codec, spec->linein_amp_nid);
}
static void cs_8409_intmike_volume_mute(struct hda_codec *codec)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_mute(codec, spec->intmike_adc_nid);
}
static void cs_8409_linein_volume_mute(struct hda_codec *codec)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_mute(codec, spec->linein_amp_nid);
}
static void cs_8409_intmike_volume_setup_new(struct hda_codec *codec, int volume)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_set(codec, spec->intmike_adc_nid, volume);
cs_8409_volume_mute(codec, spec->intmike_adc_nid);
cs_8409_volume_set(codec, spec->intmike_nid, 0x00);
}
static void cs_8409_linein_volume_setup_new(struct hda_codec *codec, int volume)
{
struct cs8409_apple_spec *spec = codec->spec;
cs_8409_volume_set(codec, spec->linein_amp_nid, volume);
cs_8409_volume_mute(codec, spec->linein_amp_nid);
cs_8409_volume_set(codec, spec->linein_nid, 0x00);
}
static void cs_8409_intmike_volume_setup(struct hda_codec *codec, int volume)
{
int retgain;
int newgain;
struct cs8409_apple_spec *spec = codec->spec;
// plausibly AppleHDAWidget::setWidgetAmplifierGain
//retgain = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000033, 0); // 0x022b2000
retgain = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000033, 0); // 0x022b2000
// snd_hda: amp gain/mute 34 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 34 0x0033 mute 0 gain 0x33 51
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x6000;
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02236027
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006027); // 0x02236027
// snd_hda: amp gain/mute 34 0x6027 mute 0 gain 0x27 39 index 0x00 left 1 right 0 output 0 input 1 left input
//retgain = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000033, 0); // 0x022b0000
retgain = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000033, 0); // 0x022b0000
// snd_hda: amp gain/mute 34 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 34 0x0033 mute 0 gain 0x33 51
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x5000;
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x02235027
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005027); // 0x02235027
// snd_hda: amp gain/mute 34 0x5027 mute 0 gain 0x27 39 index 0x00 left 0 right 1 output 0 input 1 right input
// mute
// plausibly AppleHDAWidget::setWidgetAmplifierMute
//retgain = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000027, 0); // 0x022b2000
retgain = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000027, 0); // 0x022b2000
// snd_hda: amp gain/mute 34 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 34 0x0027 mute 0 gain 0x27 39
newgain = (retgain & 0x7f) | 0x80 | 0x6000;
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x022360a7
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060a7); // 0x022360a7
// snd_hda: amp gain/mute 34 0x60a7 mute 1 gain 0x27 39 index 0x00 left 1 right 0 output 0 input 1 left input
//retgain = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000027, 0); // 0x022b0000
retgain = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000027, 0); // 0x022b0000
// snd_hda: amp gain/mute 34 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 34 0x0027 mute 0 gain 0x27 39
newgain = (retgain & 0x7f) | 0x80 | 0x5000;
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x022350a7
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050a7); // 0x022350a7
// snd_hda: amp gain/mute 34 0x50a7 mute 1 gain 0x27 39 index 0x00 left 0 right 1 output 0 input 1 right input
// this is working on node 0x44 macbook pro
// plausibly AppleHDAWidget::setWidgetAmplifierGain
//retgain = snd_hda_codec_read_check(codec, 0x44, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000000, 0); // 0x044b2000
retgain = snd_hda_codec_read_check(codec, spec->intmike_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000000, 0); // 0x044b2000
// snd_hda: amp gain/mute 68 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 68 0x0000 mute 0 gain 0x0 0
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x6000;
snd_hda_codec_write(codec, spec->intmike_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x04436000
//snd_hda_codec_write(codec, 0x44, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006000); // 0x04436000
// snd_hda: amp gain/mute 68 0x6000 mute 0 gain 0x0 0 index 0x00 left 1 right 0 output 0 input 1 left input
//retgain = snd_hda_codec_read_check(codec, 0x44, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000000, 0); // 0x044b0000
retgain = snd_hda_codec_read_check(codec, spec->intmike_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000000, 0); // 0x044b0000
// snd_hda: amp gain/mute 68 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 68 0x0000 mute 0 gain 0x0 0
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x5000;
snd_hda_codec_write(codec, spec->intmike_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x04435000
//snd_hda_codec_write(codec, 0x44, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005000); // 0x04435000
// snd_hda: amp gain/mute 68 0x5000 mute 0 gain 0x0 0 index 0x00 left 0 right 1 output 0 input 1 right input
}
static void cs_8409_linein_volume_setup(struct hda_codec *codec, int volume)
{
int retgain;
int newgain;
struct cs8409_apple_spec *spec = codec->spec;
// so as far as I can see the 1st section sets the gain and the second section sets the mute
// it appears we do masked updates
//volume = 0x27;
// plausibly AppleHDAWidget::setWidgetAmplifierGain
//retgain = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000b3, 0); // 0x023b2000
retgain = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000b3, 0); // 0x023b2000
// snd_hda: amp gain/mute 35 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 35 0x00b3 mute 1 gain 0x33 51
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x6000;
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060a7); // 0x023360a7
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060a7); // 0x023360a7
// snd_hda: amp gain/mute 35 0x60a7 mute 1 gain 0x27 39 index 0x00 left 1 right 0 output 0 input 1 left input
//retgain = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000b3, 0); // 0x023b0000
retgain = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000b3, 0); // 0x023b0000
// snd_hda: amp gain/mute 35 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 35 0x00b3 mute 1 gain 0x33 51
newgain = (retgain & 0x80) | (volume & 0x7f) | 0x5000;
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x023350a7
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050a7); // 0x023350a7
// snd_hda: amp gain/mute 35 0x50a7 mute 1 gain 0x27 39 index 0x00 left 0 right 1 output 0 input 1 right input
// mute
// plausibly AppleHDAWidget::setWidgetAmplifierMute
//retgain = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000a7, 0); // 0x023b2000
retgain = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000a7, 0); // 0x023b2000
// snd_hda: amp gain/mute 35 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 35 0x00a7 mute 1 gain 0x27 39
newgain = (retgain & 0x7f) | 0x80 | 0x6000;
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x023360a7
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060a7); // 0x023360a7
// snd_hda: amp gain/mute 35 0x60a7 mute 1 gain 0x27 39 index 0x00 left 1 right 0 output 0 input 1 left input
//retgain = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000a7, 0); // 0x023b0000
retgain = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000a7, 0); // 0x023b0000
// snd_hda: amp gain/mute 35 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 35 0x00a7 mute 1 gain 0x27 39
newgain = (retgain & 0x7f) | 0x80 | 0x5000;
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, newgain); // 0x023350a7
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050a7); // 0x023350a7
// snd_hda: amp gain/mute 35 0x50a7 mute 1 gain 0x27 39 index 0x00 left 0 right 1 output 0 input 1 right input
// this is working on node 0x45 macbook pro
// plausibly AppleHDAWidget::setWidgetAmplifierGain
//retgain = snd_hda_codec_read_check(codec, 0x45, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000000, 0); // 0x045b2000
retgain = snd_hda_codec_read_check(codec, spec->linein_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x00000000, 0); // 0x045b2000
// snd_hda: amp gain/mute 69 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 69 0x0000 mute 0 gain 0x0 0
snd_hda_codec_write(codec, spec->linein_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006000); // 0x04536000
//snd_hda_codec_write(codec, 0x45, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006000); // 0x04536000
// snd_hda: amp gain/mute 69 0x6000 mute 0 gain 0x0 0 index 0x00 left 1 right 0 output 0 input 1 left input
//retgain = snd_hda_codec_read_check(codec, 0x45, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000000, 0); // 0x045b0000
retgain = snd_hda_codec_read_check(codec, spec->linein_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x00000000, 0); // 0x045b0000
// snd_hda: amp gain/mute 69 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 69 0x0000 mute 0 gain 0x0 0
snd_hda_codec_write(codec, spec->linein_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005000); // 0x04535000
//snd_hda_codec_write(codec, 0x45, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005000); // 0x04535000
// snd_hda: amp gain/mute 69 0x5000 mute 0 gain 0x0 0 index 0x00 left 0 right 1 output 0 input 1 right input
}
static void cs_8409_intmike_stream_on_nid(struct hda_codec *codec)
{
int retval;
int reg_coef82 = 0;
int new_coef82 = 0;
struct cs8409_apple_spec *spec = codec->spec;
reg_coef82 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0082, 0x0000, 0x00005400, 0 ); // coef read 10544
//new_coef82 = (reg_coef82 | 0x1);
new_coef82 = (reg_coef82 | spec->reg82_intmike_dmic_scl);
myprintk_dbg("snd_hda_intel: masked cs_8409_intmike_stream_on_nid coef 0x0082 update 0x%04x 0x%04x \n", reg_coef82, new_coef82);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0082, 0x5401, 0x00000000, 10548 ); // coef write 10548
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0082, new_coef82, 0x00000000, 0 ); // coef write 10548
//retval = snd_hda_codec_read_check(codec, 0x44, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000000, 0); // 0x044f0700
retval = snd_hda_codec_read_check(codec, spec->intmike_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000000, 0); // 0x044f0700
snd_hda_codec_write(codec, spec->intmike_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000020); // 0x04470720
//snd_hda_codec_write(codec, 0x44, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000020); // 0x04470720
// snd_hda: 68 ['AC_PINCTL_IN_EN']
//snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x00170503
//hda_set_node_power_state(codec, codec->core.afg, AC_PWRST_D3);
}
static void cs_8409_intmike_format_setup_disable(struct hda_codec *codec)
{
int retval;
int reg_coef82 = 0;
int new_coef82 = 0;
struct cs8409_apple_spec *spec = codec->spec;
// set to defaults and disable input
// note here we really reset to 0 format in addition to stream id 0/channel id 0
// note this means the cached stream data in the hda_cvt_setup struct will now be inconsistent
// we need to ensure any further stream format re-update MUST be a forced update
// still not clear if should be calling eg __snd_hda_codec_cleanup_stream
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12217); // 0x022f0500
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02270500
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 12220); // 0x022f0500
hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D0);
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02270600
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02270600
// snd_hda: conv stream channel map 34 [('CHAN', 0), ('STREAMID', 0)]
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02270503
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12223); // 0x022f0500
hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D3);
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0x00000000); // 0x02220000
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_STREAM_FORMAT, 0x00000000); // 0x02220000
// snd_hda: stream format 34 [('CHAN', 1), ('RATE', 48000), ('BITS', 8), ('RATE_MUL', 1), ('RATE_DIV', 1)]
// AppleHDAWidgetCS8409::configurePinForIO(bool)??
reg_coef82 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0082, 0x0000, 0x0000a801, 0 ); // coef read 12226
//new_coef82 = (reg_coef82 & 0xfffffffe);
new_coef82 = (reg_coef82 & ~spec->reg82_intmike_dmic_scl);
myprintk_dbg("snd_hda_intel: masked cs_8409_intmike_format_setup_disable coef 0x0082 update 0x%04x 0x%04x \n", reg_coef82, new_coef82);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0082, 0xa800, 0x00000000, 12230 ); // coef write 12230
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0082, new_coef82, 0x00000000, 0 ); // coef write 12230
//retval = snd_hda_codec_read_check(codec, 0x44, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000020, 0); // 0x044f0700
retval = snd_hda_codec_read_check(codec, spec->intmike_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000020, 0); // 0x044f0700
snd_hda_codec_write(codec, spec->intmike_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000000); // 0x04470700
//snd_hda_codec_write(codec, 0x44, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000000); // 0x04470700
// snd_hda: 68 []
}
static void cs_8409_linein_format_setup_disable(struct hda_codec *codec)
{
int retval;
int reg_coef82 = 0;
int new_coef82 = 0;
struct cs8409_apple_spec *spec = codec->spec;
// 0x45 -> 0x23 is line input (macbook pro)
// set to defaults and disable input
// note here we really reset to 0 format in addition to stream id 0/channel id 0
// note this means the cached stream data in the hda_cvt_setup struct will now be inconsistent
// we need to ensure any further stream format re-update MUST be a forced update
// still not clear if should be calling eg __snd_hda_codec_cleanup_stream
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12248); // 0x023f0500
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02370500
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 12251); // 0x023f0500
hda_set_node_power_state(codec, spec->linein_amp_nid, AC_PWRST_D0);
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02370600
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02370600
// snd_hda: conv stream channel map 35 [('CHAN', 0), ('STREAMID', 0)]
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02370503
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12254); // 0x023f0500
hda_set_node_power_state(codec, spec->linein_amp_nid, AC_PWRST_D3);
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0x00000000); // 0x02320000
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_STREAM_FORMAT, 0x00000000); // 0x02320000
// snd_hda: stream format 35 [('CHAN', 1), ('RATE', 48000), ('BITS', 8), ('RATE_MUL', 1), ('RATE_DIV', 1)]
reg_coef82 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0082, 0x0000, 0x0000a800, 0 ); // coef read 12257
//new_coef82 = (reg_coef82 & 0xfffffffd);
new_coef82 = (reg_coef82 & ~spec->reg82_linein_dmic_scl);
myprintk_dbg("snd_hda_intel: masked cs_8409_linein_format_setup_disable coef 0x0082 update 0x%04x 0x%04x \n", reg_coef82, new_coef82);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0082, 0xa800, 0x00000000, 12261 ); // coef write 12261
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0082, new_coef82, 0x00000000, 0 ); // coef write 12261
//retval = snd_hda_codec_read_check(codec, 0x45, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000000, 0); // 0x045f0700
retval = snd_hda_codec_read_check(codec, spec->linein_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000000, 0); // 0x045f0700
snd_hda_codec_write(codec, spec->linein_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000000); // 0x04570700
//snd_hda_codec_write(codec, 0x45, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000000); // 0x04570700
// snd_hda: 69 []
}
static void cs_8409_intmike_stream_conn_off(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0, AC_VERB_SET_PROC_STATE, 0x00000001); // 0x04770301
// 0x44 -> 0x22 is internal (I think) mike input (macbook pro)
retval = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_CONV, 0x00000000, 0x00000000, 0); // 0x022f0600
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_CONV, 0x00000000, 0x00000000, 0); // 0x022f0600
// snd_hda: conv stream channel map 34 [('CHAN', 0), ('STREAMID', 0)]
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12160); // 0x022f0500
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02270500
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 12163); // 0x022f0500
hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D0);
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02270600
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02270600
// snd_hda: conv stream channel map 34 [('CHAN', 0), ('STREAMID', 0)]
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02270503
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12166); // 0x022f0500
hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D3);
// this seems to be updating the coef index associated with setConnectionSelect
// unable to figure where this is coming from currently
// snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0009, 0x0033, 0xffff, 0x00000033, 0, 12168 ); // coef write mask 12168
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0009, 0x0000, 0x0000, 0x00000033, 0x0033, 0 ); // coef write mask 12168
}
static void cs_8409_linein_stream_conn_off(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
// Im thinking of a bugfix here to turn off bit 0x80 of index 0x0009
// 0x45 -> 0x23 is line input (macbook pro)
retval = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_CONV, 0x00000000, 0x00000000, 0); // 0x023f0600
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_CONV, 0x00000000, 0x00000000, 0); // 0x023f0600
// snd_hda: conv stream channel map 35 [('CHAN', 0), ('STREAMID', 0)]
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12175); // 0x023f0500
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02370500
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 12178); // 0x023f0500
hda_set_node_power_state(codec, spec->linein_amp_nid, AC_PWRST_D0);
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02370600
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02370600
// snd_hda: conv stream channel map 35 [('CHAN', 0), ('STREAMID', 0)]
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02370503
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12181); // 0x023f0500
hda_set_node_power_state(codec, spec->linein_amp_nid, AC_PWRST_D3);
// this seems to be updating the coef index associated with setConnectionSelect
// unable to figure where this is coming from currently
// snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0009, 0x0033, 0xffff, 0x00000033, 0, 12183 ); // coef write mask 12183
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0009, 0x0000, 0x0000, 0x00000033, 0x0033, 0 ); // coef write mask 12183
// possible correct mask to use
//snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0009, 0x0000, 0x0080, 0x00000033, 0, 0 ); // coef write mask 12183
}
static void cs_8409_intmike_stream_off_nid(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12189); // 0x022f0500
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02270500
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 12192); // 0x022f0500
hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D0);
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02270600
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02270600
// snd_hda: conv stream channel map 34 [('CHAN', 0), ('STREAMID', 0)]
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02270503
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12195); // 0x022f0500
hda_set_node_power_state(codec, spec->intmike_adc_nid, AC_PWRST_D3);
}
static void cs_8409_linein_stream_off_nid(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12197); // 0x023f0500
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x02370500
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000030, 12200); // 0x023f0500
hda_set_node_power_state(codec, spec->linein_amp_nid, AC_PWRST_D0);
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02370600
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x02370600
// snd_hda: conv stream channel map 35 [('CHAN', 0), ('STREAMID', 0)]
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_POWER_STATE, 0x00000003); // 0x02370503
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_POWER_STATE, 0x00000000, 0x00000033, 12203); // 0x023f0500
hda_set_node_power_state(codec, spec->linein_amp_nid, AC_PWRST_D3);
}
static void cs_8409_intmike_volume_mute_nouse(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
// nodes 0x44 is connected to 0x22 which is labelled mic input (macbook pro)
//snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_POWER_STATE, 0x00000000); // 0x00170500
//hda_set_node_power_state(codec, codec->core.afg, AC_PWRST_D0);
retval = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000a7, 0); // 0x022b2000
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000a7, 0); // 0x022b2000
// snd_hda: amp gain/mute 34 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 34 0x00a7 mute 1 gain 0x27 39
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060b3); // 0x022360b3
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060b3); // 0x022360b3
// snd_hda: amp gain/mute 34 0x60b3 mute 1 gain 0x33 51 index 0x00 left 1 right 0 output 0 input 1 left input
retval = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000a7, 0); // 0x022b0000
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000a7, 0); // 0x022b0000
// snd_hda: amp gain/mute 34 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 34 0x00a7 mute 1 gain 0x27 39
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050b3); // 0x022350b3
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050b3); // 0x022350b3
// snd_hda: amp gain/mute 34 0x50b3 mute 1 gain 0x33 51 index 0x00 left 0 right 1 output 0 input 1 right input
}
static void cs_8409_linein_volume_mute_nouse(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
// nodes 0x45 which are connected to 0x23 is labelled as line input (macbook pro)
retval = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000a7, 0); // 0x023b2000
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000a7, 0); // 0x023b2000
// snd_hda: amp gain/mute 35 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 35 0x00a7 mute 1 gain 0x27 39
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060b3); // 0x023360b3
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000060b3); // 0x023360b3
// snd_hda: amp gain/mute 35 0x60b3 mute 1 gain 0x33 51 index 0x00 left 1 right 0 output 0 input 1 left input
retval = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000a7, 0); // 0x023b0000
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000a7, 0); // 0x023b0000
// snd_hda: amp gain/mute 35 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 35 0x00a7 mute 1 gain 0x27 39
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050b3); // 0x023350b3
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x000050b3); // 0x023350b3
// snd_hda: amp gain/mute 35 0x50b3 mute 1 gain 0x33 51 index 0x00 left 0 right 1 output 0 input 1 right input
}
static void cs_8409_intmike_volume_unmute_nouse(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
// nodes 0x44 is connected to 0x22 which is labelled mic input (macbook pro)
retval = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000b3, 0); // 0x022b2000
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000b3, 0); // 0x022b2000
// snd_hda: amp gain/mute 34 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 34 0x00b3 mute 1 gain 0x33 51
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006033); // 0x02236033
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006033); // 0x02236033
// snd_hda: amp gain/mute 34 0x6033 mute 0 gain 0x33 51 index 0x00 left 1 right 0 output 0 input 1 left input
retval = snd_hda_codec_read_check(codec, spec->intmike_adc_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000b3, 0); // 0x022b0000
//retval = snd_hda_codec_read_check(codec, 0x22, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000b3, 0); // 0x022b0000
// snd_hda: amp gain/mute 34 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 34 0x00b3 mute 1 gain 0x33 51
snd_hda_codec_write(codec, spec->intmike_adc_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005033); // 0x02235033
//snd_hda_codec_write(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005033); // 0x02235033
// snd_hda: amp gain/mute 34 0x5033 mute 0 gain 0x33 51 index 0x00 left 0 right 1 output 0 input 1 right input
}
static void cs_8409_linein_volume_unmute_nouse(struct hda_codec *codec)
{
int retval;
struct cs8409_apple_spec *spec = codec->spec;
// nodes 0x45 which are connected to 0x23 is labelled as line input (macbook pro)
retval = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000b3, 0); // 0x023b2000
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00002000, 0x000000b3, 0); // 0x023b2000
// snd_hda: amp gain/mute 35 0x2000 index 0x00 left/right 1 left output/input 0 input
// snd_hda: amp gain/mute 35 0x00b3 mute 1 gain 0x33 51
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006033); // 0x02336033
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00006033); // 0x02336033
// snd_hda: amp gain/mute 35 0x6033 mute 0 gain 0x33 51 index 0x00 left 1 right 0 output 0 input 1 left input
retval = snd_hda_codec_read_check(codec, spec->linein_amp_nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000b3, 0); // 0x023b0000
//retval = snd_hda_codec_read_check(codec, 0x23, 0, AC_VERB_GET_AMP_GAIN_MUTE, 0x00000000, 0x000000b3, 0); // 0x023b0000
// snd_hda: amp gain/mute 35 0x0000 index 0x00 left/right 0 right output/input 0 input
// snd_hda: amp gain/mute 35 0x00b3 mute 1 gain 0x33 51
snd_hda_codec_write(codec, spec->linein_amp_nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005033); // 0x02335033
//snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x00005033); // 0x02335033
// snd_hda: amp gain/mute 35 0x5033 mute 0 gain 0x33 51 index 0x00 left 0 right 1 output 0 input 1 right input
}
static void cs_8409_setup_TDM_sample_rate(struct hda_codec *codec)
{
// codes from windows cs4208_38.inf file
// 0x0001 undocumented (0x0066 = ASP1/2_EN = 1, ASP1/2_STP = 1 ie ASP1_EN = 0x40, ASP2_EN = 0x20, ASP1_STP = 0x4, ASP2_STP = 0x2)
// 0x0005 0x0001 SCDIV 1:4 (0x005a = ASP1: MCEN = 0, FSD = 010 (0x40), SCPOL_IN/OUT = 1 (0x10), SCDIV = 1:4 ie 0x0-0xf)
// 0x0004 0x08ff SC_SRCSEL? = PLL1, LCPR = 0xff (0x28FF = (ASP1: MC/SC_SRCSEL = PLL1, LCPR = FFh), 0x2801 = (ASP1: MC/SC_SRCSEL = PLL1, LCPR = 01h))
// snd_hda: # AppleHDATDMBusManagerCS8409::setSampleRate:
//snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0001, 0x0200, 0xffff, 0x00000200, 0, 25 ); // coef write mask 25
//snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0005, 0x0001, 0xffff, 0x00000001, 0, 31 ); // coef write mask 31
//snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0004, 0x08ff, 0xffff, 0x000008ff, 0, 37 ); // coef write mask 37
// we need to use proper masked versions here - in particular for register 1 which seems to be some form of enable control
// for the subsystems and bits 0x7f need to pass thro here
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0001, 0x0200, 0x0380, 0x00000200, 0, 0 ); // coef write mask 25
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0005, 0x0001, 0x0007, 0x00000001, 0, 0 ); // coef write mask 31
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0004, 0x08ff, 0x01ff, 0x000008ff, 0, 0 ); // coef write mask 37
}
static void cs_8409_setup_TDM_proper_amps12(struct hda_codec *codec)
{
int ret_coef0 = 0;
int new_coef0 = 0;
int ret_coef1 = 0;
int new_coef1 = 0;
int ret_coef71 = 0;
int new_coef71 = 0;
// codes from windows cs4208_38.inf file
// 0x0019 0x0800 = (ASP1.A: TX.LAP = 0, TX.LSZ = 24 bits, TX.LCS = 0)
// 0x001a 0x0820 = (ASP1.A: TX.RAP = 0, TX.RSZ = 24 bits, TX.RCS = 32)
// snd_hda: # AppleHDATDMBusManagerCS8409::setupTDMPath:
snd_hda_coef_item(codec, 0, CS8409_VENDOR_NID, 0x0019, 0x0000, 0x00008800, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef read 44
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0019, 0x0800, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 48
snd_hda_coef_item(codec, 0, CS8409_VENDOR_NID, 0x001a, 0x0000, 0x00008820, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef read 52
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x001a, 0x0820, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 56
// codes from windows cs4208_38.inf file
// 0x0000 0xb000 = PLL2_EN (0x2000) PLL1_EN (0x1000) I2C disabled
// 0x0004 0x08ff SC_SRCSEL? = PLL1, LCPR = 0xff (0x28FF = (ASP1: MC/SC_SRCSEL = PLL1, LCPR = FFh), 0x2801 = (ASP1: MC/SC_SRCSEL = PLL1, LCPR = 01h))
// 0x0000 0x9000 = PLL1_EN (0x1000) I2C disabled
ret_coef0 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0000, 0x0000, 0x00009000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef read 60
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0000, 0xb000, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 64
snd_hda_coef_item(codec, 0, CS8409_VENDOR_NID, 0x0004, 0x0000, 0x000008ff, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef read 68
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0004, 0x08ff, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 72
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0000, 0x9000, 0x00000000, 76 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 76
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0000, 0xb000, 0x00000000, 76 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 76
// it seems we re-write what we read just above here - if never plugin headphones its 0x9000
// after headphone plugin its 0xb0000 - even after unplugging headphones!!
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0000, ret_coef0, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 76
// codes from windows cs4208_38.inf file
// 0x0003 0x8000 = (ASP1: LCHI = 00h)
// 0x0005 0x0001 = SCDIV = 1:4 (0x005A = (ASP1: MCEN = 0, FSD = 010 (0x40), SCPOL_IN/OUT = 1 (0x10), SCDIV = 1:4))
// snd_hda: # AppleHDATDMBusManagerCS8409::setupTDMPath:
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0003, 0x8000, 0xffff, 0x00008000, 0, 0 ); // coef write mask 80
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0005, 0x0001, 0xffff, 0x00000001, 0, 0 ); // coef write mask 86
// codes from windows cs4208_38.inf file
// 0x0082 0x5401 = ASP1_xxx_EN (0x4000) ASP1_xxx_EN (0x1000) ASP1_xxx_EN (0x400) DMIC1_SCL_EN = 1 (0xFC01 = (ASP1/2_xxx_EN = 1, ASP1/2_MCLK_EN = 0, DMIC1_SCL_EN = 1))
// snd_hda: # AppleHDATDMBusManagerCS8409::setupTDMPath:
//snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0082, 0x5401, 0xffff, 0x00000001, 0, 92 ); // coef write mask 92
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0082, 0x5400, 0x0000, 0x00000001, 0x5401, 0 ); // coef write mask 92
// codes from windows cs4208_38.inf file
// 0x0002 0x0280 = ASP2_BUS_IDLE (0x02) GPIO_I2C (0x0A80 = (ASP1/2_BUS_IDLE = 10, +GPIO_I2C))
// no evidence this is anything other than 0x0280 yet
snd_hda_coef_item_masked(codec, 2, CS8409_VENDOR_NID, 0x0002, 0x0280, 0xffff, 0x00000280, 0, 0 ); // coef write mask 98
ret_coef1 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0001, 0x0000, 0x00000200, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef read 104
new_coef1 = (ret_coef1 & 0xffff) | 0x20;
myprintk_dbg("snd_hda_intel: masked cs_8409_setup_TDM_proper_amps12 coef 0x01 update 0x%04x 0x%04x \n", ret_coef1, new_coef1);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0001, 0x0220, 0x00000000, 108 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 108
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0001, new_coef1, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::setupTDMPath coef write 108
// snd_hda: # AppleHDATDMBusManagerCS8409::configureTDMUR: AppleHDATDMBusManagerCS8409::tdmInUse:
//snd_hda_coef_item(codec, 0, CS8409_VENDOR_NID, 0x0019, 0x0000, 0x00000800, 112 ); // coef read 112
tdm_in_use(codec, 1);
// snd_hda: # AppleHDATDMBusManagerCS8409::configureTDMUR:
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x006b, 0x001f, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::configureTDMUR coef write 117
ret_coef71 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0071, 0x0000, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::configureTDMUR coef read 121
new_coef71 = (ret_coef71 & 0xffff) | 0x400f;
myprintk_dbg("snd_hda_intel: masked cs_8409_setup_TDM_proper_amps12 coef 0x71 update 0x%04x 0x%04x \n", ret_coef71, new_coef71);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0071, 0x400f, 0x00000000, 125 ); // AppleHDATDMBusManagerCS8409::configureTDMUR coef write 125
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0071, new_coef71, 0x00000000, 0 ); // AppleHDATDMBusManagerCS8409::configureTDMUR coef write 125
snd_hda_codec_write(codec, CS8409_VENDOR_NID, 0, 0x7f0, 0x00b6 ); // AppleHDATDMBusManagerCS8409::configureTDMUR write verb 128
}
static void cs_8409_setup_TDM_amps12(struct hda_codec *codec, int setrate, int nullformat)
{
int retval;
int ret_coef1 = 0;
int new_coef1 = 0;
// this seems to be setup for node 0x02 chain - which seems to use node 0x24 and amps 0x64 and 0x62 (or 0x28 0x2a)
//snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004033); // 0x00224033
// snd_hda: stream format 2 [('CHAN', 4), ('RATE', 44100), ('BITS', 24), ('RATE_MUL', 1), ('RATE_DIV', 1)]
//snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000010); // 0x00270610
// snd_hda: conv stream channel map 2 [('CHAN', 0), ('STREAMID', 1)]
if (nullformat)
{
// note that 0x4033 is Apples fixed format - but this is for boot stage when we have
// not defined any format yet so just use it - we overwrite below when actually play
snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_STREAM_FORMAT, 0x00004033); // 0x00224033
snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CHANNEL_STREAMID, 0x00000000); // 0x00270600
}
else
{
// using the stored stream parameters update nid 0x2 stream parameters
// we have limited the allowed formats so should only have working formats here
cs_8409_really_update_stream_format(codec, 0x02, 1, 2, 0);
}
// snd_hda: # AppleHDATDMBusManagerCS8409::setupTDMPath:
ret_coef1 = snd_hda_coef_item_check(codec, 0, CS8409_VENDOR_NID, 0x0001, 0x0000, 0x00000200, 0 ); // coef read 16
new_coef1 = (ret_coef1 & 0xffff); // not clear what this is setting - no difference between read and write
// however if used in different places the actual value may be different
myprintk_dbg("snd_hda_intel: masked cs_8409_setup_TDM_amps12 coef 0x01 update 0x%04x 0x%04x \n", ret_coef1, new_coef1);
//snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0001, 0x0200, 0x00000000, 20 ); // coef write 20
snd_hda_coef_item(codec, 1, CS8409_VENDOR_NID, 0x0001, new_coef1, 0x00000000, 0 ); // coef write 20
if (setrate)
cs_8409_setup_TDM_sample_rate(codec);
cs_8409_setup_TDM_proper_amps12(codec);
// enable output node 0x24
//retval = snd_hda_codec_read_check(codec, 0x24, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000, 0x00000000, 132); // 0x024f0700
retval = snd_hda_codec_read(codec, 0x24, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00000000); // 0x024f0700
snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00000040); // 0x02470740
// snd_hda: 36 ['AC_PINCTL_OUT_EN']
}
static void play_setup_TDM_amps12(struct hda_codec *codec, int setrate)
{