Skip to content

Commit 825315b

Browse files
ikminetttiwai
authored andcommitted
ALSA: hda/ca0132: Add PCM enhancements
Remove the playback PCM open callback. PCM stream setup and cleanup functions are added for use by PCM callbacks. Delay stream cleanup if effects are on, to allow time for any effects tail to finish. Add the analog capture PCM callbacks. Change the max channels of analog playback to 6. Add two new PCMs: AMic2 and What-U-Hear. Signed-off-by: Ian Minett <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent a7e7627 commit 825315b

File tree

1 file changed

+118
-13
lines changed

1 file changed

+118
-13
lines changed

sound/pci/hda/patch_ca0132.c

Lines changed: 118 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,34 +2630,92 @@ static bool dspload_wait_loaded(struct hda_codec *codec)
26302630
CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir)
26312631

26322632
/*
2633-
* PCM callbacks
2633+
* PCM stuffs
26342634
*/
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)
26382638
{
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);
26422684
}
26432685

2686+
/*
2687+
* PCM callbacks
2688+
*/
26442689
static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
26452690
struct hda_codec *codec,
26462691
unsigned int stream_tag,
26472692
unsigned int format,
26482693
struct snd_pcm_substream *substream)
26492694
{
26502695
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;
26532700
}
26542701

26552702
static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
26562703
struct hda_codec *codec,
26572704
struct snd_pcm_substream *substream)
26582705
{
26592706
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;
26612719
}
26622720

26632721
/*
@@ -2698,6 +2756,36 @@ static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
26982756
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
26992757
}
27002758

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+
27012789
/*
27022790
* Select the active output.
27032791
* If autodetect is enabled, output will be selected based on jack detection.
@@ -3509,9 +3597,8 @@ static struct snd_kcontrol_new ca0132_mixer[] = {
35093597
static struct hda_pcm_stream ca0132_pcm_analog_playback = {
35103598
.substreams = 1,
35113599
.channels_min = 2,
3512-
.channels_max = 2,
3600+
.channels_max = 6,
35133601
.ops = {
3514-
.open = ca0132_playback_pcm_open,
35153602
.prepare = ca0132_playback_pcm_prepare,
35163603
.cleanup = ca0132_playback_pcm_cleanup
35173604
},
@@ -3521,6 +3608,10 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = {
35213608
.substreams = 1,
35223609
.channels_min = 2,
35233610
.channels_max = 2,
3611+
.ops = {
3612+
.prepare = ca0132_capture_pcm_prepare,
3613+
.cleanup = ca0132_capture_pcm_cleanup
3614+
},
35243615
};
35253616

35263617
static struct hda_pcm_stream ca0132_pcm_digital_playback = {
@@ -3555,10 +3646,24 @@ static int ca0132_build_pcms(struct hda_codec *codec)
35553646
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
35563647
spec->multiout.max_channels;
35573648
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;
35593650
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
35603651
codec->num_pcms++;
35613652

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+
35623667
if (!spec->dig_out && !spec->dig_in)
35633668
return 0;
35643669

0 commit comments

Comments
 (0)