Commit 6ffe168f822cf7f777987cddc00ade542fd73bf0
Committed by
Takashi Iwai
1 parent
b78562b10f
Exists in
master
and in
20 other branches
ALSA: hda - bug fix for invalid connection list of Haswell HDMI codec pins
Haswell HDMI codec pins may report invalid connection list entries, which will cause failure to play audio via HDMI or Display Port. So this patch adds fixup for Haswell to workaround this hardware issue: enable DP1.2 mode and override the pins' connection list entries with proper value. Signed-off-by: Mengdong Lin <mengdong.lin@intel.com> Signed-off-by: Xingchao Wang <xingchao.wang@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Showing 1 changed file with 28 additions and 0 deletions Inline Diff
sound/pci/hda/patch_hdmi.c
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | 3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs |
4 | * | 4 | * |
5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. |
6 | * Copyright (c) 2006 ATI Technologies Inc. | 6 | * Copyright (c) 2006 ATI Technologies Inc. |
7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | 7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. |
8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | 8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> |
9 | * | 9 | * |
10 | * Authors: | 10 | * Authors: |
11 | * Wu Fengguang <wfg@linux.intel.com> | 11 | * Wu Fengguang <wfg@linux.intel.com> |
12 | * | 12 | * |
13 | * Maintained by: | 13 | * Maintained by: |
14 | * Wu Fengguang <wfg@linux.intel.com> | 14 | * Wu Fengguang <wfg@linux.intel.com> |
15 | * | 15 | * |
16 | * This program is free software; you can redistribute it and/or modify it | 16 | * This program is free software; you can redistribute it and/or modify it |
17 | * under the terms of the GNU General Public License as published by the Free | 17 | * under the terms of the GNU General Public License as published by the Free |
18 | * Software Foundation; either version 2 of the License, or (at your option) | 18 | * Software Foundation; either version 2 of the License, or (at your option) |
19 | * any later version. | 19 | * any later version. |
20 | * | 20 | * |
21 | * This program is distributed in the hope that it will be useful, but | 21 | * This program is distributed in the hope that it will be useful, but |
22 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | 22 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
23 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | 23 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
24 | * for more details. | 24 | * for more details. |
25 | * | 25 | * |
26 | * You should have received a copy of the GNU General Public License | 26 | * You should have received a copy of the GNU General Public License |
27 | * along with this program; if not, write to the Free Software Foundation, | 27 | * along with this program; if not, write to the Free Software Foundation, |
28 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 28 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
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 <sound/tlv.h> |
39 | #include "hda_codec.h" | 39 | #include "hda_codec.h" |
40 | #include "hda_local.h" | 40 | #include "hda_local.h" |
41 | #include "hda_jack.h" | 41 | #include "hda_jack.h" |
42 | 42 | ||
43 | static bool static_hdmi_pcm; | 43 | static bool static_hdmi_pcm; |
44 | module_param(static_hdmi_pcm, bool, 0644); | 44 | module_param(static_hdmi_pcm, bool, 0644); |
45 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); | 45 | MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | 48 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device |
49 | * could support N independent pipes, each of them can be connected to one or | 49 | * could support N independent pipes, each of them can be connected to one or |
50 | * more ports (DVI, HDMI or DisplayPort). | 50 | * more ports (DVI, HDMI or DisplayPort). |
51 | * | 51 | * |
52 | * The HDA correspondence of pipes/ports are converter/pin nodes. | 52 | * The HDA correspondence of pipes/ports are converter/pin nodes. |
53 | */ | 53 | */ |
54 | #define MAX_HDMI_CVTS 8 | 54 | #define MAX_HDMI_CVTS 8 |
55 | #define MAX_HDMI_PINS 8 | 55 | #define MAX_HDMI_PINS 8 |
56 | 56 | ||
57 | struct hdmi_spec_per_cvt { | 57 | struct hdmi_spec_per_cvt { |
58 | hda_nid_t cvt_nid; | 58 | hda_nid_t cvt_nid; |
59 | int assigned; | 59 | int assigned; |
60 | unsigned int channels_min; | 60 | unsigned int channels_min; |
61 | unsigned int channels_max; | 61 | unsigned int channels_max; |
62 | u32 rates; | 62 | u32 rates; |
63 | u64 formats; | 63 | u64 formats; |
64 | unsigned int maxbps; | 64 | unsigned int maxbps; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct hdmi_spec_per_pin { | 67 | struct hdmi_spec_per_pin { |
68 | hda_nid_t pin_nid; | 68 | hda_nid_t pin_nid; |
69 | int num_mux_nids; | 69 | int num_mux_nids; |
70 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; | 70 | hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; |
71 | 71 | ||
72 | struct hda_codec *codec; | 72 | struct hda_codec *codec; |
73 | struct hdmi_eld sink_eld; | 73 | struct hdmi_eld sink_eld; |
74 | struct delayed_work work; | 74 | struct delayed_work work; |
75 | int repoll_count; | 75 | int repoll_count; |
76 | bool non_pcm; | 76 | bool non_pcm; |
77 | bool chmap_set; /* channel-map override by ALSA API? */ | 77 | bool chmap_set; /* channel-map override by ALSA API? */ |
78 | unsigned char chmap[8]; /* ALSA API channel-map */ | 78 | unsigned char chmap[8]; /* ALSA API channel-map */ |
79 | }; | 79 | }; |
80 | 80 | ||
81 | struct hdmi_spec { | 81 | struct hdmi_spec { |
82 | int num_cvts; | 82 | int num_cvts; |
83 | struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS]; | 83 | struct hdmi_spec_per_cvt cvts[MAX_HDMI_CVTS]; |
84 | 84 | ||
85 | int num_pins; | 85 | int num_pins; |
86 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; | 86 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; |
87 | 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 */ | 88 | unsigned int channels_max; /* max over all cvts */ |
89 | 89 | ||
90 | /* | 90 | /* |
91 | * Non-generic ATI/NVIDIA specific | 91 | * Non-generic ATI/NVIDIA specific |
92 | */ | 92 | */ |
93 | struct hda_multi_out multiout; | 93 | struct hda_multi_out multiout; |
94 | struct hda_pcm_stream pcm_playback; | 94 | struct hda_pcm_stream pcm_playback; |
95 | }; | 95 | }; |
96 | 96 | ||
97 | 97 | ||
98 | struct hdmi_audio_infoframe { | 98 | struct hdmi_audio_infoframe { |
99 | u8 type; /* 0x84 */ | 99 | u8 type; /* 0x84 */ |
100 | u8 ver; /* 0x01 */ | 100 | u8 ver; /* 0x01 */ |
101 | u8 len; /* 0x0a */ | 101 | u8 len; /* 0x0a */ |
102 | 102 | ||
103 | u8 checksum; | 103 | u8 checksum; |
104 | 104 | ||
105 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | 105 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ |
106 | u8 SS01_SF24; | 106 | u8 SS01_SF24; |
107 | u8 CXT04; | 107 | u8 CXT04; |
108 | u8 CA; | 108 | u8 CA; |
109 | u8 LFEPBL01_LSV36_DM_INH7; | 109 | u8 LFEPBL01_LSV36_DM_INH7; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | struct dp_audio_infoframe { | 112 | struct dp_audio_infoframe { |
113 | u8 type; /* 0x84 */ | 113 | u8 type; /* 0x84 */ |
114 | u8 len; /* 0x1b */ | 114 | u8 len; /* 0x1b */ |
115 | u8 ver; /* 0x11 << 2 */ | 115 | u8 ver; /* 0x11 << 2 */ |
116 | 116 | ||
117 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ | 117 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ |
118 | u8 SS01_SF24; | 118 | u8 SS01_SF24; |
119 | u8 CXT04; | 119 | u8 CXT04; |
120 | u8 CA; | 120 | u8 CA; |
121 | u8 LFEPBL01_LSV36_DM_INH7; | 121 | u8 LFEPBL01_LSV36_DM_INH7; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | union audio_infoframe { | 124 | union audio_infoframe { |
125 | struct hdmi_audio_infoframe hdmi; | 125 | struct hdmi_audio_infoframe hdmi; |
126 | struct dp_audio_infoframe dp; | 126 | struct dp_audio_infoframe dp; |
127 | u8 bytes[0]; | 127 | u8 bytes[0]; |
128 | }; | 128 | }; |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * CEA speaker placement: | 131 | * CEA speaker placement: |
132 | * | 132 | * |
133 | * FLH FCH FRH | 133 | * FLH FCH FRH |
134 | * FLW FL FLC FC FRC FR FRW | 134 | * FLW FL FLC FC FRC FR FRW |
135 | * | 135 | * |
136 | * LFE | 136 | * LFE |
137 | * TC | 137 | * TC |
138 | * | 138 | * |
139 | * RL RLC RC RRC RR | 139 | * RL RLC RC RRC RR |
140 | * | 140 | * |
141 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to | 141 | * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to |
142 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. | 142 | * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. |
143 | */ | 143 | */ |
144 | enum cea_speaker_placement { | 144 | enum cea_speaker_placement { |
145 | FL = (1 << 0), /* Front Left */ | 145 | FL = (1 << 0), /* Front Left */ |
146 | FC = (1 << 1), /* Front Center */ | 146 | FC = (1 << 1), /* Front Center */ |
147 | FR = (1 << 2), /* Front Right */ | 147 | FR = (1 << 2), /* Front Right */ |
148 | FLC = (1 << 3), /* Front Left Center */ | 148 | FLC = (1 << 3), /* Front Left Center */ |
149 | FRC = (1 << 4), /* Front Right Center */ | 149 | FRC = (1 << 4), /* Front Right Center */ |
150 | RL = (1 << 5), /* Rear Left */ | 150 | RL = (1 << 5), /* Rear Left */ |
151 | RC = (1 << 6), /* Rear Center */ | 151 | RC = (1 << 6), /* Rear Center */ |
152 | RR = (1 << 7), /* Rear Right */ | 152 | RR = (1 << 7), /* Rear Right */ |
153 | RLC = (1 << 8), /* Rear Left Center */ | 153 | RLC = (1 << 8), /* Rear Left Center */ |
154 | RRC = (1 << 9), /* Rear Right Center */ | 154 | RRC = (1 << 9), /* Rear Right Center */ |
155 | LFE = (1 << 10), /* Low Frequency Effect */ | 155 | LFE = (1 << 10), /* Low Frequency Effect */ |
156 | FLW = (1 << 11), /* Front Left Wide */ | 156 | FLW = (1 << 11), /* Front Left Wide */ |
157 | FRW = (1 << 12), /* Front Right Wide */ | 157 | FRW = (1 << 12), /* Front Right Wide */ |
158 | FLH = (1 << 13), /* Front Left High */ | 158 | FLH = (1 << 13), /* Front Left High */ |
159 | FCH = (1 << 14), /* Front Center High */ | 159 | FCH = (1 << 14), /* Front Center High */ |
160 | FRH = (1 << 15), /* Front Right High */ | 160 | FRH = (1 << 15), /* Front Right High */ |
161 | TC = (1 << 16), /* Top Center */ | 161 | TC = (1 << 16), /* Top Center */ |
162 | }; | 162 | }; |
163 | 163 | ||
164 | /* | 164 | /* |
165 | * ELD SA bits in the CEA Speaker Allocation data block | 165 | * ELD SA bits in the CEA Speaker Allocation data block |
166 | */ | 166 | */ |
167 | static int eld_speaker_allocation_bits[] = { | 167 | static int eld_speaker_allocation_bits[] = { |
168 | [0] = FL | FR, | 168 | [0] = FL | FR, |
169 | [1] = LFE, | 169 | [1] = LFE, |
170 | [2] = FC, | 170 | [2] = FC, |
171 | [3] = RL | RR, | 171 | [3] = RL | RR, |
172 | [4] = RC, | 172 | [4] = RC, |
173 | [5] = FLC | FRC, | 173 | [5] = FLC | FRC, |
174 | [6] = RLC | RRC, | 174 | [6] = RLC | RRC, |
175 | /* the following are not defined in ELD yet */ | 175 | /* the following are not defined in ELD yet */ |
176 | [7] = FLW | FRW, | 176 | [7] = FLW | FRW, |
177 | [8] = FLH | FRH, | 177 | [8] = FLH | FRH, |
178 | [9] = TC, | 178 | [9] = TC, |
179 | [10] = FCH, | 179 | [10] = FCH, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | struct cea_channel_speaker_allocation { | 182 | struct cea_channel_speaker_allocation { |
183 | int ca_index; | 183 | int ca_index; |
184 | int speakers[8]; | 184 | int speakers[8]; |
185 | 185 | ||
186 | /* derived values, just for convenience */ | 186 | /* derived values, just for convenience */ |
187 | int channels; | 187 | int channels; |
188 | int spk_mask; | 188 | int spk_mask; |
189 | }; | 189 | }; |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * ALSA sequence is: | 192 | * ALSA sequence is: |
193 | * | 193 | * |
194 | * surround40 surround41 surround50 surround51 surround71 | 194 | * surround40 surround41 surround50 surround51 surround71 |
195 | * ch0 front left = = = = | 195 | * ch0 front left = = = = |
196 | * ch1 front right = = = = | 196 | * ch1 front right = = = = |
197 | * ch2 rear left = = = = | 197 | * ch2 rear left = = = = |
198 | * ch3 rear right = = = = | 198 | * ch3 rear right = = = = |
199 | * ch4 LFE center center center | 199 | * ch4 LFE center center center |
200 | * ch5 LFE LFE | 200 | * ch5 LFE LFE |
201 | * ch6 side left | 201 | * ch6 side left |
202 | * ch7 side right | 202 | * ch7 side right |
203 | * | 203 | * |
204 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} | 204 | * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} |
205 | */ | 205 | */ |
206 | static int hdmi_channel_mapping[0x32][8] = { | 206 | static int hdmi_channel_mapping[0x32][8] = { |
207 | /* stereo */ | 207 | /* stereo */ |
208 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | 208 | [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, |
209 | /* 2.1 */ | 209 | /* 2.1 */ |
210 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, | 210 | [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, |
211 | /* Dolby Surround */ | 211 | /* Dolby Surround */ |
212 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, | 212 | [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, |
213 | /* surround40 */ | 213 | /* surround40 */ |
214 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, | 214 | [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, |
215 | /* 4ch */ | 215 | /* 4ch */ |
216 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | 216 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, |
217 | /* surround41 */ | 217 | /* surround41 */ |
218 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, | 218 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, |
219 | /* surround50 */ | 219 | /* surround50 */ |
220 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | 220 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, |
221 | /* surround51 */ | 221 | /* surround51 */ |
222 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, | 222 | [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, |
223 | /* 7.1 */ | 223 | /* 7.1 */ |
224 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, | 224 | [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, |
225 | }; | 225 | }; |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * This is an ordered list! | 228 | * This is an ordered list! |
229 | * | 229 | * |
230 | * The preceding ones have better chances to be selected by | 230 | * The preceding ones have better chances to be selected by |
231 | * hdmi_channel_allocation(). | 231 | * hdmi_channel_allocation(). |
232 | */ | 232 | */ |
233 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 233 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
234 | /* channel: 7 6 5 4 3 2 1 0 */ | 234 | /* channel: 7 6 5 4 3 2 1 0 */ |
235 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, | 235 | { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, |
236 | /* 2.1 */ | 236 | /* 2.1 */ |
237 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, | 237 | { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, |
238 | /* Dolby Surround */ | 238 | /* Dolby Surround */ |
239 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, | 239 | { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, |
240 | /* surround40 */ | 240 | /* surround40 */ |
241 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, | 241 | { .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, |
242 | /* surround41 */ | 242 | /* surround41 */ |
243 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, | 243 | { .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, |
244 | /* surround50 */ | 244 | /* surround50 */ |
245 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, | 245 | { .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, |
246 | /* surround51 */ | 246 | /* surround51 */ |
247 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, | 247 | { .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, |
248 | /* 6.1 */ | 248 | /* 6.1 */ |
249 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, | 249 | { .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, |
250 | /* surround71 */ | 250 | /* surround71 */ |
251 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, | 251 | { .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, |
252 | 252 | ||
253 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, | 253 | { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, |
254 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, | 254 | { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, |
255 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, | 255 | { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, |
256 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, | 256 | { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, |
257 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, | 257 | { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, |
258 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, | 258 | { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, |
259 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, | 259 | { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, |
260 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, | 260 | { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, |
261 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, | 261 | { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, |
262 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, | 262 | { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, |
263 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, | 263 | { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, |
264 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, | 264 | { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, |
265 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, | 265 | { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, |
266 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, | 266 | { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, |
267 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, | 267 | { .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, |
268 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, | 268 | { .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, |
269 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, | 269 | { .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, |
270 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, | 270 | { .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, |
271 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, | 271 | { .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, |
272 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, | 272 | { .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, |
273 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, | 273 | { .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, |
274 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, | 274 | { .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, |
275 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, | 275 | { .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, |
276 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, | 276 | { .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, |
277 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, | 277 | { .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, |
278 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, | 278 | { .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, |
279 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, | 279 | { .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, |
280 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, | 280 | { .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, |
281 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, | 281 | { .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, |
282 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, | 282 | { .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, |
283 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, | 283 | { .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, |
284 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, | 284 | { .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, |
285 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, | 285 | { .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, |
286 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, | 286 | { .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, |
287 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, | 287 | { .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, |
288 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, | 288 | { .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, |
289 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, | 289 | { .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, |
290 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, | 290 | { .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, |
291 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, | 291 | { .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, |
292 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, | 292 | { .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, |
293 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, | 293 | { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, |
294 | }; | 294 | }; |
295 | 295 | ||
296 | 296 | ||
297 | /* | 297 | /* |
298 | * HDMI routines | 298 | * HDMI routines |
299 | */ | 299 | */ |
300 | 300 | ||
301 | static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid) | 301 | static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid) |
302 | { | 302 | { |
303 | int pin_idx; | 303 | int pin_idx; |
304 | 304 | ||
305 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) | 305 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) |
306 | if (spec->pins[pin_idx].pin_nid == pin_nid) | 306 | if (spec->pins[pin_idx].pin_nid == pin_nid) |
307 | return pin_idx; | 307 | return pin_idx; |
308 | 308 | ||
309 | snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid); | 309 | snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid); |
310 | return -EINVAL; | 310 | return -EINVAL; |
311 | } | 311 | } |
312 | 312 | ||
313 | static int hinfo_to_pin_index(struct hdmi_spec *spec, | 313 | static int hinfo_to_pin_index(struct hdmi_spec *spec, |
314 | struct hda_pcm_stream *hinfo) | 314 | struct hda_pcm_stream *hinfo) |
315 | { | 315 | { |
316 | int pin_idx; | 316 | int pin_idx; |
317 | 317 | ||
318 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) | 318 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) |
319 | if (&spec->pcm_rec[pin_idx].stream[0] == hinfo) | 319 | if (&spec->pcm_rec[pin_idx].stream[0] == hinfo) |
320 | return pin_idx; | 320 | return pin_idx; |
321 | 321 | ||
322 | snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo); | 322 | snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo); |
323 | return -EINVAL; | 323 | return -EINVAL; |
324 | } | 324 | } |
325 | 325 | ||
326 | static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid) | 326 | static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid) |
327 | { | 327 | { |
328 | int cvt_idx; | 328 | int cvt_idx; |
329 | 329 | ||
330 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) | 330 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) |
331 | if (spec->cvts[cvt_idx].cvt_nid == cvt_nid) | 331 | if (spec->cvts[cvt_idx].cvt_nid == cvt_nid) |
332 | return cvt_idx; | 332 | return cvt_idx; |
333 | 333 | ||
334 | snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid); | 334 | snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid); |
335 | return -EINVAL; | 335 | return -EINVAL; |
336 | } | 336 | } |
337 | 337 | ||
338 | static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, | 338 | static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, |
339 | struct snd_ctl_elem_info *uinfo) | 339 | struct snd_ctl_elem_info *uinfo) |
340 | { | 340 | { |
341 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 341 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
342 | struct hdmi_spec *spec; | 342 | struct hdmi_spec *spec; |
343 | int pin_idx; | 343 | int pin_idx; |
344 | 344 | ||
345 | spec = codec->spec; | 345 | spec = codec->spec; |
346 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | 346 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
347 | 347 | ||
348 | pin_idx = kcontrol->private_value; | 348 | pin_idx = kcontrol->private_value; |
349 | uinfo->count = spec->pins[pin_idx].sink_eld.eld_size; | 349 | uinfo->count = spec->pins[pin_idx].sink_eld.eld_size; |
350 | 350 | ||
351 | return 0; | 351 | return 0; |
352 | } | 352 | } |
353 | 353 | ||
354 | static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | 354 | static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, |
355 | struct snd_ctl_elem_value *ucontrol) | 355 | struct snd_ctl_elem_value *ucontrol) |
356 | { | 356 | { |
357 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 357 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
358 | struct hdmi_spec *spec; | 358 | struct hdmi_spec *spec; |
359 | int pin_idx; | 359 | int pin_idx; |
360 | 360 | ||
361 | spec = codec->spec; | 361 | spec = codec->spec; |
362 | pin_idx = kcontrol->private_value; | 362 | pin_idx = kcontrol->private_value; |
363 | 363 | ||
364 | memcpy(ucontrol->value.bytes.data, | 364 | memcpy(ucontrol->value.bytes.data, |
365 | spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE); | 365 | spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE); |
366 | 366 | ||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | static struct snd_kcontrol_new eld_bytes_ctl = { | 370 | static struct snd_kcontrol_new eld_bytes_ctl = { |
371 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, | 371 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
372 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 372 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
373 | .name = "ELD", | 373 | .name = "ELD", |
374 | .info = hdmi_eld_ctl_info, | 374 | .info = hdmi_eld_ctl_info, |
375 | .get = hdmi_eld_ctl_get, | 375 | .get = hdmi_eld_ctl_get, |
376 | }; | 376 | }; |
377 | 377 | ||
378 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, | 378 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, |
379 | int device) | 379 | int device) |
380 | { | 380 | { |
381 | struct snd_kcontrol *kctl; | 381 | struct snd_kcontrol *kctl; |
382 | struct hdmi_spec *spec = codec->spec; | 382 | struct hdmi_spec *spec = codec->spec; |
383 | int err; | 383 | int err; |
384 | 384 | ||
385 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); | 385 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); |
386 | if (!kctl) | 386 | if (!kctl) |
387 | return -ENOMEM; | 387 | return -ENOMEM; |
388 | kctl->private_value = pin_idx; | 388 | kctl->private_value = pin_idx; |
389 | kctl->id.device = device; | 389 | kctl->id.device = device; |
390 | 390 | ||
391 | err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl); | 391 | err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl); |
392 | if (err < 0) | 392 | if (err < 0) |
393 | return err; | 393 | return err; |
394 | 394 | ||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
397 | 397 | ||
398 | #ifdef BE_PARANOID | 398 | #ifdef BE_PARANOID |
399 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | 399 | static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, |
400 | int *packet_index, int *byte_index) | 400 | int *packet_index, int *byte_index) |
401 | { | 401 | { |
402 | int val; | 402 | int val; |
403 | 403 | ||
404 | val = snd_hda_codec_read(codec, pin_nid, 0, | 404 | val = snd_hda_codec_read(codec, pin_nid, 0, |
405 | AC_VERB_GET_HDMI_DIP_INDEX, 0); | 405 | AC_VERB_GET_HDMI_DIP_INDEX, 0); |
406 | 406 | ||
407 | *packet_index = val >> 5; | 407 | *packet_index = val >> 5; |
408 | *byte_index = val & 0x1f; | 408 | *byte_index = val & 0x1f; |
409 | } | 409 | } |
410 | #endif | 410 | #endif |
411 | 411 | ||
412 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, | 412 | static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, |
413 | int packet_index, int byte_index) | 413 | int packet_index, int byte_index) |
414 | { | 414 | { |
415 | int val; | 415 | int val; |
416 | 416 | ||
417 | val = (packet_index << 5) | (byte_index & 0x1f); | 417 | val = (packet_index << 5) | (byte_index & 0x1f); |
418 | 418 | ||
419 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); | 419 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); |
420 | } | 420 | } |
421 | 421 | ||
422 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, | 422 | static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, |
423 | unsigned char val) | 423 | unsigned char val) |
424 | { | 424 | { |
425 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); | 425 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); |
426 | } | 426 | } |
427 | 427 | ||
428 | static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) | 428 | static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid) |
429 | { | 429 | { |
430 | /* Unmute */ | 430 | /* Unmute */ |
431 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) | 431 | if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) |
432 | snd_hda_codec_write(codec, pin_nid, 0, | 432 | snd_hda_codec_write(codec, pin_nid, 0, |
433 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | 433 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); |
434 | /* Enable pin out: some machines with GM965 gets broken output when | 434 | /* Enable pin out: some machines with GM965 gets broken output when |
435 | * the pin is disabled or changed while using with HDMI | 435 | * the pin is disabled or changed while using with HDMI |
436 | */ | 436 | */ |
437 | snd_hda_codec_write(codec, pin_nid, 0, | 437 | snd_hda_codec_write(codec, pin_nid, 0, |
438 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 438 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
439 | } | 439 | } |
440 | 440 | ||
441 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) | 441 | static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid) |
442 | { | 442 | { |
443 | return 1 + snd_hda_codec_read(codec, cvt_nid, 0, | 443 | return 1 + snd_hda_codec_read(codec, cvt_nid, 0, |
444 | AC_VERB_GET_CVT_CHAN_COUNT, 0); | 444 | AC_VERB_GET_CVT_CHAN_COUNT, 0); |
445 | } | 445 | } |
446 | 446 | ||
447 | static void hdmi_set_channel_count(struct hda_codec *codec, | 447 | static void hdmi_set_channel_count(struct hda_codec *codec, |
448 | hda_nid_t cvt_nid, int chs) | 448 | hda_nid_t cvt_nid, int chs) |
449 | { | 449 | { |
450 | if (chs != hdmi_get_channel_count(codec, cvt_nid)) | 450 | if (chs != hdmi_get_channel_count(codec, cvt_nid)) |
451 | snd_hda_codec_write(codec, cvt_nid, 0, | 451 | snd_hda_codec_write(codec, cvt_nid, 0, |
452 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); | 452 | AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); |
453 | } | 453 | } |
454 | 454 | ||
455 | 455 | ||
456 | /* | 456 | /* |
457 | * Channel mapping routines | 457 | * Channel mapping routines |
458 | */ | 458 | */ |
459 | 459 | ||
460 | /* | 460 | /* |
461 | * Compute derived values in channel_allocations[]. | 461 | * Compute derived values in channel_allocations[]. |
462 | */ | 462 | */ |
463 | static void init_channel_allocations(void) | 463 | static void init_channel_allocations(void) |
464 | { | 464 | { |
465 | int i, j; | 465 | int i, j; |
466 | struct cea_channel_speaker_allocation *p; | 466 | struct cea_channel_speaker_allocation *p; |
467 | 467 | ||
468 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 468 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
469 | p = channel_allocations + i; | 469 | p = channel_allocations + i; |
470 | p->channels = 0; | 470 | p->channels = 0; |
471 | p->spk_mask = 0; | 471 | p->spk_mask = 0; |
472 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) | 472 | for (j = 0; j < ARRAY_SIZE(p->speakers); j++) |
473 | if (p->speakers[j]) { | 473 | if (p->speakers[j]) { |
474 | p->channels++; | 474 | p->channels++; |
475 | p->spk_mask |= p->speakers[j]; | 475 | p->spk_mask |= p->speakers[j]; |
476 | } | 476 | } |
477 | } | 477 | } |
478 | } | 478 | } |
479 | 479 | ||
480 | static int get_channel_allocation_order(int ca) | 480 | static int get_channel_allocation_order(int ca) |
481 | { | 481 | { |
482 | int i; | 482 | int i; |
483 | 483 | ||
484 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 484 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
485 | if (channel_allocations[i].ca_index == ca) | 485 | if (channel_allocations[i].ca_index == ca) |
486 | break; | 486 | break; |
487 | } | 487 | } |
488 | return i; | 488 | return i; |
489 | } | 489 | } |
490 | 490 | ||
491 | /* | 491 | /* |
492 | * The transformation takes two steps: | 492 | * The transformation takes two steps: |
493 | * | 493 | * |
494 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask | 494 | * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask |
495 | * spk_mask => (channel_allocations[]) => ai->CA | 495 | * spk_mask => (channel_allocations[]) => ai->CA |
496 | * | 496 | * |
497 | * TODO: it could select the wrong CA from multiple candidates. | 497 | * TODO: it could select the wrong CA from multiple candidates. |
498 | */ | 498 | */ |
499 | static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) | 499 | static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels) |
500 | { | 500 | { |
501 | int i; | 501 | int i; |
502 | int ca = 0; | 502 | int ca = 0; |
503 | int spk_mask = 0; | 503 | int spk_mask = 0; |
504 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 504 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
505 | 505 | ||
506 | /* | 506 | /* |
507 | * CA defaults to 0 for basic stereo audio | 507 | * CA defaults to 0 for basic stereo audio |
508 | */ | 508 | */ |
509 | if (channels <= 2) | 509 | if (channels <= 2) |
510 | return 0; | 510 | return 0; |
511 | 511 | ||
512 | /* | 512 | /* |
513 | * expand ELD's speaker allocation mask | 513 | * expand ELD's speaker allocation mask |
514 | * | 514 | * |
515 | * ELD tells the speaker mask in a compact(paired) form, | 515 | * ELD tells the speaker mask in a compact(paired) form, |
516 | * expand ELD's notions to match the ones used by Audio InfoFrame. | 516 | * expand ELD's notions to match the ones used by Audio InfoFrame. |
517 | */ | 517 | */ |
518 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { | 518 | for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { |
519 | if (eld->spk_alloc & (1 << i)) | 519 | if (eld->spk_alloc & (1 << i)) |
520 | spk_mask |= eld_speaker_allocation_bits[i]; | 520 | spk_mask |= eld_speaker_allocation_bits[i]; |
521 | } | 521 | } |
522 | 522 | ||
523 | /* search for the first working match in the CA table */ | 523 | /* search for the first working match in the CA table */ |
524 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 524 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
525 | if (channels == channel_allocations[i].channels && | 525 | if (channels == channel_allocations[i].channels && |
526 | (spk_mask & channel_allocations[i].spk_mask) == | 526 | (spk_mask & channel_allocations[i].spk_mask) == |
527 | channel_allocations[i].spk_mask) { | 527 | channel_allocations[i].spk_mask) { |
528 | ca = channel_allocations[i].ca_index; | 528 | ca = channel_allocations[i].ca_index; |
529 | break; | 529 | break; |
530 | } | 530 | } |
531 | } | 531 | } |
532 | 532 | ||
533 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | 533 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); |
534 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 534 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
535 | ca, channels, buf); | 535 | ca, channels, buf); |
536 | 536 | ||
537 | return ca; | 537 | return ca; |
538 | } | 538 | } |
539 | 539 | ||
540 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | 540 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
541 | hda_nid_t pin_nid) | 541 | hda_nid_t pin_nid) |
542 | { | 542 | { |
543 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 543 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
544 | int i; | 544 | int i; |
545 | int slot; | 545 | int slot; |
546 | 546 | ||
547 | for (i = 0; i < 8; i++) { | 547 | for (i = 0; i < 8; i++) { |
548 | slot = snd_hda_codec_read(codec, pin_nid, 0, | 548 | slot = snd_hda_codec_read(codec, pin_nid, 0, |
549 | AC_VERB_GET_HDMI_CHAN_SLOT, i); | 549 | AC_VERB_GET_HDMI_CHAN_SLOT, i); |
550 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", | 550 | printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", |
551 | slot >> 4, slot & 0xf); | 551 | slot >> 4, slot & 0xf); |
552 | } | 552 | } |
553 | #endif | 553 | #endif |
554 | } | 554 | } |
555 | 555 | ||
556 | 556 | ||
557 | static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, | 557 | static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, |
558 | hda_nid_t pin_nid, | 558 | hda_nid_t pin_nid, |
559 | bool non_pcm, | 559 | bool non_pcm, |
560 | int ca) | 560 | int ca) |
561 | { | 561 | { |
562 | int i; | 562 | int i; |
563 | int err; | 563 | int err; |
564 | int order; | 564 | int order; |
565 | int non_pcm_mapping[8]; | 565 | int non_pcm_mapping[8]; |
566 | 566 | ||
567 | order = get_channel_allocation_order(ca); | 567 | order = get_channel_allocation_order(ca); |
568 | 568 | ||
569 | if (hdmi_channel_mapping[ca][1] == 0) { | 569 | if (hdmi_channel_mapping[ca][1] == 0) { |
570 | for (i = 0; i < channel_allocations[order].channels; i++) | 570 | for (i = 0; i < channel_allocations[order].channels; i++) |
571 | hdmi_channel_mapping[ca][i] = i | (i << 4); | 571 | hdmi_channel_mapping[ca][i] = i | (i << 4); |
572 | for (; i < 8; i++) | 572 | for (; i < 8; i++) |
573 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | 573 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); |
574 | } | 574 | } |
575 | 575 | ||
576 | if (non_pcm) { | 576 | if (non_pcm) { |
577 | for (i = 0; i < channel_allocations[order].channels; i++) | 577 | for (i = 0; i < channel_allocations[order].channels; i++) |
578 | non_pcm_mapping[i] = i | (i << 4); | 578 | non_pcm_mapping[i] = i | (i << 4); |
579 | for (; i < 8; i++) | 579 | for (; i < 8; i++) |
580 | non_pcm_mapping[i] = 0xf | (i << 4); | 580 | non_pcm_mapping[i] = 0xf | (i << 4); |
581 | } | 581 | } |
582 | 582 | ||
583 | for (i = 0; i < 8; i++) { | 583 | for (i = 0; i < 8; i++) { |
584 | err = snd_hda_codec_write(codec, pin_nid, 0, | 584 | err = snd_hda_codec_write(codec, pin_nid, 0, |
585 | AC_VERB_SET_HDMI_CHAN_SLOT, | 585 | AC_VERB_SET_HDMI_CHAN_SLOT, |
586 | non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]); | 586 | non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]); |
587 | if (err) { | 587 | if (err) { |
588 | snd_printdd(KERN_NOTICE | 588 | snd_printdd(KERN_NOTICE |
589 | "HDMI: channel mapping failed\n"); | 589 | "HDMI: channel mapping failed\n"); |
590 | break; | 590 | break; |
591 | } | 591 | } |
592 | } | 592 | } |
593 | 593 | ||
594 | hdmi_debug_channel_mapping(codec, pin_nid); | 594 | hdmi_debug_channel_mapping(codec, pin_nid); |
595 | } | 595 | } |
596 | 596 | ||
597 | struct channel_map_table { | 597 | struct channel_map_table { |
598 | unsigned char map; /* ALSA API channel map position */ | 598 | unsigned char map; /* ALSA API channel map position */ |
599 | unsigned char cea_slot; /* CEA slot value */ | 599 | unsigned char cea_slot; /* CEA slot value */ |
600 | int spk_mask; /* speaker position bit mask */ | 600 | int spk_mask; /* speaker position bit mask */ |
601 | }; | 601 | }; |
602 | 602 | ||
603 | static struct channel_map_table map_tables[] = { | 603 | static struct channel_map_table map_tables[] = { |
604 | { SNDRV_CHMAP_FL, 0x00, FL }, | 604 | { SNDRV_CHMAP_FL, 0x00, FL }, |
605 | { SNDRV_CHMAP_FR, 0x01, FR }, | 605 | { SNDRV_CHMAP_FR, 0x01, FR }, |
606 | { SNDRV_CHMAP_RL, 0x04, RL }, | 606 | { SNDRV_CHMAP_RL, 0x04, RL }, |
607 | { SNDRV_CHMAP_RR, 0x05, RR }, | 607 | { SNDRV_CHMAP_RR, 0x05, RR }, |
608 | { SNDRV_CHMAP_LFE, 0x02, LFE }, | 608 | { SNDRV_CHMAP_LFE, 0x02, LFE }, |
609 | { SNDRV_CHMAP_FC, 0x03, FC }, | 609 | { SNDRV_CHMAP_FC, 0x03, FC }, |
610 | { SNDRV_CHMAP_RLC, 0x06, RLC }, | 610 | { SNDRV_CHMAP_RLC, 0x06, RLC }, |
611 | { SNDRV_CHMAP_RRC, 0x07, RRC }, | 611 | { SNDRV_CHMAP_RRC, 0x07, RRC }, |
612 | {} /* terminator */ | 612 | {} /* terminator */ |
613 | }; | 613 | }; |
614 | 614 | ||
615 | /* from ALSA API channel position to speaker bit mask */ | 615 | /* from ALSA API channel position to speaker bit mask */ |
616 | static int to_spk_mask(unsigned char c) | 616 | static int to_spk_mask(unsigned char c) |
617 | { | 617 | { |
618 | struct channel_map_table *t = map_tables; | 618 | struct channel_map_table *t = map_tables; |
619 | for (; t->map; t++) { | 619 | for (; t->map; t++) { |
620 | if (t->map == c) | 620 | if (t->map == c) |
621 | return t->spk_mask; | 621 | return t->spk_mask; |
622 | } | 622 | } |
623 | return 0; | 623 | return 0; |
624 | } | 624 | } |
625 | 625 | ||
626 | /* from ALSA API channel position to CEA slot */ | 626 | /* from ALSA API channel position to CEA slot */ |
627 | static int to_cea_slot(unsigned char c) | 627 | static int to_cea_slot(unsigned char c) |
628 | { | 628 | { |
629 | struct channel_map_table *t = map_tables; | 629 | struct channel_map_table *t = map_tables; |
630 | for (; t->map; t++) { | 630 | for (; t->map; t++) { |
631 | if (t->map == c) | 631 | if (t->map == c) |
632 | return t->cea_slot; | 632 | return t->cea_slot; |
633 | } | 633 | } |
634 | return 0x0f; | 634 | return 0x0f; |
635 | } | 635 | } |
636 | 636 | ||
637 | /* from CEA slot to ALSA API channel position */ | 637 | /* from CEA slot to ALSA API channel position */ |
638 | static int from_cea_slot(unsigned char c) | 638 | static int from_cea_slot(unsigned char c) |
639 | { | 639 | { |
640 | struct channel_map_table *t = map_tables; | 640 | struct channel_map_table *t = map_tables; |
641 | for (; t->map; t++) { | 641 | for (; t->map; t++) { |
642 | if (t->cea_slot == c) | 642 | if (t->cea_slot == c) |
643 | return t->map; | 643 | return t->map; |
644 | } | 644 | } |
645 | return 0; | 645 | return 0; |
646 | } | 646 | } |
647 | 647 | ||
648 | /* from speaker bit mask to ALSA API channel position */ | 648 | /* from speaker bit mask to ALSA API channel position */ |
649 | static int spk_to_chmap(int spk) | 649 | static int spk_to_chmap(int spk) |
650 | { | 650 | { |
651 | struct channel_map_table *t = map_tables; | 651 | struct channel_map_table *t = map_tables; |
652 | for (; t->map; t++) { | 652 | for (; t->map; t++) { |
653 | if (t->spk_mask == spk) | 653 | if (t->spk_mask == spk) |
654 | return t->map; | 654 | return t->map; |
655 | } | 655 | } |
656 | return 0; | 656 | return 0; |
657 | } | 657 | } |
658 | 658 | ||
659 | /* get the CA index corresponding to the given ALSA API channel map */ | 659 | /* get the CA index corresponding to the given ALSA API channel map */ |
660 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) | 660 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) |
661 | { | 661 | { |
662 | int i, spks = 0, spk_mask = 0; | 662 | int i, spks = 0, spk_mask = 0; |
663 | 663 | ||
664 | for (i = 0; i < chs; i++) { | 664 | for (i = 0; i < chs; i++) { |
665 | int mask = to_spk_mask(map[i]); | 665 | int mask = to_spk_mask(map[i]); |
666 | if (mask) { | 666 | if (mask) { |
667 | spk_mask |= mask; | 667 | spk_mask |= mask; |
668 | spks++; | 668 | spks++; |
669 | } | 669 | } |
670 | } | 670 | } |
671 | 671 | ||
672 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | 672 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { |
673 | if ((chs == channel_allocations[i].channels || | 673 | if ((chs == channel_allocations[i].channels || |
674 | spks == channel_allocations[i].channels) && | 674 | spks == channel_allocations[i].channels) && |
675 | (spk_mask & channel_allocations[i].spk_mask) == | 675 | (spk_mask & channel_allocations[i].spk_mask) == |
676 | channel_allocations[i].spk_mask) | 676 | channel_allocations[i].spk_mask) |
677 | return channel_allocations[i].ca_index; | 677 | return channel_allocations[i].ca_index; |
678 | } | 678 | } |
679 | return -1; | 679 | return -1; |
680 | } | 680 | } |
681 | 681 | ||
682 | /* set up the channel slots for the given ALSA API channel map */ | 682 | /* set up the channel slots for the given ALSA API channel map */ |
683 | static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, | 683 | static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, |
684 | hda_nid_t pin_nid, | 684 | hda_nid_t pin_nid, |
685 | int chs, unsigned char *map) | 685 | int chs, unsigned char *map) |
686 | { | 686 | { |
687 | int i; | 687 | int i; |
688 | for (i = 0; i < 8; i++) { | 688 | for (i = 0; i < 8; i++) { |
689 | int val, err; | 689 | int val, err; |
690 | if (i < chs) | 690 | if (i < chs) |
691 | val = to_cea_slot(map[i]); | 691 | val = to_cea_slot(map[i]); |
692 | else | 692 | else |
693 | val = 0xf; | 693 | val = 0xf; |
694 | val |= (i << 4); | 694 | val |= (i << 4); |
695 | err = snd_hda_codec_write(codec, pin_nid, 0, | 695 | err = snd_hda_codec_write(codec, pin_nid, 0, |
696 | AC_VERB_SET_HDMI_CHAN_SLOT, val); | 696 | AC_VERB_SET_HDMI_CHAN_SLOT, val); |
697 | if (err) | 697 | if (err) |
698 | return -EINVAL; | 698 | return -EINVAL; |
699 | } | 699 | } |
700 | return 0; | 700 | return 0; |
701 | } | 701 | } |
702 | 702 | ||
703 | /* store ALSA API channel map from the current default map */ | 703 | /* store ALSA API channel map from the current default map */ |
704 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) | 704 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) |
705 | { | 705 | { |
706 | int i; | 706 | int i; |
707 | for (i = 0; i < 8; i++) { | 707 | for (i = 0; i < 8; i++) { |
708 | if (i < channel_allocations[ca].channels) | 708 | if (i < channel_allocations[ca].channels) |
709 | map[i] = from_cea_slot((hdmi_channel_mapping[ca][i] >> 4) & 0x0f); | 709 | map[i] = from_cea_slot((hdmi_channel_mapping[ca][i] >> 4) & 0x0f); |
710 | else | 710 | else |
711 | map[i] = 0; | 711 | map[i] = 0; |
712 | } | 712 | } |
713 | } | 713 | } |
714 | 714 | ||
715 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 715 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
716 | hda_nid_t pin_nid, bool non_pcm, int ca, | 716 | hda_nid_t pin_nid, bool non_pcm, int ca, |
717 | int channels, unsigned char *map) | 717 | int channels, unsigned char *map) |
718 | { | 718 | { |
719 | if (!non_pcm && map) { | 719 | if (!non_pcm && map) { |
720 | hdmi_manual_setup_channel_mapping(codec, pin_nid, | 720 | hdmi_manual_setup_channel_mapping(codec, pin_nid, |
721 | channels, map); | 721 | channels, map); |
722 | } else { | 722 | } else { |
723 | hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); | 723 | hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); |
724 | hdmi_setup_fake_chmap(map, ca); | 724 | hdmi_setup_fake_chmap(map, ca); |
725 | } | 725 | } |
726 | } | 726 | } |
727 | 727 | ||
728 | /* | 728 | /* |
729 | * Audio InfoFrame routines | 729 | * Audio InfoFrame routines |
730 | */ | 730 | */ |
731 | 731 | ||
732 | /* | 732 | /* |
733 | * Enable Audio InfoFrame Transmission | 733 | * Enable Audio InfoFrame Transmission |
734 | */ | 734 | */ |
735 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, | 735 | static void hdmi_start_infoframe_trans(struct hda_codec *codec, |
736 | hda_nid_t pin_nid) | 736 | hda_nid_t pin_nid) |
737 | { | 737 | { |
738 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 738 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
739 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | 739 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, |
740 | AC_DIPXMIT_BEST); | 740 | AC_DIPXMIT_BEST); |
741 | } | 741 | } |
742 | 742 | ||
743 | /* | 743 | /* |
744 | * Disable Audio InfoFrame Transmission | 744 | * Disable Audio InfoFrame Transmission |
745 | */ | 745 | */ |
746 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, | 746 | static void hdmi_stop_infoframe_trans(struct hda_codec *codec, |
747 | hda_nid_t pin_nid) | 747 | hda_nid_t pin_nid) |
748 | { | 748 | { |
749 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 749 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
750 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, | 750 | snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, |
751 | AC_DIPXMIT_DISABLE); | 751 | AC_DIPXMIT_DISABLE); |
752 | } | 752 | } |
753 | 753 | ||
754 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) | 754 | static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) |
755 | { | 755 | { |
756 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 756 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
757 | int i; | 757 | int i; |
758 | int size; | 758 | int size; |
759 | 759 | ||
760 | size = snd_hdmi_get_eld_size(codec, pin_nid); | 760 | size = snd_hdmi_get_eld_size(codec, pin_nid); |
761 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); | 761 | printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); |
762 | 762 | ||
763 | for (i = 0; i < 8; i++) { | 763 | for (i = 0; i < 8; i++) { |
764 | size = snd_hda_codec_read(codec, pin_nid, 0, | 764 | size = snd_hda_codec_read(codec, pin_nid, 0, |
765 | AC_VERB_GET_HDMI_DIP_SIZE, i); | 765 | AC_VERB_GET_HDMI_DIP_SIZE, i); |
766 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); | 766 | printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); |
767 | } | 767 | } |
768 | #endif | 768 | #endif |
769 | } | 769 | } |
770 | 770 | ||
771 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | 771 | static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) |
772 | { | 772 | { |
773 | #ifdef BE_PARANOID | 773 | #ifdef BE_PARANOID |
774 | int i, j; | 774 | int i, j; |
775 | int size; | 775 | int size; |
776 | int pi, bi; | 776 | int pi, bi; |
777 | for (i = 0; i < 8; i++) { | 777 | for (i = 0; i < 8; i++) { |
778 | size = snd_hda_codec_read(codec, pin_nid, 0, | 778 | size = snd_hda_codec_read(codec, pin_nid, 0, |
779 | AC_VERB_GET_HDMI_DIP_SIZE, i); | 779 | AC_VERB_GET_HDMI_DIP_SIZE, i); |
780 | if (size == 0) | 780 | if (size == 0) |
781 | continue; | 781 | continue; |
782 | 782 | ||
783 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); | 783 | hdmi_set_dip_index(codec, pin_nid, i, 0x0); |
784 | for (j = 1; j < 1000; j++) { | 784 | for (j = 1; j < 1000; j++) { |
785 | hdmi_write_dip_byte(codec, pin_nid, 0x0); | 785 | hdmi_write_dip_byte(codec, pin_nid, 0x0); |
786 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); | 786 | hdmi_get_dip_index(codec, pin_nid, &pi, &bi); |
787 | if (pi != i) | 787 | if (pi != i) |
788 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", | 788 | snd_printd(KERN_INFO "dip index %d: %d != %d\n", |
789 | bi, pi, i); | 789 | bi, pi, i); |
790 | if (bi == 0) /* byte index wrapped around */ | 790 | if (bi == 0) /* byte index wrapped around */ |
791 | break; | 791 | break; |
792 | } | 792 | } |
793 | snd_printd(KERN_INFO | 793 | snd_printd(KERN_INFO |
794 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", | 794 | "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", |
795 | i, size, j); | 795 | i, size, j); |
796 | } | 796 | } |
797 | #endif | 797 | #endif |
798 | } | 798 | } |
799 | 799 | ||
800 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) | 800 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) |
801 | { | 801 | { |
802 | u8 *bytes = (u8 *)hdmi_ai; | 802 | u8 *bytes = (u8 *)hdmi_ai; |
803 | u8 sum = 0; | 803 | u8 sum = 0; |
804 | int i; | 804 | int i; |
805 | 805 | ||
806 | hdmi_ai->checksum = 0; | 806 | hdmi_ai->checksum = 0; |
807 | 807 | ||
808 | for (i = 0; i < sizeof(*hdmi_ai); i++) | 808 | for (i = 0; i < sizeof(*hdmi_ai); i++) |
809 | sum += bytes[i]; | 809 | sum += bytes[i]; |
810 | 810 | ||
811 | hdmi_ai->checksum = -sum; | 811 | hdmi_ai->checksum = -sum; |
812 | } | 812 | } |
813 | 813 | ||
814 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | 814 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, |
815 | hda_nid_t pin_nid, | 815 | hda_nid_t pin_nid, |
816 | u8 *dip, int size) | 816 | u8 *dip, int size) |
817 | { | 817 | { |
818 | int i; | 818 | int i; |
819 | 819 | ||
820 | hdmi_debug_dip_size(codec, pin_nid); | 820 | hdmi_debug_dip_size(codec, pin_nid); |
821 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | 821 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ |
822 | 822 | ||
823 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 823 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
824 | for (i = 0; i < size; i++) | 824 | for (i = 0; i < size; i++) |
825 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); | 825 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); |
826 | } | 826 | } |
827 | 827 | ||
828 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 828 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
829 | u8 *dip, int size) | 829 | u8 *dip, int size) |
830 | { | 830 | { |
831 | u8 val; | 831 | u8 val; |
832 | int i; | 832 | int i; |
833 | 833 | ||
834 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) | 834 | if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) |
835 | != AC_DIPXMIT_BEST) | 835 | != AC_DIPXMIT_BEST) |
836 | return false; | 836 | return false; |
837 | 837 | ||
838 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 838 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
839 | for (i = 0; i < size; i++) { | 839 | for (i = 0; i < size; i++) { |
840 | val = snd_hda_codec_read(codec, pin_nid, 0, | 840 | val = snd_hda_codec_read(codec, pin_nid, 0, |
841 | AC_VERB_GET_HDMI_DIP_DATA, 0); | 841 | AC_VERB_GET_HDMI_DIP_DATA, 0); |
842 | if (val != dip[i]) | 842 | if (val != dip[i]) |
843 | return false; | 843 | return false; |
844 | } | 844 | } |
845 | 845 | ||
846 | return true; | 846 | return true; |
847 | } | 847 | } |
848 | 848 | ||
849 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | 849 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, |
850 | bool non_pcm, | 850 | bool non_pcm, |
851 | struct snd_pcm_substream *substream) | 851 | struct snd_pcm_substream *substream) |
852 | { | 852 | { |
853 | struct hdmi_spec *spec = codec->spec; | 853 | struct hdmi_spec *spec = codec->spec; |
854 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 854 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
855 | hda_nid_t pin_nid = per_pin->pin_nid; | 855 | hda_nid_t pin_nid = per_pin->pin_nid; |
856 | int channels = substream->runtime->channels; | 856 | int channels = substream->runtime->channels; |
857 | struct hdmi_eld *eld; | 857 | struct hdmi_eld *eld; |
858 | int ca; | 858 | int ca; |
859 | union audio_infoframe ai; | 859 | union audio_infoframe ai; |
860 | 860 | ||
861 | eld = &spec->pins[pin_idx].sink_eld; | 861 | eld = &spec->pins[pin_idx].sink_eld; |
862 | if (!eld->monitor_present) | 862 | if (!eld->monitor_present) |
863 | return; | 863 | return; |
864 | 864 | ||
865 | if (!non_pcm && per_pin->chmap_set) | 865 | if (!non_pcm && per_pin->chmap_set) |
866 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | 866 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); |
867 | else | 867 | else |
868 | ca = hdmi_channel_allocation(eld, channels); | 868 | ca = hdmi_channel_allocation(eld, channels); |
869 | if (ca < 0) | 869 | if (ca < 0) |
870 | ca = 0; | 870 | ca = 0; |
871 | 871 | ||
872 | memset(&ai, 0, sizeof(ai)); | 872 | memset(&ai, 0, sizeof(ai)); |
873 | if (eld->conn_type == 0) { /* HDMI */ | 873 | if (eld->conn_type == 0) { /* HDMI */ |
874 | struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; | 874 | struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; |
875 | 875 | ||
876 | hdmi_ai->type = 0x84; | 876 | hdmi_ai->type = 0x84; |
877 | hdmi_ai->ver = 0x01; | 877 | hdmi_ai->ver = 0x01; |
878 | hdmi_ai->len = 0x0a; | 878 | hdmi_ai->len = 0x0a; |
879 | hdmi_ai->CC02_CT47 = channels - 1; | 879 | hdmi_ai->CC02_CT47 = channels - 1; |
880 | hdmi_ai->CA = ca; | 880 | hdmi_ai->CA = ca; |
881 | hdmi_checksum_audio_infoframe(hdmi_ai); | 881 | hdmi_checksum_audio_infoframe(hdmi_ai); |
882 | } else if (eld->conn_type == 1) { /* DisplayPort */ | 882 | } else if (eld->conn_type == 1) { /* DisplayPort */ |
883 | struct dp_audio_infoframe *dp_ai = &ai.dp; | 883 | struct dp_audio_infoframe *dp_ai = &ai.dp; |
884 | 884 | ||
885 | dp_ai->type = 0x84; | 885 | dp_ai->type = 0x84; |
886 | dp_ai->len = 0x1b; | 886 | dp_ai->len = 0x1b; |
887 | dp_ai->ver = 0x11 << 2; | 887 | dp_ai->ver = 0x11 << 2; |
888 | dp_ai->CC02_CT47 = channels - 1; | 888 | dp_ai->CC02_CT47 = channels - 1; |
889 | dp_ai->CA = ca; | 889 | dp_ai->CA = ca; |
890 | } else { | 890 | } else { |
891 | snd_printd("HDMI: unknown connection type at pin %d\n", | 891 | snd_printd("HDMI: unknown connection type at pin %d\n", |
892 | pin_nid); | 892 | pin_nid); |
893 | return; | 893 | return; |
894 | } | 894 | } |
895 | 895 | ||
896 | /* | 896 | /* |
897 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or | 897 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or |
898 | * sizeof(*dp_ai) to avoid partial match/update problems when | 898 | * sizeof(*dp_ai) to avoid partial match/update problems when |
899 | * the user switches between HDMI/DP monitors. | 899 | * the user switches between HDMI/DP monitors. |
900 | */ | 900 | */ |
901 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, | 901 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, |
902 | sizeof(ai))) { | 902 | sizeof(ai))) { |
903 | snd_printdd("hdmi_setup_audio_infoframe: " | 903 | snd_printdd("hdmi_setup_audio_infoframe: " |
904 | "pin=%d channels=%d\n", | 904 | "pin=%d channels=%d\n", |
905 | pin_nid, | 905 | pin_nid, |
906 | channels); | 906 | channels); |
907 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | 907 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
908 | channels, per_pin->chmap); | 908 | channels, per_pin->chmap); |
909 | hdmi_stop_infoframe_trans(codec, pin_nid); | 909 | hdmi_stop_infoframe_trans(codec, pin_nid); |
910 | hdmi_fill_audio_infoframe(codec, pin_nid, | 910 | hdmi_fill_audio_infoframe(codec, pin_nid, |
911 | ai.bytes, sizeof(ai)); | 911 | ai.bytes, sizeof(ai)); |
912 | hdmi_start_infoframe_trans(codec, pin_nid); | 912 | hdmi_start_infoframe_trans(codec, pin_nid); |
913 | } else { | 913 | } else { |
914 | /* For non-pcm audio switch, setup new channel mapping | 914 | /* For non-pcm audio switch, setup new channel mapping |
915 | * accordingly */ | 915 | * accordingly */ |
916 | if (per_pin->non_pcm != non_pcm) | 916 | if (per_pin->non_pcm != non_pcm) |
917 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | 917 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
918 | channels, per_pin->chmap); | 918 | channels, per_pin->chmap); |
919 | } | 919 | } |
920 | 920 | ||
921 | per_pin->non_pcm = non_pcm; | 921 | per_pin->non_pcm = non_pcm; |
922 | } | 922 | } |
923 | 923 | ||
924 | 924 | ||
925 | /* | 925 | /* |
926 | * Unsolicited events | 926 | * Unsolicited events |
927 | */ | 927 | */ |
928 | 928 | ||
929 | static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); | 929 | static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); |
930 | 930 | ||
931 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 931 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) |
932 | { | 932 | { |
933 | struct hdmi_spec *spec = codec->spec; | 933 | struct hdmi_spec *spec = codec->spec; |
934 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 934 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
935 | int pin_nid; | 935 | int pin_nid; |
936 | int pin_idx; | 936 | int pin_idx; |
937 | struct hda_jack_tbl *jack; | 937 | struct hda_jack_tbl *jack; |
938 | 938 | ||
939 | jack = snd_hda_jack_tbl_get_from_tag(codec, tag); | 939 | jack = snd_hda_jack_tbl_get_from_tag(codec, tag); |
940 | if (!jack) | 940 | if (!jack) |
941 | return; | 941 | return; |
942 | pin_nid = jack->nid; | 942 | pin_nid = jack->nid; |
943 | jack->jack_dirty = 1; | 943 | jack->jack_dirty = 1; |
944 | 944 | ||
945 | _snd_printd(SND_PR_VERBOSE, | 945 | _snd_printd(SND_PR_VERBOSE, |
946 | "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | 946 | "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", |
947 | codec->addr, pin_nid, | 947 | codec->addr, pin_nid, |
948 | !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); | 948 | !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); |
949 | 949 | ||
950 | pin_idx = pin_nid_to_pin_index(spec, pin_nid); | 950 | pin_idx = pin_nid_to_pin_index(spec, pin_nid); |
951 | if (pin_idx < 0) | 951 | if (pin_idx < 0) |
952 | return; | 952 | return; |
953 | 953 | ||
954 | hdmi_present_sense(&spec->pins[pin_idx], 1); | 954 | hdmi_present_sense(&spec->pins[pin_idx], 1); |
955 | snd_hda_jack_report_sync(codec); | 955 | snd_hda_jack_report_sync(codec); |
956 | } | 956 | } |
957 | 957 | ||
958 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) | 958 | static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) |
959 | { | 959 | { |
960 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 960 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
961 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | 961 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; |
962 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); | 962 | int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); |
963 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); | 963 | int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); |
964 | 964 | ||
965 | printk(KERN_INFO | 965 | printk(KERN_INFO |
966 | "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", | 966 | "HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", |
967 | codec->addr, | 967 | codec->addr, |
968 | tag, | 968 | tag, |
969 | subtag, | 969 | subtag, |
970 | cp_state, | 970 | cp_state, |
971 | cp_ready); | 971 | cp_ready); |
972 | 972 | ||
973 | /* TODO */ | 973 | /* TODO */ |
974 | if (cp_state) | 974 | if (cp_state) |
975 | ; | 975 | ; |
976 | if (cp_ready) | 976 | if (cp_ready) |
977 | ; | 977 | ; |
978 | } | 978 | } |
979 | 979 | ||
980 | 980 | ||
981 | static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) | 981 | static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) |
982 | { | 982 | { |
983 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; | 983 | int tag = res >> AC_UNSOL_RES_TAG_SHIFT; |
984 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; | 984 | int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; |
985 | 985 | ||
986 | if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { | 986 | if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { |
987 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); | 987 | snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); |
988 | return; | 988 | return; |
989 | } | 989 | } |
990 | 990 | ||
991 | if (subtag == 0) | 991 | if (subtag == 0) |
992 | hdmi_intrinsic_event(codec, res); | 992 | hdmi_intrinsic_event(codec, res); |
993 | else | 993 | else |
994 | hdmi_non_intrinsic_event(codec, res); | 994 | hdmi_non_intrinsic_event(codec, res); |
995 | } | 995 | } |
996 | 996 | ||
997 | /* | 997 | /* |
998 | * Callbacks | 998 | * Callbacks |
999 | */ | 999 | */ |
1000 | 1000 | ||
1001 | /* HBR should be Non-PCM, 8 channels */ | 1001 | /* HBR should be Non-PCM, 8 channels */ |
1002 | #define is_hbr_format(format) \ | 1002 | #define is_hbr_format(format) \ |
1003 | ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) | 1003 | ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) |
1004 | 1004 | ||
1005 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | 1005 | static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, |
1006 | hda_nid_t pin_nid, u32 stream_tag, int format) | 1006 | hda_nid_t pin_nid, u32 stream_tag, int format) |
1007 | { | 1007 | { |
1008 | int pinctl; | 1008 | int pinctl; |
1009 | int new_pinctl = 0; | 1009 | int new_pinctl = 0; |
1010 | 1010 | ||
1011 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { | 1011 | if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { |
1012 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1012 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
1013 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1013 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
1014 | 1014 | ||
1015 | new_pinctl = pinctl & ~AC_PINCTL_EPT; | 1015 | new_pinctl = pinctl & ~AC_PINCTL_EPT; |
1016 | if (is_hbr_format(format)) | 1016 | if (is_hbr_format(format)) |
1017 | new_pinctl |= AC_PINCTL_EPT_HBR; | 1017 | new_pinctl |= AC_PINCTL_EPT_HBR; |
1018 | else | 1018 | else |
1019 | new_pinctl |= AC_PINCTL_EPT_NATIVE; | 1019 | new_pinctl |= AC_PINCTL_EPT_NATIVE; |
1020 | 1020 | ||
1021 | snd_printdd("hdmi_setup_stream: " | 1021 | snd_printdd("hdmi_setup_stream: " |
1022 | "NID=0x%x, %spinctl=0x%x\n", | 1022 | "NID=0x%x, %spinctl=0x%x\n", |
1023 | pin_nid, | 1023 | pin_nid, |
1024 | pinctl == new_pinctl ? "" : "new-", | 1024 | pinctl == new_pinctl ? "" : "new-", |
1025 | new_pinctl); | 1025 | new_pinctl); |
1026 | 1026 | ||
1027 | if (pinctl != new_pinctl) | 1027 | if (pinctl != new_pinctl) |
1028 | snd_hda_codec_write(codec, pin_nid, 0, | 1028 | snd_hda_codec_write(codec, pin_nid, 0, |
1029 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1029 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1030 | new_pinctl); | 1030 | new_pinctl); |
1031 | 1031 | ||
1032 | } | 1032 | } |
1033 | if (is_hbr_format(format) && !new_pinctl) { | 1033 | if (is_hbr_format(format) && !new_pinctl) { |
1034 | snd_printdd("hdmi_setup_stream: HBR is not supported\n"); | 1034 | snd_printdd("hdmi_setup_stream: HBR is not supported\n"); |
1035 | return -EINVAL; | 1035 | return -EINVAL; |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); | 1038 | snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format); |
1039 | return 0; | 1039 | return 0; |
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | /* | 1042 | /* |
1043 | * HDA PCM callbacks | 1043 | * HDA PCM callbacks |
1044 | */ | 1044 | */ |
1045 | static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | 1045 | static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, |
1046 | struct hda_codec *codec, | 1046 | struct hda_codec *codec, |
1047 | struct snd_pcm_substream *substream) | 1047 | struct snd_pcm_substream *substream) |
1048 | { | 1048 | { |
1049 | struct hdmi_spec *spec = codec->spec; | 1049 | struct hdmi_spec *spec = codec->spec; |
1050 | struct snd_pcm_runtime *runtime = substream->runtime; | 1050 | struct snd_pcm_runtime *runtime = substream->runtime; |
1051 | int pin_idx, cvt_idx, mux_idx = 0; | 1051 | int pin_idx, cvt_idx, mux_idx = 0; |
1052 | struct hdmi_spec_per_pin *per_pin; | 1052 | struct hdmi_spec_per_pin *per_pin; |
1053 | struct hdmi_eld *eld; | 1053 | struct hdmi_eld *eld; |
1054 | struct hdmi_spec_per_cvt *per_cvt = NULL; | 1054 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
1055 | 1055 | ||
1056 | /* Validate hinfo */ | 1056 | /* Validate hinfo */ |
1057 | pin_idx = hinfo_to_pin_index(spec, hinfo); | 1057 | pin_idx = hinfo_to_pin_index(spec, hinfo); |
1058 | if (snd_BUG_ON(pin_idx < 0)) | 1058 | if (snd_BUG_ON(pin_idx < 0)) |
1059 | return -EINVAL; | 1059 | return -EINVAL; |
1060 | per_pin = &spec->pins[pin_idx]; | 1060 | per_pin = &spec->pins[pin_idx]; |
1061 | eld = &per_pin->sink_eld; | 1061 | eld = &per_pin->sink_eld; |
1062 | 1062 | ||
1063 | /* Dynamically assign converter to stream */ | 1063 | /* Dynamically assign converter to stream */ |
1064 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { | 1064 | for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { |
1065 | per_cvt = &spec->cvts[cvt_idx]; | 1065 | per_cvt = &spec->cvts[cvt_idx]; |
1066 | 1066 | ||
1067 | /* Must not already be assigned */ | 1067 | /* Must not already be assigned */ |
1068 | if (per_cvt->assigned) | 1068 | if (per_cvt->assigned) |
1069 | continue; | 1069 | continue; |
1070 | /* Must be in pin's mux's list of converters */ | 1070 | /* Must be in pin's mux's list of converters */ |
1071 | for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) | 1071 | for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) |
1072 | if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid) | 1072 | if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid) |
1073 | break; | 1073 | break; |
1074 | /* Not in mux list */ | 1074 | /* Not in mux list */ |
1075 | if (mux_idx == per_pin->num_mux_nids) | 1075 | if (mux_idx == per_pin->num_mux_nids) |
1076 | continue; | 1076 | continue; |
1077 | break; | 1077 | break; |
1078 | } | 1078 | } |
1079 | /* No free converters */ | 1079 | /* No free converters */ |
1080 | if (cvt_idx == spec->num_cvts) | 1080 | if (cvt_idx == spec->num_cvts) |
1081 | return -ENODEV; | 1081 | return -ENODEV; |
1082 | 1082 | ||
1083 | /* Claim converter */ | 1083 | /* Claim converter */ |
1084 | per_cvt->assigned = 1; | 1084 | per_cvt->assigned = 1; |
1085 | hinfo->nid = per_cvt->cvt_nid; | 1085 | hinfo->nid = per_cvt->cvt_nid; |
1086 | 1086 | ||
1087 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, | 1087 | snd_hda_codec_write(codec, per_pin->pin_nid, 0, |
1088 | AC_VERB_SET_CONNECT_SEL, | 1088 | AC_VERB_SET_CONNECT_SEL, |
1089 | mux_idx); | 1089 | mux_idx); |
1090 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); | 1090 | snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); |
1091 | 1091 | ||
1092 | /* Initially set the converter's capabilities */ | 1092 | /* Initially set the converter's capabilities */ |
1093 | hinfo->channels_min = per_cvt->channels_min; | 1093 | hinfo->channels_min = per_cvt->channels_min; |
1094 | hinfo->channels_max = per_cvt->channels_max; | 1094 | hinfo->channels_max = per_cvt->channels_max; |
1095 | hinfo->rates = per_cvt->rates; | 1095 | hinfo->rates = per_cvt->rates; |
1096 | hinfo->formats = per_cvt->formats; | 1096 | hinfo->formats = per_cvt->formats; |
1097 | hinfo->maxbps = per_cvt->maxbps; | 1097 | hinfo->maxbps = per_cvt->maxbps; |
1098 | 1098 | ||
1099 | /* Restrict capabilities by ELD if this isn't disabled */ | 1099 | /* Restrict capabilities by ELD if this isn't disabled */ |
1100 | if (!static_hdmi_pcm && eld->eld_valid) { | 1100 | if (!static_hdmi_pcm && eld->eld_valid) { |
1101 | snd_hdmi_eld_update_pcm_info(eld, hinfo); | 1101 | snd_hdmi_eld_update_pcm_info(eld, hinfo); |
1102 | if (hinfo->channels_min > hinfo->channels_max || | 1102 | if (hinfo->channels_min > hinfo->channels_max || |
1103 | !hinfo->rates || !hinfo->formats) | 1103 | !hinfo->rates || !hinfo->formats) |
1104 | return -ENODEV; | 1104 | return -ENODEV; |
1105 | } | 1105 | } |
1106 | 1106 | ||
1107 | /* Store the updated parameters */ | 1107 | /* Store the updated parameters */ |
1108 | runtime->hw.channels_min = hinfo->channels_min; | 1108 | runtime->hw.channels_min = hinfo->channels_min; |
1109 | runtime->hw.channels_max = hinfo->channels_max; | 1109 | runtime->hw.channels_max = hinfo->channels_max; |
1110 | runtime->hw.formats = hinfo->formats; | 1110 | runtime->hw.formats = hinfo->formats; |
1111 | runtime->hw.rates = hinfo->rates; | 1111 | runtime->hw.rates = hinfo->rates; |
1112 | 1112 | ||
1113 | snd_pcm_hw_constraint_step(substream->runtime, 0, | 1113 | snd_pcm_hw_constraint_step(substream->runtime, 0, |
1114 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); | 1114 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); |
1115 | return 0; | 1115 | return 0; |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /* | 1118 | /* |
1119 | * HDA/HDMI auto parsing | 1119 | * HDA/HDMI auto parsing |
1120 | */ | 1120 | */ |
1121 | static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) | 1121 | static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) |
1122 | { | 1122 | { |
1123 | struct hdmi_spec *spec = codec->spec; | 1123 | struct hdmi_spec *spec = codec->spec; |
1124 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1124 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1125 | hda_nid_t pin_nid = per_pin->pin_nid; | 1125 | hda_nid_t pin_nid = per_pin->pin_nid; |
1126 | 1126 | ||
1127 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { | 1127 | if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { |
1128 | snd_printk(KERN_WARNING | 1128 | snd_printk(KERN_WARNING |
1129 | "HDMI: pin %d wcaps %#x " | 1129 | "HDMI: pin %d wcaps %#x " |
1130 | "does not support connection list\n", | 1130 | "does not support connection list\n", |
1131 | pin_nid, get_wcaps(codec, pin_nid)); | 1131 | pin_nid, get_wcaps(codec, pin_nid)); |
1132 | return -EINVAL; | 1132 | return -EINVAL; |
1133 | } | 1133 | } |
1134 | 1134 | ||
1135 | per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, | 1135 | per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, |
1136 | per_pin->mux_nids, | 1136 | per_pin->mux_nids, |
1137 | HDA_MAX_CONNECTIONS); | 1137 | HDA_MAX_CONNECTIONS); |
1138 | 1138 | ||
1139 | return 0; | 1139 | return 0; |
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) | 1142 | static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) |
1143 | { | 1143 | { |
1144 | struct hda_codec *codec = per_pin->codec; | 1144 | struct hda_codec *codec = per_pin->codec; |
1145 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1145 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1146 | hda_nid_t pin_nid = per_pin->pin_nid; | 1146 | hda_nid_t pin_nid = per_pin->pin_nid; |
1147 | /* | 1147 | /* |
1148 | * Always execute a GetPinSense verb here, even when called from | 1148 | * Always execute a GetPinSense verb here, even when called from |
1149 | * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited | 1149 | * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited |
1150 | * response's PD bit is not the real PD value, but indicates that | 1150 | * response's PD bit is not the real PD value, but indicates that |
1151 | * the real PD value changed. An older version of the HD-audio | 1151 | * the real PD value changed. An older version of the HD-audio |
1152 | * specification worked this way. Hence, we just ignore the data in | 1152 | * specification worked this way. Hence, we just ignore the data in |
1153 | * the unsolicited response to avoid custom WARs. | 1153 | * the unsolicited response to avoid custom WARs. |
1154 | */ | 1154 | */ |
1155 | int present = snd_hda_pin_sense(codec, pin_nid); | 1155 | int present = snd_hda_pin_sense(codec, pin_nid); |
1156 | bool eld_valid = false; | 1156 | bool eld_valid = false; |
1157 | 1157 | ||
1158 | memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); | 1158 | memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); |
1159 | 1159 | ||
1160 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); | 1160 | eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); |
1161 | if (eld->monitor_present) | 1161 | if (eld->monitor_present) |
1162 | eld_valid = !!(present & AC_PINSENSE_ELDV); | 1162 | eld_valid = !!(present & AC_PINSENSE_ELDV); |
1163 | 1163 | ||
1164 | _snd_printd(SND_PR_VERBOSE, | 1164 | _snd_printd(SND_PR_VERBOSE, |
1165 | "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", | 1165 | "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", |
1166 | codec->addr, pin_nid, eld->monitor_present, eld_valid); | 1166 | codec->addr, pin_nid, eld->monitor_present, eld_valid); |
1167 | 1167 | ||
1168 | if (eld_valid) { | 1168 | if (eld_valid) { |
1169 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) | 1169 | if (!snd_hdmi_get_eld(eld, codec, pin_nid)) |
1170 | snd_hdmi_show_eld(eld); | 1170 | snd_hdmi_show_eld(eld); |
1171 | else if (repoll) { | 1171 | else if (repoll) { |
1172 | queue_delayed_work(codec->bus->workq, | 1172 | queue_delayed_work(codec->bus->workq, |
1173 | &per_pin->work, | 1173 | &per_pin->work, |
1174 | msecs_to_jiffies(300)); | 1174 | msecs_to_jiffies(300)); |
1175 | } | 1175 | } |
1176 | } | 1176 | } |
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | static void hdmi_repoll_eld(struct work_struct *work) | 1179 | static void hdmi_repoll_eld(struct work_struct *work) |
1180 | { | 1180 | { |
1181 | struct hdmi_spec_per_pin *per_pin = | 1181 | struct hdmi_spec_per_pin *per_pin = |
1182 | container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); | 1182 | container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); |
1183 | 1183 | ||
1184 | if (per_pin->repoll_count++ > 6) | 1184 | if (per_pin->repoll_count++ > 6) |
1185 | per_pin->repoll_count = 0; | 1185 | per_pin->repoll_count = 0; |
1186 | 1186 | ||
1187 | hdmi_present_sense(per_pin, per_pin->repoll_count); | 1187 | hdmi_present_sense(per_pin, per_pin->repoll_count); |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | 1190 | static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) |
1191 | { | 1191 | { |
1192 | struct hdmi_spec *spec = codec->spec; | 1192 | struct hdmi_spec *spec = codec->spec; |
1193 | unsigned int caps, config; | 1193 | unsigned int caps, config; |
1194 | int pin_idx; | 1194 | int pin_idx; |
1195 | struct hdmi_spec_per_pin *per_pin; | 1195 | struct hdmi_spec_per_pin *per_pin; |
1196 | int err; | 1196 | int err; |
1197 | 1197 | ||
1198 | caps = snd_hda_query_pin_caps(codec, pin_nid); | 1198 | caps = snd_hda_query_pin_caps(codec, pin_nid); |
1199 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) | 1199 | if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) |
1200 | return 0; | 1200 | return 0; |
1201 | 1201 | ||
1202 | config = snd_hda_codec_get_pincfg(codec, pin_nid); | 1202 | config = snd_hda_codec_get_pincfg(codec, pin_nid); |
1203 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) | 1203 | if (get_defcfg_connect(config) == AC_JACK_PORT_NONE) |
1204 | return 0; | 1204 | return 0; |
1205 | 1205 | ||
1206 | if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS)) | 1206 | if (snd_BUG_ON(spec->num_pins >= MAX_HDMI_PINS)) |
1207 | return -E2BIG; | 1207 | return -E2BIG; |
1208 | 1208 | ||
1209 | pin_idx = spec->num_pins; | 1209 | pin_idx = spec->num_pins; |
1210 | per_pin = &spec->pins[pin_idx]; | 1210 | per_pin = &spec->pins[pin_idx]; |
1211 | 1211 | ||
1212 | per_pin->pin_nid = pin_nid; | 1212 | per_pin->pin_nid = pin_nid; |
1213 | per_pin->non_pcm = false; | 1213 | per_pin->non_pcm = false; |
1214 | 1214 | ||
1215 | err = hdmi_read_pin_conn(codec, pin_idx); | 1215 | err = hdmi_read_pin_conn(codec, pin_idx); |
1216 | if (err < 0) | 1216 | if (err < 0) |
1217 | return err; | 1217 | return err; |
1218 | 1218 | ||
1219 | spec->num_pins++; | 1219 | spec->num_pins++; |
1220 | 1220 | ||
1221 | return 0; | 1221 | return 0; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | 1224 | static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
1225 | { | 1225 | { |
1226 | struct hdmi_spec *spec = codec->spec; | 1226 | struct hdmi_spec *spec = codec->spec; |
1227 | int cvt_idx; | 1227 | int cvt_idx; |
1228 | struct hdmi_spec_per_cvt *per_cvt; | 1228 | struct hdmi_spec_per_cvt *per_cvt; |
1229 | unsigned int chans; | 1229 | unsigned int chans; |
1230 | int err; | 1230 | int err; |
1231 | 1231 | ||
1232 | if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS)) | 1232 | if (snd_BUG_ON(spec->num_cvts >= MAX_HDMI_CVTS)) |
1233 | return -E2BIG; | 1233 | return -E2BIG; |
1234 | 1234 | ||
1235 | chans = get_wcaps(codec, cvt_nid); | 1235 | chans = get_wcaps(codec, cvt_nid); |
1236 | chans = get_wcaps_channels(chans); | 1236 | chans = get_wcaps_channels(chans); |
1237 | 1237 | ||
1238 | cvt_idx = spec->num_cvts; | 1238 | cvt_idx = spec->num_cvts; |
1239 | per_cvt = &spec->cvts[cvt_idx]; | 1239 | per_cvt = &spec->cvts[cvt_idx]; |
1240 | 1240 | ||
1241 | per_cvt->cvt_nid = cvt_nid; | 1241 | per_cvt->cvt_nid = cvt_nid; |
1242 | per_cvt->channels_min = 2; | 1242 | per_cvt->channels_min = 2; |
1243 | if (chans <= 16) { | 1243 | if (chans <= 16) { |
1244 | per_cvt->channels_max = chans; | 1244 | per_cvt->channels_max = chans; |
1245 | if (chans > spec->channels_max) | 1245 | if (chans > spec->channels_max) |
1246 | spec->channels_max = chans; | 1246 | spec->channels_max = chans; |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | err = snd_hda_query_supported_pcm(codec, cvt_nid, | 1249 | err = snd_hda_query_supported_pcm(codec, cvt_nid, |
1250 | &per_cvt->rates, | 1250 | &per_cvt->rates, |
1251 | &per_cvt->formats, | 1251 | &per_cvt->formats, |
1252 | &per_cvt->maxbps); | 1252 | &per_cvt->maxbps); |
1253 | if (err < 0) | 1253 | if (err < 0) |
1254 | return err; | 1254 | return err; |
1255 | 1255 | ||
1256 | spec->num_cvts++; | 1256 | spec->num_cvts++; |
1257 | 1257 | ||
1258 | return 0; | 1258 | return 0; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | static int hdmi_parse_codec(struct hda_codec *codec) | 1261 | static int hdmi_parse_codec(struct hda_codec *codec) |
1262 | { | 1262 | { |
1263 | hda_nid_t nid; | 1263 | hda_nid_t nid; |
1264 | int i, nodes; | 1264 | int i, nodes; |
1265 | 1265 | ||
1266 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); | 1266 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); |
1267 | if (!nid || nodes < 0) { | 1267 | if (!nid || nodes < 0) { |
1268 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); | 1268 | snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); |
1269 | return -EINVAL; | 1269 | return -EINVAL; |
1270 | } | 1270 | } |
1271 | 1271 | ||
1272 | for (i = 0; i < nodes; i++, nid++) { | 1272 | for (i = 0; i < nodes; i++, nid++) { |
1273 | unsigned int caps; | 1273 | unsigned int caps; |
1274 | unsigned int type; | 1274 | unsigned int type; |
1275 | 1275 | ||
1276 | caps = get_wcaps(codec, nid); | 1276 | caps = get_wcaps(codec, nid); |
1277 | type = get_wcaps_type(caps); | 1277 | type = get_wcaps_type(caps); |
1278 | 1278 | ||
1279 | if (!(caps & AC_WCAP_DIGITAL)) | 1279 | if (!(caps & AC_WCAP_DIGITAL)) |
1280 | continue; | 1280 | continue; |
1281 | 1281 | ||
1282 | switch (type) { | 1282 | switch (type) { |
1283 | case AC_WID_AUD_OUT: | 1283 | case AC_WID_AUD_OUT: |
1284 | hdmi_add_cvt(codec, nid); | 1284 | hdmi_add_cvt(codec, nid); |
1285 | break; | 1285 | break; |
1286 | case AC_WID_PIN: | 1286 | case AC_WID_PIN: |
1287 | hdmi_add_pin(codec, nid); | 1287 | hdmi_add_pin(codec, nid); |
1288 | break; | 1288 | break; |
1289 | } | 1289 | } |
1290 | } | 1290 | } |
1291 | 1291 | ||
1292 | #ifdef CONFIG_PM | 1292 | #ifdef CONFIG_PM |
1293 | /* We're seeing some problems with unsolicited hot plug events on | 1293 | /* We're seeing some problems with unsolicited hot plug events on |
1294 | * PantherPoint after S3, if this is not enabled */ | 1294 | * PantherPoint after S3, if this is not enabled */ |
1295 | if (codec->vendor_id == 0x80862806) | 1295 | if (codec->vendor_id == 0x80862806) |
1296 | codec->bus->power_keep_link_on = 1; | 1296 | codec->bus->power_keep_link_on = 1; |
1297 | /* | 1297 | /* |
1298 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | 1298 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event |
1299 | * can be lost and presence sense verb will become inaccurate if the | 1299 | * can be lost and presence sense verb will become inaccurate if the |
1300 | * HDA link is powered off at hot plug or hw initialization time. | 1300 | * HDA link is powered off at hot plug or hw initialization time. |
1301 | */ | 1301 | */ |
1302 | else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | 1302 | else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & |
1303 | AC_PWRST_EPSS)) | 1303 | AC_PWRST_EPSS)) |
1304 | codec->bus->power_keep_link_on = 1; | 1304 | codec->bus->power_keep_link_on = 1; |
1305 | #endif | 1305 | #endif |
1306 | 1306 | ||
1307 | return 0; | 1307 | return 0; |
1308 | } | 1308 | } |
1309 | 1309 | ||
1310 | /* | 1310 | /* |
1311 | */ | 1311 | */ |
1312 | static char *get_hdmi_pcm_name(int idx) | 1312 | static char *get_hdmi_pcm_name(int idx) |
1313 | { | 1313 | { |
1314 | static char names[MAX_HDMI_PINS][8]; | 1314 | static char names[MAX_HDMI_PINS][8]; |
1315 | sprintf(&names[idx][0], "HDMI %d", idx); | 1315 | sprintf(&names[idx][0], "HDMI %d", idx); |
1316 | return &names[idx][0]; | 1316 | return &names[idx][0]; |
1317 | } | 1317 | } |
1318 | 1318 | ||
1319 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | 1319 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) |
1320 | { | 1320 | { |
1321 | struct hda_spdif_out *spdif; | 1321 | struct hda_spdif_out *spdif; |
1322 | bool non_pcm; | 1322 | bool non_pcm; |
1323 | 1323 | ||
1324 | mutex_lock(&codec->spdif_mutex); | 1324 | mutex_lock(&codec->spdif_mutex); |
1325 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); | 1325 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); |
1326 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); | 1326 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); |
1327 | mutex_unlock(&codec->spdif_mutex); | 1327 | mutex_unlock(&codec->spdif_mutex); |
1328 | return non_pcm; | 1328 | return non_pcm; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | 1331 | ||
1332 | /* | 1332 | /* |
1333 | * HDMI callbacks | 1333 | * HDMI callbacks |
1334 | */ | 1334 | */ |
1335 | 1335 | ||
1336 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 1336 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
1337 | struct hda_codec *codec, | 1337 | struct hda_codec *codec, |
1338 | unsigned int stream_tag, | 1338 | unsigned int stream_tag, |
1339 | unsigned int format, | 1339 | unsigned int format, |
1340 | struct snd_pcm_substream *substream) | 1340 | struct snd_pcm_substream *substream) |
1341 | { | 1341 | { |
1342 | hda_nid_t cvt_nid = hinfo->nid; | 1342 | hda_nid_t cvt_nid = hinfo->nid; |
1343 | struct hdmi_spec *spec = codec->spec; | 1343 | struct hdmi_spec *spec = codec->spec; |
1344 | int pin_idx = hinfo_to_pin_index(spec, hinfo); | 1344 | int pin_idx = hinfo_to_pin_index(spec, hinfo); |
1345 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; | 1345 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; |
1346 | bool non_pcm; | 1346 | bool non_pcm; |
1347 | 1347 | ||
1348 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); | 1348 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); |
1349 | 1349 | ||
1350 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); | 1350 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); |
1351 | 1351 | ||
1352 | hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream); | 1352 | hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream); |
1353 | 1353 | ||
1354 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); | 1354 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); |
1355 | } | 1355 | } |
1356 | 1356 | ||
1357 | static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 1357 | static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, |
1358 | struct hda_codec *codec, | 1358 | struct hda_codec *codec, |
1359 | struct snd_pcm_substream *substream) | 1359 | struct snd_pcm_substream *substream) |
1360 | { | 1360 | { |
1361 | snd_hda_codec_cleanup_stream(codec, hinfo->nid); | 1361 | snd_hda_codec_cleanup_stream(codec, hinfo->nid); |
1362 | return 0; | 1362 | return 0; |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | 1365 | static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, |
1366 | struct hda_codec *codec, | 1366 | struct hda_codec *codec, |
1367 | struct snd_pcm_substream *substream) | 1367 | struct snd_pcm_substream *substream) |
1368 | { | 1368 | { |
1369 | struct hdmi_spec *spec = codec->spec; | 1369 | struct hdmi_spec *spec = codec->spec; |
1370 | int cvt_idx, pin_idx; | 1370 | int cvt_idx, pin_idx; |
1371 | struct hdmi_spec_per_cvt *per_cvt; | 1371 | struct hdmi_spec_per_cvt *per_cvt; |
1372 | struct hdmi_spec_per_pin *per_pin; | 1372 | struct hdmi_spec_per_pin *per_pin; |
1373 | 1373 | ||
1374 | if (hinfo->nid) { | 1374 | if (hinfo->nid) { |
1375 | cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); | 1375 | cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); |
1376 | if (snd_BUG_ON(cvt_idx < 0)) | 1376 | if (snd_BUG_ON(cvt_idx < 0)) |
1377 | return -EINVAL; | 1377 | return -EINVAL; |
1378 | per_cvt = &spec->cvts[cvt_idx]; | 1378 | per_cvt = &spec->cvts[cvt_idx]; |
1379 | 1379 | ||
1380 | snd_BUG_ON(!per_cvt->assigned); | 1380 | snd_BUG_ON(!per_cvt->assigned); |
1381 | per_cvt->assigned = 0; | 1381 | per_cvt->assigned = 0; |
1382 | hinfo->nid = 0; | 1382 | hinfo->nid = 0; |
1383 | 1383 | ||
1384 | pin_idx = hinfo_to_pin_index(spec, hinfo); | 1384 | pin_idx = hinfo_to_pin_index(spec, hinfo); |
1385 | if (snd_BUG_ON(pin_idx < 0)) | 1385 | if (snd_BUG_ON(pin_idx < 0)) |
1386 | return -EINVAL; | 1386 | return -EINVAL; |
1387 | per_pin = &spec->pins[pin_idx]; | 1387 | per_pin = &spec->pins[pin_idx]; |
1388 | 1388 | ||
1389 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1389 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1390 | per_pin->chmap_set = false; | 1390 | per_pin->chmap_set = false; |
1391 | memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); | 1391 | memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); |
1392 | } | 1392 | } |
1393 | 1393 | ||
1394 | return 0; | 1394 | return 0; |
1395 | } | 1395 | } |
1396 | 1396 | ||
1397 | static const struct hda_pcm_ops generic_ops = { | 1397 | static const struct hda_pcm_ops generic_ops = { |
1398 | .open = hdmi_pcm_open, | 1398 | .open = hdmi_pcm_open, |
1399 | .close = hdmi_pcm_close, | 1399 | .close = hdmi_pcm_close, |
1400 | .prepare = generic_hdmi_playback_pcm_prepare, | 1400 | .prepare = generic_hdmi_playback_pcm_prepare, |
1401 | .cleanup = generic_hdmi_playback_pcm_cleanup, | 1401 | .cleanup = generic_hdmi_playback_pcm_cleanup, |
1402 | }; | 1402 | }; |
1403 | 1403 | ||
1404 | /* | 1404 | /* |
1405 | * ALSA API channel-map control callbacks | 1405 | * ALSA API channel-map control callbacks |
1406 | */ | 1406 | */ |
1407 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, | 1407 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, |
1408 | struct snd_ctl_elem_info *uinfo) | 1408 | struct snd_ctl_elem_info *uinfo) |
1409 | { | 1409 | { |
1410 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1410 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1411 | struct hda_codec *codec = info->private_data; | 1411 | struct hda_codec *codec = info->private_data; |
1412 | struct hdmi_spec *spec = codec->spec; | 1412 | struct hdmi_spec *spec = codec->spec; |
1413 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1413 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1414 | uinfo->count = spec->channels_max; | 1414 | uinfo->count = spec->channels_max; |
1415 | uinfo->value.integer.min = 0; | 1415 | uinfo->value.integer.min = 0; |
1416 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | 1416 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; |
1417 | return 0; | 1417 | return 0; |
1418 | } | 1418 | } |
1419 | 1419 | ||
1420 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | 1420 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
1421 | unsigned int size, unsigned int __user *tlv) | 1421 | unsigned int size, unsigned int __user *tlv) |
1422 | { | 1422 | { |
1423 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1423 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1424 | struct hda_codec *codec = info->private_data; | 1424 | struct hda_codec *codec = info->private_data; |
1425 | struct hdmi_spec *spec = codec->spec; | 1425 | struct hdmi_spec *spec = codec->spec; |
1426 | const unsigned int valid_mask = | 1426 | const unsigned int valid_mask = |
1427 | FL | FR | RL | RR | LFE | FC | RLC | RRC; | 1427 | FL | FR | RL | RR | LFE | FC | RLC | RRC; |
1428 | unsigned int __user *dst; | 1428 | unsigned int __user *dst; |
1429 | int chs, count = 0; | 1429 | int chs, count = 0; |
1430 | 1430 | ||
1431 | if (size < 8) | 1431 | if (size < 8) |
1432 | return -ENOMEM; | 1432 | return -ENOMEM; |
1433 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | 1433 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) |
1434 | return -EFAULT; | 1434 | return -EFAULT; |
1435 | size -= 8; | 1435 | size -= 8; |
1436 | dst = tlv + 2; | 1436 | dst = tlv + 2; |
1437 | for (chs = 2; chs <= spec->channels_max; chs++) { | 1437 | for (chs = 2; chs <= spec->channels_max; chs++) { |
1438 | int i, c; | 1438 | int i, c; |
1439 | struct cea_channel_speaker_allocation *cap; | 1439 | struct cea_channel_speaker_allocation *cap; |
1440 | cap = channel_allocations; | 1440 | cap = channel_allocations; |
1441 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { | 1441 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { |
1442 | int chs_bytes = chs * 4; | 1442 | int chs_bytes = chs * 4; |
1443 | if (cap->channels != chs) | 1443 | if (cap->channels != chs) |
1444 | continue; | 1444 | continue; |
1445 | if (cap->spk_mask & ~valid_mask) | 1445 | if (cap->spk_mask & ~valid_mask) |
1446 | continue; | 1446 | continue; |
1447 | if (size < 8) | 1447 | if (size < 8) |
1448 | return -ENOMEM; | 1448 | return -ENOMEM; |
1449 | if (put_user(SNDRV_CTL_TLVT_CHMAP_VAR, dst) || | 1449 | if (put_user(SNDRV_CTL_TLVT_CHMAP_VAR, dst) || |
1450 | put_user(chs_bytes, dst + 1)) | 1450 | put_user(chs_bytes, dst + 1)) |
1451 | return -EFAULT; | 1451 | return -EFAULT; |
1452 | dst += 2; | 1452 | dst += 2; |
1453 | size -= 8; | 1453 | size -= 8; |
1454 | count += 8; | 1454 | count += 8; |
1455 | if (size < chs_bytes) | 1455 | if (size < chs_bytes) |
1456 | return -ENOMEM; | 1456 | return -ENOMEM; |
1457 | size -= chs_bytes; | 1457 | size -= chs_bytes; |
1458 | count += chs_bytes; | 1458 | count += chs_bytes; |
1459 | for (c = 7; c >= 0; c--) { | 1459 | for (c = 7; c >= 0; c--) { |
1460 | int spk = cap->speakers[c]; | 1460 | int spk = cap->speakers[c]; |
1461 | if (!spk) | 1461 | if (!spk) |
1462 | continue; | 1462 | continue; |
1463 | if (put_user(spk_to_chmap(spk), dst)) | 1463 | if (put_user(spk_to_chmap(spk), dst)) |
1464 | return -EFAULT; | 1464 | return -EFAULT; |
1465 | dst++; | 1465 | dst++; |
1466 | } | 1466 | } |
1467 | } | 1467 | } |
1468 | } | 1468 | } |
1469 | if (put_user(count, tlv + 1)) | 1469 | if (put_user(count, tlv + 1)) |
1470 | return -EFAULT; | 1470 | return -EFAULT; |
1471 | return 0; | 1471 | return 0; |
1472 | } | 1472 | } |
1473 | 1473 | ||
1474 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, | 1474 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, |
1475 | struct snd_ctl_elem_value *ucontrol) | 1475 | struct snd_ctl_elem_value *ucontrol) |
1476 | { | 1476 | { |
1477 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1477 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1478 | struct hda_codec *codec = info->private_data; | 1478 | struct hda_codec *codec = info->private_data; |
1479 | struct hdmi_spec *spec = codec->spec; | 1479 | struct hdmi_spec *spec = codec->spec; |
1480 | int pin_idx = kcontrol->private_value; | 1480 | int pin_idx = kcontrol->private_value; |
1481 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1481 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1482 | int i; | 1482 | int i; |
1483 | 1483 | ||
1484 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) | 1484 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) |
1485 | ucontrol->value.integer.value[i] = per_pin->chmap[i]; | 1485 | ucontrol->value.integer.value[i] = per_pin->chmap[i]; |
1486 | return 0; | 1486 | return 0; |
1487 | } | 1487 | } |
1488 | 1488 | ||
1489 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, | 1489 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, |
1490 | struct snd_ctl_elem_value *ucontrol) | 1490 | struct snd_ctl_elem_value *ucontrol) |
1491 | { | 1491 | { |
1492 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | 1492 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); |
1493 | struct hda_codec *codec = info->private_data; | 1493 | struct hda_codec *codec = info->private_data; |
1494 | struct hdmi_spec *spec = codec->spec; | 1494 | struct hdmi_spec *spec = codec->spec; |
1495 | int pin_idx = kcontrol->private_value; | 1495 | int pin_idx = kcontrol->private_value; |
1496 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1496 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1497 | unsigned int ctl_idx; | 1497 | unsigned int ctl_idx; |
1498 | struct snd_pcm_substream *substream; | 1498 | struct snd_pcm_substream *substream; |
1499 | unsigned char chmap[8]; | 1499 | unsigned char chmap[8]; |
1500 | int i, ca, prepared = 0; | 1500 | int i, ca, prepared = 0; |
1501 | 1501 | ||
1502 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 1502 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
1503 | substream = snd_pcm_chmap_substream(info, ctl_idx); | 1503 | substream = snd_pcm_chmap_substream(info, ctl_idx); |
1504 | if (!substream || !substream->runtime) | 1504 | if (!substream || !substream->runtime) |
1505 | return -EBADFD; | 1505 | return -EBADFD; |
1506 | switch (substream->runtime->status->state) { | 1506 | switch (substream->runtime->status->state) { |
1507 | case SNDRV_PCM_STATE_OPEN: | 1507 | case SNDRV_PCM_STATE_OPEN: |
1508 | case SNDRV_PCM_STATE_SETUP: | 1508 | case SNDRV_PCM_STATE_SETUP: |
1509 | break; | 1509 | break; |
1510 | case SNDRV_PCM_STATE_PREPARED: | 1510 | case SNDRV_PCM_STATE_PREPARED: |
1511 | prepared = 1; | 1511 | prepared = 1; |
1512 | break; | 1512 | break; |
1513 | default: | 1513 | default: |
1514 | return -EBUSY; | 1514 | return -EBUSY; |
1515 | } | 1515 | } |
1516 | memset(chmap, 0, sizeof(chmap)); | 1516 | memset(chmap, 0, sizeof(chmap)); |
1517 | for (i = 0; i < ARRAY_SIZE(chmap); i++) | 1517 | for (i = 0; i < ARRAY_SIZE(chmap); i++) |
1518 | chmap[i] = ucontrol->value.integer.value[i]; | 1518 | chmap[i] = ucontrol->value.integer.value[i]; |
1519 | if (!memcmp(chmap, per_pin->chmap, sizeof(chmap))) | 1519 | if (!memcmp(chmap, per_pin->chmap, sizeof(chmap))) |
1520 | return 0; | 1520 | return 0; |
1521 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); | 1521 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); |
1522 | if (ca < 0) | 1522 | if (ca < 0) |
1523 | return -EINVAL; | 1523 | return -EINVAL; |
1524 | per_pin->chmap_set = true; | 1524 | per_pin->chmap_set = true; |
1525 | memcpy(per_pin->chmap, chmap, sizeof(chmap)); | 1525 | memcpy(per_pin->chmap, chmap, sizeof(chmap)); |
1526 | if (prepared) | 1526 | if (prepared) |
1527 | hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm, | 1527 | hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm, |
1528 | substream); | 1528 | substream); |
1529 | 1529 | ||
1530 | return 0; | 1530 | return 0; |
1531 | } | 1531 | } |
1532 | 1532 | ||
1533 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | 1533 | static int generic_hdmi_build_pcms(struct hda_codec *codec) |
1534 | { | 1534 | { |
1535 | struct hdmi_spec *spec = codec->spec; | 1535 | struct hdmi_spec *spec = codec->spec; |
1536 | int pin_idx; | 1536 | int pin_idx; |
1537 | 1537 | ||
1538 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1538 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1539 | struct hda_pcm *info; | 1539 | struct hda_pcm *info; |
1540 | struct hda_pcm_stream *pstr; | 1540 | struct hda_pcm_stream *pstr; |
1541 | 1541 | ||
1542 | info = &spec->pcm_rec[pin_idx]; | 1542 | info = &spec->pcm_rec[pin_idx]; |
1543 | info->name = get_hdmi_pcm_name(pin_idx); | 1543 | info->name = get_hdmi_pcm_name(pin_idx); |
1544 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1544 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1545 | info->own_chmap = true; | 1545 | info->own_chmap = true; |
1546 | 1546 | ||
1547 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1547 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
1548 | pstr->substreams = 1; | 1548 | pstr->substreams = 1; |
1549 | pstr->ops = generic_ops; | 1549 | pstr->ops = generic_ops; |
1550 | /* other pstr fields are set in open */ | 1550 | /* other pstr fields are set in open */ |
1551 | } | 1551 | } |
1552 | 1552 | ||
1553 | codec->num_pcms = spec->num_pins; | 1553 | codec->num_pcms = spec->num_pins; |
1554 | codec->pcm_info = spec->pcm_rec; | 1554 | codec->pcm_info = spec->pcm_rec; |
1555 | 1555 | ||
1556 | return 0; | 1556 | return 0; |
1557 | } | 1557 | } |
1558 | 1558 | ||
1559 | static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) | 1559 | static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) |
1560 | { | 1560 | { |
1561 | char hdmi_str[32] = "HDMI/DP"; | 1561 | char hdmi_str[32] = "HDMI/DP"; |
1562 | struct hdmi_spec *spec = codec->spec; | 1562 | struct hdmi_spec *spec = codec->spec; |
1563 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1563 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1564 | int pcmdev = spec->pcm_rec[pin_idx].device; | 1564 | int pcmdev = spec->pcm_rec[pin_idx].device; |
1565 | 1565 | ||
1566 | if (pcmdev > 0) | 1566 | if (pcmdev > 0) |
1567 | sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); | 1567 | sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); |
1568 | 1568 | ||
1569 | return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); | 1569 | return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0); |
1570 | } | 1570 | } |
1571 | 1571 | ||
1572 | static int generic_hdmi_build_controls(struct hda_codec *codec) | 1572 | static int generic_hdmi_build_controls(struct hda_codec *codec) |
1573 | { | 1573 | { |
1574 | struct hdmi_spec *spec = codec->spec; | 1574 | struct hdmi_spec *spec = codec->spec; |
1575 | int err; | 1575 | int err; |
1576 | int pin_idx; | 1576 | int pin_idx; |
1577 | 1577 | ||
1578 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1578 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1579 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1579 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1580 | 1580 | ||
1581 | err = generic_hdmi_build_jack(codec, pin_idx); | 1581 | err = generic_hdmi_build_jack(codec, pin_idx); |
1582 | if (err < 0) | 1582 | if (err < 0) |
1583 | return err; | 1583 | return err; |
1584 | 1584 | ||
1585 | err = snd_hda_create_dig_out_ctls(codec, | 1585 | err = snd_hda_create_dig_out_ctls(codec, |
1586 | per_pin->pin_nid, | 1586 | per_pin->pin_nid, |
1587 | per_pin->mux_nids[0], | 1587 | per_pin->mux_nids[0], |
1588 | HDA_PCM_TYPE_HDMI); | 1588 | HDA_PCM_TYPE_HDMI); |
1589 | if (err < 0) | 1589 | if (err < 0) |
1590 | return err; | 1590 | return err; |
1591 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1591 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
1592 | 1592 | ||
1593 | /* add control for ELD Bytes */ | 1593 | /* add control for ELD Bytes */ |
1594 | err = hdmi_create_eld_ctl(codec, | 1594 | err = hdmi_create_eld_ctl(codec, |
1595 | pin_idx, | 1595 | pin_idx, |
1596 | spec->pcm_rec[pin_idx].device); | 1596 | spec->pcm_rec[pin_idx].device); |
1597 | 1597 | ||
1598 | if (err < 0) | 1598 | if (err < 0) |
1599 | return err; | 1599 | return err; |
1600 | 1600 | ||
1601 | hdmi_present_sense(per_pin, 0); | 1601 | hdmi_present_sense(per_pin, 0); |
1602 | } | 1602 | } |
1603 | 1603 | ||
1604 | /* add channel maps */ | 1604 | /* add channel maps */ |
1605 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1605 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1606 | struct snd_pcm_chmap *chmap; | 1606 | struct snd_pcm_chmap *chmap; |
1607 | struct snd_kcontrol *kctl; | 1607 | struct snd_kcontrol *kctl; |
1608 | int i; | 1608 | int i; |
1609 | err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, | 1609 | err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, |
1610 | SNDRV_PCM_STREAM_PLAYBACK, | 1610 | SNDRV_PCM_STREAM_PLAYBACK, |
1611 | NULL, 0, pin_idx, &chmap); | 1611 | NULL, 0, pin_idx, &chmap); |
1612 | if (err < 0) | 1612 | if (err < 0) |
1613 | return err; | 1613 | return err; |
1614 | /* override handlers */ | 1614 | /* override handlers */ |
1615 | chmap->private_data = codec; | 1615 | chmap->private_data = codec; |
1616 | kctl = chmap->kctl; | 1616 | kctl = chmap->kctl; |
1617 | for (i = 0; i < kctl->count; i++) | 1617 | for (i = 0; i < kctl->count; i++) |
1618 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; | 1618 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; |
1619 | kctl->info = hdmi_chmap_ctl_info; | 1619 | kctl->info = hdmi_chmap_ctl_info; |
1620 | kctl->get = hdmi_chmap_ctl_get; | 1620 | kctl->get = hdmi_chmap_ctl_get; |
1621 | kctl->put = hdmi_chmap_ctl_put; | 1621 | kctl->put = hdmi_chmap_ctl_put; |
1622 | kctl->tlv.c = hdmi_chmap_ctl_tlv; | 1622 | kctl->tlv.c = hdmi_chmap_ctl_tlv; |
1623 | } | 1623 | } |
1624 | 1624 | ||
1625 | return 0; | 1625 | return 0; |
1626 | } | 1626 | } |
1627 | 1627 | ||
1628 | static int generic_hdmi_init_per_pins(struct hda_codec *codec) | 1628 | static int generic_hdmi_init_per_pins(struct hda_codec *codec) |
1629 | { | 1629 | { |
1630 | struct hdmi_spec *spec = codec->spec; | 1630 | struct hdmi_spec *spec = codec->spec; |
1631 | int pin_idx; | 1631 | int pin_idx; |
1632 | 1632 | ||
1633 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1633 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1634 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1634 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1635 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1635 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1636 | 1636 | ||
1637 | per_pin->codec = codec; | 1637 | per_pin->codec = codec; |
1638 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); | 1638 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); |
1639 | snd_hda_eld_proc_new(codec, eld, pin_idx); | 1639 | snd_hda_eld_proc_new(codec, eld, pin_idx); |
1640 | } | 1640 | } |
1641 | return 0; | 1641 | return 0; |
1642 | } | 1642 | } |
1643 | 1643 | ||
1644 | static int generic_hdmi_init(struct hda_codec *codec) | 1644 | static int generic_hdmi_init(struct hda_codec *codec) |
1645 | { | 1645 | { |
1646 | struct hdmi_spec *spec = codec->spec; | 1646 | struct hdmi_spec *spec = codec->spec; |
1647 | int pin_idx; | 1647 | int pin_idx; |
1648 | 1648 | ||
1649 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1649 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1650 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1650 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1651 | hda_nid_t pin_nid = per_pin->pin_nid; | 1651 | hda_nid_t pin_nid = per_pin->pin_nid; |
1652 | 1652 | ||
1653 | hdmi_init_pin(codec, pin_nid); | 1653 | hdmi_init_pin(codec, pin_nid); |
1654 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | 1654 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); |
1655 | } | 1655 | } |
1656 | return 0; | 1656 | return 0; |
1657 | } | 1657 | } |
1658 | 1658 | ||
1659 | static void generic_hdmi_free(struct hda_codec *codec) | 1659 | static void generic_hdmi_free(struct hda_codec *codec) |
1660 | { | 1660 | { |
1661 | struct hdmi_spec *spec = codec->spec; | 1661 | struct hdmi_spec *spec = codec->spec; |
1662 | int pin_idx; | 1662 | int pin_idx; |
1663 | 1663 | ||
1664 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | 1664 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { |
1665 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 1665 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
1666 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1666 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1667 | 1667 | ||
1668 | cancel_delayed_work(&per_pin->work); | 1668 | cancel_delayed_work(&per_pin->work); |
1669 | snd_hda_eld_proc_free(codec, eld); | 1669 | snd_hda_eld_proc_free(codec, eld); |
1670 | } | 1670 | } |
1671 | 1671 | ||
1672 | flush_workqueue(codec->bus->workq); | 1672 | flush_workqueue(codec->bus->workq); |
1673 | kfree(spec); | 1673 | kfree(spec); |
1674 | } | 1674 | } |
1675 | 1675 | ||
1676 | static const struct hda_codec_ops generic_hdmi_patch_ops = { | 1676 | static const struct hda_codec_ops generic_hdmi_patch_ops = { |
1677 | .init = generic_hdmi_init, | 1677 | .init = generic_hdmi_init, |
1678 | .free = generic_hdmi_free, | 1678 | .free = generic_hdmi_free, |
1679 | .build_pcms = generic_hdmi_build_pcms, | 1679 | .build_pcms = generic_hdmi_build_pcms, |
1680 | .build_controls = generic_hdmi_build_controls, | 1680 | .build_controls = generic_hdmi_build_controls, |
1681 | .unsol_event = hdmi_unsol_event, | 1681 | .unsol_event = hdmi_unsol_event, |
1682 | }; | 1682 | }; |
1683 | 1683 | ||
1684 | static void intel_haswell_fixup_connect_list(struct hda_codec *codec) | ||
1685 | { | ||
1686 | unsigned int vendor_param; | ||
1687 | hda_nid_t list[3] = {0x2, 0x3, 0x4}; | ||
1688 | |||
1689 | vendor_param = snd_hda_codec_read(codec, 0x08, 0, 0xf81, 0); | ||
1690 | if (vendor_param == -1 || vendor_param & 0x02) | ||
1691 | return; | ||
1692 | |||
1693 | /* enable DP1.2 mode */ | ||
1694 | vendor_param |= 0x02; | ||
1695 | snd_hda_codec_read(codec, 0x08, 0, 0x781, vendor_param); | ||
1696 | |||
1697 | vendor_param = snd_hda_codec_read(codec, 0x08, 0, 0xf81, 0); | ||
1698 | if (vendor_param == -1 || !(vendor_param & 0x02)) | ||
1699 | return; | ||
1700 | |||
1701 | /* override 3 pins connection list */ | ||
1702 | snd_hda_override_conn_list(codec, 0x05, 3, list); | ||
1703 | snd_hda_override_conn_list(codec, 0x06, 3, list); | ||
1704 | snd_hda_override_conn_list(codec, 0x07, 3, list); | ||
1705 | } | ||
1706 | |||
1707 | |||
1684 | static int patch_generic_hdmi(struct hda_codec *codec) | 1708 | static int patch_generic_hdmi(struct hda_codec *codec) |
1685 | { | 1709 | { |
1686 | struct hdmi_spec *spec; | 1710 | struct hdmi_spec *spec; |
1687 | 1711 | ||
1688 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1712 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1689 | if (spec == NULL) | 1713 | if (spec == NULL) |
1690 | return -ENOMEM; | 1714 | return -ENOMEM; |
1691 | 1715 | ||
1692 | codec->spec = spec; | 1716 | codec->spec = spec; |
1717 | |||
1718 | if (codec->vendor_id == 0x80862807) | ||
1719 | intel_haswell_fixup_connect_list(codec); | ||
1720 | |||
1693 | if (hdmi_parse_codec(codec) < 0) { | 1721 | if (hdmi_parse_codec(codec) < 0) { |
1694 | codec->spec = NULL; | 1722 | codec->spec = NULL; |
1695 | kfree(spec); | 1723 | kfree(spec); |
1696 | return -EINVAL; | 1724 | return -EINVAL; |
1697 | } | 1725 | } |
1698 | codec->patch_ops = generic_hdmi_patch_ops; | 1726 | codec->patch_ops = generic_hdmi_patch_ops; |
1699 | generic_hdmi_init_per_pins(codec); | 1727 | generic_hdmi_init_per_pins(codec); |
1700 | 1728 | ||
1701 | init_channel_allocations(); | 1729 | init_channel_allocations(); |
1702 | 1730 | ||
1703 | return 0; | 1731 | return 0; |
1704 | } | 1732 | } |
1705 | 1733 | ||
1706 | /* | 1734 | /* |
1707 | * Shared non-generic implementations | 1735 | * Shared non-generic implementations |
1708 | */ | 1736 | */ |
1709 | 1737 | ||
1710 | static int simple_playback_build_pcms(struct hda_codec *codec) | 1738 | static int simple_playback_build_pcms(struct hda_codec *codec) |
1711 | { | 1739 | { |
1712 | struct hdmi_spec *spec = codec->spec; | 1740 | struct hdmi_spec *spec = codec->spec; |
1713 | struct hda_pcm *info = spec->pcm_rec; | 1741 | struct hda_pcm *info = spec->pcm_rec; |
1714 | unsigned int chans; | 1742 | unsigned int chans; |
1715 | struct hda_pcm_stream *pstr; | 1743 | struct hda_pcm_stream *pstr; |
1716 | 1744 | ||
1717 | codec->num_pcms = 1; | 1745 | codec->num_pcms = 1; |
1718 | codec->pcm_info = info; | 1746 | codec->pcm_info = info; |
1719 | 1747 | ||
1720 | chans = get_wcaps(codec, spec->cvts[0].cvt_nid); | 1748 | chans = get_wcaps(codec, spec->cvts[0].cvt_nid); |
1721 | chans = get_wcaps_channels(chans); | 1749 | chans = get_wcaps_channels(chans); |
1722 | 1750 | ||
1723 | info->name = get_hdmi_pcm_name(0); | 1751 | info->name = get_hdmi_pcm_name(0); |
1724 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1752 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
1725 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1753 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
1726 | *pstr = spec->pcm_playback; | 1754 | *pstr = spec->pcm_playback; |
1727 | pstr->nid = spec->cvts[0].cvt_nid; | 1755 | pstr->nid = spec->cvts[0].cvt_nid; |
1728 | if (pstr->channels_max <= 2 && chans && chans <= 16) | 1756 | if (pstr->channels_max <= 2 && chans && chans <= 16) |
1729 | pstr->channels_max = chans; | 1757 | pstr->channels_max = chans; |
1730 | 1758 | ||
1731 | return 0; | 1759 | return 0; |
1732 | } | 1760 | } |
1733 | 1761 | ||
1734 | /* unsolicited event for jack sensing */ | 1762 | /* unsolicited event for jack sensing */ |
1735 | static void simple_hdmi_unsol_event(struct hda_codec *codec, | 1763 | static void simple_hdmi_unsol_event(struct hda_codec *codec, |
1736 | unsigned int res) | 1764 | unsigned int res) |
1737 | { | 1765 | { |
1738 | snd_hda_jack_set_dirty_all(codec); | 1766 | snd_hda_jack_set_dirty_all(codec); |
1739 | snd_hda_jack_report_sync(codec); | 1767 | snd_hda_jack_report_sync(codec); |
1740 | } | 1768 | } |
1741 | 1769 | ||
1742 | /* generic_hdmi_build_jack can be used for simple_hdmi, too, | 1770 | /* generic_hdmi_build_jack can be used for simple_hdmi, too, |
1743 | * as long as spec->pins[] is set correctly | 1771 | * as long as spec->pins[] is set correctly |
1744 | */ | 1772 | */ |
1745 | #define simple_hdmi_build_jack generic_hdmi_build_jack | 1773 | #define simple_hdmi_build_jack generic_hdmi_build_jack |
1746 | 1774 | ||
1747 | static int simple_playback_build_controls(struct hda_codec *codec) | 1775 | static int simple_playback_build_controls(struct hda_codec *codec) |
1748 | { | 1776 | { |
1749 | struct hdmi_spec *spec = codec->spec; | 1777 | struct hdmi_spec *spec = codec->spec; |
1750 | int err; | 1778 | int err; |
1751 | 1779 | ||
1752 | err = snd_hda_create_spdif_out_ctls(codec, | 1780 | err = snd_hda_create_spdif_out_ctls(codec, |
1753 | spec->cvts[0].cvt_nid, | 1781 | spec->cvts[0].cvt_nid, |
1754 | spec->cvts[0].cvt_nid); | 1782 | spec->cvts[0].cvt_nid); |
1755 | if (err < 0) | 1783 | if (err < 0) |
1756 | return err; | 1784 | return err; |
1757 | return simple_hdmi_build_jack(codec, 0); | 1785 | return simple_hdmi_build_jack(codec, 0); |
1758 | } | 1786 | } |
1759 | 1787 | ||
1760 | static int simple_playback_init(struct hda_codec *codec) | 1788 | static int simple_playback_init(struct hda_codec *codec) |
1761 | { | 1789 | { |
1762 | struct hdmi_spec *spec = codec->spec; | 1790 | struct hdmi_spec *spec = codec->spec; |
1763 | hda_nid_t pin = spec->pins[0].pin_nid; | 1791 | hda_nid_t pin = spec->pins[0].pin_nid; |
1764 | 1792 | ||
1765 | snd_hda_codec_write(codec, pin, 0, | 1793 | snd_hda_codec_write(codec, pin, 0, |
1766 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | 1794 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); |
1767 | /* some codecs require to unmute the pin */ | 1795 | /* some codecs require to unmute the pin */ |
1768 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) | 1796 | if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) |
1769 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 1797 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
1770 | AMP_OUT_UNMUTE); | 1798 | AMP_OUT_UNMUTE); |
1771 | snd_hda_jack_detect_enable(codec, pin, pin); | 1799 | snd_hda_jack_detect_enable(codec, pin, pin); |
1772 | return 0; | 1800 | return 0; |
1773 | } | 1801 | } |
1774 | 1802 | ||
1775 | static void simple_playback_free(struct hda_codec *codec) | 1803 | static void simple_playback_free(struct hda_codec *codec) |
1776 | { | 1804 | { |
1777 | struct hdmi_spec *spec = codec->spec; | 1805 | struct hdmi_spec *spec = codec->spec; |
1778 | 1806 | ||
1779 | kfree(spec); | 1807 | kfree(spec); |
1780 | } | 1808 | } |
1781 | 1809 | ||
1782 | /* | 1810 | /* |
1783 | * Nvidia specific implementations | 1811 | * Nvidia specific implementations |
1784 | */ | 1812 | */ |
1785 | 1813 | ||
1786 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | 1814 | #define Nv_VERB_SET_Channel_Allocation 0xF79 |
1787 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | 1815 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A |
1788 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | 1816 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 |
1789 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | 1817 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 |
1790 | 1818 | ||
1791 | #define nvhdmi_master_con_nid_7x 0x04 | 1819 | #define nvhdmi_master_con_nid_7x 0x04 |
1792 | #define nvhdmi_master_pin_nid_7x 0x05 | 1820 | #define nvhdmi_master_pin_nid_7x 0x05 |
1793 | 1821 | ||
1794 | static const hda_nid_t nvhdmi_con_nids_7x[4] = { | 1822 | static const hda_nid_t nvhdmi_con_nids_7x[4] = { |
1795 | /*front, rear, clfe, rear_surr */ | 1823 | /*front, rear, clfe, rear_surr */ |
1796 | 0x6, 0x8, 0xa, 0xc, | 1824 | 0x6, 0x8, 0xa, 0xc, |
1797 | }; | 1825 | }; |
1798 | 1826 | ||
1799 | static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { | 1827 | static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = { |
1800 | /* set audio protect on */ | 1828 | /* set audio protect on */ |
1801 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 1829 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
1802 | /* enable digital output on pin widget */ | 1830 | /* enable digital output on pin widget */ |
1803 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 1831 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
1804 | {} /* terminator */ | 1832 | {} /* terminator */ |
1805 | }; | 1833 | }; |
1806 | 1834 | ||
1807 | static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { | 1835 | static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = { |
1808 | /* set audio protect on */ | 1836 | /* set audio protect on */ |
1809 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | 1837 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, |
1810 | /* enable digital output on pin widget */ | 1838 | /* enable digital output on pin widget */ |
1811 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 1839 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
1812 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 1840 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
1813 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 1841 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
1814 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 1842 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
1815 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | 1843 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, |
1816 | {} /* terminator */ | 1844 | {} /* terminator */ |
1817 | }; | 1845 | }; |
1818 | 1846 | ||
1819 | #ifdef LIMITED_RATE_FMT_SUPPORT | 1847 | #ifdef LIMITED_RATE_FMT_SUPPORT |
1820 | /* support only the safe format and rate */ | 1848 | /* support only the safe format and rate */ |
1821 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | 1849 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 |
1822 | #define SUPPORTED_MAXBPS 16 | 1850 | #define SUPPORTED_MAXBPS 16 |
1823 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 1851 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE |
1824 | #else | 1852 | #else |
1825 | /* support all rates and formats */ | 1853 | /* support all rates and formats */ |
1826 | #define SUPPORTED_RATES \ | 1854 | #define SUPPORTED_RATES \ |
1827 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | 1855 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ |
1828 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | 1856 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ |
1829 | SNDRV_PCM_RATE_192000) | 1857 | SNDRV_PCM_RATE_192000) |
1830 | #define SUPPORTED_MAXBPS 24 | 1858 | #define SUPPORTED_MAXBPS 24 |
1831 | #define SUPPORTED_FORMATS \ | 1859 | #define SUPPORTED_FORMATS \ |
1832 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | 1860 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) |
1833 | #endif | 1861 | #endif |
1834 | 1862 | ||
1835 | static int nvhdmi_7x_init_2ch(struct hda_codec *codec) | 1863 | static int nvhdmi_7x_init_2ch(struct hda_codec *codec) |
1836 | { | 1864 | { |
1837 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); | 1865 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch); |
1838 | return 0; | 1866 | return 0; |
1839 | } | 1867 | } |
1840 | 1868 | ||
1841 | static int nvhdmi_7x_init_8ch(struct hda_codec *codec) | 1869 | static int nvhdmi_7x_init_8ch(struct hda_codec *codec) |
1842 | { | 1870 | { |
1843 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); | 1871 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch); |
1844 | return 0; | 1872 | return 0; |
1845 | } | 1873 | } |
1846 | 1874 | ||
1847 | static unsigned int channels_2_6_8[] = { | 1875 | static unsigned int channels_2_6_8[] = { |
1848 | 2, 6, 8 | 1876 | 2, 6, 8 |
1849 | }; | 1877 | }; |
1850 | 1878 | ||
1851 | static unsigned int channels_2_8[] = { | 1879 | static unsigned int channels_2_8[] = { |
1852 | 2, 8 | 1880 | 2, 8 |
1853 | }; | 1881 | }; |
1854 | 1882 | ||
1855 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { | 1883 | static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { |
1856 | .count = ARRAY_SIZE(channels_2_6_8), | 1884 | .count = ARRAY_SIZE(channels_2_6_8), |
1857 | .list = channels_2_6_8, | 1885 | .list = channels_2_6_8, |
1858 | .mask = 0, | 1886 | .mask = 0, |
1859 | }; | 1887 | }; |
1860 | 1888 | ||
1861 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { | 1889 | static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { |
1862 | .count = ARRAY_SIZE(channels_2_8), | 1890 | .count = ARRAY_SIZE(channels_2_8), |
1863 | .list = channels_2_8, | 1891 | .list = channels_2_8, |
1864 | .mask = 0, | 1892 | .mask = 0, |
1865 | }; | 1893 | }; |
1866 | 1894 | ||
1867 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | 1895 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, |
1868 | struct hda_codec *codec, | 1896 | struct hda_codec *codec, |
1869 | struct snd_pcm_substream *substream) | 1897 | struct snd_pcm_substream *substream) |
1870 | { | 1898 | { |
1871 | struct hdmi_spec *spec = codec->spec; | 1899 | struct hdmi_spec *spec = codec->spec; |
1872 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; | 1900 | struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; |
1873 | 1901 | ||
1874 | switch (codec->preset->id) { | 1902 | switch (codec->preset->id) { |
1875 | case 0x10de0002: | 1903 | case 0x10de0002: |
1876 | case 0x10de0003: | 1904 | case 0x10de0003: |
1877 | case 0x10de0005: | 1905 | case 0x10de0005: |
1878 | case 0x10de0006: | 1906 | case 0x10de0006: |
1879 | hw_constraints_channels = &hw_constraints_2_8_channels; | 1907 | hw_constraints_channels = &hw_constraints_2_8_channels; |
1880 | break; | 1908 | break; |
1881 | case 0x10de0007: | 1909 | case 0x10de0007: |
1882 | hw_constraints_channels = &hw_constraints_2_6_8_channels; | 1910 | hw_constraints_channels = &hw_constraints_2_6_8_channels; |
1883 | break; | 1911 | break; |
1884 | default: | 1912 | default: |
1885 | break; | 1913 | break; |
1886 | } | 1914 | } |
1887 | 1915 | ||
1888 | if (hw_constraints_channels != NULL) { | 1916 | if (hw_constraints_channels != NULL) { |
1889 | snd_pcm_hw_constraint_list(substream->runtime, 0, | 1917 | snd_pcm_hw_constraint_list(substream->runtime, 0, |
1890 | SNDRV_PCM_HW_PARAM_CHANNELS, | 1918 | SNDRV_PCM_HW_PARAM_CHANNELS, |
1891 | hw_constraints_channels); | 1919 | hw_constraints_channels); |
1892 | } else { | 1920 | } else { |
1893 | snd_pcm_hw_constraint_step(substream->runtime, 0, | 1921 | snd_pcm_hw_constraint_step(substream->runtime, 0, |
1894 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); | 1922 | SNDRV_PCM_HW_PARAM_CHANNELS, 2); |
1895 | } | 1923 | } |
1896 | 1924 | ||
1897 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 1925 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); |
1898 | } | 1926 | } |
1899 | 1927 | ||
1900 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, | 1928 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, |
1901 | struct hda_codec *codec, | 1929 | struct hda_codec *codec, |
1902 | struct snd_pcm_substream *substream) | 1930 | struct snd_pcm_substream *substream) |
1903 | { | 1931 | { |
1904 | struct hdmi_spec *spec = codec->spec; | 1932 | struct hdmi_spec *spec = codec->spec; |
1905 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 1933 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
1906 | } | 1934 | } |
1907 | 1935 | ||
1908 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 1936 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
1909 | struct hda_codec *codec, | 1937 | struct hda_codec *codec, |
1910 | unsigned int stream_tag, | 1938 | unsigned int stream_tag, |
1911 | unsigned int format, | 1939 | unsigned int format, |
1912 | struct snd_pcm_substream *substream) | 1940 | struct snd_pcm_substream *substream) |
1913 | { | 1941 | { |
1914 | struct hdmi_spec *spec = codec->spec; | 1942 | struct hdmi_spec *spec = codec->spec; |
1915 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | 1943 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, |
1916 | stream_tag, format, substream); | 1944 | stream_tag, format, substream); |
1917 | } | 1945 | } |
1918 | 1946 | ||
1919 | static const struct hda_pcm_stream simple_pcm_playback = { | 1947 | static const struct hda_pcm_stream simple_pcm_playback = { |
1920 | .substreams = 1, | 1948 | .substreams = 1, |
1921 | .channels_min = 2, | 1949 | .channels_min = 2, |
1922 | .channels_max = 2, | 1950 | .channels_max = 2, |
1923 | .ops = { | 1951 | .ops = { |
1924 | .open = simple_playback_pcm_open, | 1952 | .open = simple_playback_pcm_open, |
1925 | .close = simple_playback_pcm_close, | 1953 | .close = simple_playback_pcm_close, |
1926 | .prepare = simple_playback_pcm_prepare | 1954 | .prepare = simple_playback_pcm_prepare |
1927 | }, | 1955 | }, |
1928 | }; | 1956 | }; |
1929 | 1957 | ||
1930 | static const struct hda_codec_ops simple_hdmi_patch_ops = { | 1958 | static const struct hda_codec_ops simple_hdmi_patch_ops = { |
1931 | .build_controls = simple_playback_build_controls, | 1959 | .build_controls = simple_playback_build_controls, |
1932 | .build_pcms = simple_playback_build_pcms, | 1960 | .build_pcms = simple_playback_build_pcms, |
1933 | .init = simple_playback_init, | 1961 | .init = simple_playback_init, |
1934 | .free = simple_playback_free, | 1962 | .free = simple_playback_free, |
1935 | .unsol_event = simple_hdmi_unsol_event, | 1963 | .unsol_event = simple_hdmi_unsol_event, |
1936 | }; | 1964 | }; |
1937 | 1965 | ||
1938 | static int patch_simple_hdmi(struct hda_codec *codec, | 1966 | static int patch_simple_hdmi(struct hda_codec *codec, |
1939 | hda_nid_t cvt_nid, hda_nid_t pin_nid) | 1967 | hda_nid_t cvt_nid, hda_nid_t pin_nid) |
1940 | { | 1968 | { |
1941 | struct hdmi_spec *spec; | 1969 | struct hdmi_spec *spec; |
1942 | 1970 | ||
1943 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 1971 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
1944 | if (!spec) | 1972 | if (!spec) |
1945 | return -ENOMEM; | 1973 | return -ENOMEM; |
1946 | 1974 | ||
1947 | codec->spec = spec; | 1975 | codec->spec = spec; |
1948 | 1976 | ||
1949 | spec->multiout.num_dacs = 0; /* no analog */ | 1977 | spec->multiout.num_dacs = 0; /* no analog */ |
1950 | spec->multiout.max_channels = 2; | 1978 | spec->multiout.max_channels = 2; |
1951 | spec->multiout.dig_out_nid = cvt_nid; | 1979 | spec->multiout.dig_out_nid = cvt_nid; |
1952 | spec->num_cvts = 1; | 1980 | spec->num_cvts = 1; |
1953 | spec->num_pins = 1; | 1981 | spec->num_pins = 1; |
1954 | spec->cvts[0].cvt_nid = cvt_nid; | 1982 | spec->cvts[0].cvt_nid = cvt_nid; |
1955 | spec->pins[0].pin_nid = pin_nid; | 1983 | spec->pins[0].pin_nid = pin_nid; |
1956 | spec->pcm_playback = simple_pcm_playback; | 1984 | spec->pcm_playback = simple_pcm_playback; |
1957 | 1985 | ||
1958 | codec->patch_ops = simple_hdmi_patch_ops; | 1986 | codec->patch_ops = simple_hdmi_patch_ops; |
1959 | 1987 | ||
1960 | return 0; | 1988 | return 0; |
1961 | } | 1989 | } |
1962 | 1990 | ||
1963 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, | 1991 | static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec, |
1964 | int channels) | 1992 | int channels) |
1965 | { | 1993 | { |
1966 | unsigned int chanmask; | 1994 | unsigned int chanmask; |
1967 | int chan = channels ? (channels - 1) : 1; | 1995 | int chan = channels ? (channels - 1) : 1; |
1968 | 1996 | ||
1969 | switch (channels) { | 1997 | switch (channels) { |
1970 | default: | 1998 | default: |
1971 | case 0: | 1999 | case 0: |
1972 | case 2: | 2000 | case 2: |
1973 | chanmask = 0x00; | 2001 | chanmask = 0x00; |
1974 | break; | 2002 | break; |
1975 | case 4: | 2003 | case 4: |
1976 | chanmask = 0x08; | 2004 | chanmask = 0x08; |
1977 | break; | 2005 | break; |
1978 | case 6: | 2006 | case 6: |
1979 | chanmask = 0x0b; | 2007 | chanmask = 0x0b; |
1980 | break; | 2008 | break; |
1981 | case 8: | 2009 | case 8: |
1982 | chanmask = 0x13; | 2010 | chanmask = 0x13; |
1983 | break; | 2011 | break; |
1984 | } | 2012 | } |
1985 | 2013 | ||
1986 | /* Set the audio infoframe channel allocation and checksum fields. The | 2014 | /* Set the audio infoframe channel allocation and checksum fields. The |
1987 | * channel count is computed implicitly by the hardware. */ | 2015 | * channel count is computed implicitly by the hardware. */ |
1988 | snd_hda_codec_write(codec, 0x1, 0, | 2016 | snd_hda_codec_write(codec, 0x1, 0, |
1989 | Nv_VERB_SET_Channel_Allocation, chanmask); | 2017 | Nv_VERB_SET_Channel_Allocation, chanmask); |
1990 | 2018 | ||
1991 | snd_hda_codec_write(codec, 0x1, 0, | 2019 | snd_hda_codec_write(codec, 0x1, 0, |
1992 | Nv_VERB_SET_Info_Frame_Checksum, | 2020 | Nv_VERB_SET_Info_Frame_Checksum, |
1993 | (0x71 - chan - chanmask)); | 2021 | (0x71 - chan - chanmask)); |
1994 | } | 2022 | } |
1995 | 2023 | ||
1996 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, | 2024 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, |
1997 | struct hda_codec *codec, | 2025 | struct hda_codec *codec, |
1998 | struct snd_pcm_substream *substream) | 2026 | struct snd_pcm_substream *substream) |
1999 | { | 2027 | { |
2000 | struct hdmi_spec *spec = codec->spec; | 2028 | struct hdmi_spec *spec = codec->spec; |
2001 | int i; | 2029 | int i; |
2002 | 2030 | ||
2003 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | 2031 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, |
2004 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | 2032 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); |
2005 | for (i = 0; i < 4; i++) { | 2033 | for (i = 0; i < 4; i++) { |
2006 | /* set the stream id */ | 2034 | /* set the stream id */ |
2007 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | 2035 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
2008 | AC_VERB_SET_CHANNEL_STREAMID, 0); | 2036 | AC_VERB_SET_CHANNEL_STREAMID, 0); |
2009 | /* set the stream format */ | 2037 | /* set the stream format */ |
2010 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | 2038 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, |
2011 | AC_VERB_SET_STREAM_FORMAT, 0); | 2039 | AC_VERB_SET_STREAM_FORMAT, 0); |
2012 | } | 2040 | } |
2013 | 2041 | ||
2014 | /* The audio hardware sends a channel count of 0x7 (8ch) when all the | 2042 | /* The audio hardware sends a channel count of 0x7 (8ch) when all the |
2015 | * streams are disabled. */ | 2043 | * streams are disabled. */ |
2016 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); | 2044 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); |
2017 | 2045 | ||
2018 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 2046 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
2019 | } | 2047 | } |
2020 | 2048 | ||
2021 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | 2049 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, |
2022 | struct hda_codec *codec, | 2050 | struct hda_codec *codec, |
2023 | unsigned int stream_tag, | 2051 | unsigned int stream_tag, |
2024 | unsigned int format, | 2052 | unsigned int format, |
2025 | struct snd_pcm_substream *substream) | 2053 | struct snd_pcm_substream *substream) |
2026 | { | 2054 | { |
2027 | int chs; | 2055 | int chs; |
2028 | unsigned int dataDCC2, channel_id; | 2056 | unsigned int dataDCC2, channel_id; |
2029 | int i; | 2057 | int i; |
2030 | struct hdmi_spec *spec = codec->spec; | 2058 | struct hdmi_spec *spec = codec->spec; |
2031 | struct hda_spdif_out *spdif; | 2059 | struct hda_spdif_out *spdif; |
2032 | 2060 | ||
2033 | mutex_lock(&codec->spdif_mutex); | 2061 | mutex_lock(&codec->spdif_mutex); |
2034 | spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid); | 2062 | spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid); |
2035 | 2063 | ||
2036 | chs = substream->runtime->channels; | 2064 | chs = substream->runtime->channels; |
2037 | 2065 | ||
2038 | dataDCC2 = 0x2; | 2066 | dataDCC2 = 0x2; |
2039 | 2067 | ||
2040 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | 2068 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ |
2041 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) | 2069 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) |
2042 | snd_hda_codec_write(codec, | 2070 | snd_hda_codec_write(codec, |
2043 | nvhdmi_master_con_nid_7x, | 2071 | nvhdmi_master_con_nid_7x, |
2044 | 0, | 2072 | 0, |
2045 | AC_VERB_SET_DIGI_CONVERT_1, | 2073 | AC_VERB_SET_DIGI_CONVERT_1, |
2046 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); | 2074 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); |
2047 | 2075 | ||
2048 | /* set the stream id */ | 2076 | /* set the stream id */ |
2049 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | 2077 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
2050 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | 2078 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); |
2051 | 2079 | ||
2052 | /* set the stream format */ | 2080 | /* set the stream format */ |
2053 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | 2081 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, |
2054 | AC_VERB_SET_STREAM_FORMAT, format); | 2082 | AC_VERB_SET_STREAM_FORMAT, format); |
2055 | 2083 | ||
2056 | /* turn on again (if needed) */ | 2084 | /* turn on again (if needed) */ |
2057 | /* enable and set the channel status audio/data flag */ | 2085 | /* enable and set the channel status audio/data flag */ |
2058 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) { | 2086 | if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) { |
2059 | snd_hda_codec_write(codec, | 2087 | snd_hda_codec_write(codec, |
2060 | nvhdmi_master_con_nid_7x, | 2088 | nvhdmi_master_con_nid_7x, |
2061 | 0, | 2089 | 0, |
2062 | AC_VERB_SET_DIGI_CONVERT_1, | 2090 | AC_VERB_SET_DIGI_CONVERT_1, |
2063 | spdif->ctls & 0xff); | 2091 | spdif->ctls & 0xff); |
2064 | snd_hda_codec_write(codec, | 2092 | snd_hda_codec_write(codec, |
2065 | nvhdmi_master_con_nid_7x, | 2093 | nvhdmi_master_con_nid_7x, |
2066 | 0, | 2094 | 0, |
2067 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 2095 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
2068 | } | 2096 | } |
2069 | 2097 | ||
2070 | for (i = 0; i < 4; i++) { | 2098 | for (i = 0; i < 4; i++) { |
2071 | if (chs == 2) | 2099 | if (chs == 2) |
2072 | channel_id = 0; | 2100 | channel_id = 0; |
2073 | else | 2101 | else |
2074 | channel_id = i * 2; | 2102 | channel_id = i * 2; |
2075 | 2103 | ||
2076 | /* turn off SPDIF once; | 2104 | /* turn off SPDIF once; |
2077 | *otherwise the IEC958 bits won't be updated | 2105 | *otherwise the IEC958 bits won't be updated |
2078 | */ | 2106 | */ |
2079 | if (codec->spdif_status_reset && | 2107 | if (codec->spdif_status_reset && |
2080 | (spdif->ctls & AC_DIG1_ENABLE)) | 2108 | (spdif->ctls & AC_DIG1_ENABLE)) |
2081 | snd_hda_codec_write(codec, | 2109 | snd_hda_codec_write(codec, |
2082 | nvhdmi_con_nids_7x[i], | 2110 | nvhdmi_con_nids_7x[i], |
2083 | 0, | 2111 | 0, |
2084 | AC_VERB_SET_DIGI_CONVERT_1, | 2112 | AC_VERB_SET_DIGI_CONVERT_1, |
2085 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); | 2113 | spdif->ctls & ~AC_DIG1_ENABLE & 0xff); |
2086 | /* set the stream id */ | 2114 | /* set the stream id */ |
2087 | snd_hda_codec_write(codec, | 2115 | snd_hda_codec_write(codec, |
2088 | nvhdmi_con_nids_7x[i], | 2116 | nvhdmi_con_nids_7x[i], |
2089 | 0, | 2117 | 0, |
2090 | AC_VERB_SET_CHANNEL_STREAMID, | 2118 | AC_VERB_SET_CHANNEL_STREAMID, |
2091 | (stream_tag << 4) | channel_id); | 2119 | (stream_tag << 4) | channel_id); |
2092 | /* set the stream format */ | 2120 | /* set the stream format */ |
2093 | snd_hda_codec_write(codec, | 2121 | snd_hda_codec_write(codec, |
2094 | nvhdmi_con_nids_7x[i], | 2122 | nvhdmi_con_nids_7x[i], |
2095 | 0, | 2123 | 0, |
2096 | AC_VERB_SET_STREAM_FORMAT, | 2124 | AC_VERB_SET_STREAM_FORMAT, |
2097 | format); | 2125 | format); |
2098 | /* turn on again (if needed) */ | 2126 | /* turn on again (if needed) */ |
2099 | /* enable and set the channel status audio/data flag */ | 2127 | /* enable and set the channel status audio/data flag */ |
2100 | if (codec->spdif_status_reset && | 2128 | if (codec->spdif_status_reset && |
2101 | (spdif->ctls & AC_DIG1_ENABLE)) { | 2129 | (spdif->ctls & AC_DIG1_ENABLE)) { |
2102 | snd_hda_codec_write(codec, | 2130 | snd_hda_codec_write(codec, |
2103 | nvhdmi_con_nids_7x[i], | 2131 | nvhdmi_con_nids_7x[i], |
2104 | 0, | 2132 | 0, |
2105 | AC_VERB_SET_DIGI_CONVERT_1, | 2133 | AC_VERB_SET_DIGI_CONVERT_1, |
2106 | spdif->ctls & 0xff); | 2134 | spdif->ctls & 0xff); |
2107 | snd_hda_codec_write(codec, | 2135 | snd_hda_codec_write(codec, |
2108 | nvhdmi_con_nids_7x[i], | 2136 | nvhdmi_con_nids_7x[i], |
2109 | 0, | 2137 | 0, |
2110 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | 2138 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); |
2111 | } | 2139 | } |
2112 | } | 2140 | } |
2113 | 2141 | ||
2114 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); | 2142 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs); |
2115 | 2143 | ||
2116 | mutex_unlock(&codec->spdif_mutex); | 2144 | mutex_unlock(&codec->spdif_mutex); |
2117 | return 0; | 2145 | return 0; |
2118 | } | 2146 | } |
2119 | 2147 | ||
2120 | static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | 2148 | static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { |
2121 | .substreams = 1, | 2149 | .substreams = 1, |
2122 | .channels_min = 2, | 2150 | .channels_min = 2, |
2123 | .channels_max = 8, | 2151 | .channels_max = 8, |
2124 | .nid = nvhdmi_master_con_nid_7x, | 2152 | .nid = nvhdmi_master_con_nid_7x, |
2125 | .rates = SUPPORTED_RATES, | 2153 | .rates = SUPPORTED_RATES, |
2126 | .maxbps = SUPPORTED_MAXBPS, | 2154 | .maxbps = SUPPORTED_MAXBPS, |
2127 | .formats = SUPPORTED_FORMATS, | 2155 | .formats = SUPPORTED_FORMATS, |
2128 | .ops = { | 2156 | .ops = { |
2129 | .open = simple_playback_pcm_open, | 2157 | .open = simple_playback_pcm_open, |
2130 | .close = nvhdmi_8ch_7x_pcm_close, | 2158 | .close = nvhdmi_8ch_7x_pcm_close, |
2131 | .prepare = nvhdmi_8ch_7x_pcm_prepare | 2159 | .prepare = nvhdmi_8ch_7x_pcm_prepare |
2132 | }, | 2160 | }, |
2133 | }; | 2161 | }; |
2134 | 2162 | ||
2135 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | 2163 | static int patch_nvhdmi_2ch(struct hda_codec *codec) |
2136 | { | 2164 | { |
2137 | struct hdmi_spec *spec; | 2165 | struct hdmi_spec *spec; |
2138 | int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, | 2166 | int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x, |
2139 | nvhdmi_master_pin_nid_7x); | 2167 | nvhdmi_master_pin_nid_7x); |
2140 | if (err < 0) | 2168 | if (err < 0) |
2141 | return err; | 2169 | return err; |
2142 | 2170 | ||
2143 | codec->patch_ops.init = nvhdmi_7x_init_2ch; | 2171 | codec->patch_ops.init = nvhdmi_7x_init_2ch; |
2144 | /* override the PCM rates, etc, as the codec doesn't give full list */ | 2172 | /* override the PCM rates, etc, as the codec doesn't give full list */ |
2145 | spec = codec->spec; | 2173 | spec = codec->spec; |
2146 | spec->pcm_playback.rates = SUPPORTED_RATES; | 2174 | spec->pcm_playback.rates = SUPPORTED_RATES; |
2147 | spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; | 2175 | spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; |
2148 | spec->pcm_playback.formats = SUPPORTED_FORMATS; | 2176 | spec->pcm_playback.formats = SUPPORTED_FORMATS; |
2149 | return 0; | 2177 | return 0; |
2150 | } | 2178 | } |
2151 | 2179 | ||
2152 | static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) | 2180 | static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) |
2153 | { | 2181 | { |
2154 | struct hdmi_spec *spec = codec->spec; | 2182 | struct hdmi_spec *spec = codec->spec; |
2155 | int err = simple_playback_build_pcms(codec); | 2183 | int err = simple_playback_build_pcms(codec); |
2156 | spec->pcm_rec[0].own_chmap = true; | 2184 | spec->pcm_rec[0].own_chmap = true; |
2157 | return err; | 2185 | return err; |
2158 | } | 2186 | } |
2159 | 2187 | ||
2160 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) | 2188 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) |
2161 | { | 2189 | { |
2162 | struct hdmi_spec *spec = codec->spec; | 2190 | struct hdmi_spec *spec = codec->spec; |
2163 | struct snd_pcm_chmap *chmap; | 2191 | struct snd_pcm_chmap *chmap; |
2164 | int err; | 2192 | int err; |
2165 | 2193 | ||
2166 | err = simple_playback_build_controls(codec); | 2194 | err = simple_playback_build_controls(codec); |
2167 | if (err < 0) | 2195 | if (err < 0) |
2168 | return err; | 2196 | return err; |
2169 | 2197 | ||
2170 | /* add channel maps */ | 2198 | /* add channel maps */ |
2171 | err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm, | 2199 | err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm, |
2172 | SNDRV_PCM_STREAM_PLAYBACK, | 2200 | SNDRV_PCM_STREAM_PLAYBACK, |
2173 | snd_pcm_alt_chmaps, 8, 0, &chmap); | 2201 | snd_pcm_alt_chmaps, 8, 0, &chmap); |
2174 | if (err < 0) | 2202 | if (err < 0) |
2175 | return err; | 2203 | return err; |
2176 | switch (codec->preset->id) { | 2204 | switch (codec->preset->id) { |
2177 | case 0x10de0002: | 2205 | case 0x10de0002: |
2178 | case 0x10de0003: | 2206 | case 0x10de0003: |
2179 | case 0x10de0005: | 2207 | case 0x10de0005: |
2180 | case 0x10de0006: | 2208 | case 0x10de0006: |
2181 | chmap->channel_mask = (1U << 2) | (1U << 8); | 2209 | chmap->channel_mask = (1U << 2) | (1U << 8); |
2182 | break; | 2210 | break; |
2183 | case 0x10de0007: | 2211 | case 0x10de0007: |
2184 | chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8); | 2212 | chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8); |
2185 | } | 2213 | } |
2186 | return 0; | 2214 | return 0; |
2187 | } | 2215 | } |
2188 | 2216 | ||
2189 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | 2217 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) |
2190 | { | 2218 | { |
2191 | struct hdmi_spec *spec; | 2219 | struct hdmi_spec *spec; |
2192 | int err = patch_nvhdmi_2ch(codec); | 2220 | int err = patch_nvhdmi_2ch(codec); |
2193 | if (err < 0) | 2221 | if (err < 0) |
2194 | return err; | 2222 | return err; |
2195 | spec = codec->spec; | 2223 | spec = codec->spec; |
2196 | spec->multiout.max_channels = 8; | 2224 | spec->multiout.max_channels = 8; |
2197 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; | 2225 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; |
2198 | codec->patch_ops.init = nvhdmi_7x_init_8ch; | 2226 | codec->patch_ops.init = nvhdmi_7x_init_8ch; |
2199 | codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms; | 2227 | codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms; |
2200 | codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls; | 2228 | codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls; |
2201 | 2229 | ||
2202 | /* Initialize the audio infoframe channel mask and checksum to something | 2230 | /* Initialize the audio infoframe channel mask and checksum to something |
2203 | * valid */ | 2231 | * valid */ |
2204 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); | 2232 | nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8); |
2205 | 2233 | ||
2206 | return 0; | 2234 | return 0; |
2207 | } | 2235 | } |
2208 | 2236 | ||
2209 | /* | 2237 | /* |
2210 | * ATI-specific implementations | 2238 | * ATI-specific implementations |
2211 | * | 2239 | * |
2212 | * FIXME: we may omit the whole this and use the generic code once after | 2240 | * FIXME: we may omit the whole this and use the generic code once after |
2213 | * it's confirmed to work. | 2241 | * it's confirmed to work. |
2214 | */ | 2242 | */ |
2215 | 2243 | ||
2216 | #define ATIHDMI_CVT_NID 0x02 /* audio converter */ | 2244 | #define ATIHDMI_CVT_NID 0x02 /* audio converter */ |
2217 | #define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ | 2245 | #define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ |
2218 | 2246 | ||
2219 | static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 2247 | static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
2220 | struct hda_codec *codec, | 2248 | struct hda_codec *codec, |
2221 | unsigned int stream_tag, | 2249 | unsigned int stream_tag, |
2222 | unsigned int format, | 2250 | unsigned int format, |
2223 | struct snd_pcm_substream *substream) | 2251 | struct snd_pcm_substream *substream) |
2224 | { | 2252 | { |
2225 | struct hdmi_spec *spec = codec->spec; | 2253 | struct hdmi_spec *spec = codec->spec; |
2226 | int chans = substream->runtime->channels; | 2254 | int chans = substream->runtime->channels; |
2227 | int i, err; | 2255 | int i, err; |
2228 | 2256 | ||
2229 | err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, | 2257 | err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, |
2230 | substream); | 2258 | substream); |
2231 | if (err < 0) | 2259 | if (err < 0) |
2232 | return err; | 2260 | return err; |
2233 | snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, | 2261 | snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, |
2234 | AC_VERB_SET_CVT_CHAN_COUNT, chans - 1); | 2262 | AC_VERB_SET_CVT_CHAN_COUNT, chans - 1); |
2235 | /* FIXME: XXX */ | 2263 | /* FIXME: XXX */ |
2236 | for (i = 0; i < chans; i++) { | 2264 | for (i = 0; i < chans; i++) { |
2237 | snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, | 2265 | snd_hda_codec_write(codec, spec->cvts[0].cvt_nid, 0, |
2238 | AC_VERB_SET_HDMI_CHAN_SLOT, | 2266 | AC_VERB_SET_HDMI_CHAN_SLOT, |
2239 | (i << 4) | i); | 2267 | (i << 4) | i); |
2240 | } | 2268 | } |
2241 | return 0; | 2269 | return 0; |
2242 | } | 2270 | } |
2243 | 2271 | ||
2244 | static int patch_atihdmi(struct hda_codec *codec) | 2272 | static int patch_atihdmi(struct hda_codec *codec) |
2245 | { | 2273 | { |
2246 | struct hdmi_spec *spec; | 2274 | struct hdmi_spec *spec; |
2247 | int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); | 2275 | int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID); |
2248 | if (err < 0) | 2276 | if (err < 0) |
2249 | return err; | 2277 | return err; |
2250 | spec = codec->spec; | 2278 | spec = codec->spec; |
2251 | spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; | 2279 | spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare; |
2252 | return 0; | 2280 | return 0; |
2253 | } | 2281 | } |
2254 | 2282 | ||
2255 | /* VIA HDMI Implementation */ | 2283 | /* VIA HDMI Implementation */ |
2256 | #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ | 2284 | #define VIAHDMI_CVT_NID 0x02 /* audio converter1 */ |
2257 | #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ | 2285 | #define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */ |
2258 | 2286 | ||
2259 | static int patch_via_hdmi(struct hda_codec *codec) | 2287 | static int patch_via_hdmi(struct hda_codec *codec) |
2260 | { | 2288 | { |
2261 | return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); | 2289 | return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID); |
2262 | } | 2290 | } |
2263 | 2291 | ||
2264 | /* | 2292 | /* |
2265 | * patch entries | 2293 | * patch entries |
2266 | */ | 2294 | */ |
2267 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | 2295 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { |
2268 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | 2296 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, |
2269 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | 2297 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, |
2270 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | 2298 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, |
2271 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi }, | 2299 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi }, |
2272 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | 2300 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, |
2273 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | 2301 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, |
2274 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | 2302 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, |
2275 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 2303 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
2276 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 2304 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
2277 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 2305 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
2278 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | 2306 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, |
2279 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | 2307 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, |
2280 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi }, | 2308 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi }, |
2281 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi }, | 2309 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi }, |
2282 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi }, | 2310 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi }, |
2283 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi }, | 2311 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi }, |
2284 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi }, | 2312 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi }, |
2285 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi }, | 2313 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi }, |
2286 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi }, | 2314 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi }, |
2287 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi }, | 2315 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi }, |
2288 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi }, | 2316 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi }, |
2289 | { .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi }, | 2317 | { .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi }, |
2290 | { .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi }, | 2318 | { .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi }, |
2291 | /* 17 is known to be absent */ | 2319 | /* 17 is known to be absent */ |
2292 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi }, | 2320 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi }, |
2293 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi }, | 2321 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi }, |
2294 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi }, | 2322 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi }, |
2295 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi }, | 2323 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi }, |
2296 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi }, | 2324 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi }, |
2297 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi }, | 2325 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi }, |
2298 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi }, | 2326 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi }, |
2299 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, | 2327 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi }, |
2300 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, | 2328 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi }, |
2301 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, | 2329 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi }, |
2302 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi }, | 2330 | { .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi }, |
2303 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | 2331 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, |
2304 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | 2332 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, |
2305 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 2333 | { .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
2306 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, | 2334 | { .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi }, |
2307 | { .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | 2335 | { .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, |
2308 | { .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, | 2336 | { .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi }, |
2309 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 2337 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
2310 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | 2338 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, |
2311 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | 2339 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, |
2312 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, | 2340 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, |
2313 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | 2341 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, |
2314 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | 2342 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, |
2315 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, | 2343 | { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi }, |
2316 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, | 2344 | { .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi }, |
2317 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, | 2345 | { .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi }, |
2318 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | 2346 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, |
2319 | {} /* terminator */ | 2347 | {} /* terminator */ |
2320 | }; | 2348 | }; |
2321 | 2349 | ||
2322 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | 2350 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); |
2323 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | 2351 | MODULE_ALIAS("snd-hda-codec-id:10027919"); |
2324 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | 2352 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); |
2325 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | 2353 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); |
2326 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | 2354 | MODULE_ALIAS("snd-hda-codec-id:10951390"); |
2327 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | 2355 | MODULE_ALIAS("snd-hda-codec-id:10951392"); |
2328 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | 2356 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); |
2329 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | 2357 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); |
2330 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | 2358 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); |
2331 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | 2359 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); |
2332 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | 2360 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); |
2333 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | 2361 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); |
2334 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | 2362 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); |
2335 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | 2363 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); |
2336 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | 2364 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); |
2337 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | 2365 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); |
2338 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | 2366 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); |
2339 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | 2367 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); |
2340 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | 2368 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); |
2341 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | 2369 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); |
2342 | MODULE_ALIAS("snd-hda-codec-id:10de0015"); | 2370 | MODULE_ALIAS("snd-hda-codec-id:10de0015"); |
2343 | MODULE_ALIAS("snd-hda-codec-id:10de0016"); | 2371 | MODULE_ALIAS("snd-hda-codec-id:10de0016"); |
2344 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | 2372 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); |
2345 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | 2373 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); |
2346 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | 2374 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); |
2347 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | 2375 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); |
2348 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | 2376 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); |
2349 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | 2377 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); |
2350 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | 2378 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); |
2351 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | 2379 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); |
2352 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | 2380 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); |
2353 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | 2381 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); |
2354 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); | 2382 | MODULE_ALIAS("snd-hda-codec-id:10de0051"); |
2355 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | 2383 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); |
2356 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | 2384 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); |
2357 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); | 2385 | MODULE_ALIAS("snd-hda-codec-id:11069f80"); |
2358 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); | 2386 | MODULE_ALIAS("snd-hda-codec-id:11069f81"); |
2359 | MODULE_ALIAS("snd-hda-codec-id:11069f84"); | 2387 | MODULE_ALIAS("snd-hda-codec-id:11069f84"); |
2360 | MODULE_ALIAS("snd-hda-codec-id:11069f85"); | 2388 | MODULE_ALIAS("snd-hda-codec-id:11069f85"); |
2361 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | 2389 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); |
2362 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | 2390 | MODULE_ALIAS("snd-hda-codec-id:80860054"); |
2363 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | 2391 | MODULE_ALIAS("snd-hda-codec-id:80862801"); |
2364 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | 2392 | MODULE_ALIAS("snd-hda-codec-id:80862802"); |
2365 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | 2393 | MODULE_ALIAS("snd-hda-codec-id:80862803"); |
2366 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | 2394 | MODULE_ALIAS("snd-hda-codec-id:80862804"); |
2367 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | 2395 | MODULE_ALIAS("snd-hda-codec-id:80862805"); |
2368 | MODULE_ALIAS("snd-hda-codec-id:80862806"); | 2396 | MODULE_ALIAS("snd-hda-codec-id:80862806"); |
2369 | MODULE_ALIAS("snd-hda-codec-id:80862807"); | 2397 | MODULE_ALIAS("snd-hda-codec-id:80862807"); |
2370 | MODULE_ALIAS("snd-hda-codec-id:80862880"); | 2398 | MODULE_ALIAS("snd-hda-codec-id:80862880"); |
2371 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | 2399 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); |
2372 | 2400 | ||
2373 | MODULE_LICENSE("GPL"); | 2401 | MODULE_LICENSE("GPL"); |
2374 | MODULE_DESCRIPTION("HDMI HD-audio codec"); | 2402 | MODULE_DESCRIPTION("HDMI HD-audio codec"); |
2375 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); | 2403 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); |
2376 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); | 2404 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); |
2377 | MODULE_ALIAS("snd-hda-codec-atihdmi"); | 2405 | MODULE_ALIAS("snd-hda-codec-atihdmi"); |
2378 | 2406 | ||
2379 | static struct hda_codec_preset_list intel_list = { | 2407 | static struct hda_codec_preset_list intel_list = { |
2380 | .preset = snd_hda_preset_hdmi, | 2408 | .preset = snd_hda_preset_hdmi, |
2381 | .owner = THIS_MODULE, | 2409 | .owner = THIS_MODULE, |
2382 | }; | 2410 | }; |
2383 | 2411 | ||
2384 | static int __init patch_hdmi_init(void) | 2412 | static int __init patch_hdmi_init(void) |
2385 | { | 2413 | { |
2386 | return snd_hda_add_codec_preset(&intel_list); | 2414 | return snd_hda_add_codec_preset(&intel_list); |
2387 | } | 2415 | } |
2388 | 2416 | ||
2389 | static void __exit patch_hdmi_exit(void) | 2417 | static void __exit patch_hdmi_exit(void) |
2390 | { | 2418 | { |
2391 | snd_hda_delete_codec_preset(&intel_list); | 2419 | snd_hda_delete_codec_preset(&intel_list); |
2392 | } | 2420 | } |
2393 | 2421 | ||
2394 | module_init(patch_hdmi_init) | 2422 | module_init(patch_hdmi_init) |
2395 | module_exit(patch_hdmi_exit) | 2423 | module_exit(patch_hdmi_exit) |
2396 | 2424 |