aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-03-21 07:18:33 -0400
committerTakashi Iwai <tiwai@suse.de>2016-03-28 03:38:40 -0400
commita686632fd9a857776798f3479e2b58b07d938076 (patch)
treedcf3b4842c0ef238cd0176ca551e75007aa2fe6d /sound/pci/hda/patch_hdmi.c
parent5c5daf9188e24c38ad931b2e28253997e777f9c8 (diff)
ALSA: hda - Split out Intel-specific codes from patch_generic_hdmi()
We have too many Intel-specific codes in patch_hdmi_generic() despite its function name. And this makes it difficult to adjust per chipset, e.g. for allowing the audio notifier on an old chipset, one would need to add an explicit if() check. This patch attempts some code refactoring and cleanups in this regard; the Intel-specific codes are moved out of patch_generic_hdmi() into the new functions, patch_i915_hsw_hdmi() and patch_i915_byt_hdmi(), depending on the chipset. The other old Intel chipsets keep using patch_generic_hdmi() without Intel hacks. The existing patch_generic_hdmi() is also split to a few components so that they can be called from the Intel codec parsers. There are still many is_haswell*() and is_valleyview*() macro usages in the code. They will be cleaned up later. For the time being, only the entry are concerned. Along with this change, the i915_bound flag and the on-demand i915 component binding have been removed as a cleanup, since there is no user at this moment. This will be added back later once when Cougar Point and else start using the i915 eld notifier. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c218
1 files changed, 139 insertions, 79 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 5af372d01834..48c63fea7018 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -154,7 +154,6 @@ struct hdmi_spec {
154 /* i915/powerwell (Haswell+/Valleyview+) specific */ 154 /* i915/powerwell (Haswell+/Valleyview+) specific */
155 bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ 155 bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */
156 struct i915_audio_component_audio_ops i915_audio_ops; 156 struct i915_audio_component_audio_ops i915_audio_ops;
157 bool i915_bound; /* was i915 bound in this driver? */
158 157
159 struct hdac_chmap chmap; 158 struct hdac_chmap chmap;
160}; 159};
@@ -2074,6 +2073,18 @@ static void hdmi_array_free(struct hdmi_spec *spec)
2074 snd_array_free(&spec->cvts); 2073 snd_array_free(&spec->cvts);
2075} 2074}
2076 2075
2076static void generic_spec_free(struct hda_codec *codec)
2077{
2078 struct hdmi_spec *spec = codec->spec;
2079
2080 if (spec) {
2081 hdmi_array_free(spec);
2082 kfree(spec);
2083 codec->spec = NULL;
2084 }
2085 codec->dp_mst = false;
2086}
2087
2077static void generic_hdmi_free(struct hda_codec *codec) 2088static void generic_hdmi_free(struct hda_codec *codec)
2078{ 2089{
2079 struct hdmi_spec *spec = codec->spec; 2090 struct hdmi_spec *spec = codec->spec;
@@ -2098,10 +2109,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
2098 spec->pcm_rec[pcm_idx].jack = NULL; 2109 spec->pcm_rec[pcm_idx].jack = NULL;
2099 } 2110 }
2100 2111
2101 if (spec->i915_bound) 2112 generic_spec_free(codec);
2102 snd_hdac_i915_exit(&codec->bus->core);
2103 hdmi_array_free(spec);
2104 kfree(spec);
2105} 2113}
2106 2114
2107#ifdef CONFIG_PM 2115#ifdef CONFIG_PM
@@ -2139,6 +2147,54 @@ static const struct hdmi_ops generic_standard_hdmi_ops = {
2139 .setup_stream = hdmi_setup_stream, 2147 .setup_stream = hdmi_setup_stream,
2140}; 2148};
2141 2149
2150/* allocate codec->spec and assign/initialize generic parser ops */
2151static int alloc_generic_hdmi(struct hda_codec *codec)
2152{
2153 struct hdmi_spec *spec;
2154
2155 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2156 if (!spec)
2157 return -ENOMEM;
2158
2159 spec->ops = generic_standard_hdmi_ops;
2160 mutex_init(&spec->pcm_lock);
2161 snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
2162
2163 spec->chmap.ops.get_chmap = hdmi_get_chmap;
2164 spec->chmap.ops.set_chmap = hdmi_set_chmap;
2165 spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached;
2166
2167 codec->spec = spec;
2168 hdmi_array_init(spec, 4);
2169
2170 codec->patch_ops = generic_hdmi_patch_ops;
2171
2172 return 0;
2173}
2174
2175/* generic HDMI parser */
2176static int patch_generic_hdmi(struct hda_codec *codec)
2177{
2178 int err;
2179
2180 err = alloc_generic_hdmi(codec);
2181 if (err < 0)
2182 return err;
2183
2184 err = hdmi_parse_codec(codec);
2185 if (err < 0) {
2186 generic_spec_free(codec);
2187 return err;
2188 }
2189
2190 generic_hdmi_init_per_pins(codec);
2191 return 0;
2192}
2193
2194/*
2195 * Intel codec parsers and helpers
2196 */
2197
2142static void intel_haswell_fixup_connect_list(struct hda_codec *codec, 2198static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
2143 hda_nid_t nid) 2199 hda_nid_t nid)
2144{ 2200{
@@ -2234,92 +2290,96 @@ static void intel_pin_eld_notify(void *audio_ptr, int port)
2234 check_presence_and_report(codec, pin_nid); 2290 check_presence_and_report(codec, pin_nid);
2235} 2291}
2236 2292
2237static int patch_generic_hdmi(struct hda_codec *codec) 2293/* register i915 component pin_eld_notify callback */
2294static void register_i915_notifier(struct hda_codec *codec)
2238{ 2295{
2239 struct hdmi_spec *spec; 2296 struct hdmi_spec *spec = codec->spec;
2240
2241 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2242 if (spec == NULL)
2243 return -ENOMEM;
2244
2245 spec->ops = generic_standard_hdmi_ops;
2246 mutex_init(&spec->pcm_lock);
2247 snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
2248 2297
2249 spec->chmap.ops.get_chmap = hdmi_get_chmap; 2298 spec->use_acomp_notifier = true;
2250 spec->chmap.ops.set_chmap = hdmi_set_chmap; 2299 spec->i915_audio_ops.audio_ptr = codec;
2251 spec->chmap.ops.is_pcm_attached = is_hdmi_pcm_attached; 2300 /* intel_audio_codec_enable() or intel_audio_codec_disable()
2301 * will call pin_eld_notify with using audio_ptr pointer
2302 * We need make sure audio_ptr is really setup
2303 */
2304 wmb();
2305 spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
2306 snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
2307}
2252 2308
2253 codec->spec = spec; 2309/* Intel Haswell and onwards; audio component with eld notifier */
2254 hdmi_array_init(spec, 4); 2310static int patch_i915_hsw_hdmi(struct hda_codec *codec)
2311{
2312 struct hdmi_spec *spec;
2313 int err;
2255 2314
2256#ifdef CONFIG_SND_HDA_I915 2315 /* HSW+ requires i915 binding */
2257 /* Try to bind with i915 for Intel HSW+ codecs (if not done yet) */ 2316 if (!codec->bus->core.audio_component) {
2258 if ((codec->core.vendor_id >> 16) == 0x8086 && 2317 codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
2259 is_haswell_plus(codec)) { 2318 return -ENODEV;
2260#if 0
2261 /* on-demand binding leads to an unbalanced refcount when
2262 * both i915 and hda drivers are probed concurrently;
2263 * disabled temporarily for now
2264 */
2265 if (!codec->bus->core.audio_component)
2266 if (!snd_hdac_i915_init(&codec->bus->core))
2267 spec->i915_bound = true;
2268#endif
2269 /* use i915 audio component notifier for hotplug */
2270 if (codec->bus->core.audio_component)
2271 spec->use_acomp_notifier = true;
2272 } 2319 }
2273#endif
2274 2320
2275 if (is_haswell_plus(codec)) { 2321 err = alloc_generic_hdmi(codec);
2276 intel_haswell_enable_all_pins(codec, true); 2322 if (err < 0)
2277 intel_haswell_fixup_enable_dp12(codec); 2323 return err;
2278 } 2324 spec = codec->spec;
2279 2325
2280 /* For Valleyview/Cherryview, only the display codec is in the display 2326 intel_haswell_enable_all_pins(codec, true);
2281 * power well and can use link_power ops to request/release the power. 2327 intel_haswell_fixup_enable_dp12(codec);
2282 * For Haswell/Broadwell, the controller is also in the power well and 2328
2329 /* For Haswell/Broadwell, the controller is also in the power well and
2283 * can cover the codec power request, and so need not set this flag. 2330 * can cover the codec power request, and so need not set this flag.
2284 * For previous platforms, there is no such power well feature.
2285 */ 2331 */
2286 if (is_valleyview_plus(codec) || is_skylake(codec) || 2332 if (!is_haswell(codec) && !is_broadwell(codec))
2287 is_broxton(codec))
2288 codec->core.link_power_control = 1; 2333 codec->core.link_power_control = 1;
2289 2334
2290 if (hdmi_parse_codec(codec) < 0) { 2335 codec->patch_ops.set_power_state = haswell_set_power_state;
2291 if (spec->i915_bound) 2336 codec->dp_mst = true;
2292 snd_hdac_i915_exit(&codec->bus->core); 2337 codec->depop_delay = 0;
2293 codec->spec = NULL; 2338 codec->auto_runtime_pm = 1;
2294 kfree(spec); 2339
2295 return -EINVAL; 2340 err = hdmi_parse_codec(codec);
2341 if (err < 0) {
2342 generic_spec_free(codec);
2343 return err;
2296 } 2344 }
2297 codec->patch_ops = generic_hdmi_patch_ops; 2345
2298 if (is_haswell_plus(codec)) { 2346 generic_hdmi_init_per_pins(codec);
2299 codec->patch_ops.set_power_state = haswell_set_power_state; 2347 register_i915_notifier(codec);
2300 codec->dp_mst = true; 2348 return 0;
2349}
2350
2351/* Intel Baytrail and Braswell; without get_eld notifier */
2352static int patch_i915_byt_hdmi(struct hda_codec *codec)
2353{
2354 struct hdmi_spec *spec;
2355 int err;
2356
2357 /* requires i915 binding */
2358 if (!codec->bus->core.audio_component) {
2359 codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n");
2360 return -ENODEV;
2301 } 2361 }
2302 2362
2303 /* Enable runtime pm for HDMI audio codec of HSW/BDW/SKL/BYT/BSW */ 2363 err = alloc_generic_hdmi(codec);
2304 if (is_haswell_plus(codec) || is_valleyview_plus(codec)) 2364 if (err < 0)
2305 codec->auto_runtime_pm = 1; 2365 return err;
2366 spec = codec->spec;
2306 2367
2307 generic_hdmi_init_per_pins(codec); 2368 /* For Valleyview/Cherryview, only the display codec is in the display
2369 * power well and can use link_power ops to request/release the power.
2370 */
2371 codec->core.link_power_control = 1;
2308 2372
2373 codec->depop_delay = 0;
2374 codec->auto_runtime_pm = 1;
2309 2375
2310 if (codec_has_acomp(codec)) { 2376 err = hdmi_parse_codec(codec);
2311 codec->depop_delay = 0; 2377 if (err < 0) {
2312 spec->i915_audio_ops.audio_ptr = codec; 2378 generic_spec_free(codec);
2313 /* intel_audio_codec_enable() or intel_audio_codec_disable() 2379 return err;
2314 * will call pin_eld_notify with using audio_ptr pointer
2315 * We need make sure audio_ptr is really setup
2316 */
2317 wmb();
2318 spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
2319 snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
2320 } 2380 }
2321 2381
2322 WARN_ON(spec->dyn_pcm_assign && !codec_has_acomp(codec)); 2382 generic_hdmi_init_per_pins(codec);
2323 return 0; 2383 return 0;
2324} 2384}
2325 2385
@@ -3498,14 +3558,14 @@ HDA_CODEC_ENTRY(0x80862803, "Eaglelake HDMI", patch_generic_hdmi),
3498HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_generic_hdmi), 3558HDA_CODEC_ENTRY(0x80862804, "IbexPeak HDMI", patch_generic_hdmi),
3499HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_generic_hdmi), 3559HDA_CODEC_ENTRY(0x80862805, "CougarPoint HDMI", patch_generic_hdmi),
3500HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_generic_hdmi), 3560HDA_CODEC_ENTRY(0x80862806, "PantherPoint HDMI", patch_generic_hdmi),
3501HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_generic_hdmi), 3561HDA_CODEC_ENTRY(0x80862807, "Haswell HDMI", patch_i915_hsw_hdmi),
3502HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_generic_hdmi), 3562HDA_CODEC_ENTRY(0x80862808, "Broadwell HDMI", patch_i915_hsw_hdmi),
3503HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_generic_hdmi), 3563HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi),
3504HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_generic_hdmi), 3564HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi),
3505HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_generic_hdmi), 3565HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi),
3506HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), 3566HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
3507HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_generic_hdmi), 3567HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
3508HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_generic_hdmi), 3568HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
3509HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI", patch_generic_hdmi), 3569HDA_CODEC_ENTRY(0x808629fb, "Crestline HDMI", patch_generic_hdmi),
3510/* special ID for generic HDMI */ 3570/* special ID for generic HDMI */
3511HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi), 3571HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC_HDMI, "Generic HDMI", patch_generic_hdmi),