aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_via.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-06-18 10:40:14 -0400
committerTakashi Iwai <tiwai@suse.de>2011-06-20 10:24:05 -0400
commit7eb56e84e6c4deaa552db96834ea0b233ba92f50 (patch)
treee9904734cc9d14f23b2cd05568d3a7292fcd3023 /sound/pci/hda/patch_via.c
parent9af7421091fd37a2f8c35ca8b3a5f78a6f20fa89 (diff)
ALSA: hda - Assign HP-independent PCM to individual stream
Instead of using the secondary substream, create an individual PCM stream for HP-independent PCM. Otherwise it's difficult to handle different channel numbers with multi-channel stream in the sam PCM stream structure. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r--sound/pci/hda/patch_via.c144
1 files changed, 91 insertions, 53 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 18f2a135c026..264889c9c177 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -122,6 +122,7 @@ struct via_spec {
122 unsigned int num_iverbs; 122 unsigned int num_iverbs;
123 123
124 char stream_name_analog[32]; 124 char stream_name_analog[32];
125 char stream_name_hp[32];
125 const struct hda_pcm_stream *stream_analog_playback; 126 const struct hda_pcm_stream *stream_analog_playback;
126 const struct hda_pcm_stream *stream_analog_capture; 127 const struct hda_pcm_stream *stream_analog_capture;
127 128
@@ -1210,14 +1211,20 @@ static const struct hda_verb vt1708_volume_init_verbs[] = {
1210 { } 1211 { }
1211}; 1212};
1212 1213
1214static void substream_set_idle(struct hda_codec *codec,
1215 struct snd_pcm_substream *substream)
1216{
1217 int idle = substream->pstr->substream_opened == 1
1218 && substream->ref_count == 0;
1219 analog_low_current_mode(codec, idle);
1220}
1221
1213static int via_playback_pcm_open(struct hda_pcm_stream *hinfo, 1222static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
1214 struct hda_codec *codec, 1223 struct hda_codec *codec,
1215 struct snd_pcm_substream *substream) 1224 struct snd_pcm_substream *substream)
1216{ 1225{
1217 struct via_spec *spec = codec->spec; 1226 struct via_spec *spec = codec->spec;
1218 int idle = substream->pstr->substream_opened == 1 1227 substream_set_idle(codec, substream);
1219 && substream->ref_count == 0;
1220 analog_low_current_mode(codec, idle);
1221 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, 1228 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
1222 hinfo); 1229 hinfo);
1223} 1230}
@@ -1226,17 +1233,29 @@ static int via_playback_pcm_close(struct hda_pcm_stream *hinfo,
1226 struct hda_codec *codec, 1233 struct hda_codec *codec,
1227 struct snd_pcm_substream *substream) 1234 struct snd_pcm_substream *substream)
1228{ 1235{
1229 int idle = substream->pstr->substream_opened == 1 1236 substream_set_idle(codec, substream);
1230 && substream->ref_count == 0; 1237 return 0;
1238}
1231 1239
1232 analog_low_current_mode(codec, idle); 1240static int via_playback_hp_pcm_open(struct hda_pcm_stream *hinfo,
1241 struct hda_codec *codec,
1242 struct snd_pcm_substream *substream)
1243{
1244 struct via_spec *spec = codec->spec;
1245 struct hda_multi_out *mout = &spec->multiout;
1246
1247 if (!mout->hp_nid || mout->hp_nid == mout->dac_nids[HDA_FRONT] ||
1248 !spec->hp_independent_mode)
1249 return -EINVAL;
1250 substream_set_idle(codec, substream);
1233 return 0; 1251 return 0;
1234} 1252}
1235 1253
1236static void playback_multi_pcm_prep_0(struct hda_codec *codec, 1254static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
1237 unsigned int stream_tag, 1255 struct hda_codec *codec,
1238 unsigned int format, 1256 unsigned int stream_tag,
1239 struct snd_pcm_substream *substream) 1257 unsigned int format,
1258 struct snd_pcm_substream *substream)
1240{ 1259{
1241 struct via_spec *spec = codec->spec; 1260 struct via_spec *spec = codec->spec;
1242 struct hda_multi_out *mout = &spec->multiout; 1261 struct hda_multi_out *mout = &spec->multiout;
@@ -1301,27 +1320,20 @@ static void playback_multi_pcm_prep_0(struct hda_codec *codec,
1301 snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 1320 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
1302 0, format); 1321 0, format);
1303 } 1322 }
1323 vt1708_start_hp_work(spec);
1324 return 0;
1304} 1325}
1305 1326
1306static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, 1327static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo,
1307 struct hda_codec *codec, 1328 struct hda_codec *codec,
1308 unsigned int stream_tag, 1329 unsigned int stream_tag,
1309 unsigned int format, 1330 unsigned int format,
1310 struct snd_pcm_substream *substream) 1331 struct snd_pcm_substream *substream)
1311{ 1332{
1312 struct via_spec *spec = codec->spec; 1333 struct via_spec *spec = codec->spec;
1313 struct hda_multi_out *mout = &spec->multiout; 1334 struct hda_multi_out *mout = &spec->multiout;
1314 const hda_nid_t *nids = mout->dac_nids;
1315 1335
1316 if (substream->number == 0) 1336 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
1317 playback_multi_pcm_prep_0(codec, stream_tag, format,
1318 substream);
1319 else {
1320 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
1321 spec->hp_independent_mode)
1322 snd_hda_codec_setup_stream(codec, mout->hp_nid,
1323 stream_tag, 0, format);
1324 }
1325 vt1708_start_hp_work(spec); 1337 vt1708_start_hp_work(spec);
1326 return 0; 1338 return 0;
1327} 1339}
@@ -1335,33 +1347,38 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
1335 const hda_nid_t *nids = mout->dac_nids; 1347 const hda_nid_t *nids = mout->dac_nids;
1336 int i; 1348 int i;
1337 1349
1338 if (substream->number == 0) { 1350 for (i = 0; i < mout->num_dacs; i++)
1339 for (i = 0; i < mout->num_dacs; i++) 1351 snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
1340 snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
1341 1352
1342 if (mout->hp_nid && !spec->hp_independent_mode) 1353 if (mout->hp_nid && !spec->hp_independent_mode)
1343 snd_hda_codec_setup_stream(codec, mout->hp_nid, 1354 snd_hda_codec_setup_stream(codec, mout->hp_nid,
1344 0, 0, 0); 1355 0, 0, 0);
1345 1356
1346 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) 1357 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
1347 if (mout->extra_out_nid[i]) 1358 if (mout->extra_out_nid[i])
1348 snd_hda_codec_setup_stream(codec, 1359 snd_hda_codec_setup_stream(codec,
1349 mout->extra_out_nid[i], 1360 mout->extra_out_nid[i],
1350 0, 0, 0);
1351 mutex_lock(&codec->spdif_mutex);
1352 if (mout->dig_out_nid &&
1353 mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
1354 snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
1355 0, 0, 0);
1356 mout->dig_out_used = 0;
1357 }
1358 mutex_unlock(&codec->spdif_mutex);
1359 } else {
1360 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
1361 spec->hp_independent_mode)
1362 snd_hda_codec_setup_stream(codec, mout->hp_nid,
1363 0, 0, 0); 1361 0, 0, 0);
1362 mutex_lock(&codec->spdif_mutex);
1363 if (mout->dig_out_nid &&
1364 mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
1365 snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
1366 0, 0, 0);
1367 mout->dig_out_used = 0;
1364 } 1368 }
1369 mutex_unlock(&codec->spdif_mutex);
1370 vt1708_stop_hp_work(spec);
1371 return 0;
1372}
1373
1374static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo,
1375 struct hda_codec *codec,
1376 struct snd_pcm_substream *substream)
1377{
1378 struct via_spec *spec = codec->spec;
1379 struct hda_multi_out *mout = &spec->multiout;
1380
1381 snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
1365 vt1708_stop_hp_work(spec); 1382 vt1708_stop_hp_work(spec);
1366 return 0; 1383 return 0;
1367} 1384}
@@ -1431,7 +1448,7 @@ static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1431} 1448}
1432 1449
1433static const struct hda_pcm_stream via_pcm_analog_playback = { 1450static const struct hda_pcm_stream via_pcm_analog_playback = {
1434 .substreams = 2, /* will be changed in via_build_pcms() */ 1451 .substreams = 1,
1435 .channels_min = 2, 1452 .channels_min = 2,
1436 .channels_max = 8, 1453 .channels_max = 8,
1437 /* NID is set in via_build_pcms */ 1454 /* NID is set in via_build_pcms */
@@ -1443,8 +1460,21 @@ static const struct hda_pcm_stream via_pcm_analog_playback = {
1443 }, 1460 },
1444}; 1461};
1445 1462
1463static const struct hda_pcm_stream via_pcm_hp_playback = {
1464 .substreams = 1,
1465 .channels_min = 2,
1466 .channels_max = 2,
1467 /* NID is set in via_build_pcms */
1468 .ops = {
1469 .open = via_playback_hp_pcm_open,
1470 .close = via_playback_pcm_close,
1471 .prepare = via_playback_hp_pcm_prepare,
1472 .cleanup = via_playback_hp_pcm_cleanup
1473 },
1474};
1475
1446static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { 1476static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
1447 .substreams = 2, /* will be changed in via_build_pcms() */ 1477 .substreams = 1,
1448 .channels_min = 2, 1478 .channels_min = 2,
1449 .channels_max = 8, 1479 .channels_max = 8,
1450 /* NID is set in via_build_pcms */ 1480 /* NID is set in via_build_pcms */
@@ -1462,7 +1492,7 @@ static const struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
1462}; 1492};
1463 1493
1464static const struct hda_pcm_stream via_pcm_analog_capture = { 1494static const struct hda_pcm_stream via_pcm_analog_capture = {
1465 .substreams = 2, /* will be changed in via_build_pcms() */ 1495 .substreams = 1, /* will be changed in via_build_pcms() */
1466 .channels_min = 2, 1496 .channels_min = 2,
1467 .channels_max = 2, 1497 .channels_max = 2,
1468 /* NID is set in via_build_pcms */ 1498 /* NID is set in via_build_pcms */
@@ -1577,8 +1607,6 @@ static int via_build_pcms(struct hda_codec *codec)
1577 spec->multiout.dac_nids[0]; 1607 spec->multiout.dac_nids[0];
1578 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 1608 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
1579 spec->multiout.max_channels; 1609 spec->multiout.max_channels;
1580 if (!spec->multiout.hp_nid)
1581 info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams = 1;
1582 1610
1583 if (!spec->stream_analog_capture) 1611 if (!spec->stream_analog_capture)
1584 spec->stream_analog_capture = &via_pcm_analog_capture; 1612 spec->stream_analog_capture = &via_pcm_analog_capture;
@@ -1616,6 +1644,16 @@ static int via_build_pcms(struct hda_codec *codec)
1616 } 1644 }
1617 } 1645 }
1618 1646
1647 if (spec->multiout.hp_nid) {
1648 codec->num_pcms++;
1649 info++;
1650 snprintf(spec->stream_name_hp, sizeof(spec->stream_name_hp),
1651 "%s HP", codec->chip_name);
1652 info->name = spec->stream_name_hp;
1653 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = via_pcm_hp_playback;
1654 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
1655 spec->multiout.hp_nid;
1656 }
1619 return 0; 1657 return 0;
1620} 1658}
1621 1659