diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-09-15 10:32:31 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-09-15 10:32:31 -0400 |
commit | e5d6db8e6039d7f51a9a648d74db1109c7fdc746 (patch) | |
tree | 1f8ec13b6bda70fdf6c607a86d02c3e974e4c469 /sound | |
parent | 62cbde1868b16e7cf1ed115cdfb9cbe82e230f0a (diff) | |
parent | 5efbc2610a7b2aac6c51f8fc943c019106568939 (diff) |
Merge branch 'topic/tlv-chmap' into for-next
This is a merge of a topic branch containing the support for the new
channel map API using control elements.
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/pcm.c | 4 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 214 | ||||
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 24 | ||||
-rw-r--r-- | sound/pci/atiixp.c | 9 | ||||
-rw-r--r-- | sound/pci/ca0106/ca0106_main.c | 28 | ||||
-rw-r--r-- | sound/pci/cmipci.c | 6 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctpcm.c | 50 | ||||
-rw-r--r-- | sound/pci/emu10k1/emu10k1x.c | 21 | ||||
-rw-r--r-- | sound/pci/ens1370.c | 66 | ||||
-rw-r--r-- | sound/pci/fm801.c | 7 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 36 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 347 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 2 | ||||
-rw-r--r-- | sound/pci/intel8x0.c | 20 | ||||
-rw-r--r-- | sound/pci/via82xx.c | 23 | ||||
-rw-r--r-- | sound/pci/ymfpci/ymfpci_main.c | 18 |
17 files changed, 840 insertions, 36 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 1a3070b4e5b5..f2991940b271 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -1105,6 +1105,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1105 | break; | 1105 | break; |
1106 | } | 1106 | } |
1107 | snd_unregister_device(devtype, pcm->card, pcm->device); | 1107 | snd_unregister_device(devtype, pcm->card, pcm->device); |
1108 | if (pcm->streams[cidx].chmap_kctl) { | ||
1109 | snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); | ||
1110 | pcm->streams[cidx].chmap_kctl = NULL; | ||
1111 | } | ||
1108 | } | 1112 | } |
1109 | unlock: | 1113 | unlock: |
1110 | mutex_unlock(®ister_mutex); | 1114 | mutex_unlock(®ister_mutex); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 7ae671923393..f42c10a43315 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
28 | #include <sound/control.h> | 28 | #include <sound/control.h> |
29 | #include <sound/tlv.h> | ||
29 | #include <sound/info.h> | 30 | #include <sound/info.h> |
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
31 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
@@ -2302,3 +2303,216 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | |||
2302 | } | 2303 | } |
2303 | 2304 | ||
2304 | EXPORT_SYMBOL(snd_pcm_lib_readv); | 2305 | EXPORT_SYMBOL(snd_pcm_lib_readv); |
2306 | |||
2307 | /* | ||
2308 | * standard channel mapping helpers | ||
2309 | */ | ||
2310 | |||
2311 | /* default channel maps for multi-channel playbacks, up to 8 channels */ | ||
2312 | const struct snd_pcm_chmap_elem snd_pcm_std_chmaps[] = { | ||
2313 | { .channels = 1, | ||
2314 | .map = { SNDRV_CHMAP_MONO } }, | ||
2315 | { .channels = 2, | ||
2316 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
2317 | { .channels = 4, | ||
2318 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
2319 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
2320 | { .channels = 6, | ||
2321 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
2322 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
2323 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
2324 | { .channels = 8, | ||
2325 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
2326 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
2327 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
2328 | SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
2329 | { } | ||
2330 | }; | ||
2331 | EXPORT_SYMBOL_GPL(snd_pcm_std_chmaps); | ||
2332 | |||
2333 | /* alternative channel maps with CLFE <-> surround swapped for 6/8 channels */ | ||
2334 | const struct snd_pcm_chmap_elem snd_pcm_alt_chmaps[] = { | ||
2335 | { .channels = 1, | ||
2336 | .map = { SNDRV_CHMAP_MONO } }, | ||
2337 | { .channels = 2, | ||
2338 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
2339 | { .channels = 4, | ||
2340 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
2341 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
2342 | { .channels = 6, | ||
2343 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
2344 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
2345 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
2346 | { .channels = 8, | ||
2347 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
2348 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
2349 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
2350 | SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
2351 | { } | ||
2352 | }; | ||
2353 | EXPORT_SYMBOL_GPL(snd_pcm_alt_chmaps); | ||
2354 | |||
2355 | static bool valid_chmap_channels(const struct snd_pcm_chmap *info, int ch) | ||
2356 | { | ||
2357 | if (ch > info->max_channels) | ||
2358 | return false; | ||
2359 | return !info->channel_mask || (info->channel_mask & (1U << ch)); | ||
2360 | } | ||
2361 | |||
2362 | static int pcm_chmap_ctl_info(struct snd_kcontrol *kcontrol, | ||
2363 | struct snd_ctl_elem_info *uinfo) | ||
2364 | { | ||
2365 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2366 | |||
2367 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2368 | uinfo->count = 0; | ||
2369 | uinfo->count = info->max_channels; | ||
2370 | uinfo->value.integer.min = 0; | ||
2371 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | ||
2372 | return 0; | ||
2373 | } | ||
2374 | |||
2375 | /* get callback for channel map ctl element | ||
2376 | * stores the channel position firstly matching with the current channels | ||
2377 | */ | ||
2378 | static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol, | ||
2379 | struct snd_ctl_elem_value *ucontrol) | ||
2380 | { | ||
2381 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2382 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
2383 | struct snd_pcm_substream *substream; | ||
2384 | const struct snd_pcm_chmap_elem *map; | ||
2385 | |||
2386 | if (snd_BUG_ON(!info->chmap)) | ||
2387 | return -EINVAL; | ||
2388 | substream = snd_pcm_chmap_substream(info, idx); | ||
2389 | if (!substream) | ||
2390 | return -ENODEV; | ||
2391 | memset(ucontrol->value.integer.value, 0, | ||
2392 | sizeof(ucontrol->value.integer.value)); | ||
2393 | if (!substream->runtime) | ||
2394 | return 0; /* no channels set */ | ||
2395 | for (map = info->chmap; map->channels; map++) { | ||
2396 | int i; | ||
2397 | if (map->channels == substream->runtime->channels && | ||
2398 | valid_chmap_channels(info, map->channels)) { | ||
2399 | for (i = 0; i < map->channels; i++) | ||
2400 | ucontrol->value.integer.value[i] = map->map[i]; | ||
2401 | return 0; | ||
2402 | } | ||
2403 | } | ||
2404 | return -EINVAL; | ||
2405 | } | ||
2406 | |||
2407 | /* tlv callback for channel map ctl element | ||
2408 | * expands the pre-defined channel maps in a form of TLV | ||
2409 | */ | ||
2410 | static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
2411 | unsigned int size, unsigned int __user *tlv) | ||
2412 | { | ||
2413 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2414 | const struct snd_pcm_chmap_elem *map; | ||
2415 | unsigned int __user *dst; | ||
2416 | int c, count = 0; | ||
2417 | |||
2418 | if (snd_BUG_ON(!info->chmap)) | ||
2419 | return -EINVAL; | ||
2420 | if (size < 8) | ||
2421 | return -ENOMEM; | ||
2422 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | ||
2423 | return -EFAULT; | ||
2424 | size -= 8; | ||
2425 | dst = tlv + 2; | ||
2426 | for (map = info->chmap; map->channels; map++) { | ||
2427 | int chs_bytes = map->channels * 4; | ||
2428 | if (!valid_chmap_channels(info, map->channels)) | ||
2429 | continue; | ||
2430 | if (size < 8) | ||
2431 | return -ENOMEM; | ||
2432 | if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) || | ||
2433 | put_user(chs_bytes, dst + 1)) | ||
2434 | return -EFAULT; | ||
2435 | dst += 2; | ||
2436 | size -= 8; | ||
2437 | count += 8; | ||
2438 | if (size < chs_bytes) | ||
2439 | return -ENOMEM; | ||
2440 | size -= chs_bytes; | ||
2441 | count += chs_bytes; | ||
2442 | for (c = 0; c < map->channels; c++) { | ||
2443 | if (put_user(map->map[c], dst)) | ||
2444 | return -EFAULT; | ||
2445 | dst++; | ||
2446 | } | ||
2447 | } | ||
2448 | if (put_user(count, tlv + 1)) | ||
2449 | return -EFAULT; | ||
2450 | return 0; | ||
2451 | } | ||
2452 | |||
2453 | static void pcm_chmap_ctl_private_free(struct snd_kcontrol *kcontrol) | ||
2454 | { | ||
2455 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
2456 | info->pcm->streams[info->stream].chmap_kctl = NULL; | ||
2457 | kfree(info); | ||
2458 | } | ||
2459 | |||
2460 | /** | ||
2461 | * snd_pcm_add_chmap_ctls - create channel-mapping control elements | ||
2462 | * @pcm: the assigned PCM instance | ||
2463 | * @stream: stream direction | ||
2464 | * @chmap: channel map elements (for query) | ||
2465 | * @max_channels: the max number of channels for the stream | ||
2466 | * @private_value: the value passed to each kcontrol's private_value field | ||
2467 | * @info_ret: store struct snd_pcm_chmap instance if non-NULL | ||
2468 | * | ||
2469 | * Create channel-mapping control elements assigned to the given PCM stream(s). | ||
2470 | * Returns zero if succeed, or a negative error value. | ||
2471 | */ | ||
2472 | int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream, | ||
2473 | const struct snd_pcm_chmap_elem *chmap, | ||
2474 | int max_channels, | ||
2475 | unsigned long private_value, | ||
2476 | struct snd_pcm_chmap **info_ret) | ||
2477 | { | ||
2478 | struct snd_pcm_chmap *info; | ||
2479 | struct snd_kcontrol_new knew = { | ||
2480 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
2481 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
2482 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
2483 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
2484 | .info = pcm_chmap_ctl_info, | ||
2485 | .get = pcm_chmap_ctl_get, | ||
2486 | .tlv.c = pcm_chmap_ctl_tlv, | ||
2487 | }; | ||
2488 | int err; | ||
2489 | |||
2490 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
2491 | if (!info) | ||
2492 | return -ENOMEM; | ||
2493 | info->pcm = pcm; | ||
2494 | info->stream = stream; | ||
2495 | info->chmap = chmap; | ||
2496 | info->max_channels = max_channels; | ||
2497 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
2498 | knew.name = "Playback Channel Map"; | ||
2499 | else | ||
2500 | knew.name = "Capture Channel Map"; | ||
2501 | knew.device = pcm->device; | ||
2502 | knew.count = pcm->streams[stream].substream_count; | ||
2503 | knew.private_value = private_value; | ||
2504 | info->kctl = snd_ctl_new1(&knew, info); | ||
2505 | if (!info->kctl) { | ||
2506 | kfree(info); | ||
2507 | return -ENOMEM; | ||
2508 | } | ||
2509 | info->kctl->private_free = pcm_chmap_ctl_private_free; | ||
2510 | err = snd_ctl_add(pcm->card, info->kctl); | ||
2511 | if (err < 0) | ||
2512 | return err; | ||
2513 | pcm->streams[stream].chmap_kctl = info->kctl; | ||
2514 | if (info_ret) | ||
2515 | *info_ret = info; | ||
2516 | return 0; | ||
2517 | } | ||
2518 | EXPORT_SYMBOL_GPL(snd_pcm_add_chmap_ctls); | ||
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index a872d0a82976..66a3bc95fb84 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -2595,6 +2595,21 @@ static void alc650_update_jacks(struct snd_ac97 *ac97) | |||
2595 | shared ? 0 : 0x100); | 2595 | shared ? 0 : 0x100); |
2596 | } | 2596 | } |
2597 | 2597 | ||
2598 | static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol, | ||
2599 | struct snd_ctl_elem_value *ucontrol) | ||
2600 | { | ||
2601 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | ||
2602 | struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK]; | ||
2603 | |||
2604 | if (map) { | ||
2605 | if (ucontrol->value.integer.value[0]) | ||
2606 | map->chmap = snd_pcm_std_chmaps; | ||
2607 | else | ||
2608 | map->chmap = snd_pcm_alt_chmaps; | ||
2609 | } | ||
2610 | return snd_ac97_put_volsw(kcontrol, ucontrol); | ||
2611 | } | ||
2612 | |||
2598 | static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { | 2613 | static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { |
2599 | AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), | 2614 | AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), |
2600 | AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0), | 2615 | AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0), |
@@ -2608,7 +2623,14 @@ static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { | |||
2608 | /* 9: Line-In/Surround share */ | 2623 | /* 9: Line-In/Surround share */ |
2609 | /* 10: Mic/CLFE share */ | 2624 | /* 10: Mic/CLFE share */ |
2610 | /* 11-13: in IEC958 controls */ | 2625 | /* 11-13: in IEC958 controls */ |
2611 | AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), | 2626 | { |
2627 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2628 | .name = "Swap Surround Slot", | ||
2629 | .info = snd_ac97_info_volsw, | ||
2630 | .get = snd_ac97_get_volsw, | ||
2631 | .put = alc650_swap_surround_put, | ||
2632 | .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0), | ||
2633 | }, | ||
2612 | #if 0 /* always set in patch_alc650 */ | 2634 | #if 0 /* always set in patch_alc650 */ |
2613 | AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0), | 2635 | AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0), |
2614 | AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0), | 2636 | AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0), |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index c744df5bb1c6..368df8b0853e 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1250,6 +1250,7 @@ static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = { | |||
1250 | static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) | 1250 | static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) |
1251 | { | 1251 | { |
1252 | struct snd_pcm *pcm; | 1252 | struct snd_pcm *pcm; |
1253 | struct snd_pcm_chmap *chmap; | ||
1253 | struct snd_ac97_bus *pbus = chip->ac97_bus; | 1254 | struct snd_ac97_bus *pbus = chip->ac97_bus; |
1254 | int err, i, num_pcms; | 1255 | int err, i, num_pcms; |
1255 | 1256 | ||
@@ -1293,6 +1294,14 @@ static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) | |||
1293 | snd_dma_pci_data(chip->pci), | 1294 | snd_dma_pci_data(chip->pci), |
1294 | 64*1024, 128*1024); | 1295 | 64*1024, 128*1024); |
1295 | 1296 | ||
1297 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1298 | snd_pcm_alt_chmaps, chip->max_channels, 0, | ||
1299 | &chmap); | ||
1300 | if (err < 0) | ||
1301 | return err; | ||
1302 | chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; | ||
1303 | chip->ac97[0]->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
1304 | |||
1296 | /* no SPDIF support on codec? */ | 1305 | /* no SPDIF support on codec? */ |
1297 | if (chip->pcms[ATI_PCM_SPDIF] && ! chip->pcms[ATI_PCM_SPDIF]->rates) | 1306 | if (chip->pcms[ATI_PCM_SPDIF] && ! chip->pcms[ATI_PCM_SPDIF]->rates) |
1298 | return 0; | 1307 | return 0; |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index fc6787699ba9..65c55910566b 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1334,10 +1334,29 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) | |||
1334 | return IRQ_HANDLED; | 1334 | return IRQ_HANDLED; |
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
1338 | { .channels = 2, | ||
1339 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
1340 | { } | ||
1341 | }; | ||
1342 | |||
1343 | static const struct snd_pcm_chmap_elem clfe_map[] = { | ||
1344 | { .channels = 2, | ||
1345 | .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
1346 | { } | ||
1347 | }; | ||
1348 | |||
1349 | static const struct snd_pcm_chmap_elem side_map[] = { | ||
1350 | { .channels = 2, | ||
1351 | .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
1352 | { } | ||
1353 | }; | ||
1354 | |||
1337 | static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) | 1355 | static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) |
1338 | { | 1356 | { |
1339 | struct snd_pcm *pcm; | 1357 | struct snd_pcm *pcm; |
1340 | struct snd_pcm_substream *substream; | 1358 | struct snd_pcm_substream *substream; |
1359 | const struct snd_pcm_chmap_elem *map = NULL; | ||
1341 | int err; | 1360 | int err; |
1342 | 1361 | ||
1343 | err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); | 1362 | err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); |
@@ -1350,18 +1369,22 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) | |||
1350 | case 0: | 1369 | case 0: |
1351 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops); | 1370 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops); |
1352 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops); | 1371 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops); |
1372 | map = snd_pcm_std_chmaps; | ||
1353 | break; | 1373 | break; |
1354 | case 1: | 1374 | case 1: |
1355 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops); | 1375 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops); |
1356 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops); | 1376 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops); |
1377 | map = surround_map; | ||
1357 | break; | 1378 | break; |
1358 | case 2: | 1379 | case 2: |
1359 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops); | 1380 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops); |
1360 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops); | 1381 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops); |
1382 | map = clfe_map; | ||
1361 | break; | 1383 | break; |
1362 | case 3: | 1384 | case 3: |
1363 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops); | 1385 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops); |
1364 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops); | 1386 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops); |
1387 | map = side_map; | ||
1365 | break; | 1388 | break; |
1366 | } | 1389 | } |
1367 | 1390 | ||
@@ -1388,6 +1411,11 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) | |||
1388 | return err; | 1411 | return err; |
1389 | } | 1412 | } |
1390 | 1413 | ||
1414 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2, | ||
1415 | 1 << 2, NULL); | ||
1416 | if (err < 0) | ||
1417 | return err; | ||
1418 | |||
1391 | emu->pcm[device] = pcm; | 1419 | emu->pcm[device] = pcm; |
1392 | 1420 | ||
1393 | return 0; | 1421 | return 0; |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 7c25906b5f88..22122ff26e34 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -1962,6 +1962,12 @@ static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device) | |||
1962 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1962 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1963 | snd_dma_pci_data(cm->pci), 64*1024, 128*1024); | 1963 | snd_dma_pci_data(cm->pci), 64*1024, 128*1024); |
1964 | 1964 | ||
1965 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1966 | snd_pcm_alt_chmaps, cm->max_channels, 0, | ||
1967 | NULL); | ||
1968 | if (err < 0) | ||
1969 | return err; | ||
1970 | |||
1965 | return 0; | 1971 | return 0; |
1966 | } | 1972 | } |
1967 | 1973 | ||
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index d021876901bb..e8a4feb1ed86 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c | |||
@@ -395,12 +395,38 @@ static struct snd_pcm_ops ct_pcm_capture_ops = { | |||
395 | .page = snd_pcm_sgbuf_ops_page, | 395 | .page = snd_pcm_sgbuf_ops_page, |
396 | }; | 396 | }; |
397 | 397 | ||
398 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
399 | { .channels = 1, | ||
400 | .map = { SNDRV_CHMAP_MONO } }, | ||
401 | { .channels = 2, | ||
402 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
403 | { } | ||
404 | }; | ||
405 | |||
406 | static const struct snd_pcm_chmap_elem clfe_map[] = { | ||
407 | { .channels = 1, | ||
408 | .map = { SNDRV_CHMAP_MONO } }, | ||
409 | { .channels = 2, | ||
410 | .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
411 | { } | ||
412 | }; | ||
413 | |||
414 | static const struct snd_pcm_chmap_elem side_map[] = { | ||
415 | { .channels = 1, | ||
416 | .map = { SNDRV_CHMAP_MONO } }, | ||
417 | { .channels = 2, | ||
418 | .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
419 | { } | ||
420 | }; | ||
421 | |||
398 | /* Create ALSA pcm device */ | 422 | /* Create ALSA pcm device */ |
399 | int ct_alsa_pcm_create(struct ct_atc *atc, | 423 | int ct_alsa_pcm_create(struct ct_atc *atc, |
400 | enum CTALSADEVS device, | 424 | enum CTALSADEVS device, |
401 | const char *device_name) | 425 | const char *device_name) |
402 | { | 426 | { |
403 | struct snd_pcm *pcm; | 427 | struct snd_pcm *pcm; |
428 | const struct snd_pcm_chmap_elem *map; | ||
429 | int chs; | ||
404 | int err; | 430 | int err; |
405 | int playback_count, capture_count; | 431 | int playback_count, capture_count; |
406 | 432 | ||
@@ -427,6 +453,30 @@ int ct_alsa_pcm_create(struct ct_atc *atc, | |||
427 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 453 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
428 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); | 454 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); |
429 | 455 | ||
456 | chs = 2; | ||
457 | switch (device) { | ||
458 | case FRONT: | ||
459 | chs = 8; | ||
460 | map = snd_pcm_std_chmaps; | ||
461 | break; | ||
462 | case SURROUND: | ||
463 | map = surround_map; | ||
464 | break; | ||
465 | case CLFE: | ||
466 | map = clfe_map; | ||
467 | break; | ||
468 | case SIDE: | ||
469 | map = side_map; | ||
470 | break; | ||
471 | default: | ||
472 | map = snd_pcm_std_chmaps; | ||
473 | break; | ||
474 | } | ||
475 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs, | ||
476 | 0, NULL); | ||
477 | if (err < 0) | ||
478 | return err; | ||
479 | |||
430 | #ifdef CONFIG_PM_SLEEP | 480 | #ifdef CONFIG_PM_SLEEP |
431 | atc->pcms[device] = pcm; | 481 | atc->pcms[device] = pcm; |
432 | #endif | 482 | #endif |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 5c8978b2c4d9..556fd6f456e3 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -830,9 +830,22 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id) | |||
830 | return IRQ_HANDLED; | 830 | return IRQ_HANDLED; |
831 | } | 831 | } |
832 | 832 | ||
833 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
834 | { .channels = 2, | ||
835 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
836 | { } | ||
837 | }; | ||
838 | |||
839 | static const struct snd_pcm_chmap_elem clfe_map[] = { | ||
840 | { .channels = 2, | ||
841 | .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
842 | { } | ||
843 | }; | ||
844 | |||
833 | static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) | 845 | static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) |
834 | { | 846 | { |
835 | struct snd_pcm *pcm; | 847 | struct snd_pcm *pcm; |
848 | const struct snd_pcm_chmap_elem *map = NULL; | ||
836 | int err; | 849 | int err; |
837 | int capture = 0; | 850 | int capture = 0; |
838 | 851 | ||
@@ -861,12 +874,15 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s | |||
861 | switch(device) { | 874 | switch(device) { |
862 | case 0: | 875 | case 0: |
863 | strcpy(pcm->name, "EMU10K1X Front"); | 876 | strcpy(pcm->name, "EMU10K1X Front"); |
877 | map = snd_pcm_std_chmaps; | ||
864 | break; | 878 | break; |
865 | case 1: | 879 | case 1: |
866 | strcpy(pcm->name, "EMU10K1X Rear"); | 880 | strcpy(pcm->name, "EMU10K1X Rear"); |
881 | map = surround_map; | ||
867 | break; | 882 | break; |
868 | case 2: | 883 | case 2: |
869 | strcpy(pcm->name, "EMU10K1X Center/LFE"); | 884 | strcpy(pcm->name, "EMU10K1X Center/LFE"); |
885 | map = clfe_map; | ||
870 | break; | 886 | break; |
871 | } | 887 | } |
872 | emu->pcm = pcm; | 888 | emu->pcm = pcm; |
@@ -875,6 +891,11 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s | |||
875 | snd_dma_pci_data(emu->pci), | 891 | snd_dma_pci_data(emu->pci), |
876 | 32*1024, 32*1024); | 892 | 32*1024, 32*1024); |
877 | 893 | ||
894 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2, | ||
895 | 1 << 2, NULL); | ||
896 | if (err < 0) | ||
897 | return err; | ||
898 | |||
878 | if (rpcm) | 899 | if (rpcm) |
879 | *rpcm = pcm; | 900 | *rpcm = pcm; |
880 | 901 | ||
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 2ba58d365959..5674cc316530 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -55,8 +55,10 @@ | |||
55 | 55 | ||
56 | #ifdef CHIP1370 | 56 | #ifdef CHIP1370 |
57 | #define DRIVER_NAME "ENS1370" | 57 | #define DRIVER_NAME "ENS1370" |
58 | #define CHIP_NAME "ES1370" /* it can be ENS but just to keep compatibility... */ | ||
58 | #else | 59 | #else |
59 | #define DRIVER_NAME "ENS1371" | 60 | #define DRIVER_NAME "ENS1371" |
61 | #define CHIP_NAME "ES1371" | ||
60 | #endif | 62 | #endif |
61 | 63 | ||
62 | 64 | ||
@@ -1258,6 +1260,14 @@ static struct snd_pcm_ops snd_ensoniq_capture_ops = { | |||
1258 | .pointer = snd_ensoniq_capture_pointer, | 1260 | .pointer = snd_ensoniq_capture_pointer, |
1259 | }; | 1261 | }; |
1260 | 1262 | ||
1263 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
1264 | { .channels = 1, | ||
1265 | .map = { SNDRV_CHMAP_MONO } }, | ||
1266 | { .channels = 2, | ||
1267 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
1268 | { } | ||
1269 | }; | ||
1270 | |||
1261 | static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, | 1271 | static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, |
1262 | struct snd_pcm ** rpcm) | 1272 | struct snd_pcm ** rpcm) |
1263 | { | 1273 | { |
@@ -1266,11 +1276,7 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, | |||
1266 | 1276 | ||
1267 | if (rpcm) | 1277 | if (rpcm) |
1268 | *rpcm = NULL; | 1278 | *rpcm = NULL; |
1269 | #ifdef CHIP1370 | 1279 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/1", device, 1, 1, &pcm); |
1270 | err = snd_pcm_new(ensoniq->card, "ES1370/1", device, 1, 1, &pcm); | ||
1271 | #else | ||
1272 | err = snd_pcm_new(ensoniq->card, "ES1371/1", device, 1, 1, &pcm); | ||
1273 | #endif | ||
1274 | if (err < 0) | 1280 | if (err < 0) |
1275 | return err; | 1281 | return err; |
1276 | 1282 | ||
@@ -1283,16 +1289,22 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, | |||
1283 | 1289 | ||
1284 | pcm->private_data = ensoniq; | 1290 | pcm->private_data = ensoniq; |
1285 | pcm->info_flags = 0; | 1291 | pcm->info_flags = 0; |
1286 | #ifdef CHIP1370 | 1292 | strcpy(pcm->name, CHIP_NAME " DAC2/ADC"); |
1287 | strcpy(pcm->name, "ES1370 DAC2/ADC"); | ||
1288 | #else | ||
1289 | strcpy(pcm->name, "ES1371 DAC2/ADC"); | ||
1290 | #endif | ||
1291 | ensoniq->pcm1 = pcm; | 1293 | ensoniq->pcm1 = pcm; |
1292 | 1294 | ||
1293 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1295 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1294 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); | 1296 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); |
1295 | 1297 | ||
1298 | #ifdef CHIP1370 | ||
1299 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1300 | surround_map, 2, 0, NULL); | ||
1301 | #else | ||
1302 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1303 | snd_pcm_std_chmaps, 2, 0, NULL); | ||
1304 | #endif | ||
1305 | if (err < 0) | ||
1306 | return err; | ||
1307 | |||
1296 | if (rpcm) | 1308 | if (rpcm) |
1297 | *rpcm = pcm; | 1309 | *rpcm = pcm; |
1298 | return 0; | 1310 | return 0; |
@@ -1306,11 +1318,7 @@ static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device, | |||
1306 | 1318 | ||
1307 | if (rpcm) | 1319 | if (rpcm) |
1308 | *rpcm = NULL; | 1320 | *rpcm = NULL; |
1309 | #ifdef CHIP1370 | 1321 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/2", device, 1, 0, &pcm); |
1310 | err = snd_pcm_new(ensoniq->card, "ES1370/2", device, 1, 0, &pcm); | ||
1311 | #else | ||
1312 | err = snd_pcm_new(ensoniq->card, "ES1371/2", device, 1, 0, &pcm); | ||
1313 | #endif | ||
1314 | if (err < 0) | 1322 | if (err < 0) |
1315 | return err; | 1323 | return err; |
1316 | 1324 | ||
@@ -1321,16 +1329,22 @@ static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device, | |||
1321 | #endif | 1329 | #endif |
1322 | pcm->private_data = ensoniq; | 1330 | pcm->private_data = ensoniq; |
1323 | pcm->info_flags = 0; | 1331 | pcm->info_flags = 0; |
1324 | #ifdef CHIP1370 | 1332 | strcpy(pcm->name, CHIP_NAME " DAC1"); |
1325 | strcpy(pcm->name, "ES1370 DAC1"); | ||
1326 | #else | ||
1327 | strcpy(pcm->name, "ES1371 DAC1"); | ||
1328 | #endif | ||
1329 | ensoniq->pcm2 = pcm; | 1333 | ensoniq->pcm2 = pcm; |
1330 | 1334 | ||
1331 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1335 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1332 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); | 1336 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); |
1333 | 1337 | ||
1338 | #ifdef CHIP1370 | ||
1339 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1340 | snd_pcm_std_chmaps, 2, 0, NULL); | ||
1341 | #else | ||
1342 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1343 | surround_map, 2, 0, NULL); | ||
1344 | #endif | ||
1345 | if (err < 0) | ||
1346 | return err; | ||
1347 | |||
1334 | if (rpcm) | 1348 | if (rpcm) |
1335 | *rpcm = pcm; | 1349 | *rpcm = pcm; |
1336 | return 0; | 1350 | return 0; |
@@ -1885,11 +1899,7 @@ static void snd_ensoniq_proc_read(struct snd_info_entry *entry, | |||
1885 | { | 1899 | { |
1886 | struct ensoniq *ensoniq = entry->private_data; | 1900 | struct ensoniq *ensoniq = entry->private_data; |
1887 | 1901 | ||
1888 | #ifdef CHIP1370 | 1902 | snd_iprintf(buffer, "Ensoniq AudioPCI " CHIP_NAME "\n\n"); |
1889 | snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n"); | ||
1890 | #else | ||
1891 | snd_iprintf(buffer, "Ensoniq AudioPCI ES1371\n\n"); | ||
1892 | #endif | ||
1893 | snd_iprintf(buffer, "Joystick enable : %s\n", | 1903 | snd_iprintf(buffer, "Joystick enable : %s\n", |
1894 | ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off"); | 1904 | ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off"); |
1895 | #ifdef CHIP1370 | 1905 | #ifdef CHIP1370 |
@@ -2361,11 +2371,7 @@ static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device, | |||
2361 | *rrawmidi = NULL; | 2371 | *rrawmidi = NULL; |
2362 | if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) | 2372 | if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) |
2363 | return err; | 2373 | return err; |
2364 | #ifdef CHIP1370 | 2374 | strcpy(rmidi->name, CHIP_NAME); |
2365 | strcpy(rmidi->name, "ES1370"); | ||
2366 | #else | ||
2367 | strcpy(rmidi->name, "ES1371"); | ||
2368 | #endif | ||
2369 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output); | 2375 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output); |
2370 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input); | 2376 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input); |
2371 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | | 2377 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index ce3e548de41d..cc2e91d15538 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -711,6 +711,13 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc | |||
711 | snd_dma_pci_data(chip->pci), | 711 | snd_dma_pci_data(chip->pci), |
712 | chip->multichannel ? 128*1024 : 64*1024, 128*1024); | 712 | chip->multichannel ? 128*1024 : 64*1024, 128*1024); |
713 | 713 | ||
714 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
715 | snd_pcm_alt_chmaps, | ||
716 | chip->multichannel ? 6 : 2, 0, | ||
717 | NULL); | ||
718 | if (err < 0) | ||
719 | return err; | ||
720 | |||
714 | if (rpcm) | 721 | if (rpcm) |
715 | *rpcm = pcm; | 722 | *rpcm = pcm; |
716 | return 0; | 723 | return 0; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index d71d101e9293..960800b862ab 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -3688,6 +3688,36 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
3688 | } | 3688 | } |
3689 | EXPORT_SYMBOL_HDA(snd_hda_build_controls); | 3689 | EXPORT_SYMBOL_HDA(snd_hda_build_controls); |
3690 | 3690 | ||
3691 | /* | ||
3692 | * add standard channel maps if not specified | ||
3693 | */ | ||
3694 | static int add_std_chmaps(struct hda_codec *codec) | ||
3695 | { | ||
3696 | int i, str, err; | ||
3697 | |||
3698 | for (i = 0; i < codec->num_pcms; i++) { | ||
3699 | for (str = 0; str < 2; str++) { | ||
3700 | struct snd_pcm *pcm = codec->pcm_info[i].pcm; | ||
3701 | struct hda_pcm_stream *hinfo = | ||
3702 | &codec->pcm_info[i].stream[str]; | ||
3703 | struct snd_pcm_chmap *chmap; | ||
3704 | |||
3705 | if (codec->pcm_info[i].own_chmap) | ||
3706 | continue; | ||
3707 | if (!pcm || !hinfo->substreams) | ||
3708 | continue; | ||
3709 | err = snd_pcm_add_chmap_ctls(pcm, str, | ||
3710 | snd_pcm_std_chmaps, | ||
3711 | hinfo->channels_max, | ||
3712 | 0, &chmap); | ||
3713 | if (err < 0) | ||
3714 | return err; | ||
3715 | chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; | ||
3716 | } | ||
3717 | } | ||
3718 | return 0; | ||
3719 | } | ||
3720 | |||
3691 | int snd_hda_codec_build_controls(struct hda_codec *codec) | 3721 | int snd_hda_codec_build_controls(struct hda_codec *codec) |
3692 | { | 3722 | { |
3693 | int err = 0; | 3723 | int err = 0; |
@@ -3699,6 +3729,12 @@ int snd_hda_codec_build_controls(struct hda_codec *codec) | |||
3699 | err = codec->patch_ops.build_controls(codec); | 3729 | err = codec->patch_ops.build_controls(codec); |
3700 | if (err < 0) | 3730 | if (err < 0) |
3701 | return err; | 3731 | return err; |
3732 | |||
3733 | /* we create chmaps here instead of build_pcms */ | ||
3734 | err = add_std_chmaps(codec); | ||
3735 | if (err < 0) | ||
3736 | return err; | ||
3737 | |||
3702 | snd_hda_jack_report_sync(codec); /* call at the last init point */ | 3738 | snd_hda_jack_report_sync(codec); /* call at the last init point */ |
3703 | return 0; | 3739 | return 0; |
3704 | } | 3740 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index ee4ae8e271e3..507fe8a917b6 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -776,6 +776,7 @@ struct hda_pcm { | |||
776 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ | 776 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ |
777 | int device; /* device number to assign */ | 777 | int device; /* device number to assign */ |
778 | struct snd_pcm *pcm; /* assigned PCM instance */ | 778 | struct snd_pcm *pcm; /* assigned PCM instance */ |
779 | bool own_chmap; /* codec driver provides own channel maps */ | ||
779 | }; | 780 | }; |
780 | 781 | ||
781 | /* codec information */ | 782 | /* codec information */ |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 333d5338c15c..71555cc54db1 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
36 | #include <sound/jack.h> | 36 | #include <sound/jack.h> |
37 | #include <sound/asoundef.h> | 37 | #include <sound/asoundef.h> |
38 | #include <sound/tlv.h> | ||
38 | #include "hda_codec.h" | 39 | #include "hda_codec.h" |
39 | #include "hda_local.h" | 40 | #include "hda_local.h" |
40 | #include "hda_jack.h" | 41 | #include "hda_jack.h" |
@@ -73,6 +74,8 @@ struct hdmi_spec_per_pin { | |||
73 | struct delayed_work work; | 74 | struct delayed_work work; |
74 | int repoll_count; | 75 | int repoll_count; |
75 | bool non_pcm; | 76 | bool non_pcm; |
77 | bool chmap_set; /* channel-map override by ALSA API? */ | ||
78 | unsigned char chmap[8]; /* ALSA API channel-map */ | ||
76 | }; | 79 | }; |
77 | 80 | ||
78 | struct hdmi_spec { | 81 | struct hdmi_spec { |
@@ -82,6 +85,7 @@ struct hdmi_spec { | |||
82 | int num_pins; | 85 | int num_pins; |
83 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; | 86 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; |
84 | struct hda_pcm pcm_rec[MAX_HDMI_PINS]; | 87 | struct hda_pcm pcm_rec[MAX_HDMI_PINS]; |
88 | unsigned int channels_max; /* max over all cvts */ | ||
85 | 89 | ||
86 | /* | 90 | /* |
87 | * Non-generic ATI/NVIDIA specific | 91 | * Non-generic ATI/NVIDIA specific |
@@ -548,7 +552,7 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
548 | } | 552 | } |
549 | 553 | ||
550 | 554 | ||
551 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 555 | static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, |
552 | hda_nid_t pin_nid, | 556 | hda_nid_t pin_nid, |
553 | bool non_pcm, | 557 | bool non_pcm, |
554 | int ca) | 558 | int ca) |
@@ -588,6 +592,136 @@ static void hdmi_setup_channel_mapping(struct hda_codec *codec, | |||
588 | hdmi_debug_channel_mapping(codec, pin_nid); | 592 | hdmi_debug_channel_mapping(codec, pin_nid); |
589 | } | 593 | } |
590 | 594 | ||
595 | struct channel_map_table { | ||
596 | unsigned char map; /* ALSA API channel map position */ | ||
597 | unsigned char cea_slot; /* CEA slot value */ | ||
598 | int spk_mask; /* speaker position bit mask */ | ||
599 | }; | ||
600 | |||
601 | static struct channel_map_table map_tables[] = { | ||
602 | { SNDRV_CHMAP_FL, 0x00, FL }, | ||
603 | { SNDRV_CHMAP_FR, 0x01, FR }, | ||
604 | { SNDRV_CHMAP_RL, 0x04, RL }, | ||
605 | { SNDRV_CHMAP_RR, 0x05, RR }, | ||
606 | { SNDRV_CHMAP_LFE, 0x02, LFE }, | ||
607 | { SNDRV_CHMAP_FC, 0x03, FC }, | ||
608 | { SNDRV_CHMAP_RLC, 0x06, RLC }, | ||
609 | { SNDRV_CHMAP_RRC, 0x07, RRC }, | ||
610 | {} /* terminator */ | ||
611 | }; | ||
612 | |||
613 | /* from ALSA API channel position to speaker bit mask */ | ||
614 | static int to_spk_mask(unsigned char c) | ||
615 | { | ||
616 | struct channel_map_table *t = map_tables; | ||
617 | for (; t->map; t++) { | ||
618 | if (t->map == c) | ||
619 | return t->spk_mask; | ||
620 | } | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | /* from ALSA API channel position to CEA slot */ | ||
625 | static int to_cea_slot(unsigned char c) | ||
626 | { | ||
627 | struct channel_map_table *t = map_tables; | ||
628 | for (; t->map; t++) { | ||
629 | if (t->map == c) | ||
630 | return t->cea_slot; | ||
631 | } | ||
632 | return 0x0f; | ||
633 | } | ||
634 | |||
635 | /* from CEA slot to ALSA API channel position */ | ||
636 | static int from_cea_slot(unsigned char c) | ||
637 | { | ||
638 | struct channel_map_table *t = map_tables; | ||
639 | for (; t->map; t++) { | ||
640 | if (t->cea_slot == c) | ||
641 | return t->map; | ||
642 | } | ||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | /* from speaker bit mask to ALSA API channel position */ | ||
647 | static int spk_to_chmap(int spk) | ||
648 | { | ||
649 | struct channel_map_table *t = map_tables; | ||
650 | for (; t->map; t++) { | ||
651 | if (t->spk_mask == spk) | ||
652 | return t->map; | ||
653 | } | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | /* get the CA index corresponding to the given ALSA API channel map */ | ||
658 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) | ||
659 | { | ||
660 | int i, spks = 0, spk_mask = 0; | ||
661 | |||
662 | for (i = 0; i < chs; i++) { | ||
663 | int mask = to_spk_mask(map[i]); | ||
664 | if (mask) { | ||
665 | spk_mask |= mask; | ||
666 | spks++; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
671 | if ((chs == channel_allocations[i].channels || | ||
672 | spks == channel_allocations[i].channels) && | ||
673 | (spk_mask & channel_allocations[i].spk_mask) == | ||
674 | channel_allocations[i].spk_mask) | ||
675 | return channel_allocations[i].ca_index; | ||
676 | } | ||
677 | return -1; | ||
678 | } | ||
679 | |||
680 | /* set up the channel slots for the given ALSA API channel map */ | ||
681 | static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, | ||
682 | hda_nid_t pin_nid, | ||
683 | int chs, unsigned char *map) | ||
684 | { | ||
685 | int i; | ||
686 | for (i = 0; i < 8; i++) { | ||
687 | int val, err; | ||
688 | if (i < chs) | ||
689 | val = to_cea_slot(map[i]); | ||
690 | else | ||
691 | val = 0xf; | ||
692 | val |= (i << 4); | ||
693 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
694 | AC_VERB_SET_HDMI_CHAN_SLOT, val); | ||
695 | if (err) | ||
696 | return -EINVAL; | ||
697 | } | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | /* store ALSA API channel map from the current default map */ | ||
702 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) | ||
703 | { | ||
704 | int i; | ||
705 | for (i = 0; i < 8; i++) { | ||
706 | if (i < channel_allocations[ca].channels) | ||
707 | map[i] = from_cea_slot((hdmi_channel_mapping[ca][i] >> 4) & 0x0f); | ||
708 | else | ||
709 | map[i] = 0; | ||
710 | } | ||
711 | } | ||
712 | |||
713 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
714 | hda_nid_t pin_nid, bool non_pcm, int ca, | ||
715 | int channels, unsigned char *map) | ||
716 | { | ||
717 | if (!non_pcm && map) { | ||
718 | hdmi_manual_setup_channel_mapping(codec, pin_nid, | ||
719 | channels, map); | ||
720 | } else { | ||
721 | hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); | ||
722 | hdmi_setup_fake_chmap(map, ca); | ||
723 | } | ||
724 | } | ||
591 | 725 | ||
592 | /* | 726 | /* |
593 | * Audio InfoFrame routines | 727 | * Audio InfoFrame routines |
@@ -726,7 +860,12 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
726 | if (!eld->monitor_present) | 860 | if (!eld->monitor_present) |
727 | return; | 861 | return; |
728 | 862 | ||
729 | ca = hdmi_channel_allocation(eld, channels); | 863 | if (!non_pcm && per_pin->chmap_set) |
864 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | ||
865 | else | ||
866 | ca = hdmi_channel_allocation(eld, channels); | ||
867 | if (ca < 0) | ||
868 | ca = 0; | ||
730 | 869 | ||
731 | memset(&ai, 0, sizeof(ai)); | 870 | memset(&ai, 0, sizeof(ai)); |
732 | if (eld->conn_type == 0) { /* HDMI */ | 871 | if (eld->conn_type == 0) { /* HDMI */ |
@@ -763,7 +902,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
763 | "pin=%d channels=%d\n", | 902 | "pin=%d channels=%d\n", |
764 | pin_nid, | 903 | pin_nid, |
765 | channels); | 904 | channels); |
766 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca); | 905 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
906 | channels, per_pin->chmap); | ||
767 | hdmi_stop_infoframe_trans(codec, pin_nid); | 907 | hdmi_stop_infoframe_trans(codec, pin_nid); |
768 | hdmi_fill_audio_infoframe(codec, pin_nid, | 908 | hdmi_fill_audio_infoframe(codec, pin_nid, |
769 | ai.bytes, sizeof(ai)); | 909 | ai.bytes, sizeof(ai)); |
@@ -772,7 +912,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
772 | /* For non-pcm audio switch, setup new channel mapping | 912 | /* For non-pcm audio switch, setup new channel mapping |
773 | * accordingly */ | 913 | * accordingly */ |
774 | if (per_pin->non_pcm != non_pcm) | 914 | if (per_pin->non_pcm != non_pcm) |
775 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca); | 915 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
916 | channels, per_pin->chmap); | ||
776 | } | 917 | } |
777 | 918 | ||
778 | per_pin->non_pcm = non_pcm; | 919 | per_pin->non_pcm = non_pcm; |
@@ -1098,8 +1239,11 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | |||
1098 | 1239 | ||
1099 | per_cvt->cvt_nid = cvt_nid; | 1240 | per_cvt->cvt_nid = cvt_nid; |
1100 | per_cvt->channels_min = 2; | 1241 | per_cvt->channels_min = 2; |
1101 | if (chans <= 16) | 1242 | if (chans <= 16) { |
1102 | per_cvt->channels_max = chans; | 1243 | per_cvt->channels_max = chans; |
1244 | if (chans > spec->channels_max) | ||
1245 | spec->channels_max = chans; | ||
1246 | } | ||
1103 | 1247 | ||
1104 | err = snd_hda_query_supported_pcm(codec, cvt_nid, | 1248 | err = snd_hda_query_supported_pcm(codec, cvt_nid, |
1105 | &per_cvt->rates, | 1249 | &per_cvt->rates, |
@@ -1250,7 +1394,10 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | |||
1250 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1394 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1251 | pinctl & ~PIN_OUT); | 1395 | pinctl & ~PIN_OUT); |
1252 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1396 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1397 | per_pin->chmap_set = false; | ||
1398 | memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); | ||
1253 | } | 1399 | } |
1400 | |||
1254 | return 0; | 1401 | return 0; |
1255 | } | 1402 | } |
1256 | 1403 | ||
@@ -1261,6 +1408,135 @@ static const struct hda_pcm_ops generic_ops = { | |||
1261 | .cleanup = generic_hdmi_playback_pcm_cleanup, | 1408 | .cleanup = generic_hdmi_playback_pcm_cleanup, |
1262 | }; | 1409 | }; |
1263 | 1410 | ||
1411 | /* | ||
1412 | * ALSA API channel-map control callbacks | ||
1413 | */ | ||
1414 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, | ||
1415 | struct snd_ctl_elem_info *uinfo) | ||
1416 | { | ||
1417 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
1418 | struct hda_codec *codec = info->private_data; | ||
1419 | struct hdmi_spec *spec = codec->spec; | ||
1420 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1421 | uinfo->count = spec->channels_max; | ||
1422 | uinfo->value.integer.min = 0; | ||
1423 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | ||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1427 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1428 | unsigned int size, unsigned int __user *tlv) | ||
1429 | { | ||
1430 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
1431 | struct hda_codec *codec = info->private_data; | ||
1432 | struct hdmi_spec *spec = codec->spec; | ||
1433 | const unsigned int valid_mask = | ||
1434 | FL | FR | RL | RR | LFE | FC | RLC | RRC; | ||
1435 | unsigned int __user *dst; | ||
1436 | int chs, count = 0; | ||
1437 | |||
1438 | if (size < 8) | ||
1439 | return -ENOMEM; | ||
1440 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | ||
1441 | return -EFAULT; | ||
1442 | size -= 8; | ||
1443 | dst = tlv + 2; | ||
1444 | for (chs = 2; chs <= spec->channels_max; chs++) { | ||
1445 | int i, c; | ||
1446 | struct cea_channel_speaker_allocation *cap; | ||
1447 | cap = channel_allocations; | ||
1448 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { | ||
1449 | int chs_bytes = chs * 4; | ||
1450 | if (cap->channels != chs) | ||
1451 | continue; | ||
1452 | if (cap->spk_mask & ~valid_mask) | ||
1453 | continue; | ||
1454 | if (size < 8) | ||
1455 | return -ENOMEM; | ||
1456 | if (put_user(SNDRV_CTL_TLVT_CHMAP_VAR, dst) || | ||
1457 | put_user(chs_bytes, dst + 1)) | ||
1458 | return -EFAULT; | ||
1459 | dst += 2; | ||
1460 | size -= 8; | ||
1461 | count += 8; | ||
1462 | if (size < chs_bytes) | ||
1463 | return -ENOMEM; | ||
1464 | size -= chs_bytes; | ||
1465 | count += chs_bytes; | ||
1466 | for (c = 7; c >= 0; c--) { | ||
1467 | int spk = cap->speakers[c]; | ||
1468 | if (!spk) | ||
1469 | continue; | ||
1470 | if (put_user(spk_to_chmap(spk), dst)) | ||
1471 | return -EFAULT; | ||
1472 | dst++; | ||
1473 | } | ||
1474 | } | ||
1475 | } | ||
1476 | if (put_user(count, tlv + 1)) | ||
1477 | return -EFAULT; | ||
1478 | return 0; | ||
1479 | } | ||
1480 | |||
1481 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, | ||
1482 | struct snd_ctl_elem_value *ucontrol) | ||
1483 | { | ||
1484 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
1485 | struct hda_codec *codec = info->private_data; | ||
1486 | struct hdmi_spec *spec = codec->spec; | ||
1487 | int pin_idx = kcontrol->private_value; | ||
1488 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
1489 | int i; | ||
1490 | |||
1491 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) | ||
1492 | ucontrol->value.integer.value[i] = per_pin->chmap[i]; | ||
1493 | return 0; | ||
1494 | } | ||
1495 | |||
1496 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, | ||
1497 | struct snd_ctl_elem_value *ucontrol) | ||
1498 | { | ||
1499 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
1500 | struct hda_codec *codec = info->private_data; | ||
1501 | struct hdmi_spec *spec = codec->spec; | ||
1502 | int pin_idx = kcontrol->private_value; | ||
1503 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
1504 | unsigned int ctl_idx; | ||
1505 | struct snd_pcm_substream *substream; | ||
1506 | unsigned char chmap[8]; | ||
1507 | int i, ca, prepared = 0; | ||
1508 | |||
1509 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
1510 | substream = snd_pcm_chmap_substream(info, ctl_idx); | ||
1511 | if (!substream || !substream->runtime) | ||
1512 | return -EBADFD; | ||
1513 | switch (substream->runtime->status->state) { | ||
1514 | case SNDRV_PCM_STATE_OPEN: | ||
1515 | case SNDRV_PCM_STATE_SETUP: | ||
1516 | break; | ||
1517 | case SNDRV_PCM_STATE_PREPARED: | ||
1518 | prepared = 1; | ||
1519 | break; | ||
1520 | default: | ||
1521 | return -EBUSY; | ||
1522 | } | ||
1523 | memset(chmap, 0, sizeof(chmap)); | ||
1524 | for (i = 0; i < ARRAY_SIZE(chmap); i++) | ||
1525 | chmap[i] = ucontrol->value.integer.value[i]; | ||
1526 | if (!memcmp(chmap, per_pin->chmap, sizeof(chmap))) | ||
1527 | return 0; | ||
1528 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); | ||
1529 | if (ca < 0) | ||
1530 | return -EINVAL; | ||
1531 | per_pin->chmap_set = true; | ||
1532 | memcpy(per_pin->chmap, chmap, sizeof(chmap)); | ||
1533 | if (prepared) | ||
1534 | hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm, | ||
1535 | substream); | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1264 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | 1540 | static int generic_hdmi_build_pcms(struct hda_codec *codec) |
1265 | { | 1541 | { |
1266 | struct hdmi_spec *spec = codec->spec; | 1542 | struct hdmi_spec *spec = codec->spec; |
@@ -1273,6 +1549,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) | |||
1273 | info = &spec->pcm_rec[pin_idx]; | 1549 | info = &spec->pcm_rec[pin_idx]; |
1274 | info->name = get_hdmi_pcm_name(pin_idx); | 1550 | info->name = get_hdmi_pcm_name(pin_idx); |
1275 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1551 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1552 | info->own_chmap = true; | ||
1276 | 1553 | ||
1277 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1554 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
1278 | pstr->substreams = 1; | 1555 | pstr->substreams = 1; |
@@ -1330,6 +1607,27 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
1330 | hdmi_present_sense(per_pin, 0); | 1607 | hdmi_present_sense(per_pin, 0); |
1331 | } | 1608 | } |
1332 | 1609 | ||
1610 | /* add channel maps */ | ||
1611 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
1612 | struct snd_pcm_chmap *chmap; | ||
1613 | struct snd_kcontrol *kctl; | ||
1614 | int i; | ||
1615 | err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, | ||
1616 | SNDRV_PCM_STREAM_PLAYBACK, | ||
1617 | NULL, 0, pin_idx, &chmap); | ||
1618 | if (err < 0) | ||
1619 | return err; | ||
1620 | /* override handlers */ | ||
1621 | chmap->private_data = codec; | ||
1622 | kctl = chmap->kctl; | ||
1623 | for (i = 0; i < kctl->count; i++) | ||
1624 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
1625 | kctl->info = hdmi_chmap_ctl_info; | ||
1626 | kctl->get = hdmi_chmap_ctl_get; | ||
1627 | kctl->put = hdmi_chmap_ctl_put; | ||
1628 | kctl->tlv.c = hdmi_chmap_ctl_tlv; | ||
1629 | } | ||
1630 | |||
1333 | return 0; | 1631 | return 0; |
1334 | } | 1632 | } |
1335 | 1633 | ||
@@ -1857,6 +2155,43 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
1857 | return 0; | 2155 | return 0; |
1858 | } | 2156 | } |
1859 | 2157 | ||
2158 | static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) | ||
2159 | { | ||
2160 | struct hdmi_spec *spec = codec->spec; | ||
2161 | int err = simple_playback_build_pcms(codec); | ||
2162 | spec->pcm_rec[0].own_chmap = true; | ||
2163 | return err; | ||
2164 | } | ||
2165 | |||
2166 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) | ||
2167 | { | ||
2168 | struct hdmi_spec *spec = codec->spec; | ||
2169 | struct snd_pcm_chmap *chmap; | ||
2170 | int err; | ||
2171 | |||
2172 | err = simple_playback_build_controls(codec); | ||
2173 | if (err < 0) | ||
2174 | return err; | ||
2175 | |||
2176 | /* add channel maps */ | ||
2177 | err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm, | ||
2178 | SNDRV_PCM_STREAM_PLAYBACK, | ||
2179 | snd_pcm_alt_chmaps, 8, 0, &chmap); | ||
2180 | if (err < 0) | ||
2181 | return err; | ||
2182 | switch (codec->preset->id) { | ||
2183 | case 0x10de0002: | ||
2184 | case 0x10de0003: | ||
2185 | case 0x10de0005: | ||
2186 | case 0x10de0006: | ||
2187 | chmap->channel_mask = (1U << 2) | (1U << 8); | ||
2188 | break; | ||
2189 | case 0x10de0007: | ||
2190 | chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8); | ||
2191 | } | ||
2192 | return 0; | ||
2193 | } | ||
2194 | |||
1860 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | 2195 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) |
1861 | { | 2196 | { |
1862 | struct hdmi_spec *spec; | 2197 | struct hdmi_spec *spec; |
@@ -1867,6 +2202,8 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | |||
1867 | spec->multiout.max_channels = 8; | 2202 | spec->multiout.max_channels = 8; |
1868 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; | 2203 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; |
1869 | codec->patch_ops.init = nvhdmi_7x_init_8ch; | 2204 | codec->patch_ops.init = nvhdmi_7x_init_8ch; |
2205 | codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms; | ||
2206 | codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls; | ||
1870 | 2207 | ||
1871 | /* Initialize the audio infoframe channel mask and checksum to something | 2208 | /* Initialize the audio infoframe channel mask and checksum to something |
1872 | * valid */ | 2209 | * valid */ |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 613499932b2b..1907ddad3840 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2287,6 +2287,8 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2287 | p = &alc_pcm_analog_playback; | 2287 | p = &alc_pcm_analog_playback; |
2288 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; | 2288 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; |
2289 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; | 2289 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; |
2290 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
2291 | spec->multiout.max_channels; | ||
2290 | } | 2292 | } |
2291 | if (spec->adc_nids) { | 2293 | if (spec->adc_nids) { |
2292 | p = spec->stream_analog_capture; | 2294 | p = spec->stream_analog_capture; |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5c4115289a9a..848102e5d864 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -1541,6 +1541,26 @@ static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device, | |||
1541 | snd_dma_pci_data(chip->pci), | 1541 | snd_dma_pci_data(chip->pci), |
1542 | rec->prealloc_size, rec->prealloc_max_size); | 1542 | rec->prealloc_size, rec->prealloc_max_size); |
1543 | 1543 | ||
1544 | if (rec->ac97_idx == ICHD_PCMOUT && rec->playback_ops) { | ||
1545 | struct snd_pcm_chmap *chmap; | ||
1546 | int chs = 2; | ||
1547 | if (rec->ac97_idx == ICHD_PCMOUT) { | ||
1548 | if (chip->multi8) | ||
1549 | chs = 8; | ||
1550 | else if (chip->multi6) | ||
1551 | chs = 6; | ||
1552 | else if (chip->multi4) | ||
1553 | chs = 4; | ||
1554 | } | ||
1555 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1556 | snd_pcm_alt_chmaps, chs, 0, | ||
1557 | &chmap); | ||
1558 | if (err < 0) | ||
1559 | return err; | ||
1560 | chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; | ||
1561 | chip->ac97[0]->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
1562 | } | ||
1563 | |||
1544 | return 0; | 1564 | return 0; |
1545 | } | 1565 | } |
1546 | 1566 | ||
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index e3d32e2d574e..f0b4efdb483c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -1440,6 +1440,7 @@ static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset, | |||
1440 | static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | 1440 | static int __devinit snd_via8233_pcm_new(struct via82xx *chip) |
1441 | { | 1441 | { |
1442 | struct snd_pcm *pcm; | 1442 | struct snd_pcm *pcm; |
1443 | struct snd_pcm_chmap *chmap; | ||
1443 | int i, err; | 1444 | int i, err; |
1444 | 1445 | ||
1445 | chip->playback_devno = 0; /* x 4 */ | 1446 | chip->playback_devno = 0; /* x 4 */ |
@@ -1467,6 +1468,12 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | |||
1467 | snd_dma_pci_data(chip->pci), | 1468 | snd_dma_pci_data(chip->pci), |
1468 | 64*1024, VIA_MAX_BUFSIZE); | 1469 | 64*1024, VIA_MAX_BUFSIZE); |
1469 | 1470 | ||
1471 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1472 | snd_pcm_std_chmaps, 2, 0, | ||
1473 | &chmap); | ||
1474 | if (err < 0) | ||
1475 | return err; | ||
1476 | |||
1470 | /* PCM #1: multi-channel playback and 2nd capture */ | 1477 | /* PCM #1: multi-channel playback and 2nd capture */ |
1471 | err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 1, &pcm); | 1478 | err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 1, &pcm); |
1472 | if (err < 0) | 1479 | if (err < 0) |
@@ -1484,6 +1491,14 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | |||
1484 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1491 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
1485 | snd_dma_pci_data(chip->pci), | 1492 | snd_dma_pci_data(chip->pci), |
1486 | 64*1024, VIA_MAX_BUFSIZE); | 1493 | 64*1024, VIA_MAX_BUFSIZE); |
1494 | |||
1495 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1496 | snd_pcm_alt_chmaps, 6, 0, | ||
1497 | &chmap); | ||
1498 | if (err < 0) | ||
1499 | return err; | ||
1500 | chip->ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
1501 | |||
1487 | return 0; | 1502 | return 0; |
1488 | } | 1503 | } |
1489 | 1504 | ||
@@ -1493,6 +1508,7 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | |||
1493 | static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) | 1508 | static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) |
1494 | { | 1509 | { |
1495 | struct snd_pcm *pcm; | 1510 | struct snd_pcm *pcm; |
1511 | struct snd_pcm_chmap *chmap; | ||
1496 | int err; | 1512 | int err; |
1497 | 1513 | ||
1498 | chip->multi_devno = 0; | 1514 | chip->multi_devno = 0; |
@@ -1519,6 +1535,13 @@ static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) | |||
1519 | snd_dma_pci_data(chip->pci), | 1535 | snd_dma_pci_data(chip->pci), |
1520 | 64*1024, VIA_MAX_BUFSIZE); | 1536 | 64*1024, VIA_MAX_BUFSIZE); |
1521 | 1537 | ||
1538 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1539 | snd_pcm_alt_chmaps, 6, 0, | ||
1540 | &chmap); | ||
1541 | if (err < 0) | ||
1542 | return err; | ||
1543 | chip->ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
1544 | |||
1522 | /* SPDIF supported? */ | 1545 | /* SPDIF supported? */ |
1523 | if (! ac97_can_spdif(chip->ac97)) | 1546 | if (! ac97_can_spdif(chip->ac97)) |
1524 | return 0; | 1547 | return 0; |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index ee8b6366e48d..3a6f03f9b02f 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -1166,6 +1166,11 @@ int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm | |||
1166 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1166 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1167 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1167 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1168 | 1168 | ||
1169 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1170 | snd_pcm_std_chmaps, 2, 0, NULL); | ||
1171 | if (err < 0) | ||
1172 | return err; | ||
1173 | |||
1169 | if (rpcm) | 1174 | if (rpcm) |
1170 | *rpcm = pcm; | 1175 | *rpcm = pcm; |
1171 | return 0; | 1176 | return 0; |
@@ -1257,6 +1262,14 @@ static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { | |||
1257 | .pointer = snd_ymfpci_playback_pointer, | 1262 | .pointer = snd_ymfpci_playback_pointer, |
1258 | }; | 1263 | }; |
1259 | 1264 | ||
1265 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
1266 | { .channels = 1, | ||
1267 | .map = { SNDRV_CHMAP_MONO } }, | ||
1268 | { .channels = 2, | ||
1269 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
1270 | { } | ||
1271 | }; | ||
1272 | |||
1260 | int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) | 1273 | int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) |
1261 | { | 1274 | { |
1262 | struct snd_pcm *pcm; | 1275 | struct snd_pcm *pcm; |
@@ -1278,6 +1291,11 @@ int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd | |||
1278 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1291 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1279 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1292 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
1280 | 1293 | ||
1294 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
1295 | surround_map, 2, 0, NULL); | ||
1296 | if (err < 0) | ||
1297 | return err; | ||
1298 | |||
1281 | if (rpcm) | 1299 | if (rpcm) |
1282 | *rpcm = pcm; | 1300 | *rpcm = pcm; |
1283 | return 0; | 1301 | return 0; |