@@ -2630,34 +2630,92 @@ static bool dspload_wait_loaded(struct hda_codec *codec)
2630
2630
CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir)
2631
2631
2632
2632
/*
2633
- * PCM callbacks
2633
+ * PCM stuffs
2634
2634
*/
2635
- static int ca0132_playback_pcm_open (struct hda_pcm_stream * hinfo ,
2636
- struct hda_codec * codec ,
2637
- struct snd_pcm_substream * substream )
2635
+ static void ca0132_setup_stream (struct hda_codec * codec , hda_nid_t nid ,
2636
+ u32 stream_tag ,
2637
+ int channel_id , int format )
2638
2638
{
2639
- struct ca0132_spec * spec = codec -> spec ;
2640
- return snd_hda_multi_out_analog_open (codec , & spec -> multiout , substream ,
2641
- hinfo );
2639
+ unsigned int oldval , newval ;
2640
+
2641
+ if (!nid )
2642
+ return ;
2643
+
2644
+ snd_printdd (
2645
+ "ca0132_setup_stream: NID=0x%x, stream=0x%x, "
2646
+ "channel=%d, format=0x%x\n" ,
2647
+ nid , stream_tag , channel_id , format );
2648
+
2649
+ /* update the format-id if changed */
2650
+ oldval = snd_hda_codec_read (codec , nid , 0 ,
2651
+ AC_VERB_GET_STREAM_FORMAT ,
2652
+ 0 );
2653
+ if (oldval != format ) {
2654
+ msleep (20 );
2655
+ snd_hda_codec_write (codec , nid , 0 ,
2656
+ AC_VERB_SET_STREAM_FORMAT ,
2657
+ format );
2658
+ }
2659
+
2660
+ oldval = snd_hda_codec_read (codec , nid , 0 , AC_VERB_GET_CONV , 0 );
2661
+ newval = (stream_tag << 4 ) | channel_id ;
2662
+ if (oldval != newval ) {
2663
+ snd_hda_codec_write (codec , nid , 0 ,
2664
+ AC_VERB_SET_CHANNEL_STREAMID ,
2665
+ newval );
2666
+ }
2667
+ }
2668
+
2669
+ static void ca0132_cleanup_stream (struct hda_codec * codec , hda_nid_t nid )
2670
+ {
2671
+ unsigned int val ;
2672
+
2673
+ if (!nid )
2674
+ return ;
2675
+
2676
+ snd_printdd (KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n" , nid );
2677
+
2678
+ val = snd_hda_codec_read (codec , nid , 0 , AC_VERB_GET_CONV , 0 );
2679
+ if (!val )
2680
+ return ;
2681
+
2682
+ snd_hda_codec_write (codec , nid , 0 , AC_VERB_SET_STREAM_FORMAT , 0 );
2683
+ snd_hda_codec_write (codec , nid , 0 , AC_VERB_SET_CHANNEL_STREAMID , 0 );
2642
2684
}
2643
2685
2686
+ /*
2687
+ * PCM callbacks
2688
+ */
2644
2689
static int ca0132_playback_pcm_prepare (struct hda_pcm_stream * hinfo ,
2645
2690
struct hda_codec * codec ,
2646
2691
unsigned int stream_tag ,
2647
2692
unsigned int format ,
2648
2693
struct snd_pcm_substream * substream )
2649
2694
{
2650
2695
struct ca0132_spec * spec = codec -> spec ;
2651
- return snd_hda_multi_out_analog_prepare (codec , & spec -> multiout ,
2652
- stream_tag , format , substream );
2696
+
2697
+ ca0132_setup_stream (codec , spec -> dacs [0 ], stream_tag , 0 , format );
2698
+
2699
+ return 0 ;
2653
2700
}
2654
2701
2655
2702
static int ca0132_playback_pcm_cleanup (struct hda_pcm_stream * hinfo ,
2656
2703
struct hda_codec * codec ,
2657
2704
struct snd_pcm_substream * substream )
2658
2705
{
2659
2706
struct ca0132_spec * spec = codec -> spec ;
2660
- return snd_hda_multi_out_analog_cleanup (codec , & spec -> multiout );
2707
+
2708
+ if (spec -> dsp_state == DSP_DOWNLOADING )
2709
+ return 0 ;
2710
+
2711
+ /*If Playback effects are on, allow stream some time to flush
2712
+ *effects tail*/
2713
+ if (spec -> effects_switch [PLAY_ENHANCEMENT - EFFECT_START_NID ])
2714
+ msleep (50 );
2715
+
2716
+ ca0132_cleanup_stream (codec , spec -> dacs [0 ]);
2717
+
2718
+ return 0 ;
2661
2719
}
2662
2720
2663
2721
/*
@@ -2698,6 +2756,36 @@ static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
2698
2756
return snd_hda_multi_out_dig_close (codec , & spec -> multiout );
2699
2757
}
2700
2758
2759
+ /*
2760
+ * Analog capture
2761
+ */
2762
+ static int ca0132_capture_pcm_prepare (struct hda_pcm_stream * hinfo ,
2763
+ struct hda_codec * codec ,
2764
+ unsigned int stream_tag ,
2765
+ unsigned int format ,
2766
+ struct snd_pcm_substream * substream )
2767
+ {
2768
+ struct ca0132_spec * spec = codec -> spec ;
2769
+
2770
+ ca0132_setup_stream (codec , spec -> adcs [substream -> number ],
2771
+ stream_tag , 0 , format );
2772
+
2773
+ return 0 ;
2774
+ }
2775
+
2776
+ static int ca0132_capture_pcm_cleanup (struct hda_pcm_stream * hinfo ,
2777
+ struct hda_codec * codec ,
2778
+ struct snd_pcm_substream * substream )
2779
+ {
2780
+ struct ca0132_spec * spec = codec -> spec ;
2781
+
2782
+ if (spec -> dsp_state == DSP_DOWNLOADING )
2783
+ return 0 ;
2784
+
2785
+ ca0132_cleanup_stream (codec , hinfo -> nid );
2786
+ return 0 ;
2787
+ }
2788
+
2701
2789
/*
2702
2790
* Select the active output.
2703
2791
* If autodetect is enabled, output will be selected based on jack detection.
@@ -3509,9 +3597,8 @@ static struct snd_kcontrol_new ca0132_mixer[] = {
3509
3597
static struct hda_pcm_stream ca0132_pcm_analog_playback = {
3510
3598
.substreams = 1 ,
3511
3599
.channels_min = 2 ,
3512
- .channels_max = 2 ,
3600
+ .channels_max = 6 ,
3513
3601
.ops = {
3514
- .open = ca0132_playback_pcm_open ,
3515
3602
.prepare = ca0132_playback_pcm_prepare ,
3516
3603
.cleanup = ca0132_playback_pcm_cleanup
3517
3604
},
@@ -3521,6 +3608,10 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = {
3521
3608
.substreams = 1 ,
3522
3609
.channels_min = 2 ,
3523
3610
.channels_max = 2 ,
3611
+ .ops = {
3612
+ .prepare = ca0132_capture_pcm_prepare ,
3613
+ .cleanup = ca0132_capture_pcm_cleanup
3614
+ },
3524
3615
};
3525
3616
3526
3617
static struct hda_pcm_stream ca0132_pcm_digital_playback = {
@@ -3555,10 +3646,24 @@ static int ca0132_build_pcms(struct hda_codec *codec)
3555
3646
info -> stream [SNDRV_PCM_STREAM_PLAYBACK ].channels_max =
3556
3647
spec -> multiout .max_channels ;
3557
3648
info -> stream [SNDRV_PCM_STREAM_CAPTURE ] = ca0132_pcm_analog_capture ;
3558
- info -> stream [SNDRV_PCM_STREAM_CAPTURE ].substreams = spec -> num_inputs ;
3649
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ].substreams = 1 ;
3559
3650
info -> stream [SNDRV_PCM_STREAM_CAPTURE ].nid = spec -> adcs [0 ];
3560
3651
codec -> num_pcms ++ ;
3561
3652
3653
+ info ++ ;
3654
+ info -> name = "CA0132 Analog Mic-In2" ;
3655
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ] = ca0132_pcm_analog_capture ;
3656
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ].substreams = 1 ;
3657
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ].nid = spec -> adcs [1 ];
3658
+ codec -> num_pcms ++ ;
3659
+
3660
+ info ++ ;
3661
+ info -> name = "CA0132 What U Hear" ;
3662
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ] = ca0132_pcm_analog_capture ;
3663
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ].substreams = 1 ;
3664
+ info -> stream [SNDRV_PCM_STREAM_CAPTURE ].nid = spec -> adcs [2 ];
3665
+ codec -> num_pcms ++ ;
3666
+
3562
3667
if (!spec -> dig_out && !spec -> dig_in )
3563
3668
return 0 ;
3564
3669
0 commit comments