diff options
| -rw-r--r-- | sound/pci/hda/hda_codec.c | 41 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.h | 21 | ||||
| -rw-r--r-- | sound/pci/hda/patch_hdmi.c | 9 |
3 files changed, 50 insertions, 21 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index bd8d7a63d7fe..05e8995f9aec 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -3013,26 +3013,31 @@ struct hda_rate_tbl { | |||
| 3013 | unsigned int hda_fmt; | 3013 | unsigned int hda_fmt; |
| 3014 | }; | 3014 | }; |
| 3015 | 3015 | ||
| 3016 | /* rate = base * mult / div */ | ||
| 3017 | #define HDA_RATE(base, mult, div) \ | ||
| 3018 | (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ | ||
| 3019 | (((div) - 1) << AC_FMT_DIV_SHIFT)) | ||
| 3020 | |||
| 3016 | static struct hda_rate_tbl rate_bits[] = { | 3021 | static struct hda_rate_tbl rate_bits[] = { |
| 3017 | /* rate in Hz, ALSA rate bitmask, HDA format value */ | 3022 | /* rate in Hz, ALSA rate bitmask, HDA format value */ |
| 3018 | 3023 | ||
| 3019 | /* autodetected value used in snd_hda_query_supported_pcm */ | 3024 | /* autodetected value used in snd_hda_query_supported_pcm */ |
| 3020 | { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */ | 3025 | { 8000, SNDRV_PCM_RATE_8000, HDA_RATE(48, 1, 6) }, |
| 3021 | { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */ | 3026 | { 11025, SNDRV_PCM_RATE_11025, HDA_RATE(44, 1, 4) }, |
| 3022 | { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */ | 3027 | { 16000, SNDRV_PCM_RATE_16000, HDA_RATE(48, 1, 3) }, |
| 3023 | { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */ | 3028 | { 22050, SNDRV_PCM_RATE_22050, HDA_RATE(44, 1, 2) }, |
| 3024 | { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */ | 3029 | { 32000, SNDRV_PCM_RATE_32000, HDA_RATE(48, 2, 3) }, |
| 3025 | { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */ | 3030 | { 44100, SNDRV_PCM_RATE_44100, HDA_RATE(44, 1, 1) }, |
| 3026 | { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */ | 3031 | { 48000, SNDRV_PCM_RATE_48000, HDA_RATE(48, 1, 1) }, |
| 3027 | { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */ | 3032 | { 88200, SNDRV_PCM_RATE_88200, HDA_RATE(44, 2, 1) }, |
| 3028 | { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */ | 3033 | { 96000, SNDRV_PCM_RATE_96000, HDA_RATE(48, 2, 1) }, |
| 3029 | { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */ | 3034 | { 176400, SNDRV_PCM_RATE_176400, HDA_RATE(44, 4, 1) }, |
| 3030 | { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */ | 3035 | { 192000, SNDRV_PCM_RATE_192000, HDA_RATE(48, 4, 1) }, |
| 3031 | #define AC_PAR_PCM_RATE_BITS 11 | 3036 | #define AC_PAR_PCM_RATE_BITS 11 |
| 3032 | /* up to bits 10, 384kHZ isn't supported properly */ | 3037 | /* up to bits 10, 384kHZ isn't supported properly */ |
| 3033 | 3038 | ||
| 3034 | /* not autodetected value */ | 3039 | /* not autodetected value */ |
| 3035 | { 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */ | 3040 | { 9600, SNDRV_PCM_RATE_KNOT, HDA_RATE(48, 1, 5) }, |
| 3036 | 3041 | ||
| 3037 | { 0 } /* terminator */ | 3042 | { 0 } /* terminator */ |
| 3038 | }; | 3043 | }; |
| @@ -3075,20 +3080,20 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
| 3075 | 3080 | ||
| 3076 | switch (snd_pcm_format_width(format)) { | 3081 | switch (snd_pcm_format_width(format)) { |
| 3077 | case 8: | 3082 | case 8: |
| 3078 | val |= 0x00; | 3083 | val |= AC_FMT_BITS_8; |
| 3079 | break; | 3084 | break; |
| 3080 | case 16: | 3085 | case 16: |
| 3081 | val |= 0x10; | 3086 | val |= AC_FMT_BITS_16; |
| 3082 | break; | 3087 | break; |
| 3083 | case 20: | 3088 | case 20: |
| 3084 | case 24: | 3089 | case 24: |
| 3085 | case 32: | 3090 | case 32: |
| 3086 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) | 3091 | if (maxbps >= 32 || format == SNDRV_PCM_FORMAT_FLOAT_LE) |
| 3087 | val |= 0x40; | 3092 | val |= AC_FMT_BITS_32; |
| 3088 | else if (maxbps >= 24) | 3093 | else if (maxbps >= 24) |
| 3089 | val |= 0x30; | 3094 | val |= AC_FMT_BITS_24; |
| 3090 | else | 3095 | else |
| 3091 | val |= 0x20; | 3096 | val |= AC_FMT_BITS_20; |
| 3092 | break; | 3097 | break; |
| 3093 | default: | 3098 | default: |
| 3094 | snd_printdd("invalid format width %d\n", | 3099 | snd_printdd("invalid format width %d\n", |
| @@ -3097,7 +3102,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
| 3097 | } | 3102 | } |
| 3098 | 3103 | ||
| 3099 | if (spdif_ctls & AC_DIG1_NONAUDIO) | 3104 | if (spdif_ctls & AC_DIG1_NONAUDIO) |
| 3100 | val |= 0x8000; | 3105 | val |= AC_FMT_TYPE_NON_PCM; |
| 3101 | 3106 | ||
| 3102 | return val; | 3107 | return val; |
| 3103 | } | 3108 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 48b33671e727..46f75bccf0d3 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
| @@ -224,6 +224,27 @@ enum { | |||
| 224 | /* Input converter SDI select */ | 224 | /* Input converter SDI select */ |
| 225 | #define AC_SDI_SELECT (0xf<<0) | 225 | #define AC_SDI_SELECT (0xf<<0) |
| 226 | 226 | ||
| 227 | /* stream format id */ | ||
| 228 | #define AC_FMT_CHAN_SHIFT 0 | ||
| 229 | #define AC_FMT_CHAN_MASK (0x0f << 0) | ||
| 230 | #define AC_FMT_BITS_SHIFT 4 | ||
| 231 | #define AC_FMT_BITS_MASK (7 << 4) | ||
| 232 | #define AC_FMT_BITS_8 (0 << 4) | ||
| 233 | #define AC_FMT_BITS_16 (1 << 4) | ||
| 234 | #define AC_FMT_BITS_20 (2 << 4) | ||
| 235 | #define AC_FMT_BITS_24 (3 << 4) | ||
| 236 | #define AC_FMT_BITS_32 (4 << 4) | ||
| 237 | #define AC_FMT_DIV_SHIFT 8 | ||
| 238 | #define AC_FMT_DIV_MASK (7 << 8) | ||
| 239 | #define AC_FMT_MULT_SHIFT 11 | ||
| 240 | #define AC_FMT_MULT_MASK (7 << 11) | ||
| 241 | #define AC_FMT_BASE_SHIFT 14 | ||
| 242 | #define AC_FMT_BASE_48K (0 << 14) | ||
| 243 | #define AC_FMT_BASE_44K (1 << 14) | ||
| 244 | #define AC_FMT_TYPE_SHIFT 15 | ||
| 245 | #define AC_FMT_TYPE_PCM (0 << 15) | ||
| 246 | #define AC_FMT_TYPE_NON_PCM (1 << 15) | ||
| 247 | |||
| 227 | /* Unsolicited response control */ | 248 | /* Unsolicited response control */ |
| 228 | #define AC_UNSOL_TAG (0x3f<<0) | 249 | #define AC_UNSOL_TAG (0x3f<<0) |
| 229 | #define AC_UNSOL_ENABLED (1<<7) | 250 | #define AC_UNSOL_ENABLED (1<<7) |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8534792591fc..522e0748ee99 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -698,6 +698,10 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | |||
| 698 | * Callbacks | 698 | * Callbacks |
| 699 | */ | 699 | */ |
| 700 | 700 | ||
| 701 | /* HBR should be Non-PCM, 8 channels */ | ||
| 702 | #define is_hbr_format(format) \ | ||
| 703 | ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) | ||
| 704 | |||
| 701 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | 705 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
| 702 | u32 stream_tag, int format) | 706 | u32 stream_tag, int format) |
| 703 | { | 707 | { |
| @@ -718,8 +722,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
| 718 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 722 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
| 719 | 723 | ||
| 720 | new_pinctl = pinctl & ~AC_PINCTL_EPT; | 724 | new_pinctl = pinctl & ~AC_PINCTL_EPT; |
| 721 | /* Non-PCM, 8 channels */ | 725 | if (is_hbr_format(format)) |
| 722 | if ((format & 0x8000) && (format & 0x0f) == 7) | ||
| 723 | new_pinctl |= AC_PINCTL_EPT_HBR; | 726 | new_pinctl |= AC_PINCTL_EPT_HBR; |
| 724 | else | 727 | else |
| 725 | new_pinctl |= AC_PINCTL_EPT_NATIVE; | 728 | new_pinctl |= AC_PINCTL_EPT_NATIVE; |
| @@ -736,7 +739,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
| 736 | new_pinctl); | 739 | new_pinctl); |
| 737 | } | 740 | } |
| 738 | 741 | ||
| 739 | if ((format & 0x8000) && (format & 0x0f) == 7 && !new_pinctl) { | 742 | if (is_hbr_format(format) && !new_pinctl) { |
| 740 | snd_printdd("hdmi_setup_stream: HBR is not supported\n"); | 743 | snd_printdd("hdmi_setup_stream: HBR is not supported\n"); |
| 741 | return -EINVAL; | 744 | return -EINVAL; |
| 742 | } | 745 | } |
