1df0566a6SJani Nikula /* 2df0566a6SJani Nikula * Copyright © 2014 Intel Corporation 3df0566a6SJani Nikula * 4df0566a6SJani Nikula * Permission is hereby granted, free of charge, to any person obtaining a 5df0566a6SJani Nikula * copy of this software and associated documentation files (the "Software"), 6df0566a6SJani Nikula * to deal in the Software without restriction, including without limitation 7df0566a6SJani Nikula * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8df0566a6SJani Nikula * and/or sell copies of the Software, and to permit persons to whom the 9df0566a6SJani Nikula * Software is furnished to do so, subject to the following conditions: 10df0566a6SJani Nikula * 11df0566a6SJani Nikula * The above copyright notice and this permission notice (including the next 12df0566a6SJani Nikula * paragraph) shall be included in all copies or substantial portions of the 13df0566a6SJani Nikula * Software. 14df0566a6SJani Nikula * 15df0566a6SJani Nikula * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16df0566a6SJani Nikula * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17df0566a6SJani Nikula * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18df0566a6SJani Nikula * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19df0566a6SJani Nikula * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20df0566a6SJani Nikula * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21df0566a6SJani Nikula * DEALINGS IN THE SOFTWARE. 22df0566a6SJani Nikula */ 23df0566a6SJani Nikula 24df0566a6SJani Nikula #include <linux/component.h> 25df0566a6SJani Nikula #include <linux/kernel.h> 26df0566a6SJani Nikula 27df0566a6SJani Nikula #include <drm/drm_edid.h> 28439590acSJani Nikula #include <drm/drm_eld.h> 292796b7ceSImre Deak #include <drm/drm_fixed.h> 301bb01bdaSJani Nikula #include <drm/intel/i915_component.h> 31df0566a6SJani Nikula 32df0566a6SJani Nikula #include "i915_drv.h" 331d5a95b5SVille Syrjälä #include "intel_atomic.h" 34df0566a6SJani Nikula #include "intel_audio.h" 35b43edc50SJani Nikula #include "intel_audio_regs.h" 3628a30b45SVille Syrjälä #include "intel_cdclk.h" 37fd2b94a5SJani Nikula #include "intel_crtc.h" 387785ae0bSVille Syrjälä #include "intel_de.h" 391d455f8dSJani Nikula #include "intel_display_types.h" 40df0566a6SJani Nikula #include "intel_lpe_audio.h" 41df0566a6SJani Nikula 42df0566a6SJani Nikula /** 43df0566a6SJani Nikula * DOC: High Definition Audio over HDMI and Display Port 44df0566a6SJani Nikula * 45df0566a6SJani Nikula * The graphics and audio drivers together support High Definition Audio over 46df0566a6SJani Nikula * HDMI and Display Port. The audio programming sequences are divided into audio 47df0566a6SJani Nikula * codec and controller enable and disable sequences. The graphics driver 48df0566a6SJani Nikula * handles the audio codec sequences, while the audio driver handles the audio 49df0566a6SJani Nikula * controller sequences. 50df0566a6SJani Nikula * 51df0566a6SJani Nikula * The disable sequences must be performed before disabling the transcoder or 52df0566a6SJani Nikula * port. The enable sequences may only be performed after enabling the 53df0566a6SJani Nikula * transcoder and port, and after completed link training. Therefore the audio 54df0566a6SJani Nikula * enable/disable sequences are part of the modeset sequence. 55df0566a6SJani Nikula * 56df0566a6SJani Nikula * The codec and controller sequences could be done either parallel or serial, 57df0566a6SJani Nikula * but generally the ELDV/PD change in the codec sequence indicates to the audio 58df0566a6SJani Nikula * driver that the controller sequence should start. Indeed, most of the 59df0566a6SJani Nikula * co-operation between the graphics and audio drivers is handled via audio 60df0566a6SJani Nikula * related registers. (The notable exception is the power management, not 61df0566a6SJani Nikula * covered here.) 62df0566a6SJani Nikula * 63df0566a6SJani Nikula * The struct &i915_audio_component is used to interact between the graphics 64df0566a6SJani Nikula * and audio drivers. The struct &i915_audio_component_ops @ops in it is 65df0566a6SJani Nikula * defined in graphics driver and called in audio driver. The 66df0566a6SJani Nikula * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver. 67df0566a6SJani Nikula */ 68df0566a6SJani Nikula 695d453746SJani Nikula struct intel_audio_funcs { 705d453746SJani Nikula void (*audio_codec_enable)(struct intel_encoder *encoder, 715d453746SJani Nikula const struct intel_crtc_state *crtc_state, 725d453746SJani Nikula const struct drm_connector_state *conn_state); 735d453746SJani Nikula void (*audio_codec_disable)(struct intel_encoder *encoder, 745d453746SJani Nikula const struct intel_crtc_state *old_crtc_state, 755d453746SJani Nikula const struct drm_connector_state *old_conn_state); 7661a60df6SVille Syrjälä void (*audio_codec_get_config)(struct intel_encoder *encoder, 7761a60df6SVille Syrjälä struct intel_crtc_state *crtc_state); 785d453746SJani Nikula }; 795d453746SJani Nikula 802c291417SAditya Swarup struct hdmi_aud_ncts { 812c291417SAditya Swarup int sample_rate; 822c291417SAditya Swarup int clock; 832c291417SAditya Swarup int n; 842c291417SAditya Swarup int cts; 852c291417SAditya Swarup }; 862c291417SAditya Swarup 87df0566a6SJani Nikula static const struct { 88df0566a6SJani Nikula int clock; 89df0566a6SJani Nikula u32 config; 90df0566a6SJani Nikula } hdmi_audio_clock[] = { 91df0566a6SJani Nikula { 25175, AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, 92df0566a6SJani Nikula { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ 93df0566a6SJani Nikula { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, 94df0566a6SJani Nikula { 27027, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, 95df0566a6SJani Nikula { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, 96df0566a6SJani Nikula { 54054, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, 97df0566a6SJani Nikula { 74176, AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, 98df0566a6SJani Nikula { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, 99df0566a6SJani Nikula { 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, 100df0566a6SJani Nikula { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, 1011aae3065SKai Vehmanen { 296703, AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 }, 1021aae3065SKai Vehmanen { 297000, AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 }, 1031aae3065SKai Vehmanen { 593407, AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 }, 1041aae3065SKai Vehmanen { 594000, AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 }, 105df0566a6SJani Nikula }; 106df0566a6SJani Nikula 107df0566a6SJani Nikula /* HDMI N/CTS table */ 108df0566a6SJani Nikula #define TMDS_297M 297000 109df0566a6SJani Nikula #define TMDS_296M 296703 110df0566a6SJani Nikula #define TMDS_594M 594000 111df0566a6SJani Nikula #define TMDS_593M 593407 112df0566a6SJani Nikula 1132c291417SAditya Swarup static const struct hdmi_aud_ncts hdmi_aud_ncts_24bpp[] = { 114df0566a6SJani Nikula { 32000, TMDS_296M, 5824, 421875 }, 115df0566a6SJani Nikula { 32000, TMDS_297M, 3072, 222750 }, 116df0566a6SJani Nikula { 32000, TMDS_593M, 5824, 843750 }, 117df0566a6SJani Nikula { 32000, TMDS_594M, 3072, 445500 }, 118df0566a6SJani Nikula { 44100, TMDS_296M, 4459, 234375 }, 119df0566a6SJani Nikula { 44100, TMDS_297M, 4704, 247500 }, 120df0566a6SJani Nikula { 44100, TMDS_593M, 8918, 937500 }, 121df0566a6SJani Nikula { 44100, TMDS_594M, 9408, 990000 }, 122df0566a6SJani Nikula { 88200, TMDS_296M, 8918, 234375 }, 123df0566a6SJani Nikula { 88200, TMDS_297M, 9408, 247500 }, 124df0566a6SJani Nikula { 88200, TMDS_593M, 17836, 937500 }, 125df0566a6SJani Nikula { 88200, TMDS_594M, 18816, 990000 }, 126df0566a6SJani Nikula { 176400, TMDS_296M, 17836, 234375 }, 127df0566a6SJani Nikula { 176400, TMDS_297M, 18816, 247500 }, 128df0566a6SJani Nikula { 176400, TMDS_593M, 35672, 937500 }, 129df0566a6SJani Nikula { 176400, TMDS_594M, 37632, 990000 }, 130df0566a6SJani Nikula { 48000, TMDS_296M, 5824, 281250 }, 131df0566a6SJani Nikula { 48000, TMDS_297M, 5120, 247500 }, 132df0566a6SJani Nikula { 48000, TMDS_593M, 5824, 562500 }, 133df0566a6SJani Nikula { 48000, TMDS_594M, 6144, 594000 }, 134df0566a6SJani Nikula { 96000, TMDS_296M, 11648, 281250 }, 135df0566a6SJani Nikula { 96000, TMDS_297M, 10240, 247500 }, 136df0566a6SJani Nikula { 96000, TMDS_593M, 11648, 562500 }, 137df0566a6SJani Nikula { 96000, TMDS_594M, 12288, 594000 }, 138df0566a6SJani Nikula { 192000, TMDS_296M, 23296, 281250 }, 139df0566a6SJani Nikula { 192000, TMDS_297M, 20480, 247500 }, 140df0566a6SJani Nikula { 192000, TMDS_593M, 23296, 562500 }, 141df0566a6SJani Nikula { 192000, TMDS_594M, 24576, 594000 }, 142df0566a6SJani Nikula }; 143df0566a6SJani Nikula 1442c291417SAditya Swarup /* Appendix C - N & CTS values for deep color from HDMI 2.0 spec*/ 1452c291417SAditya Swarup /* HDMI N/CTS table for 10 bit deep color(30 bpp)*/ 1462c291417SAditya Swarup #define TMDS_371M 371250 1472c291417SAditya Swarup #define TMDS_370M 370878 1482c291417SAditya Swarup 1492c291417SAditya Swarup static const struct hdmi_aud_ncts hdmi_aud_ncts_30bpp[] = { 1502c291417SAditya Swarup { 32000, TMDS_370M, 5824, 527344 }, 1512c291417SAditya Swarup { 32000, TMDS_371M, 6144, 556875 }, 1522c291417SAditya Swarup { 44100, TMDS_370M, 8918, 585938 }, 1532c291417SAditya Swarup { 44100, TMDS_371M, 4704, 309375 }, 1542c291417SAditya Swarup { 88200, TMDS_370M, 17836, 585938 }, 1552c291417SAditya Swarup { 88200, TMDS_371M, 9408, 309375 }, 1562c291417SAditya Swarup { 176400, TMDS_370M, 35672, 585938 }, 1572c291417SAditya Swarup { 176400, TMDS_371M, 18816, 309375 }, 1582c291417SAditya Swarup { 48000, TMDS_370M, 11648, 703125 }, 1592c291417SAditya Swarup { 48000, TMDS_371M, 5120, 309375 }, 1602c291417SAditya Swarup { 96000, TMDS_370M, 23296, 703125 }, 1612c291417SAditya Swarup { 96000, TMDS_371M, 10240, 309375 }, 1622c291417SAditya Swarup { 192000, TMDS_370M, 46592, 703125 }, 1632c291417SAditya Swarup { 192000, TMDS_371M, 20480, 309375 }, 1642c291417SAditya Swarup }; 1652c291417SAditya Swarup 1662c291417SAditya Swarup /* HDMI N/CTS table for 12 bit deep color(36 bpp)*/ 1672c291417SAditya Swarup #define TMDS_445_5M 445500 1682c291417SAditya Swarup #define TMDS_445M 445054 1692c291417SAditya Swarup 1702c291417SAditya Swarup static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = { 1712c291417SAditya Swarup { 32000, TMDS_445M, 5824, 632813 }, 1722c291417SAditya Swarup { 32000, TMDS_445_5M, 4096, 445500 }, 1732c291417SAditya Swarup { 44100, TMDS_445M, 8918, 703125 }, 1742c291417SAditya Swarup { 44100, TMDS_445_5M, 4704, 371250 }, 1752c291417SAditya Swarup { 88200, TMDS_445M, 17836, 703125 }, 1762c291417SAditya Swarup { 88200, TMDS_445_5M, 9408, 371250 }, 1772c291417SAditya Swarup { 176400, TMDS_445M, 35672, 703125 }, 1782c291417SAditya Swarup { 176400, TMDS_445_5M, 18816, 371250 }, 1792c291417SAditya Swarup { 48000, TMDS_445M, 5824, 421875 }, 1802c291417SAditya Swarup { 48000, TMDS_445_5M, 5120, 371250 }, 1812c291417SAditya Swarup { 96000, TMDS_445M, 11648, 421875 }, 1822c291417SAditya Swarup { 96000, TMDS_445_5M, 10240, 371250 }, 1832c291417SAditya Swarup { 192000, TMDS_445M, 23296, 421875 }, 1842c291417SAditya Swarup { 192000, TMDS_445_5M, 20480, 371250 }, 1852c291417SAditya Swarup }; 1862c291417SAditya Swarup 18756c12ec7SUma Shankar /* 18856c12ec7SUma Shankar * WA_14020863754: Implement Audio Workaround 18956c12ec7SUma Shankar * Corner case with Min Hblank Fix can cause audio hang 19056c12ec7SUma Shankar */ 19156c12ec7SUma Shankar static bool needs_wa_14020863754(struct drm_i915_private *i915) 19256c12ec7SUma Shankar { 19356c12ec7SUma Shankar return (DISPLAY_VER(i915) == 20 || IS_BATTLEMAGE(i915)); 19456c12ec7SUma Shankar } 19556c12ec7SUma Shankar 196df0566a6SJani Nikula /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ 197df0566a6SJani Nikula static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) 198df0566a6SJani Nikula { 19946e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 200df0566a6SJani Nikula const struct drm_display_mode *adjusted_mode = 2011326a92cSMaarten Lankhorst &crtc_state->hw.adjusted_mode; 202df0566a6SJani Nikula int i; 203df0566a6SJani Nikula 204df0566a6SJani Nikula for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { 205df0566a6SJani Nikula if (adjusted_mode->crtc_clock == hdmi_audio_clock[i].clock) 206df0566a6SJani Nikula break; 207df0566a6SJani Nikula } 208df0566a6SJani Nikula 20946e61ee4SVille Syrjälä if (DISPLAY_VER(i915) < 12 && adjusted_mode->crtc_clock > 148500) 2101aae3065SKai Vehmanen i = ARRAY_SIZE(hdmi_audio_clock); 2111aae3065SKai Vehmanen 212df0566a6SJani Nikula if (i == ARRAY_SIZE(hdmi_audio_clock)) { 21346e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, 2149282a66cSJani Nikula "HDMI audio pixel clock setting for %d not found, falling back to defaults\n", 215df0566a6SJani Nikula adjusted_mode->crtc_clock); 216df0566a6SJani Nikula i = 1; 217df0566a6SJani Nikula } 218df0566a6SJani Nikula 21946e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, 2209282a66cSJani Nikula "Configuring HDMI audio for pixel clock %d (0x%08x)\n", 221df0566a6SJani Nikula hdmi_audio_clock[i].clock, 222df0566a6SJani Nikula hdmi_audio_clock[i].config); 223df0566a6SJani Nikula 224df0566a6SJani Nikula return hdmi_audio_clock[i].config; 225df0566a6SJani Nikula } 226df0566a6SJani Nikula 227df0566a6SJani Nikula static int audio_config_hdmi_get_n(const struct intel_crtc_state *crtc_state, 228df0566a6SJani Nikula int rate) 229df0566a6SJani Nikula { 2302c291417SAditya Swarup const struct hdmi_aud_ncts *hdmi_ncts_table; 2312c291417SAditya Swarup int i, size; 232df0566a6SJani Nikula 2332c291417SAditya Swarup if (crtc_state->pipe_bpp == 36) { 2342c291417SAditya Swarup hdmi_ncts_table = hdmi_aud_ncts_36bpp; 2352c291417SAditya Swarup size = ARRAY_SIZE(hdmi_aud_ncts_36bpp); 2362c291417SAditya Swarup } else if (crtc_state->pipe_bpp == 30) { 2372c291417SAditya Swarup hdmi_ncts_table = hdmi_aud_ncts_30bpp; 2382c291417SAditya Swarup size = ARRAY_SIZE(hdmi_aud_ncts_30bpp); 2392c291417SAditya Swarup } else { 2402c291417SAditya Swarup hdmi_ncts_table = hdmi_aud_ncts_24bpp; 2412c291417SAditya Swarup size = ARRAY_SIZE(hdmi_aud_ncts_24bpp); 2422c291417SAditya Swarup } 2432c291417SAditya Swarup 2442c291417SAditya Swarup for (i = 0; i < size; i++) { 2452c291417SAditya Swarup if (rate == hdmi_ncts_table[i].sample_rate && 2462c291417SAditya Swarup crtc_state->port_clock == hdmi_ncts_table[i].clock) { 2472c291417SAditya Swarup return hdmi_ncts_table[i].n; 248df0566a6SJani Nikula } 249df0566a6SJani Nikula } 250df0566a6SJani Nikula return 0; 251df0566a6SJani Nikula } 252df0566a6SJani Nikula 2531c0ab71aSVille Syrjälä /* ELD buffer size in dwords */ 2541c0ab71aSVille Syrjälä static int g4x_eld_buffer_size(struct drm_i915_private *i915) 2551c0ab71aSVille Syrjälä { 2561c0ab71aSVille Syrjälä u32 tmp; 2571c0ab71aSVille Syrjälä 2581c0ab71aSVille Syrjälä tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); 2591c0ab71aSVille Syrjälä 2601c0ab71aSVille Syrjälä return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp); 2611c0ab71aSVille Syrjälä } 2621c0ab71aSVille Syrjälä 26361a60df6SVille Syrjälä static void g4x_audio_codec_get_config(struct intel_encoder *encoder, 26461a60df6SVille Syrjälä struct intel_crtc_state *crtc_state) 26561a60df6SVille Syrjälä { 26661a60df6SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 26761a60df6SVille Syrjälä u32 *eld = (u32 *)crtc_state->eld; 26861a60df6SVille Syrjälä int eld_buffer_size, len, i; 26961a60df6SVille Syrjälä u32 tmp; 27061a60df6SVille Syrjälä 27161a60df6SVille Syrjälä tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); 27261a60df6SVille Syrjälä if ((tmp & G4X_ELD_VALID) == 0) 27361a60df6SVille Syrjälä return; 27461a60df6SVille Syrjälä 27561a60df6SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, G4X_ELD_ADDRESS_MASK, 0); 27661a60df6SVille Syrjälä 27761a60df6SVille Syrjälä eld_buffer_size = g4x_eld_buffer_size(i915); 27861a60df6SVille Syrjälä len = min_t(int, sizeof(crtc_state->eld) / 4, eld_buffer_size); 27961a60df6SVille Syrjälä 28061a60df6SVille Syrjälä for (i = 0; i < len; i++) 28161a60df6SVille Syrjälä eld[i] = intel_de_read(i915, G4X_HDMIW_HDMIEDID); 28261a60df6SVille Syrjälä } 28361a60df6SVille Syrjälä 284df0566a6SJani Nikula static void g4x_audio_codec_disable(struct intel_encoder *encoder, 285df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 286df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 287df0566a6SJani Nikula { 28846e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 289c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 290df0566a6SJani Nikula 291df0566a6SJani Nikula /* Invalidate ELD */ 2927c8d74e8SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, 2937c8d74e8SVille Syrjälä G4X_ELD_VALID, 0); 294c3c5dc1dSVille Syrjälä 295c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 296c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 297df0566a6SJani Nikula } 298df0566a6SJani Nikula 299df0566a6SJani Nikula static void g4x_audio_codec_enable(struct intel_encoder *encoder, 300df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 301df0566a6SJani Nikula const struct drm_connector_state *conn_state) 302df0566a6SJani Nikula { 30346e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 304c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 3055d986635SVille Syrjälä const u32 *eld = (const u32 *)crtc_state->eld; 3060234cda2SVille Syrjälä int eld_buffer_size, len, i; 307df0566a6SJani Nikula 308c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 309c3c5dc1dSVille Syrjälä 3107c8d74e8SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, 3117c8d74e8SVille Syrjälä G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0); 312df0566a6SJani Nikula 3130234cda2SVille Syrjälä eld_buffer_size = g4x_eld_buffer_size(i915); 3145d986635SVille Syrjälä len = min(drm_eld_size(crtc_state->eld) / 4, eld_buffer_size); 3151c0ab71aSVille Syrjälä 316df0566a6SJani Nikula for (i = 0; i < len; i++) 31750a4a926SVille Syrjälä intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]); 3180234cda2SVille Syrjälä for (; i < eld_buffer_size; i++) 3190234cda2SVille Syrjälä intel_de_write(i915, G4X_HDMIW_HDMIEDID, 0); 3200234cda2SVille Syrjälä 3210234cda2SVille Syrjälä drm_WARN_ON(&i915->drm, 3220234cda2SVille Syrjälä (intel_de_read(i915, G4X_AUD_CNTL_ST) & G4X_ELD_ADDRESS_MASK) != 0); 323df0566a6SJani Nikula 3247c8d74e8SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, 3257c8d74e8SVille Syrjälä 0, G4X_ELD_VALID); 326df0566a6SJani Nikula } 327df0566a6SJani Nikula 328df0566a6SJani Nikula static void 329df0566a6SJani Nikula hsw_dp_audio_config_update(struct intel_encoder *encoder, 330df0566a6SJani Nikula const struct intel_crtc_state *crtc_state) 331df0566a6SJani Nikula { 33246e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 333df0566a6SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 334df0566a6SJani Nikula 3358e056b50SChaitanya Kumar Borah /* Enable time stamps. Let HW calculate Maud/Naud values */ 3368e056b50SChaitanya Kumar Borah intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), 3378e056b50SChaitanya Kumar Borah AUD_CONFIG_N_VALUE_INDEX | 3388e056b50SChaitanya Kumar Borah AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK | 3398e056b50SChaitanya Kumar Borah AUD_CONFIG_UPPER_N_MASK | 3408e056b50SChaitanya Kumar Borah AUD_CONFIG_LOWER_N_MASK | 3418e056b50SChaitanya Kumar Borah AUD_CONFIG_N_PROG_ENABLE, 3428e056b50SChaitanya Kumar Borah AUD_CONFIG_N_VALUE_INDEX); 343df0566a6SJani Nikula 344df0566a6SJani Nikula } 345df0566a6SJani Nikula 346df0566a6SJani Nikula static void 347df0566a6SJani Nikula hsw_hdmi_audio_config_update(struct intel_encoder *encoder, 348df0566a6SJani Nikula const struct intel_crtc_state *crtc_state) 349df0566a6SJani Nikula { 35046e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 35146e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 352df0566a6SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 353df0566a6SJani Nikula enum port port = encoder->port; 354df0566a6SJani Nikula int n, rate; 355df0566a6SJani Nikula u32 tmp; 356df0566a6SJani Nikula 357df0566a6SJani Nikula rate = acomp ? acomp->aud_sample_rate[port] : 0; 358df0566a6SJani Nikula 35946e61ee4SVille Syrjälä tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder)); 360df0566a6SJani Nikula tmp &= ~AUD_CONFIG_N_VALUE_INDEX; 361df0566a6SJani Nikula tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; 362df0566a6SJani Nikula tmp &= ~AUD_CONFIG_N_PROG_ENABLE; 363df0566a6SJani Nikula tmp |= audio_config_hdmi_pixel_clock(crtc_state); 364df0566a6SJani Nikula 365df0566a6SJani Nikula n = audio_config_hdmi_get_n(crtc_state, rate); 366df0566a6SJani Nikula if (n != 0) { 36746e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, "using N %d\n", n); 368df0566a6SJani Nikula 369df0566a6SJani Nikula tmp &= ~AUD_CONFIG_N_MASK; 370df0566a6SJani Nikula tmp |= AUD_CONFIG_N(n); 371df0566a6SJani Nikula tmp |= AUD_CONFIG_N_PROG_ENABLE; 372df0566a6SJani Nikula } else { 37346e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, "using automatic N\n"); 374df0566a6SJani Nikula } 375df0566a6SJani Nikula 37646e61ee4SVille Syrjälä intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp); 377df0566a6SJani Nikula 378df0566a6SJani Nikula /* 379df0566a6SJani Nikula * Let's disable "Enable CTS or M Prog bit" 380df0566a6SJani Nikula * and let HW calculate the value 381df0566a6SJani Nikula */ 38246e61ee4SVille Syrjälä tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); 383df0566a6SJani Nikula tmp &= ~AUD_M_CTS_M_PROG_ENABLE; 384df0566a6SJani Nikula tmp &= ~AUD_M_CTS_M_VALUE_INDEX; 38546e61ee4SVille Syrjälä intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); 386df0566a6SJani Nikula } 387df0566a6SJani Nikula 388df0566a6SJani Nikula static void 389df0566a6SJani Nikula hsw_audio_config_update(struct intel_encoder *encoder, 390df0566a6SJani Nikula const struct intel_crtc_state *crtc_state) 391df0566a6SJani Nikula { 392df0566a6SJani Nikula if (intel_crtc_has_dp_encoder(crtc_state)) 393df0566a6SJani Nikula hsw_dp_audio_config_update(encoder, crtc_state); 394df0566a6SJani Nikula else 395df0566a6SJani Nikula hsw_hdmi_audio_config_update(encoder, crtc_state); 396df0566a6SJani Nikula } 397df0566a6SJani Nikula 398df0566a6SJani Nikula static void hsw_audio_codec_disable(struct intel_encoder *encoder, 399df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 400df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 401df0566a6SJani Nikula { 40246e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 403c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 404df0566a6SJani Nikula enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 405df0566a6SJani Nikula 40646e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 407df0566a6SJani Nikula 408df0566a6SJani Nikula /* Disable timestamps */ 4097c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), 4107c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX | 4117c8d74e8SVille Syrjälä AUD_CONFIG_UPPER_N_MASK | 4127c8d74e8SVille Syrjälä AUD_CONFIG_LOWER_N_MASK, 4137c8d74e8SVille Syrjälä AUD_CONFIG_N_PROG_ENABLE | 4147c8d74e8SVille Syrjälä (intel_crtc_has_dp_encoder(old_crtc_state) ? 4157c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX : 0)); 416df0566a6SJani Nikula 417cbbda2ffSVille Syrjälä /* Invalidate ELD */ 4187c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 419cbbda2ffSVille Syrjälä AUDIO_ELD_VALID(cpu_transcoder), 0); 420cbbda2ffSVille Syrjälä 421c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 422c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 423c3c5dc1dSVille Syrjälä 424cbbda2ffSVille Syrjälä /* Disable audio presence detect */ 425cbbda2ffSVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 4267c8d74e8SVille Syrjälä AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0); 427df0566a6SJani Nikula 42856c12ec7SUma Shankar if (needs_wa_14020863754(i915)) 42956c12ec7SUma Shankar intel_de_rmw(i915, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); 43056c12ec7SUma Shankar 43146e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 432df0566a6SJani Nikula } 433df0566a6SJani Nikula 4342dd43144SVille Syrjälä static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, 43548b8b04cSUma Shankar const struct intel_crtc_state *crtc_state) 43648b8b04cSUma Shankar { 43748b8b04cSUma Shankar struct drm_i915_private *i915 = to_i915(encoder->base.dev); 43848b8b04cSUma Shankar unsigned int link_clks_available, link_clks_required; 43948b8b04cSUma Shankar unsigned int tu_data, tu_line, link_clks_active; 440d19b29beSVille Syrjälä unsigned int h_active, h_total, hblank_delta, pixel_clk; 44108fcb5abSAnkit Nautiyal unsigned int fec_coeff, cdclk, vdsc_bppx16; 44241ee86d6SVille Syrjälä unsigned int link_clk, lanes; 4432dd43144SVille Syrjälä unsigned int hblank_rise; 44448b8b04cSUma Shankar 44548b8b04cSUma Shankar h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay; 44648b8b04cSUma Shankar h_total = crtc_state->hw.adjusted_mode.crtc_htotal; 44748b8b04cSUma Shankar pixel_clk = crtc_state->hw.adjusted_mode.crtc_clock; 44808fcb5abSAnkit Nautiyal vdsc_bppx16 = crtc_state->dsc.compressed_bpp_x16; 449d51309b4SJani Nikula cdclk = i915->display.cdclk.hw.cdclk; 45048b8b04cSUma Shankar /* fec= 0.972261, using rounding multiplier of 1000000 */ 45148b8b04cSUma Shankar fec_coeff = 972261; 45241ee86d6SVille Syrjälä link_clk = crtc_state->port_clock; 45341ee86d6SVille Syrjälä lanes = crtc_state->lane_count; 45448b8b04cSUma Shankar 45508fcb5abSAnkit Nautiyal drm_dbg_kms(&i915->drm, 4562796b7ceSImre Deak "h_active = %u link_clk = %u : lanes = %u vdsc_bpp = " FXP_Q4_FMT " cdclk = %u\n", 4572796b7ceSImre Deak h_active, link_clk, lanes, FXP_Q4_ARGS(vdsc_bppx16), cdclk); 45848b8b04cSUma Shankar 45908fcb5abSAnkit Nautiyal if (WARN_ON(!link_clk || !pixel_clk || !lanes || !vdsc_bppx16 || !cdclk)) 46011ebc232SJani Nikula return 0; 46111ebc232SJani Nikula 4622dd43144SVille Syrjälä link_clks_available = (h_total - h_active) * link_clk / pixel_clk - 28; 4632dd43144SVille Syrjälä link_clks_required = DIV_ROUND_UP(192000 * h_total, 1000 * pixel_clk) * (48 / lanes + 2); 46448b8b04cSUma Shankar 46548b8b04cSUma Shankar if (link_clks_available > link_clks_required) 46648b8b04cSUma Shankar hblank_delta = 32; 46748b8b04cSUma Shankar else 4682dd43144SVille Syrjälä hblank_delta = DIV64_U64_ROUND_UP(mul_u32_u32(5 * (link_clk + cdclk), pixel_clk), 4692dd43144SVille Syrjälä mul_u32_u32(link_clk, cdclk)); 47048b8b04cSUma Shankar 47108fcb5abSAnkit Nautiyal tu_data = div64_u64(mul_u32_u32(pixel_clk * vdsc_bppx16 * 8, 1000000), 47208fcb5abSAnkit Nautiyal mul_u32_u32(link_clk * lanes * 16, fec_coeff)); 4732dd43144SVille Syrjälä tu_line = div64_u64(h_active * mul_u32_u32(link_clk, fec_coeff), 4742dd43144SVille Syrjälä mul_u32_u32(64 * pixel_clk, 1000000)); 47548b8b04cSUma Shankar link_clks_active = (tu_line - 1) * 64 + tu_data; 47648b8b04cSUma Shankar 4772dd43144SVille Syrjälä hblank_rise = (link_clks_active + 6 * DIV_ROUND_UP(link_clks_active, 250) + 4) * pixel_clk / link_clk; 47848b8b04cSUma Shankar 4792dd43144SVille Syrjälä return h_active - hblank_rise + hblank_delta; 48048b8b04cSUma Shankar } 48148b8b04cSUma Shankar 4822dd43144SVille Syrjälä static unsigned int calc_samples_room(const struct intel_crtc_state *crtc_state) 48348b8b04cSUma Shankar { 48448b8b04cSUma Shankar unsigned int h_active, h_total, pixel_clk; 48541ee86d6SVille Syrjälä unsigned int link_clk, lanes; 48648b8b04cSUma Shankar 48748b8b04cSUma Shankar h_active = crtc_state->hw.adjusted_mode.hdisplay; 48848b8b04cSUma Shankar h_total = crtc_state->hw.adjusted_mode.htotal; 48948b8b04cSUma Shankar pixel_clk = crtc_state->hw.adjusted_mode.clock; 49041ee86d6SVille Syrjälä link_clk = crtc_state->port_clock; 49141ee86d6SVille Syrjälä lanes = crtc_state->lane_count; 49248b8b04cSUma Shankar 4932dd43144SVille Syrjälä return ((h_total - h_active) * link_clk - 12 * pixel_clk) / 4942dd43144SVille Syrjälä (pixel_clk * (48 / lanes + 2)); 49548b8b04cSUma Shankar } 49648b8b04cSUma Shankar 49748b8b04cSUma Shankar static void enable_audio_dsc_wa(struct intel_encoder *encoder, 49848b8b04cSUma Shankar const struct intel_crtc_state *crtc_state) 49948b8b04cSUma Shankar { 50048b8b04cSUma Shankar struct drm_i915_private *i915 = to_i915(encoder->base.dev); 5015eba7426SVille Syrjälä enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 50211ebc232SJani Nikula unsigned int hblank_early_prog, samples_room; 50348b8b04cSUma Shankar unsigned int val; 50448b8b04cSUma Shankar 505005e9537SMatt Roper if (DISPLAY_VER(i915) < 11) 50648b8b04cSUma Shankar return; 50748b8b04cSUma Shankar 50848b8b04cSUma Shankar val = intel_de_read(i915, AUD_CONFIG_BE); 50948b8b04cSUma Shankar 51093e7e61eSLucas De Marchi if (DISPLAY_VER(i915) == 11) 5115eba7426SVille Syrjälä val |= HBLANK_EARLY_ENABLE_ICL(cpu_transcoder); 512005e9537SMatt Roper else if (DISPLAY_VER(i915) >= 12) 5135eba7426SVille Syrjälä val |= HBLANK_EARLY_ENABLE_TGL(cpu_transcoder); 51448b8b04cSUma Shankar 51548b8b04cSUma Shankar if (crtc_state->dsc.compression_enable && 51631824c03SJani Nikula crtc_state->hw.adjusted_mode.hdisplay >= 3840 && 51731824c03SJani Nikula crtc_state->hw.adjusted_mode.vdisplay >= 2160) { 51848b8b04cSUma Shankar /* Get hblank early enable value required */ 5195eba7426SVille Syrjälä val &= ~HBLANK_START_COUNT_MASK(cpu_transcoder); 5202dd43144SVille Syrjälä hblank_early_prog = calc_hblank_early_prog(encoder, crtc_state); 521f4c50deeSJani Nikula if (hblank_early_prog < 32) 5225eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_32); 523f4c50deeSJani Nikula else if (hblank_early_prog < 64) 5245eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_64); 525f4c50deeSJani Nikula else if (hblank_early_prog < 96) 5265eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_96); 527f4c50deeSJani Nikula else 5285eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_128); 52948b8b04cSUma Shankar 53048b8b04cSUma Shankar /* Get samples room value required */ 5315eba7426SVille Syrjälä val &= ~NUMBER_SAMPLES_PER_LINE_MASK(cpu_transcoder); 5322dd43144SVille Syrjälä samples_room = calc_samples_room(crtc_state); 533f4c50deeSJani Nikula if (samples_room < 3) 5345eba7426SVille Syrjälä val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, samples_room); 535f4c50deeSJani Nikula else /* Program 0 i.e "All Samples available in buffer" */ 5365eba7426SVille Syrjälä val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, 0x0); 53748b8b04cSUma Shankar } 53848b8b04cSUma Shankar 53948b8b04cSUma Shankar intel_de_write(i915, AUD_CONFIG_BE, val); 54048b8b04cSUma Shankar } 54148b8b04cSUma Shankar 542df0566a6SJani Nikula static void hsw_audio_codec_enable(struct intel_encoder *encoder, 543df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 544df0566a6SJani Nikula const struct drm_connector_state *conn_state) 545df0566a6SJani Nikula { 54646e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 547c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 548df0566a6SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 549df0566a6SJani Nikula 55046e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 551df0566a6SJani Nikula 55248b8b04cSUma Shankar /* Enable Audio WA for 4k DSC usecases */ 55348b8b04cSUma Shankar if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) 55448b8b04cSUma Shankar enable_audio_dsc_wa(encoder, crtc_state); 55548b8b04cSUma Shankar 55656c12ec7SUma Shankar if (needs_wa_14020863754(i915)) 55756c12ec7SUma Shankar intel_de_rmw(i915, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); 55856c12ec7SUma Shankar 559cbbda2ffSVille Syrjälä /* Enable audio presence detect */ 5607c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 561cbbda2ffSVille Syrjälä 0, AUDIO_OUTPUT_ENABLE(cpu_transcoder)); 562cbbda2ffSVille Syrjälä 563c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 564c3c5dc1dSVille Syrjälä 565cbbda2ffSVille Syrjälä /* Invalidate ELD */ 566cbbda2ffSVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 567cbbda2ffSVille Syrjälä AUDIO_ELD_VALID(cpu_transcoder), 0); 568df0566a6SJani Nikula 56968470541SVille Syrjälä /* 57068470541SVille Syrjälä * The audio componenent is used to convey the ELD 57168470541SVille Syrjälä * instead using of the hardware ELD buffer. 57268470541SVille Syrjälä */ 573df0566a6SJani Nikula 574df0566a6SJani Nikula /* Enable timestamps */ 575df0566a6SJani Nikula hsw_audio_config_update(encoder, crtc_state); 576df0566a6SJani Nikula 57746e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 578df0566a6SJani Nikula } 579df0566a6SJani Nikula 5807e95cb09SVille Syrjälä struct ibx_audio_regs { 581669d7fd6SVille Syrjälä i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; 582669d7fd6SVille Syrjälä }; 583669d7fd6SVille Syrjälä 5847e95cb09SVille Syrjälä static void ibx_audio_regs_init(struct drm_i915_private *i915, 585669d7fd6SVille Syrjälä enum pipe pipe, 5867e95cb09SVille Syrjälä struct ibx_audio_regs *regs) 587669d7fd6SVille Syrjälä { 58831395fbaSVille Syrjälä if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { 589669d7fd6SVille Syrjälä regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); 590669d7fd6SVille Syrjälä regs->aud_config = VLV_AUD_CFG(pipe); 591669d7fd6SVille Syrjälä regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe); 592669d7fd6SVille Syrjälä regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2; 59331395fbaSVille Syrjälä } else if (HAS_PCH_CPT(i915)) { 594669d7fd6SVille Syrjälä regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); 595669d7fd6SVille Syrjälä regs->aud_config = CPT_AUD_CFG(pipe); 596669d7fd6SVille Syrjälä regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe); 597669d7fd6SVille Syrjälä regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; 59831395fbaSVille Syrjälä } else if (HAS_PCH_IBX(i915)) { 59931395fbaSVille Syrjälä regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); 60031395fbaSVille Syrjälä regs->aud_config = IBX_AUD_CFG(pipe); 60131395fbaSVille Syrjälä regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); 60231395fbaSVille Syrjälä regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; 603669d7fd6SVille Syrjälä } 604669d7fd6SVille Syrjälä } 605669d7fd6SVille Syrjälä 6067e95cb09SVille Syrjälä static void ibx_audio_codec_disable(struct intel_encoder *encoder, 607df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 608df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 609df0566a6SJani Nikula { 61046e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 6112225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 612df0566a6SJani Nikula enum port port = encoder->port; 6137c8d74e8SVille Syrjälä enum pipe pipe = crtc->pipe; 6147e95cb09SVille Syrjälä struct ibx_audio_regs regs; 615df0566a6SJani Nikula 61646e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, port == PORT_A)) 617df0566a6SJani Nikula return; 618df0566a6SJani Nikula 6197e95cb09SVille Syrjälä ibx_audio_regs_init(i915, pipe, ®s); 620df0566a6SJani Nikula 6219f4a5125SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 6229f4a5125SVille Syrjälä 623df0566a6SJani Nikula /* Disable timestamps */ 6247c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_config, 6257c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX | 6267c8d74e8SVille Syrjälä AUD_CONFIG_UPPER_N_MASK | 6277c8d74e8SVille Syrjälä AUD_CONFIG_LOWER_N_MASK, 6287c8d74e8SVille Syrjälä AUD_CONFIG_N_PROG_ENABLE | 6297c8d74e8SVille Syrjälä (intel_crtc_has_dp_encoder(old_crtc_state) ? 6307c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX : 0)); 631df0566a6SJani Nikula 632df0566a6SJani Nikula /* Invalidate ELD */ 6337c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_cntrl_st2, 6347c8d74e8SVille Syrjälä IBX_ELD_VALID(port), 0); 6359f4a5125SVille Syrjälä 6369f4a5125SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 637c3c5dc1dSVille Syrjälä 638c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 639c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 640df0566a6SJani Nikula } 641df0566a6SJani Nikula 6427e95cb09SVille Syrjälä static void ibx_audio_codec_enable(struct intel_encoder *encoder, 643df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 644df0566a6SJani Nikula const struct drm_connector_state *conn_state) 645df0566a6SJani Nikula { 64646e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 6472225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 648df0566a6SJani Nikula enum port port = encoder->port; 6497c8d74e8SVille Syrjälä enum pipe pipe = crtc->pipe; 6507e95cb09SVille Syrjälä struct ibx_audio_regs regs; 651df0566a6SJani Nikula 65246e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, port == PORT_A)) 653df0566a6SJani Nikula return; 654df0566a6SJani Nikula 655c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 656df0566a6SJani Nikula 6577e95cb09SVille Syrjälä ibx_audio_regs_init(i915, pipe, ®s); 658df0566a6SJani Nikula 6599f4a5125SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 660df0566a6SJani Nikula 661df0566a6SJani Nikula /* Invalidate ELD */ 6627c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_cntrl_st2, 6637c8d74e8SVille Syrjälä IBX_ELD_VALID(port), 0); 664df0566a6SJani Nikula 665343cb0f9SVille Syrjälä /* 666343cb0f9SVille Syrjälä * The audio componenent is used to convey the ELD 667343cb0f9SVille Syrjälä * instead using of the hardware ELD buffer. 668343cb0f9SVille Syrjälä */ 669df0566a6SJani Nikula 670df0566a6SJani Nikula /* Enable timestamps */ 6717c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_config, 6727c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX | 6737c8d74e8SVille Syrjälä AUD_CONFIG_N_PROG_ENABLE | 6747c8d74e8SVille Syrjälä AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 6757c8d74e8SVille Syrjälä (intel_crtc_has_dp_encoder(crtc_state) ? 6767c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX : 6777c8d74e8SVille Syrjälä audio_config_hdmi_pixel_clock(crtc_state))); 6789f4a5125SVille Syrjälä 6799f4a5125SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 680df0566a6SJani Nikula } 681df0566a6SJani Nikula 6822f092c0cSVinod Govindapillai void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state) 6838853750dSVinod Govindapillai { 6842f092c0cSVinod Govindapillai struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 6852f092c0cSVinod Govindapillai struct drm_i915_private *i915 = to_i915(crtc->base.dev); 6868853750dSVinod Govindapillai enum transcoder trans = crtc_state->cpu_transcoder; 6878853750dSVinod Govindapillai 6888853750dSVinod Govindapillai if (HAS_DP20(i915)) 6898853750dSVinod Govindapillai intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, 6908853750dSVinod Govindapillai crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); 6918853750dSVinod Govindapillai } 6928853750dSVinod Govindapillai 6935d986635SVille Syrjälä bool intel_audio_compute_config(struct intel_encoder *encoder, 6945d986635SVille Syrjälä struct intel_crtc_state *crtc_state, 6955d986635SVille Syrjälä struct drm_connector_state *conn_state) 6965d986635SVille Syrjälä { 6975d986635SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 6985d986635SVille Syrjälä struct drm_connector *connector = conn_state->connector; 6995d986635SVille Syrjälä const struct drm_display_mode *adjusted_mode = 7005d986635SVille Syrjälä &crtc_state->hw.adjusted_mode; 7015d986635SVille Syrjälä 702d6393793SVille Syrjälä if (!connector->eld[0]) { 7035d986635SVille Syrjälä drm_dbg_kms(&i915->drm, 7045d986635SVille Syrjälä "Bogus ELD on [CONNECTOR:%d:%s]\n", 7055d986635SVille Syrjälä connector->base.id, connector->name); 706d6393793SVille Syrjälä return false; 707d6393793SVille Syrjälä } 7085d986635SVille Syrjälä 7095d986635SVille Syrjälä BUILD_BUG_ON(sizeof(crtc_state->eld) != sizeof(connector->eld)); 7105d986635SVille Syrjälä memcpy(crtc_state->eld, connector->eld, sizeof(crtc_state->eld)); 7115d986635SVille Syrjälä 7125d986635SVille Syrjälä crtc_state->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; 7135d986635SVille Syrjälä 7145d986635SVille Syrjälä return true; 7155d986635SVille Syrjälä } 7165d986635SVille Syrjälä 717df0566a6SJani Nikula /** 718df0566a6SJani Nikula * intel_audio_codec_enable - Enable the audio codec for HD audio 719df0566a6SJani Nikula * @encoder: encoder on which to enable audio 720df0566a6SJani Nikula * @crtc_state: pointer to the current crtc state. 721df0566a6SJani Nikula * @conn_state: pointer to the current connector state. 722df0566a6SJani Nikula * 723df0566a6SJani Nikula * The enable sequences may only be performed after enabling the transcoder and 724df0566a6SJani Nikula * port, and after completed link training. 725df0566a6SJani Nikula */ 726df0566a6SJani Nikula void intel_audio_codec_enable(struct intel_encoder *encoder, 727df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 728df0566a6SJani Nikula const struct drm_connector_state *conn_state) 729df0566a6SJani Nikula { 73046e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 73146e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 7322225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 733c7104c38SVille Syrjälä struct intel_connector *connector = to_intel_connector(conn_state->connector); 7345eba7426SVille Syrjälä enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 735c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 736df0566a6SJani Nikula enum port port = encoder->port; 737df0566a6SJani Nikula 738179db7c1SJani Nikula if (!crtc_state->has_audio) 739179db7c1SJani Nikula return; 740179db7c1SJani Nikula 741c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on [CRTC:%d:%s], %u bytes ELD\n", 742c7104c38SVille Syrjälä connector->base.base.id, connector->base.name, 7431f31e35fSJani Nikula encoder->base.base.id, encoder->base.name, 744c7104c38SVille Syrjälä crtc->base.base.id, crtc->base.name, 7455d986635SVille Syrjälä drm_eld_size(crtc_state->eld)); 746df0566a6SJani Nikula 74746e61ee4SVille Syrjälä if (i915->display.funcs.audio) 74846e61ee4SVille Syrjälä i915->display.funcs.audio->audio_codec_enable(encoder, 749df0566a6SJani Nikula crtc_state, 750df0566a6SJani Nikula conn_state); 751df0566a6SJani Nikula 75246e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 753df0566a6SJani Nikula 7545eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 755c7104c38SVille Syrjälä 756c7104c38SVille Syrjälä audio_state->encoder = encoder; 7575d986635SVille Syrjälä BUILD_BUG_ON(sizeof(audio_state->eld) != sizeof(crtc_state->eld)); 7585d986635SVille Syrjälä memcpy(audio_state->eld, crtc_state->eld, sizeof(audio_state->eld)); 759c7104c38SVille Syrjälä 76046e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 761df0566a6SJani Nikula 762df0566a6SJani Nikula if (acomp && acomp->base.audio_ops && 763df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify) { 7645eba7426SVille Syrjälä /* audio drivers expect cpu_transcoder = -1 to indicate Non-MST cases */ 765df0566a6SJani Nikula if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) 7665eba7426SVille Syrjälä cpu_transcoder = -1; 767df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, 7685eba7426SVille Syrjälä (int)port, (int)cpu_transcoder); 769df0566a6SJani Nikula } 770df0566a6SJani Nikula 7715eba7426SVille Syrjälä intel_lpe_audio_notify(i915, cpu_transcoder, port, crtc_state->eld, 772df0566a6SJani Nikula crtc_state->port_clock, 773df0566a6SJani Nikula intel_crtc_has_dp_encoder(crtc_state)); 774df0566a6SJani Nikula } 775df0566a6SJani Nikula 776df0566a6SJani Nikula /** 777df0566a6SJani Nikula * intel_audio_codec_disable - Disable the audio codec for HD audio 778df0566a6SJani Nikula * @encoder: encoder on which to disable audio 779df0566a6SJani Nikula * @old_crtc_state: pointer to the old crtc state. 780df0566a6SJani Nikula * @old_conn_state: pointer to the old connector state. 781df0566a6SJani Nikula * 782df0566a6SJani Nikula * The disable sequences must be performed before disabling the transcoder or 783df0566a6SJani Nikula * port. 784df0566a6SJani Nikula */ 785df0566a6SJani Nikula void intel_audio_codec_disable(struct intel_encoder *encoder, 786df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 787df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 788df0566a6SJani Nikula { 78946e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 79046e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 7912225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 792c7104c38SVille Syrjälä struct intel_connector *connector = to_intel_connector(old_conn_state->connector); 7935eba7426SVille Syrjälä enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 794c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 795df0566a6SJani Nikula enum port port = encoder->port; 796df0566a6SJani Nikula 797179db7c1SJani Nikula if (!old_crtc_state->has_audio) 798179db7c1SJani Nikula return; 799179db7c1SJani Nikula 800c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on [CRTC:%d:%s]\n", 801c7104c38SVille Syrjälä connector->base.base.id, connector->base.name, 802c7104c38SVille Syrjälä encoder->base.base.id, encoder->base.name, 803c7104c38SVille Syrjälä crtc->base.base.id, crtc->base.name); 8041f31e35fSJani Nikula 80546e61ee4SVille Syrjälä if (i915->display.funcs.audio) 80646e61ee4SVille Syrjälä i915->display.funcs.audio->audio_codec_disable(encoder, 807df0566a6SJani Nikula old_crtc_state, 808df0566a6SJani Nikula old_conn_state); 809df0566a6SJani Nikula 81046e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 811c7104c38SVille Syrjälä 8125eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 813c7104c38SVille Syrjälä 814c7104c38SVille Syrjälä audio_state->encoder = NULL; 8155d986635SVille Syrjälä memset(audio_state->eld, 0, sizeof(audio_state->eld)); 816c7104c38SVille Syrjälä 81746e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 818df0566a6SJani Nikula 819df0566a6SJani Nikula if (acomp && acomp->base.audio_ops && 820df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify) { 8215eba7426SVille Syrjälä /* audio drivers expect cpu_transcoder = -1 to indicate Non-MST cases */ 822df0566a6SJani Nikula if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) 8235eba7426SVille Syrjälä cpu_transcoder = -1; 824df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, 8255eba7426SVille Syrjälä (int)port, (int)cpu_transcoder); 826df0566a6SJani Nikula } 827df0566a6SJani Nikula 8285eba7426SVille Syrjälä intel_lpe_audio_notify(i915, cpu_transcoder, port, NULL, 0, false); 829df0566a6SJani Nikula } 830df0566a6SJani Nikula 83161a60df6SVille Syrjälä static void intel_acomp_get_config(struct intel_encoder *encoder, 83261a60df6SVille Syrjälä struct intel_crtc_state *crtc_state) 83361a60df6SVille Syrjälä { 83461a60df6SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 8355eba7426SVille Syrjälä enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 83661a60df6SVille Syrjälä struct intel_audio_state *audio_state; 83761a60df6SVille Syrjälä 83861a60df6SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 83961a60df6SVille Syrjälä 8405eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 84161a60df6SVille Syrjälä 84261a60df6SVille Syrjälä if (audio_state->encoder) 84361a60df6SVille Syrjälä memcpy(crtc_state->eld, audio_state->eld, sizeof(audio_state->eld)); 84461a60df6SVille Syrjälä 84561a60df6SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 84661a60df6SVille Syrjälä } 84761a60df6SVille Syrjälä 84861a60df6SVille Syrjälä void intel_audio_codec_get_config(struct intel_encoder *encoder, 84961a60df6SVille Syrjälä struct intel_crtc_state *crtc_state) 85061a60df6SVille Syrjälä { 85161a60df6SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 85261a60df6SVille Syrjälä 85361a60df6SVille Syrjälä if (!crtc_state->has_audio) 85461a60df6SVille Syrjälä return; 85561a60df6SVille Syrjälä 85661a60df6SVille Syrjälä if (i915->display.funcs.audio) 85761a60df6SVille Syrjälä i915->display.funcs.audio->audio_codec_get_config(encoder, crtc_state); 85861a60df6SVille Syrjälä } 85961a60df6SVille Syrjälä 8600a108bcaSDave Airlie static const struct intel_audio_funcs g4x_audio_funcs = { 8610a108bcaSDave Airlie .audio_codec_enable = g4x_audio_codec_enable, 8620a108bcaSDave Airlie .audio_codec_disable = g4x_audio_codec_disable, 86361a60df6SVille Syrjälä .audio_codec_get_config = g4x_audio_codec_get_config, 8640a108bcaSDave Airlie }; 8650a108bcaSDave Airlie 8667e95cb09SVille Syrjälä static const struct intel_audio_funcs ibx_audio_funcs = { 8677e95cb09SVille Syrjälä .audio_codec_enable = ibx_audio_codec_enable, 8687e95cb09SVille Syrjälä .audio_codec_disable = ibx_audio_codec_disable, 86961a60df6SVille Syrjälä .audio_codec_get_config = intel_acomp_get_config, 8700a108bcaSDave Airlie }; 8710a108bcaSDave Airlie 8720a108bcaSDave Airlie static const struct intel_audio_funcs hsw_audio_funcs = { 8730a108bcaSDave Airlie .audio_codec_enable = hsw_audio_codec_enable, 8740a108bcaSDave Airlie .audio_codec_disable = hsw_audio_codec_disable, 87561a60df6SVille Syrjälä .audio_codec_get_config = intel_acomp_get_config, 8760a108bcaSDave Airlie }; 8770a108bcaSDave Airlie 878df0566a6SJani Nikula /** 879f47a0e35SJani Nikula * intel_audio_hooks_init - Set up chip specific audio hooks 88046e61ee4SVille Syrjälä * @i915: device private 881df0566a6SJani Nikula */ 88246e61ee4SVille Syrjälä void intel_audio_hooks_init(struct drm_i915_private *i915) 883df0566a6SJani Nikula { 88446e61ee4SVille Syrjälä if (IS_G4X(i915)) 88546e61ee4SVille Syrjälä i915->display.funcs.audio = &g4x_audio_funcs; 88631395fbaSVille Syrjälä else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915) || 88731395fbaSVille Syrjälä HAS_PCH_CPT(i915) || HAS_PCH_IBX(i915)) 8887e95cb09SVille Syrjälä i915->display.funcs.audio = &ibx_audio_funcs; 88946e61ee4SVille Syrjälä else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) 89046e61ee4SVille Syrjälä i915->display.funcs.audio = &hsw_audio_funcs; 891df0566a6SJani Nikula } 892df0566a6SJani Nikula 893112a87c4SKai Vehmanen struct aud_ts_cdclk_m_n { 894112a87c4SKai Vehmanen u8 m; 895112a87c4SKai Vehmanen u16 n; 896112a87c4SKai Vehmanen }; 897112a87c4SKai Vehmanen 898112a87c4SKai Vehmanen void intel_audio_cdclk_change_pre(struct drm_i915_private *i915) 899112a87c4SKai Vehmanen { 900112a87c4SKai Vehmanen if (DISPLAY_VER(i915) >= 13) 901112a87c4SKai Vehmanen intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0); 902112a87c4SKai Vehmanen } 903112a87c4SKai Vehmanen 904112a87c4SKai Vehmanen static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts) 905112a87c4SKai Vehmanen { 906091496e6SClint Taylor aud_ts->m = 60; 907112a87c4SKai Vehmanen aud_ts->n = cdclk * aud_ts->m / 24000; 908112a87c4SKai Vehmanen } 909112a87c4SKai Vehmanen 910112a87c4SKai Vehmanen void intel_audio_cdclk_change_post(struct drm_i915_private *i915) 911112a87c4SKai Vehmanen { 912112a87c4SKai Vehmanen struct aud_ts_cdclk_m_n aud_ts; 913112a87c4SKai Vehmanen 914112a87c4SKai Vehmanen if (DISPLAY_VER(i915) >= 13) { 915d51309b4SJani Nikula get_aud_ts_cdclk_m_n(i915->display.cdclk.hw.ref, i915->display.cdclk.hw.cdclk, &aud_ts); 916112a87c4SKai Vehmanen 917112a87c4SKai Vehmanen intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n); 918112a87c4SKai Vehmanen intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN); 919112a87c4SKai Vehmanen drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n); 920112a87c4SKai Vehmanen } 921112a87c4SKai Vehmanen } 922112a87c4SKai Vehmanen 92328a30b45SVille Syrjälä static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state, 92408e3ed3aSChris Wilson struct intel_crtc *crtc, 92528a30b45SVille Syrjälä bool enable) 92628a30b45SVille Syrjälä { 92728a30b45SVille Syrjälä struct intel_cdclk_state *cdclk_state; 92828a30b45SVille Syrjälä int ret; 92928a30b45SVille Syrjälä 93028a30b45SVille Syrjälä /* need to hold at least one crtc lock for the global state */ 93128a30b45SVille Syrjälä ret = drm_modeset_lock(&crtc->base.mutex, state->base.acquire_ctx); 93228a30b45SVille Syrjälä if (ret) 93328a30b45SVille Syrjälä return ret; 93428a30b45SVille Syrjälä 93528a30b45SVille Syrjälä cdclk_state = intel_atomic_get_cdclk_state(state); 93628a30b45SVille Syrjälä if (IS_ERR(cdclk_state)) 93728a30b45SVille Syrjälä return PTR_ERR(cdclk_state); 93828a30b45SVille Syrjälä 93928a30b45SVille Syrjälä cdclk_state->force_min_cdclk = enable ? 2 * 96000 : 0; 94028a30b45SVille Syrjälä 94128a30b45SVille Syrjälä return drm_atomic_commit(&state->base); 94228a30b45SVille Syrjälä } 94328a30b45SVille Syrjälä 94446e61ee4SVille Syrjälä static void glk_force_audio_cdclk(struct drm_i915_private *i915, 945df0566a6SJani Nikula bool enable) 946df0566a6SJani Nikula { 947df0566a6SJani Nikula struct drm_modeset_acquire_ctx ctx; 948df0566a6SJani Nikula struct drm_atomic_state *state; 94908e3ed3aSChris Wilson struct intel_crtc *crtc; 950df0566a6SJani Nikula int ret; 951df0566a6SJani Nikula 95246e61ee4SVille Syrjälä crtc = intel_first_crtc(i915); 95308e3ed3aSChris Wilson if (!crtc) 95408e3ed3aSChris Wilson return; 95508e3ed3aSChris Wilson 956df0566a6SJani Nikula drm_modeset_acquire_init(&ctx, 0); 95746e61ee4SVille Syrjälä state = drm_atomic_state_alloc(&i915->drm); 95846e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, !state)) 959df0566a6SJani Nikula return; 960df0566a6SJani Nikula 961df0566a6SJani Nikula state->acquire_ctx = &ctx; 96276ec6927SVille Syrjälä to_intel_atomic_state(state)->internal = true; 963df0566a6SJani Nikula 964df0566a6SJani Nikula retry: 96508e3ed3aSChris Wilson ret = glk_force_audio_cdclk_commit(to_intel_atomic_state(state), crtc, 96608e3ed3aSChris Wilson enable); 967df0566a6SJani Nikula if (ret == -EDEADLK) { 968df0566a6SJani Nikula drm_atomic_state_clear(state); 969df0566a6SJani Nikula drm_modeset_backoff(&ctx); 970df0566a6SJani Nikula goto retry; 971df0566a6SJani Nikula } 972df0566a6SJani Nikula 97346e61ee4SVille Syrjälä drm_WARN_ON(&i915->drm, ret); 974df0566a6SJani Nikula 975df0566a6SJani Nikula drm_atomic_state_put(state); 976df0566a6SJani Nikula 977df0566a6SJani Nikula drm_modeset_drop_locks(&ctx); 978df0566a6SJani Nikula drm_modeset_acquire_fini(&ctx); 979df0566a6SJani Nikula } 980df0566a6SJani Nikula 981df0566a6SJani Nikula static unsigned long i915_audio_component_get_power(struct device *kdev) 982df0566a6SJani Nikula { 983*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(kdev); 984*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 985df0566a6SJani Nikula intel_wakeref_t ret; 986df0566a6SJani Nikula 987df0566a6SJani Nikula /* Catch potential impedance mismatches before they occur! */ 988df0566a6SJani Nikula BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long)); 989df0566a6SJani Nikula 99046e61ee4SVille Syrjälä ret = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK); 991df0566a6SJani Nikula 99246e61ee4SVille Syrjälä if (i915->display.audio.power_refcount++ == 0) { 99346e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 9) { 99446e61ee4SVille Syrjälä intel_de_write(i915, AUD_FREQ_CNTRL, 99546e61ee4SVille Syrjälä i915->display.audio.freq_cntrl); 99646e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, 99763855149SWambui Karuga "restored AUD_FREQ_CNTRL to 0x%x\n", 99846e61ee4SVille Syrjälä i915->display.audio.freq_cntrl); 99987c16945SKai Vehmanen } 100087c16945SKai Vehmanen 100187c16945SKai Vehmanen /* Force CDCLK to 2*BCLK as long as we need audio powered. */ 100246e61ee4SVille Syrjälä if (IS_GEMINILAKE(i915)) 100346e61ee4SVille Syrjälä glk_force_audio_cdclk(i915, true); 10041580d3cdSKai Vehmanen 100546e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 10067c8d74e8SVille Syrjälä intel_de_rmw(i915, AUD_PIN_BUF_CTL, 10077c8d74e8SVille Syrjälä 0, AUD_PIN_BUF_ENABLE); 100887c16945SKai Vehmanen } 1009df0566a6SJani Nikula 1010df0566a6SJani Nikula return ret; 1011df0566a6SJani Nikula } 1012df0566a6SJani Nikula 1013df0566a6SJani Nikula static void i915_audio_component_put_power(struct device *kdev, 1014df0566a6SJani Nikula unsigned long cookie) 1015df0566a6SJani Nikula { 1016*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(kdev); 1017*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 1018df0566a6SJani Nikula 1019df0566a6SJani Nikula /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ 102046e61ee4SVille Syrjälä if (--i915->display.audio.power_refcount == 0) 102146e61ee4SVille Syrjälä if (IS_GEMINILAKE(i915)) 102246e61ee4SVille Syrjälä glk_force_audio_cdclk(i915, false); 1023df0566a6SJani Nikula 102446e61ee4SVille Syrjälä intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, cookie); 1025df0566a6SJani Nikula } 1026df0566a6SJani Nikula 1027df0566a6SJani Nikula static void i915_audio_component_codec_wake_override(struct device *kdev, 1028df0566a6SJani Nikula bool enable) 1029df0566a6SJani Nikula { 1030*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(kdev); 1031*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 1032df0566a6SJani Nikula unsigned long cookie; 1033df0566a6SJani Nikula 103446e61ee4SVille Syrjälä if (DISPLAY_VER(i915) < 9) 1035df0566a6SJani Nikula return; 1036df0566a6SJani Nikula 1037df0566a6SJani Nikula cookie = i915_audio_component_get_power(kdev); 1038df0566a6SJani Nikula 1039df0566a6SJani Nikula /* 1040df0566a6SJani Nikula * Enable/disable generating the codec wake signal, overriding the 1041df0566a6SJani Nikula * internal logic to generate the codec wake to controller. 1042df0566a6SJani Nikula */ 10437c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_CHICKENBIT, 10447c8d74e8SVille Syrjälä SKL_AUD_CODEC_WAKE_SIGNAL, 0); 1045df0566a6SJani Nikula usleep_range(1000, 1500); 1046df0566a6SJani Nikula 1047df0566a6SJani Nikula if (enable) { 10487c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_CHICKENBIT, 10497c8d74e8SVille Syrjälä 0, SKL_AUD_CODEC_WAKE_SIGNAL); 1050df0566a6SJani Nikula usleep_range(1000, 1500); 1051df0566a6SJani Nikula } 1052df0566a6SJani Nikula 1053df0566a6SJani Nikula i915_audio_component_put_power(kdev, cookie); 1054df0566a6SJani Nikula } 1055df0566a6SJani Nikula 1056df0566a6SJani Nikula /* Get CDCLK in kHz */ 1057df0566a6SJani Nikula static int i915_audio_component_get_cdclk_freq(struct device *kdev) 1058df0566a6SJani Nikula { 1059*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(kdev); 1060*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 1061df0566a6SJani Nikula 106246e61ee4SVille Syrjälä if (drm_WARN_ON_ONCE(&i915->drm, !HAS_DDI(i915))) 1063df0566a6SJani Nikula return -ENODEV; 1064df0566a6SJani Nikula 106546e61ee4SVille Syrjälä return i915->display.cdclk.hw.cdclk; 1066df0566a6SJani Nikula } 1067df0566a6SJani Nikula 1068df0566a6SJani Nikula /* 10695eba7426SVille Syrjälä * get the intel audio state according to the parameter port and cpu_transcoder 10705eba7426SVille Syrjälä * MST & (cpu_transcoder >= 0): return the audio.state[cpu_transcoder].encoder], 1071df0566a6SJani Nikula * when port is matched 10725eba7426SVille Syrjälä * MST & (cpu_transcoder < 0): this is invalid 10735eba7426SVille Syrjälä * Non-MST & (cpu_transcoder >= 0): only cpu_transcoder = 0 (the first device entry) 1074df0566a6SJani Nikula * will get the right intel_encoder with port matched 10755eba7426SVille Syrjälä * Non-MST & (cpu_transcoder < 0): get the right intel_encoder with port matched 1076df0566a6SJani Nikula */ 1077c7104c38SVille Syrjälä static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, 10785eba7426SVille Syrjälä int port, int cpu_transcoder) 1079df0566a6SJani Nikula { 1080df0566a6SJani Nikula /* MST */ 10815eba7426SVille Syrjälä if (cpu_transcoder >= 0) { 1082c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 1083734d06d2SVille Syrjälä struct intel_encoder *encoder; 1084734d06d2SVille Syrjälä 108546e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, 10865eba7426SVille Syrjälä cpu_transcoder >= ARRAY_SIZE(i915->display.audio.state))) 1087df0566a6SJani Nikula return NULL; 1088df0566a6SJani Nikula 10895eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 1090c7104c38SVille Syrjälä encoder = audio_state->encoder; 1091c7104c38SVille Syrjälä 1092734d06d2SVille Syrjälä if (encoder && encoder->port == port && 1093df0566a6SJani Nikula encoder->type == INTEL_OUTPUT_DP_MST) 1094c7104c38SVille Syrjälä return audio_state; 1095df0566a6SJani Nikula } 1096df0566a6SJani Nikula 1097df0566a6SJani Nikula /* Non-MST */ 10985eba7426SVille Syrjälä if (cpu_transcoder > 0) 1099df0566a6SJani Nikula return NULL; 1100df0566a6SJani Nikula 11015eba7426SVille Syrjälä for_each_cpu_transcoder(i915, cpu_transcoder) { 1102c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 1103734d06d2SVille Syrjälä struct intel_encoder *encoder; 1104734d06d2SVille Syrjälä 11055eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 1106c7104c38SVille Syrjälä encoder = audio_state->encoder; 1107df0566a6SJani Nikula 1108734d06d2SVille Syrjälä if (encoder && encoder->port == port && 1109734d06d2SVille Syrjälä encoder->type != INTEL_OUTPUT_DP_MST) 1110c7104c38SVille Syrjälä return audio_state; 1111df0566a6SJani Nikula } 1112df0566a6SJani Nikula 1113df0566a6SJani Nikula return NULL; 1114df0566a6SJani Nikula } 1115df0566a6SJani Nikula 1116df0566a6SJani Nikula static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, 11175eba7426SVille Syrjälä int cpu_transcoder, int rate) 1118df0566a6SJani Nikula { 1119*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(kdev); 1120*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 112146e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 1122c7104c38SVille Syrjälä const struct intel_audio_state *audio_state; 1123df0566a6SJani Nikula struct intel_encoder *encoder; 1124df0566a6SJani Nikula struct intel_crtc *crtc; 1125df0566a6SJani Nikula unsigned long cookie; 1126df0566a6SJani Nikula int err = 0; 1127df0566a6SJani Nikula 112846e61ee4SVille Syrjälä if (!HAS_DDI(i915)) 1129df0566a6SJani Nikula return 0; 1130df0566a6SJani Nikula 1131df0566a6SJani Nikula cookie = i915_audio_component_get_power(kdev); 113246e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 1133df0566a6SJani Nikula 11345eba7426SVille Syrjälä audio_state = find_audio_state(i915, port, cpu_transcoder); 1135c7104c38SVille Syrjälä if (!audio_state) { 1136c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); 1137df0566a6SJani Nikula err = -ENODEV; 1138df0566a6SJani Nikula goto unlock; 1139df0566a6SJani Nikula } 1140df0566a6SJani Nikula 1141c7104c38SVille Syrjälä encoder = audio_state->encoder; 1142c7104c38SVille Syrjälä 1143c7104c38SVille Syrjälä /* FIXME stop using the legacy crtc pointer */ 1144df0566a6SJani Nikula crtc = to_intel_crtc(encoder->base.crtc); 1145df0566a6SJani Nikula 11465eba7426SVille Syrjälä /* port must be valid now, otherwise the cpu_transcoder will be invalid */ 1147df0566a6SJani Nikula acomp->aud_sample_rate[port] = rate; 1148df0566a6SJani Nikula 1149c7104c38SVille Syrjälä /* FIXME get rid of the crtc->config stuff */ 1150df0566a6SJani Nikula hsw_audio_config_update(encoder, crtc->config); 1151df0566a6SJani Nikula 1152df0566a6SJani Nikula unlock: 115346e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 1154df0566a6SJani Nikula i915_audio_component_put_power(kdev, cookie); 1155df0566a6SJani Nikula return err; 1156df0566a6SJani Nikula } 1157df0566a6SJani Nikula 1158df0566a6SJani Nikula static int i915_audio_component_get_eld(struct device *kdev, int port, 11595eba7426SVille Syrjälä int cpu_transcoder, bool *enabled, 1160df0566a6SJani Nikula unsigned char *buf, int max_bytes) 1161df0566a6SJani Nikula { 1162*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(kdev); 1163*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 1164c7104c38SVille Syrjälä const struct intel_audio_state *audio_state; 1165c7104c38SVille Syrjälä int ret = 0; 1166df0566a6SJani Nikula 116746e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 1168df0566a6SJani Nikula 11695eba7426SVille Syrjälä audio_state = find_audio_state(i915, port, cpu_transcoder); 1170c7104c38SVille Syrjälä if (!audio_state) { 1171c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); 117246e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 1173c7104c38SVille Syrjälä return -EINVAL; 1174df0566a6SJani Nikula } 1175df0566a6SJani Nikula 11765d986635SVille Syrjälä *enabled = audio_state->encoder != NULL; 1177df0566a6SJani Nikula if (*enabled) { 11785d986635SVille Syrjälä const u8 *eld = audio_state->eld; 1179c7104c38SVille Syrjälä 1180df0566a6SJani Nikula ret = drm_eld_size(eld); 1181df0566a6SJani Nikula memcpy(buf, eld, min(max_bytes, ret)); 1182df0566a6SJani Nikula } 1183df0566a6SJani Nikula 118446e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 1185df0566a6SJani Nikula return ret; 1186df0566a6SJani Nikula } 1187df0566a6SJani Nikula 1188df0566a6SJani Nikula static const struct drm_audio_component_ops i915_audio_component_ops = { 1189df0566a6SJani Nikula .owner = THIS_MODULE, 1190df0566a6SJani Nikula .get_power = i915_audio_component_get_power, 1191df0566a6SJani Nikula .put_power = i915_audio_component_put_power, 1192df0566a6SJani Nikula .codec_wake_override = i915_audio_component_codec_wake_override, 1193df0566a6SJani Nikula .get_cdclk_freq = i915_audio_component_get_cdclk_freq, 1194df0566a6SJani Nikula .sync_audio_rate = i915_audio_component_sync_audio_rate, 1195df0566a6SJani Nikula .get_eld = i915_audio_component_get_eld, 1196df0566a6SJani Nikula }; 1197df0566a6SJani Nikula 1198*14ee9fa8SJani Nikula static int i915_audio_component_bind(struct device *drv_kdev, 1199df0566a6SJani Nikula struct device *hda_kdev, void *data) 1200df0566a6SJani Nikula { 1201*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(drv_kdev); 1202*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 1203df0566a6SJani Nikula struct i915_audio_component *acomp = data; 1204df0566a6SJani Nikula int i; 1205df0566a6SJani Nikula 120646e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, acomp->base.ops || acomp->base.dev)) 1207df0566a6SJani Nikula return -EEXIST; 1208df0566a6SJani Nikula 120946e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, 1210*14ee9fa8SJani Nikula !device_link_add(hda_kdev, drv_kdev, 12119a3b466bSPankaj Bharadiya DL_FLAG_STATELESS))) 1212df0566a6SJani Nikula return -ENOMEM; 1213df0566a6SJani Nikula 121446e61ee4SVille Syrjälä drm_modeset_lock_all(&i915->drm); 1215df0566a6SJani Nikula acomp->base.ops = &i915_audio_component_ops; 1216*14ee9fa8SJani Nikula acomp->base.dev = drv_kdev; 1217df0566a6SJani Nikula BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); 1218df0566a6SJani Nikula for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) 1219df0566a6SJani Nikula acomp->aud_sample_rate[i] = 0; 122046e61ee4SVille Syrjälä i915->display.audio.component = acomp; 122146e61ee4SVille Syrjälä drm_modeset_unlock_all(&i915->drm); 1222df0566a6SJani Nikula 1223df0566a6SJani Nikula return 0; 1224df0566a6SJani Nikula } 1225df0566a6SJani Nikula 1226*14ee9fa8SJani Nikula static void i915_audio_component_unbind(struct device *drv_kdev, 1227df0566a6SJani Nikula struct device *hda_kdev, void *data) 1228df0566a6SJani Nikula { 1229*14ee9fa8SJani Nikula struct intel_display *display = to_intel_display(drv_kdev); 1230*14ee9fa8SJani Nikula struct drm_i915_private *i915 = to_i915(display->drm); 1231df0566a6SJani Nikula struct i915_audio_component *acomp = data; 1232df0566a6SJani Nikula 123346e61ee4SVille Syrjälä drm_modeset_lock_all(&i915->drm); 1234df0566a6SJani Nikula acomp->base.ops = NULL; 1235df0566a6SJani Nikula acomp->base.dev = NULL; 123646e61ee4SVille Syrjälä i915->display.audio.component = NULL; 123746e61ee4SVille Syrjälä drm_modeset_unlock_all(&i915->drm); 1238df0566a6SJani Nikula 1239*14ee9fa8SJani Nikula device_link_remove(hda_kdev, drv_kdev); 1240b4ed131dSJani Nikula 124146e61ee4SVille Syrjälä if (i915->display.audio.power_refcount) 124246e61ee4SVille Syrjälä drm_err(&i915->drm, "audio power refcount %d after unbind\n", 124346e61ee4SVille Syrjälä i915->display.audio.power_refcount); 1244df0566a6SJani Nikula } 1245df0566a6SJani Nikula 1246df0566a6SJani Nikula static const struct component_ops i915_audio_component_bind_ops = { 1247df0566a6SJani Nikula .bind = i915_audio_component_bind, 1248df0566a6SJani Nikula .unbind = i915_audio_component_unbind, 1249df0566a6SJani Nikula }; 1250df0566a6SJani Nikula 1251989634fbSKai Vehmanen #define AUD_FREQ_TMODE_SHIFT 14 1252989634fbSKai Vehmanen #define AUD_FREQ_4T 0 1253989634fbSKai Vehmanen #define AUD_FREQ_8T (2 << AUD_FREQ_TMODE_SHIFT) 1254989634fbSKai Vehmanen #define AUD_FREQ_PULLCLKS(x) (((x) & 0x3) << 11) 1255989634fbSKai Vehmanen #define AUD_FREQ_BCLK_96M BIT(4) 1256989634fbSKai Vehmanen 1257989634fbSKai Vehmanen #define AUD_FREQ_GEN12 (AUD_FREQ_8T | AUD_FREQ_PULLCLKS(0) | AUD_FREQ_BCLK_96M) 1258989634fbSKai Vehmanen #define AUD_FREQ_TGL_BROKEN (AUD_FREQ_8T | AUD_FREQ_PULLCLKS(2) | AUD_FREQ_BCLK_96M) 1259989634fbSKai Vehmanen 1260df0566a6SJani Nikula /** 1261df0566a6SJani Nikula * i915_audio_component_init - initialize and register the audio component 126246e61ee4SVille Syrjälä * @i915: i915 device instance 1263df0566a6SJani Nikula * 1264df0566a6SJani Nikula * This will register with the component framework a child component which 1265df0566a6SJani Nikula * will bind dynamically to the snd_hda_intel driver's corresponding master 1266df0566a6SJani Nikula * component when the latter is registered. During binding the child 1267df0566a6SJani Nikula * initializes an instance of struct i915_audio_component which it receives 1268df0566a6SJani Nikula * from the master. The master can then start to use the interface defined by 1269df0566a6SJani Nikula * this struct. Each side can break the binding at any point by deregistering 1270df0566a6SJani Nikula * its own component after which each side's component unbind callback is 1271df0566a6SJani Nikula * called. 1272df0566a6SJani Nikula * 1273df0566a6SJani Nikula * We ignore any error during registration and continue with reduced 1274df0566a6SJani Nikula * functionality (i.e. without HDMI audio). 1275df0566a6SJani Nikula */ 127646e61ee4SVille Syrjälä static void i915_audio_component_init(struct drm_i915_private *i915) 1277df0566a6SJani Nikula { 1278989634fbSKai Vehmanen u32 aud_freq, aud_freq_init; 1279df0566a6SJani Nikula 128046e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 9) { 128146e61ee4SVille Syrjälä aud_freq_init = intel_de_read(i915, AUD_FREQ_CNTRL); 1282989634fbSKai Vehmanen 128346e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 12) 1284989634fbSKai Vehmanen aud_freq = AUD_FREQ_GEN12; 1285989634fbSKai Vehmanen else 1286989634fbSKai Vehmanen aud_freq = aud_freq_init; 1287989634fbSKai Vehmanen 1288c6b40ee3SKai-Heng Feng /* use BIOS provided value for TGL and RKL unless it is a known bad value */ 128946e61ee4SVille Syrjälä if ((IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915)) && 1290c6b40ee3SKai-Heng Feng aud_freq_init != AUD_FREQ_TGL_BROKEN) 1291989634fbSKai Vehmanen aud_freq = aud_freq_init; 1292989634fbSKai Vehmanen 129346e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", 1294989634fbSKai Vehmanen aud_freq, aud_freq_init); 1295989634fbSKai Vehmanen 129646e61ee4SVille Syrjälä i915->display.audio.freq_cntrl = aud_freq; 129787c16945SKai Vehmanen } 129887c16945SKai Vehmanen 1299112a87c4SKai Vehmanen /* init with current cdclk */ 130046e61ee4SVille Syrjälä intel_audio_cdclk_change_post(i915); 1301fdd0b801SImre Deak } 1302fdd0b801SImre Deak 1303fdd0b801SImre Deak static void i915_audio_component_register(struct drm_i915_private *i915) 1304fdd0b801SImre Deak { 1305fdd0b801SImre Deak int ret; 1306fdd0b801SImre Deak 1307fdd0b801SImre Deak ret = component_add_typed(i915->drm.dev, 1308fdd0b801SImre Deak &i915_audio_component_bind_ops, 1309fdd0b801SImre Deak I915_COMPONENT_AUDIO); 1310fdd0b801SImre Deak if (ret < 0) { 1311fdd0b801SImre Deak drm_err(&i915->drm, 1312fdd0b801SImre Deak "failed to add audio component (%d)\n", ret); 1313fdd0b801SImre Deak /* continue with reduced functionality */ 1314fdd0b801SImre Deak return; 1315fdd0b801SImre Deak } 1316112a87c4SKai Vehmanen 131746e61ee4SVille Syrjälä i915->display.audio.component_registered = true; 1318df0566a6SJani Nikula } 1319df0566a6SJani Nikula 1320df0566a6SJani Nikula /** 1321df0566a6SJani Nikula * i915_audio_component_cleanup - deregister the audio component 132246e61ee4SVille Syrjälä * @i915: i915 device instance 1323df0566a6SJani Nikula * 1324df0566a6SJani Nikula * Deregisters the audio component, breaking any existing binding to the 1325df0566a6SJani Nikula * corresponding snd_hda_intel driver's master component. 1326df0566a6SJani Nikula */ 132746e61ee4SVille Syrjälä static void i915_audio_component_cleanup(struct drm_i915_private *i915) 1328df0566a6SJani Nikula { 132946e61ee4SVille Syrjälä if (!i915->display.audio.component_registered) 1330df0566a6SJani Nikula return; 1331df0566a6SJani Nikula 133246e61ee4SVille Syrjälä component_del(i915->drm.dev, &i915_audio_component_bind_ops); 133346e61ee4SVille Syrjälä i915->display.audio.component_registered = false; 1334df0566a6SJani Nikula } 1335df0566a6SJani Nikula 1336df0566a6SJani Nikula /** 1337df0566a6SJani Nikula * intel_audio_init() - Initialize the audio driver either using 1338df0566a6SJani Nikula * component framework or using lpe audio bridge 133946e61ee4SVille Syrjälä * @i915: the i915 drm device private data 1340df0566a6SJani Nikula * 1341df0566a6SJani Nikula */ 134246e61ee4SVille Syrjälä void intel_audio_init(struct drm_i915_private *i915) 1343df0566a6SJani Nikula { 134446e61ee4SVille Syrjälä if (intel_lpe_audio_init(i915) < 0) 134546e61ee4SVille Syrjälä i915_audio_component_init(i915); 1346df0566a6SJani Nikula } 1347df0566a6SJani Nikula 1348fdd0b801SImre Deak void intel_audio_register(struct drm_i915_private *i915) 1349fdd0b801SImre Deak { 1350fdd0b801SImre Deak if (!i915->display.audio.lpe.platdev) 1351fdd0b801SImre Deak i915_audio_component_register(i915); 1352fdd0b801SImre Deak } 1353fdd0b801SImre Deak 1354df0566a6SJani Nikula /** 1355df0566a6SJani Nikula * intel_audio_deinit() - deinitialize the audio driver 135646e61ee4SVille Syrjälä * @i915: the i915 drm device private data 1357df0566a6SJani Nikula * 1358df0566a6SJani Nikula */ 135946e61ee4SVille Syrjälä void intel_audio_deinit(struct drm_i915_private *i915) 1360df0566a6SJani Nikula { 136146e61ee4SVille Syrjälä if (i915->display.audio.lpe.platdev != NULL) 136246e61ee4SVille Syrjälä intel_lpe_audio_teardown(i915); 1363df0566a6SJani Nikula else 136446e61ee4SVille Syrjälä i915_audio_component_cleanup(i915); 1365df0566a6SJani Nikula } 1366