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> 29df0566a6SJani Nikula #include <drm/i915_component.h> 30df0566a6SJani Nikula 31df0566a6SJani Nikula #include "i915_drv.h" 321d5a95b5SVille Syrjälä #include "intel_atomic.h" 33df0566a6SJani Nikula #include "intel_audio.h" 34b43edc50SJani Nikula #include "intel_audio_regs.h" 3528a30b45SVille Syrjälä #include "intel_cdclk.h" 36fd2b94a5SJani Nikula #include "intel_crtc.h" 377785ae0bSVille Syrjälä #include "intel_de.h" 381d455f8dSJani Nikula #include "intel_display_types.h" 39df0566a6SJani Nikula #include "intel_lpe_audio.h" 40df0566a6SJani Nikula 41df0566a6SJani Nikula /** 42df0566a6SJani Nikula * DOC: High Definition Audio over HDMI and Display Port 43df0566a6SJani Nikula * 44df0566a6SJani Nikula * The graphics and audio drivers together support High Definition Audio over 45df0566a6SJani Nikula * HDMI and Display Port. The audio programming sequences are divided into audio 46df0566a6SJani Nikula * codec and controller enable and disable sequences. The graphics driver 47df0566a6SJani Nikula * handles the audio codec sequences, while the audio driver handles the audio 48df0566a6SJani Nikula * controller sequences. 49df0566a6SJani Nikula * 50df0566a6SJani Nikula * The disable sequences must be performed before disabling the transcoder or 51df0566a6SJani Nikula * port. The enable sequences may only be performed after enabling the 52df0566a6SJani Nikula * transcoder and port, and after completed link training. Therefore the audio 53df0566a6SJani Nikula * enable/disable sequences are part of the modeset sequence. 54df0566a6SJani Nikula * 55df0566a6SJani Nikula * The codec and controller sequences could be done either parallel or serial, 56df0566a6SJani Nikula * but generally the ELDV/PD change in the codec sequence indicates to the audio 57df0566a6SJani Nikula * driver that the controller sequence should start. Indeed, most of the 58df0566a6SJani Nikula * co-operation between the graphics and audio drivers is handled via audio 59df0566a6SJani Nikula * related registers. (The notable exception is the power management, not 60df0566a6SJani Nikula * covered here.) 61df0566a6SJani Nikula * 62df0566a6SJani Nikula * The struct &i915_audio_component is used to interact between the graphics 63df0566a6SJani Nikula * and audio drivers. The struct &i915_audio_component_ops @ops in it is 64df0566a6SJani Nikula * defined in graphics driver and called in audio driver. The 65df0566a6SJani Nikula * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver. 66df0566a6SJani Nikula */ 67df0566a6SJani Nikula 685d453746SJani Nikula struct intel_audio_funcs { 695d453746SJani Nikula void (*audio_codec_enable)(struct intel_encoder *encoder, 705d453746SJani Nikula const struct intel_crtc_state *crtc_state, 715d453746SJani Nikula const struct drm_connector_state *conn_state); 725d453746SJani Nikula void (*audio_codec_disable)(struct intel_encoder *encoder, 735d453746SJani Nikula const struct intel_crtc_state *old_crtc_state, 745d453746SJani Nikula const struct drm_connector_state *old_conn_state); 7561a60df6SVille Syrjälä void (*audio_codec_get_config)(struct intel_encoder *encoder, 7661a60df6SVille Syrjälä struct intel_crtc_state *crtc_state); 775d453746SJani Nikula }; 785d453746SJani Nikula 792c291417SAditya Swarup struct hdmi_aud_ncts { 802c291417SAditya Swarup int sample_rate; 812c291417SAditya Swarup int clock; 822c291417SAditya Swarup int n; 832c291417SAditya Swarup int cts; 842c291417SAditya Swarup }; 852c291417SAditya Swarup 86df0566a6SJani Nikula static const struct { 87df0566a6SJani Nikula int clock; 88df0566a6SJani Nikula u32 config; 89df0566a6SJani Nikula } hdmi_audio_clock[] = { 90df0566a6SJani Nikula { 25175, AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, 91df0566a6SJani Nikula { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ 92df0566a6SJani Nikula { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, 93df0566a6SJani Nikula { 27027, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, 94df0566a6SJani Nikula { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, 95df0566a6SJani Nikula { 54054, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, 96df0566a6SJani Nikula { 74176, AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, 97df0566a6SJani Nikula { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, 98df0566a6SJani Nikula { 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, 99df0566a6SJani Nikula { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, 1001aae3065SKai Vehmanen { 296703, AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 }, 1011aae3065SKai Vehmanen { 297000, AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 }, 1021aae3065SKai Vehmanen { 593407, AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 }, 1031aae3065SKai Vehmanen { 594000, AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 }, 104df0566a6SJani Nikula }; 105df0566a6SJani Nikula 106df0566a6SJani Nikula /* HDMI N/CTS table */ 107df0566a6SJani Nikula #define TMDS_297M 297000 108df0566a6SJani Nikula #define TMDS_296M 296703 109df0566a6SJani Nikula #define TMDS_594M 594000 110df0566a6SJani Nikula #define TMDS_593M 593407 111df0566a6SJani Nikula 1122c291417SAditya Swarup static const struct hdmi_aud_ncts hdmi_aud_ncts_24bpp[] = { 113df0566a6SJani Nikula { 32000, TMDS_296M, 5824, 421875 }, 114df0566a6SJani Nikula { 32000, TMDS_297M, 3072, 222750 }, 115df0566a6SJani Nikula { 32000, TMDS_593M, 5824, 843750 }, 116df0566a6SJani Nikula { 32000, TMDS_594M, 3072, 445500 }, 117df0566a6SJani Nikula { 44100, TMDS_296M, 4459, 234375 }, 118df0566a6SJani Nikula { 44100, TMDS_297M, 4704, 247500 }, 119df0566a6SJani Nikula { 44100, TMDS_593M, 8918, 937500 }, 120df0566a6SJani Nikula { 44100, TMDS_594M, 9408, 990000 }, 121df0566a6SJani Nikula { 88200, TMDS_296M, 8918, 234375 }, 122df0566a6SJani Nikula { 88200, TMDS_297M, 9408, 247500 }, 123df0566a6SJani Nikula { 88200, TMDS_593M, 17836, 937500 }, 124df0566a6SJani Nikula { 88200, TMDS_594M, 18816, 990000 }, 125df0566a6SJani Nikula { 176400, TMDS_296M, 17836, 234375 }, 126df0566a6SJani Nikula { 176400, TMDS_297M, 18816, 247500 }, 127df0566a6SJani Nikula { 176400, TMDS_593M, 35672, 937500 }, 128df0566a6SJani Nikula { 176400, TMDS_594M, 37632, 990000 }, 129df0566a6SJani Nikula { 48000, TMDS_296M, 5824, 281250 }, 130df0566a6SJani Nikula { 48000, TMDS_297M, 5120, 247500 }, 131df0566a6SJani Nikula { 48000, TMDS_593M, 5824, 562500 }, 132df0566a6SJani Nikula { 48000, TMDS_594M, 6144, 594000 }, 133df0566a6SJani Nikula { 96000, TMDS_296M, 11648, 281250 }, 134df0566a6SJani Nikula { 96000, TMDS_297M, 10240, 247500 }, 135df0566a6SJani Nikula { 96000, TMDS_593M, 11648, 562500 }, 136df0566a6SJani Nikula { 96000, TMDS_594M, 12288, 594000 }, 137df0566a6SJani Nikula { 192000, TMDS_296M, 23296, 281250 }, 138df0566a6SJani Nikula { 192000, TMDS_297M, 20480, 247500 }, 139df0566a6SJani Nikula { 192000, TMDS_593M, 23296, 562500 }, 140df0566a6SJani Nikula { 192000, TMDS_594M, 24576, 594000 }, 141df0566a6SJani Nikula }; 142df0566a6SJani Nikula 1432c291417SAditya Swarup /* Appendix C - N & CTS values for deep color from HDMI 2.0 spec*/ 1442c291417SAditya Swarup /* HDMI N/CTS table for 10 bit deep color(30 bpp)*/ 1452c291417SAditya Swarup #define TMDS_371M 371250 1462c291417SAditya Swarup #define TMDS_370M 370878 1472c291417SAditya Swarup 1482c291417SAditya Swarup static const struct hdmi_aud_ncts hdmi_aud_ncts_30bpp[] = { 1492c291417SAditya Swarup { 32000, TMDS_370M, 5824, 527344 }, 1502c291417SAditya Swarup { 32000, TMDS_371M, 6144, 556875 }, 1512c291417SAditya Swarup { 44100, TMDS_370M, 8918, 585938 }, 1522c291417SAditya Swarup { 44100, TMDS_371M, 4704, 309375 }, 1532c291417SAditya Swarup { 88200, TMDS_370M, 17836, 585938 }, 1542c291417SAditya Swarup { 88200, TMDS_371M, 9408, 309375 }, 1552c291417SAditya Swarup { 176400, TMDS_370M, 35672, 585938 }, 1562c291417SAditya Swarup { 176400, TMDS_371M, 18816, 309375 }, 1572c291417SAditya Swarup { 48000, TMDS_370M, 11648, 703125 }, 1582c291417SAditya Swarup { 48000, TMDS_371M, 5120, 309375 }, 1592c291417SAditya Swarup { 96000, TMDS_370M, 23296, 703125 }, 1602c291417SAditya Swarup { 96000, TMDS_371M, 10240, 309375 }, 1612c291417SAditya Swarup { 192000, TMDS_370M, 46592, 703125 }, 1622c291417SAditya Swarup { 192000, TMDS_371M, 20480, 309375 }, 1632c291417SAditya Swarup }; 1642c291417SAditya Swarup 1652c291417SAditya Swarup /* HDMI N/CTS table for 12 bit deep color(36 bpp)*/ 1662c291417SAditya Swarup #define TMDS_445_5M 445500 1672c291417SAditya Swarup #define TMDS_445M 445054 1682c291417SAditya Swarup 1692c291417SAditya Swarup static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = { 1702c291417SAditya Swarup { 32000, TMDS_445M, 5824, 632813 }, 1712c291417SAditya Swarup { 32000, TMDS_445_5M, 4096, 445500 }, 1722c291417SAditya Swarup { 44100, TMDS_445M, 8918, 703125 }, 1732c291417SAditya Swarup { 44100, TMDS_445_5M, 4704, 371250 }, 1742c291417SAditya Swarup { 88200, TMDS_445M, 17836, 703125 }, 1752c291417SAditya Swarup { 88200, TMDS_445_5M, 9408, 371250 }, 1762c291417SAditya Swarup { 176400, TMDS_445M, 35672, 703125 }, 1772c291417SAditya Swarup { 176400, TMDS_445_5M, 18816, 371250 }, 1782c291417SAditya Swarup { 48000, TMDS_445M, 5824, 421875 }, 1792c291417SAditya Swarup { 48000, TMDS_445_5M, 5120, 371250 }, 1802c291417SAditya Swarup { 96000, TMDS_445M, 11648, 421875 }, 1812c291417SAditya Swarup { 96000, TMDS_445_5M, 10240, 371250 }, 1822c291417SAditya Swarup { 192000, TMDS_445M, 23296, 421875 }, 1832c291417SAditya Swarup { 192000, TMDS_445_5M, 20480, 371250 }, 1842c291417SAditya Swarup }; 1852c291417SAditya Swarup 18656c12ec7SUma Shankar /* 18756c12ec7SUma Shankar * WA_14020863754: Implement Audio Workaround 18856c12ec7SUma Shankar * Corner case with Min Hblank Fix can cause audio hang 18956c12ec7SUma Shankar */ 19056c12ec7SUma Shankar static bool needs_wa_14020863754(struct drm_i915_private *i915) 19156c12ec7SUma Shankar { 19256c12ec7SUma Shankar return (DISPLAY_VER(i915) == 20 || IS_BATTLEMAGE(i915)); 19356c12ec7SUma Shankar } 19456c12ec7SUma Shankar 195df0566a6SJani Nikula /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ 196df0566a6SJani Nikula static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state) 197df0566a6SJani Nikula { 19846e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 199df0566a6SJani Nikula const struct drm_display_mode *adjusted_mode = 2001326a92cSMaarten Lankhorst &crtc_state->hw.adjusted_mode; 201df0566a6SJani Nikula int i; 202df0566a6SJani Nikula 203df0566a6SJani Nikula for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { 204df0566a6SJani Nikula if (adjusted_mode->crtc_clock == hdmi_audio_clock[i].clock) 205df0566a6SJani Nikula break; 206df0566a6SJani Nikula } 207df0566a6SJani Nikula 20846e61ee4SVille Syrjälä if (DISPLAY_VER(i915) < 12 && adjusted_mode->crtc_clock > 148500) 2091aae3065SKai Vehmanen i = ARRAY_SIZE(hdmi_audio_clock); 2101aae3065SKai Vehmanen 211df0566a6SJani Nikula if (i == ARRAY_SIZE(hdmi_audio_clock)) { 21246e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, 2139282a66cSJani Nikula "HDMI audio pixel clock setting for %d not found, falling back to defaults\n", 214df0566a6SJani Nikula adjusted_mode->crtc_clock); 215df0566a6SJani Nikula i = 1; 216df0566a6SJani Nikula } 217df0566a6SJani Nikula 21846e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, 2199282a66cSJani Nikula "Configuring HDMI audio for pixel clock %d (0x%08x)\n", 220df0566a6SJani Nikula hdmi_audio_clock[i].clock, 221df0566a6SJani Nikula hdmi_audio_clock[i].config); 222df0566a6SJani Nikula 223df0566a6SJani Nikula return hdmi_audio_clock[i].config; 224df0566a6SJani Nikula } 225df0566a6SJani Nikula 226df0566a6SJani Nikula static int audio_config_hdmi_get_n(const struct intel_crtc_state *crtc_state, 227df0566a6SJani Nikula int rate) 228df0566a6SJani Nikula { 2292c291417SAditya Swarup const struct hdmi_aud_ncts *hdmi_ncts_table; 2302c291417SAditya Swarup int i, size; 231df0566a6SJani Nikula 2322c291417SAditya Swarup if (crtc_state->pipe_bpp == 36) { 2332c291417SAditya Swarup hdmi_ncts_table = hdmi_aud_ncts_36bpp; 2342c291417SAditya Swarup size = ARRAY_SIZE(hdmi_aud_ncts_36bpp); 2352c291417SAditya Swarup } else if (crtc_state->pipe_bpp == 30) { 2362c291417SAditya Swarup hdmi_ncts_table = hdmi_aud_ncts_30bpp; 2372c291417SAditya Swarup size = ARRAY_SIZE(hdmi_aud_ncts_30bpp); 2382c291417SAditya Swarup } else { 2392c291417SAditya Swarup hdmi_ncts_table = hdmi_aud_ncts_24bpp; 2402c291417SAditya Swarup size = ARRAY_SIZE(hdmi_aud_ncts_24bpp); 2412c291417SAditya Swarup } 2422c291417SAditya Swarup 2432c291417SAditya Swarup for (i = 0; i < size; i++) { 2442c291417SAditya Swarup if (rate == hdmi_ncts_table[i].sample_rate && 2452c291417SAditya Swarup crtc_state->port_clock == hdmi_ncts_table[i].clock) { 2462c291417SAditya Swarup return hdmi_ncts_table[i].n; 247df0566a6SJani Nikula } 248df0566a6SJani Nikula } 249df0566a6SJani Nikula return 0; 250df0566a6SJani Nikula } 251df0566a6SJani Nikula 2521c0ab71aSVille Syrjälä /* ELD buffer size in dwords */ 2531c0ab71aSVille Syrjälä static int g4x_eld_buffer_size(struct drm_i915_private *i915) 2541c0ab71aSVille Syrjälä { 2551c0ab71aSVille Syrjälä u32 tmp; 2561c0ab71aSVille Syrjälä 2571c0ab71aSVille Syrjälä tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); 2581c0ab71aSVille Syrjälä 2591c0ab71aSVille Syrjälä return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp); 2601c0ab71aSVille Syrjälä } 2611c0ab71aSVille Syrjälä 26261a60df6SVille Syrjälä static void g4x_audio_codec_get_config(struct intel_encoder *encoder, 26361a60df6SVille Syrjälä struct intel_crtc_state *crtc_state) 26461a60df6SVille Syrjälä { 26561a60df6SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 26661a60df6SVille Syrjälä u32 *eld = (u32 *)crtc_state->eld; 26761a60df6SVille Syrjälä int eld_buffer_size, len, i; 26861a60df6SVille Syrjälä u32 tmp; 26961a60df6SVille Syrjälä 27061a60df6SVille Syrjälä tmp = intel_de_read(i915, G4X_AUD_CNTL_ST); 27161a60df6SVille Syrjälä if ((tmp & G4X_ELD_VALID) == 0) 27261a60df6SVille Syrjälä return; 27361a60df6SVille Syrjälä 27461a60df6SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, G4X_ELD_ADDRESS_MASK, 0); 27561a60df6SVille Syrjälä 27661a60df6SVille Syrjälä eld_buffer_size = g4x_eld_buffer_size(i915); 27761a60df6SVille Syrjälä len = min_t(int, sizeof(crtc_state->eld) / 4, eld_buffer_size); 27861a60df6SVille Syrjälä 27961a60df6SVille Syrjälä for (i = 0; i < len; i++) 28061a60df6SVille Syrjälä eld[i] = intel_de_read(i915, G4X_HDMIW_HDMIEDID); 28161a60df6SVille Syrjälä } 28261a60df6SVille Syrjälä 283df0566a6SJani Nikula static void g4x_audio_codec_disable(struct intel_encoder *encoder, 284df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 285df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 286df0566a6SJani Nikula { 28746e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 288c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 289df0566a6SJani Nikula 290df0566a6SJani Nikula /* Invalidate ELD */ 2917c8d74e8SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, 2927c8d74e8SVille Syrjälä G4X_ELD_VALID, 0); 293c3c5dc1dSVille Syrjälä 294c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 295c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 296df0566a6SJani Nikula } 297df0566a6SJani Nikula 298df0566a6SJani Nikula static void g4x_audio_codec_enable(struct intel_encoder *encoder, 299df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 300df0566a6SJani Nikula const struct drm_connector_state *conn_state) 301df0566a6SJani Nikula { 30246e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 303c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 3045d986635SVille Syrjälä const u32 *eld = (const u32 *)crtc_state->eld; 3050234cda2SVille Syrjälä int eld_buffer_size, len, i; 306df0566a6SJani Nikula 307c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 308c3c5dc1dSVille Syrjälä 3097c8d74e8SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, 3107c8d74e8SVille Syrjälä G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0); 311df0566a6SJani Nikula 3120234cda2SVille Syrjälä eld_buffer_size = g4x_eld_buffer_size(i915); 3135d986635SVille Syrjälä len = min(drm_eld_size(crtc_state->eld) / 4, eld_buffer_size); 3141c0ab71aSVille Syrjälä 315df0566a6SJani Nikula for (i = 0; i < len; i++) 31650a4a926SVille Syrjälä intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]); 3170234cda2SVille Syrjälä for (; i < eld_buffer_size; i++) 3180234cda2SVille Syrjälä intel_de_write(i915, G4X_HDMIW_HDMIEDID, 0); 3190234cda2SVille Syrjälä 3200234cda2SVille Syrjälä drm_WARN_ON(&i915->drm, 3210234cda2SVille Syrjälä (intel_de_read(i915, G4X_AUD_CNTL_ST) & G4X_ELD_ADDRESS_MASK) != 0); 322df0566a6SJani Nikula 3237c8d74e8SVille Syrjälä intel_de_rmw(i915, G4X_AUD_CNTL_ST, 3247c8d74e8SVille Syrjälä 0, G4X_ELD_VALID); 325df0566a6SJani Nikula } 326df0566a6SJani Nikula 327df0566a6SJani Nikula static void 328df0566a6SJani Nikula hsw_dp_audio_config_update(struct intel_encoder *encoder, 329df0566a6SJani Nikula const struct intel_crtc_state *crtc_state) 330df0566a6SJani Nikula { 33146e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 332df0566a6SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 333df0566a6SJani Nikula 3348e056b50SChaitanya Kumar Borah /* Enable time stamps. Let HW calculate Maud/Naud values */ 3358e056b50SChaitanya Kumar Borah intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), 3368e056b50SChaitanya Kumar Borah AUD_CONFIG_N_VALUE_INDEX | 3378e056b50SChaitanya Kumar Borah AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK | 3388e056b50SChaitanya Kumar Borah AUD_CONFIG_UPPER_N_MASK | 3398e056b50SChaitanya Kumar Borah AUD_CONFIG_LOWER_N_MASK | 3408e056b50SChaitanya Kumar Borah AUD_CONFIG_N_PROG_ENABLE, 3418e056b50SChaitanya Kumar Borah AUD_CONFIG_N_VALUE_INDEX); 342df0566a6SJani Nikula 343df0566a6SJani Nikula } 344df0566a6SJani Nikula 345df0566a6SJani Nikula static void 346df0566a6SJani Nikula hsw_hdmi_audio_config_update(struct intel_encoder *encoder, 347df0566a6SJani Nikula const struct intel_crtc_state *crtc_state) 348df0566a6SJani Nikula { 34946e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 35046e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 351df0566a6SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 352df0566a6SJani Nikula enum port port = encoder->port; 353df0566a6SJani Nikula int n, rate; 354df0566a6SJani Nikula u32 tmp; 355df0566a6SJani Nikula 356df0566a6SJani Nikula rate = acomp ? acomp->aud_sample_rate[port] : 0; 357df0566a6SJani Nikula 35846e61ee4SVille Syrjälä tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder)); 359df0566a6SJani Nikula tmp &= ~AUD_CONFIG_N_VALUE_INDEX; 360df0566a6SJani Nikula tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; 361df0566a6SJani Nikula tmp &= ~AUD_CONFIG_N_PROG_ENABLE; 362df0566a6SJani Nikula tmp |= audio_config_hdmi_pixel_clock(crtc_state); 363df0566a6SJani Nikula 364df0566a6SJani Nikula n = audio_config_hdmi_get_n(crtc_state, rate); 365df0566a6SJani Nikula if (n != 0) { 36646e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, "using N %d\n", n); 367df0566a6SJani Nikula 368df0566a6SJani Nikula tmp &= ~AUD_CONFIG_N_MASK; 369df0566a6SJani Nikula tmp |= AUD_CONFIG_N(n); 370df0566a6SJani Nikula tmp |= AUD_CONFIG_N_PROG_ENABLE; 371df0566a6SJani Nikula } else { 37246e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, "using automatic N\n"); 373df0566a6SJani Nikula } 374df0566a6SJani Nikula 37546e61ee4SVille Syrjälä intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp); 376df0566a6SJani Nikula 377df0566a6SJani Nikula /* 378df0566a6SJani Nikula * Let's disable "Enable CTS or M Prog bit" 379df0566a6SJani Nikula * and let HW calculate the value 380df0566a6SJani Nikula */ 38146e61ee4SVille Syrjälä tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder)); 382df0566a6SJani Nikula tmp &= ~AUD_M_CTS_M_PROG_ENABLE; 383df0566a6SJani Nikula tmp &= ~AUD_M_CTS_M_VALUE_INDEX; 38446e61ee4SVille Syrjälä intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp); 385df0566a6SJani Nikula } 386df0566a6SJani Nikula 387df0566a6SJani Nikula static void 388df0566a6SJani Nikula hsw_audio_config_update(struct intel_encoder *encoder, 389df0566a6SJani Nikula const struct intel_crtc_state *crtc_state) 390df0566a6SJani Nikula { 391df0566a6SJani Nikula if (intel_crtc_has_dp_encoder(crtc_state)) 392df0566a6SJani Nikula hsw_dp_audio_config_update(encoder, crtc_state); 393df0566a6SJani Nikula else 394df0566a6SJani Nikula hsw_hdmi_audio_config_update(encoder, crtc_state); 395df0566a6SJani Nikula } 396df0566a6SJani Nikula 397df0566a6SJani Nikula static void hsw_audio_codec_disable(struct intel_encoder *encoder, 398df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 399df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 400df0566a6SJani Nikula { 40146e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 402c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 403df0566a6SJani Nikula enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 404df0566a6SJani Nikula 40546e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 406df0566a6SJani Nikula 407df0566a6SJani Nikula /* Disable timestamps */ 4087c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder), 4097c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX | 4107c8d74e8SVille Syrjälä AUD_CONFIG_UPPER_N_MASK | 4117c8d74e8SVille Syrjälä AUD_CONFIG_LOWER_N_MASK, 4127c8d74e8SVille Syrjälä AUD_CONFIG_N_PROG_ENABLE | 4137c8d74e8SVille Syrjälä (intel_crtc_has_dp_encoder(old_crtc_state) ? 4147c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX : 0)); 415df0566a6SJani Nikula 416cbbda2ffSVille Syrjälä /* Invalidate ELD */ 4177c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 418cbbda2ffSVille Syrjälä AUDIO_ELD_VALID(cpu_transcoder), 0); 419cbbda2ffSVille Syrjälä 420c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 421c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 422c3c5dc1dSVille Syrjälä 423cbbda2ffSVille Syrjälä /* Disable audio presence detect */ 424cbbda2ffSVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 4257c8d74e8SVille Syrjälä AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0); 426df0566a6SJani Nikula 42756c12ec7SUma Shankar if (needs_wa_14020863754(i915)) 42856c12ec7SUma Shankar intel_de_rmw(i915, AUD_CHICKENBIT_REG3, DACBE_DISABLE_MIN_HBLANK_FIX, 0); 42956c12ec7SUma Shankar 43046e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 431df0566a6SJani Nikula } 432df0566a6SJani Nikula 4332dd43144SVille Syrjälä static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder, 43448b8b04cSUma Shankar const struct intel_crtc_state *crtc_state) 43548b8b04cSUma Shankar { 43648b8b04cSUma Shankar struct drm_i915_private *i915 = to_i915(encoder->base.dev); 43748b8b04cSUma Shankar unsigned int link_clks_available, link_clks_required; 43848b8b04cSUma Shankar unsigned int tu_data, tu_line, link_clks_active; 439d19b29beSVille Syrjälä unsigned int h_active, h_total, hblank_delta, pixel_clk; 44008fcb5abSAnkit Nautiyal unsigned int fec_coeff, cdclk, vdsc_bppx16; 44141ee86d6SVille Syrjälä unsigned int link_clk, lanes; 4422dd43144SVille Syrjälä unsigned int hblank_rise; 44348b8b04cSUma Shankar 44448b8b04cSUma Shankar h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay; 44548b8b04cSUma Shankar h_total = crtc_state->hw.adjusted_mode.crtc_htotal; 44648b8b04cSUma Shankar pixel_clk = crtc_state->hw.adjusted_mode.crtc_clock; 44708fcb5abSAnkit Nautiyal vdsc_bppx16 = crtc_state->dsc.compressed_bpp_x16; 448d51309b4SJani Nikula cdclk = i915->display.cdclk.hw.cdclk; 44948b8b04cSUma Shankar /* fec= 0.972261, using rounding multiplier of 1000000 */ 45048b8b04cSUma Shankar fec_coeff = 972261; 45141ee86d6SVille Syrjälä link_clk = crtc_state->port_clock; 45241ee86d6SVille Syrjälä lanes = crtc_state->lane_count; 45348b8b04cSUma Shankar 45408fcb5abSAnkit Nautiyal drm_dbg_kms(&i915->drm, 45508fcb5abSAnkit Nautiyal "h_active = %u link_clk = %u : lanes = %u vdsc_bpp = " BPP_X16_FMT " cdclk = %u\n", 45608fcb5abSAnkit Nautiyal h_active, link_clk, lanes, BPP_X16_ARGS(vdsc_bppx16), cdclk); 45748b8b04cSUma Shankar 45808fcb5abSAnkit Nautiyal if (WARN_ON(!link_clk || !pixel_clk || !lanes || !vdsc_bppx16 || !cdclk)) 45911ebc232SJani Nikula return 0; 46011ebc232SJani Nikula 4612dd43144SVille Syrjälä link_clks_available = (h_total - h_active) * link_clk / pixel_clk - 28; 4622dd43144SVille Syrjälä link_clks_required = DIV_ROUND_UP(192000 * h_total, 1000 * pixel_clk) * (48 / lanes + 2); 46348b8b04cSUma Shankar 46448b8b04cSUma Shankar if (link_clks_available > link_clks_required) 46548b8b04cSUma Shankar hblank_delta = 32; 46648b8b04cSUma Shankar else 4672dd43144SVille Syrjälä hblank_delta = DIV64_U64_ROUND_UP(mul_u32_u32(5 * (link_clk + cdclk), pixel_clk), 4682dd43144SVille Syrjälä mul_u32_u32(link_clk, cdclk)); 46948b8b04cSUma Shankar 47008fcb5abSAnkit Nautiyal tu_data = div64_u64(mul_u32_u32(pixel_clk * vdsc_bppx16 * 8, 1000000), 47108fcb5abSAnkit Nautiyal mul_u32_u32(link_clk * lanes * 16, fec_coeff)); 4722dd43144SVille Syrjälä tu_line = div64_u64(h_active * mul_u32_u32(link_clk, fec_coeff), 4732dd43144SVille Syrjälä mul_u32_u32(64 * pixel_clk, 1000000)); 47448b8b04cSUma Shankar link_clks_active = (tu_line - 1) * 64 + tu_data; 47548b8b04cSUma Shankar 4762dd43144SVille Syrjälä hblank_rise = (link_clks_active + 6 * DIV_ROUND_UP(link_clks_active, 250) + 4) * pixel_clk / link_clk; 47748b8b04cSUma Shankar 4782dd43144SVille Syrjälä return h_active - hblank_rise + hblank_delta; 47948b8b04cSUma Shankar } 48048b8b04cSUma Shankar 4812dd43144SVille Syrjälä static unsigned int calc_samples_room(const struct intel_crtc_state *crtc_state) 48248b8b04cSUma Shankar { 48348b8b04cSUma Shankar unsigned int h_active, h_total, pixel_clk; 48441ee86d6SVille Syrjälä unsigned int link_clk, lanes; 48548b8b04cSUma Shankar 48648b8b04cSUma Shankar h_active = crtc_state->hw.adjusted_mode.hdisplay; 48748b8b04cSUma Shankar h_total = crtc_state->hw.adjusted_mode.htotal; 48848b8b04cSUma Shankar pixel_clk = crtc_state->hw.adjusted_mode.clock; 48941ee86d6SVille Syrjälä link_clk = crtc_state->port_clock; 49041ee86d6SVille Syrjälä lanes = crtc_state->lane_count; 49148b8b04cSUma Shankar 4922dd43144SVille Syrjälä return ((h_total - h_active) * link_clk - 12 * pixel_clk) / 4932dd43144SVille Syrjälä (pixel_clk * (48 / lanes + 2)); 49448b8b04cSUma Shankar } 49548b8b04cSUma Shankar 49648b8b04cSUma Shankar static void enable_audio_dsc_wa(struct intel_encoder *encoder, 49748b8b04cSUma Shankar const struct intel_crtc_state *crtc_state) 49848b8b04cSUma Shankar { 49948b8b04cSUma Shankar struct drm_i915_private *i915 = to_i915(encoder->base.dev); 5005eba7426SVille Syrjälä enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 50111ebc232SJani Nikula unsigned int hblank_early_prog, samples_room; 50248b8b04cSUma Shankar unsigned int val; 50348b8b04cSUma Shankar 504005e9537SMatt Roper if (DISPLAY_VER(i915) < 11) 50548b8b04cSUma Shankar return; 50648b8b04cSUma Shankar 50748b8b04cSUma Shankar val = intel_de_read(i915, AUD_CONFIG_BE); 50848b8b04cSUma Shankar 50993e7e61eSLucas De Marchi if (DISPLAY_VER(i915) == 11) 5105eba7426SVille Syrjälä val |= HBLANK_EARLY_ENABLE_ICL(cpu_transcoder); 511005e9537SMatt Roper else if (DISPLAY_VER(i915) >= 12) 5125eba7426SVille Syrjälä val |= HBLANK_EARLY_ENABLE_TGL(cpu_transcoder); 51348b8b04cSUma Shankar 51448b8b04cSUma Shankar if (crtc_state->dsc.compression_enable && 51531824c03SJani Nikula crtc_state->hw.adjusted_mode.hdisplay >= 3840 && 51631824c03SJani Nikula crtc_state->hw.adjusted_mode.vdisplay >= 2160) { 51748b8b04cSUma Shankar /* Get hblank early enable value required */ 5185eba7426SVille Syrjälä val &= ~HBLANK_START_COUNT_MASK(cpu_transcoder); 5192dd43144SVille Syrjälä hblank_early_prog = calc_hblank_early_prog(encoder, crtc_state); 520f4c50deeSJani Nikula if (hblank_early_prog < 32) 5215eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_32); 522f4c50deeSJani Nikula else if (hblank_early_prog < 64) 5235eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_64); 524f4c50deeSJani Nikula else if (hblank_early_prog < 96) 5255eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_96); 526f4c50deeSJani Nikula else 5275eba7426SVille Syrjälä val |= HBLANK_START_COUNT(cpu_transcoder, HBLANK_START_COUNT_128); 52848b8b04cSUma Shankar 52948b8b04cSUma Shankar /* Get samples room value required */ 5305eba7426SVille Syrjälä val &= ~NUMBER_SAMPLES_PER_LINE_MASK(cpu_transcoder); 5312dd43144SVille Syrjälä samples_room = calc_samples_room(crtc_state); 532f4c50deeSJani Nikula if (samples_room < 3) 5335eba7426SVille Syrjälä val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, samples_room); 534f4c50deeSJani Nikula else /* Program 0 i.e "All Samples available in buffer" */ 5355eba7426SVille Syrjälä val |= NUMBER_SAMPLES_PER_LINE(cpu_transcoder, 0x0); 53648b8b04cSUma Shankar } 53748b8b04cSUma Shankar 53848b8b04cSUma Shankar intel_de_write(i915, AUD_CONFIG_BE, val); 53948b8b04cSUma Shankar } 54048b8b04cSUma Shankar 541df0566a6SJani Nikula static void hsw_audio_codec_enable(struct intel_encoder *encoder, 542df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 543df0566a6SJani Nikula const struct drm_connector_state *conn_state) 544df0566a6SJani Nikula { 54546e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 546c3c5dc1dSVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 547df0566a6SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 548df0566a6SJani Nikula 54946e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 550df0566a6SJani Nikula 55148b8b04cSUma Shankar /* Enable Audio WA for 4k DSC usecases */ 55248b8b04cSUma Shankar if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP)) 55348b8b04cSUma Shankar enable_audio_dsc_wa(encoder, crtc_state); 55448b8b04cSUma Shankar 55556c12ec7SUma Shankar if (needs_wa_14020863754(i915)) 55656c12ec7SUma Shankar intel_de_rmw(i915, AUD_CHICKENBIT_REG3, 0, DACBE_DISABLE_MIN_HBLANK_FIX); 55756c12ec7SUma Shankar 558cbbda2ffSVille Syrjälä /* Enable audio presence detect */ 5597c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 560cbbda2ffSVille Syrjälä 0, AUDIO_OUTPUT_ENABLE(cpu_transcoder)); 561cbbda2ffSVille Syrjälä 562c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 563c3c5dc1dSVille Syrjälä 564cbbda2ffSVille Syrjälä /* Invalidate ELD */ 565cbbda2ffSVille Syrjälä intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD, 566cbbda2ffSVille Syrjälä AUDIO_ELD_VALID(cpu_transcoder), 0); 567df0566a6SJani Nikula 56868470541SVille Syrjälä /* 56968470541SVille Syrjälä * The audio componenent is used to convey the ELD 57068470541SVille Syrjälä * instead using of the hardware ELD buffer. 57168470541SVille Syrjälä */ 572df0566a6SJani Nikula 573df0566a6SJani Nikula /* Enable timestamps */ 574df0566a6SJani Nikula hsw_audio_config_update(encoder, crtc_state); 575df0566a6SJani Nikula 57646e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 577df0566a6SJani Nikula } 578df0566a6SJani Nikula 5797e95cb09SVille Syrjälä struct ibx_audio_regs { 580669d7fd6SVille Syrjälä i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; 581669d7fd6SVille Syrjälä }; 582669d7fd6SVille Syrjälä 5837e95cb09SVille Syrjälä static void ibx_audio_regs_init(struct drm_i915_private *i915, 584669d7fd6SVille Syrjälä enum pipe pipe, 5857e95cb09SVille Syrjälä struct ibx_audio_regs *regs) 586669d7fd6SVille Syrjälä { 58731395fbaSVille Syrjälä if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { 588669d7fd6SVille Syrjälä regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); 589669d7fd6SVille Syrjälä regs->aud_config = VLV_AUD_CFG(pipe); 590669d7fd6SVille Syrjälä regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe); 591669d7fd6SVille Syrjälä regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2; 59231395fbaSVille Syrjälä } else if (HAS_PCH_CPT(i915)) { 593669d7fd6SVille Syrjälä regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); 594669d7fd6SVille Syrjälä regs->aud_config = CPT_AUD_CFG(pipe); 595669d7fd6SVille Syrjälä regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe); 596669d7fd6SVille Syrjälä regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; 59731395fbaSVille Syrjälä } else if (HAS_PCH_IBX(i915)) { 59831395fbaSVille Syrjälä regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); 59931395fbaSVille Syrjälä regs->aud_config = IBX_AUD_CFG(pipe); 60031395fbaSVille Syrjälä regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe); 60131395fbaSVille Syrjälä regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2; 602669d7fd6SVille Syrjälä } 603669d7fd6SVille Syrjälä } 604669d7fd6SVille Syrjälä 6057e95cb09SVille Syrjälä static void ibx_audio_codec_disable(struct intel_encoder *encoder, 606df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 607df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 608df0566a6SJani Nikula { 60946e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 6102225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 611df0566a6SJani Nikula enum port port = encoder->port; 6127c8d74e8SVille Syrjälä enum pipe pipe = crtc->pipe; 6137e95cb09SVille Syrjälä struct ibx_audio_regs regs; 614df0566a6SJani Nikula 61546e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, port == PORT_A)) 616df0566a6SJani Nikula return; 617df0566a6SJani Nikula 6187e95cb09SVille Syrjälä ibx_audio_regs_init(i915, pipe, ®s); 619df0566a6SJani Nikula 6209f4a5125SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 6219f4a5125SVille Syrjälä 622df0566a6SJani Nikula /* Disable timestamps */ 6237c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_config, 6247c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX | 6257c8d74e8SVille Syrjälä AUD_CONFIG_UPPER_N_MASK | 6267c8d74e8SVille Syrjälä AUD_CONFIG_LOWER_N_MASK, 6277c8d74e8SVille Syrjälä AUD_CONFIG_N_PROG_ENABLE | 6287c8d74e8SVille Syrjälä (intel_crtc_has_dp_encoder(old_crtc_state) ? 6297c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX : 0)); 630df0566a6SJani Nikula 631df0566a6SJani Nikula /* Invalidate ELD */ 6327c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_cntrl_st2, 6337c8d74e8SVille Syrjälä IBX_ELD_VALID(port), 0); 6349f4a5125SVille Syrjälä 6359f4a5125SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 636c3c5dc1dSVille Syrjälä 637c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 638c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 639df0566a6SJani Nikula } 640df0566a6SJani Nikula 6417e95cb09SVille Syrjälä static void ibx_audio_codec_enable(struct intel_encoder *encoder, 642df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 643df0566a6SJani Nikula const struct drm_connector_state *conn_state) 644df0566a6SJani Nikula { 64546e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 6462225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 647df0566a6SJani Nikula enum port port = encoder->port; 6487c8d74e8SVille Syrjälä enum pipe pipe = crtc->pipe; 6497e95cb09SVille Syrjälä struct ibx_audio_regs regs; 650df0566a6SJani Nikula 65146e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, port == PORT_A)) 652df0566a6SJani Nikula return; 653df0566a6SJani Nikula 654c3c5dc1dSVille Syrjälä intel_crtc_wait_for_next_vblank(crtc); 655df0566a6SJani Nikula 6567e95cb09SVille Syrjälä ibx_audio_regs_init(i915, pipe, ®s); 657df0566a6SJani Nikula 6589f4a5125SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 659df0566a6SJani Nikula 660df0566a6SJani Nikula /* Invalidate ELD */ 6617c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_cntrl_st2, 6627c8d74e8SVille Syrjälä IBX_ELD_VALID(port), 0); 663df0566a6SJani Nikula 664343cb0f9SVille Syrjälä /* 665343cb0f9SVille Syrjälä * The audio componenent is used to convey the ELD 666343cb0f9SVille Syrjälä * instead using of the hardware ELD buffer. 667343cb0f9SVille Syrjälä */ 668df0566a6SJani Nikula 669df0566a6SJani Nikula /* Enable timestamps */ 6707c8d74e8SVille Syrjälä intel_de_rmw(i915, regs.aud_config, 6717c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX | 6727c8d74e8SVille Syrjälä AUD_CONFIG_N_PROG_ENABLE | 6737c8d74e8SVille Syrjälä AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 6747c8d74e8SVille Syrjälä (intel_crtc_has_dp_encoder(crtc_state) ? 6757c8d74e8SVille Syrjälä AUD_CONFIG_N_VALUE_INDEX : 6767c8d74e8SVille Syrjälä audio_config_hdmi_pixel_clock(crtc_state))); 6779f4a5125SVille Syrjälä 6789f4a5125SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 679df0566a6SJani Nikula } 680df0566a6SJani Nikula 6812f092c0cSVinod Govindapillai void intel_audio_sdp_split_update(const struct intel_crtc_state *crtc_state) 6828853750dSVinod Govindapillai { 6832f092c0cSVinod Govindapillai struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 6842f092c0cSVinod Govindapillai struct drm_i915_private *i915 = to_i915(crtc->base.dev); 6858853750dSVinod Govindapillai enum transcoder trans = crtc_state->cpu_transcoder; 6868853750dSVinod Govindapillai 6878853750dSVinod Govindapillai if (HAS_DP20(i915)) 6888853750dSVinod Govindapillai intel_de_rmw(i915, AUD_DP_2DOT0_CTRL(trans), AUD_ENABLE_SDP_SPLIT, 6898853750dSVinod Govindapillai crtc_state->sdp_split_enable ? AUD_ENABLE_SDP_SPLIT : 0); 6908853750dSVinod Govindapillai } 6918853750dSVinod Govindapillai 6925d986635SVille Syrjälä bool intel_audio_compute_config(struct intel_encoder *encoder, 6935d986635SVille Syrjälä struct intel_crtc_state *crtc_state, 6945d986635SVille Syrjälä struct drm_connector_state *conn_state) 6955d986635SVille Syrjälä { 6965d986635SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 6975d986635SVille Syrjälä struct drm_connector *connector = conn_state->connector; 6985d986635SVille Syrjälä const struct drm_display_mode *adjusted_mode = 6995d986635SVille Syrjälä &crtc_state->hw.adjusted_mode; 7005d986635SVille Syrjälä 701d6393793SVille Syrjälä if (!connector->eld[0]) { 7025d986635SVille Syrjälä drm_dbg_kms(&i915->drm, 7035d986635SVille Syrjälä "Bogus ELD on [CONNECTOR:%d:%s]\n", 7045d986635SVille Syrjälä connector->base.id, connector->name); 705d6393793SVille Syrjälä return false; 706d6393793SVille Syrjälä } 7075d986635SVille Syrjälä 7085d986635SVille Syrjälä BUILD_BUG_ON(sizeof(crtc_state->eld) != sizeof(connector->eld)); 7095d986635SVille Syrjälä memcpy(crtc_state->eld, connector->eld, sizeof(crtc_state->eld)); 7105d986635SVille Syrjälä 7115d986635SVille Syrjälä crtc_state->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; 7125d986635SVille Syrjälä 7135d986635SVille Syrjälä return true; 7145d986635SVille Syrjälä } 7155d986635SVille Syrjälä 716df0566a6SJani Nikula /** 717df0566a6SJani Nikula * intel_audio_codec_enable - Enable the audio codec for HD audio 718df0566a6SJani Nikula * @encoder: encoder on which to enable audio 719df0566a6SJani Nikula * @crtc_state: pointer to the current crtc state. 720df0566a6SJani Nikula * @conn_state: pointer to the current connector state. 721df0566a6SJani Nikula * 722df0566a6SJani Nikula * The enable sequences may only be performed after enabling the transcoder and 723df0566a6SJani Nikula * port, and after completed link training. 724df0566a6SJani Nikula */ 725df0566a6SJani Nikula void intel_audio_codec_enable(struct intel_encoder *encoder, 726df0566a6SJani Nikula const struct intel_crtc_state *crtc_state, 727df0566a6SJani Nikula const struct drm_connector_state *conn_state) 728df0566a6SJani Nikula { 72946e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 73046e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 7312225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 732c7104c38SVille Syrjälä struct intel_connector *connector = to_intel_connector(conn_state->connector); 7335eba7426SVille Syrjälä enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 734c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 735df0566a6SJani Nikula enum port port = encoder->port; 736df0566a6SJani Nikula 737179db7c1SJani Nikula if (!crtc_state->has_audio) 738179db7c1SJani Nikula return; 739179db7c1SJani Nikula 740c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on [CRTC:%d:%s], %u bytes ELD\n", 741c7104c38SVille Syrjälä connector->base.base.id, connector->base.name, 7421f31e35fSJani Nikula encoder->base.base.id, encoder->base.name, 743c7104c38SVille Syrjälä crtc->base.base.id, crtc->base.name, 7445d986635SVille Syrjälä drm_eld_size(crtc_state->eld)); 745df0566a6SJani Nikula 74646e61ee4SVille Syrjälä if (i915->display.funcs.audio) 74746e61ee4SVille Syrjälä i915->display.funcs.audio->audio_codec_enable(encoder, 748df0566a6SJani Nikula crtc_state, 749df0566a6SJani Nikula conn_state); 750df0566a6SJani Nikula 75146e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 752df0566a6SJani Nikula 7535eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 754c7104c38SVille Syrjälä 755c7104c38SVille Syrjälä audio_state->encoder = encoder; 7565d986635SVille Syrjälä BUILD_BUG_ON(sizeof(audio_state->eld) != sizeof(crtc_state->eld)); 7575d986635SVille Syrjälä memcpy(audio_state->eld, crtc_state->eld, sizeof(audio_state->eld)); 758c7104c38SVille Syrjälä 75946e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 760df0566a6SJani Nikula 761df0566a6SJani Nikula if (acomp && acomp->base.audio_ops && 762df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify) { 7635eba7426SVille Syrjälä /* audio drivers expect cpu_transcoder = -1 to indicate Non-MST cases */ 764df0566a6SJani Nikula if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) 7655eba7426SVille Syrjälä cpu_transcoder = -1; 766df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, 7675eba7426SVille Syrjälä (int)port, (int)cpu_transcoder); 768df0566a6SJani Nikula } 769df0566a6SJani Nikula 7705eba7426SVille Syrjälä intel_lpe_audio_notify(i915, cpu_transcoder, port, crtc_state->eld, 771df0566a6SJani Nikula crtc_state->port_clock, 772df0566a6SJani Nikula intel_crtc_has_dp_encoder(crtc_state)); 773df0566a6SJani Nikula } 774df0566a6SJani Nikula 775df0566a6SJani Nikula /** 776df0566a6SJani Nikula * intel_audio_codec_disable - Disable the audio codec for HD audio 777df0566a6SJani Nikula * @encoder: encoder on which to disable audio 778df0566a6SJani Nikula * @old_crtc_state: pointer to the old crtc state. 779df0566a6SJani Nikula * @old_conn_state: pointer to the old connector state. 780df0566a6SJani Nikula * 781df0566a6SJani Nikula * The disable sequences must be performed before disabling the transcoder or 782df0566a6SJani Nikula * port. 783df0566a6SJani Nikula */ 784df0566a6SJani Nikula void intel_audio_codec_disable(struct intel_encoder *encoder, 785df0566a6SJani Nikula const struct intel_crtc_state *old_crtc_state, 786df0566a6SJani Nikula const struct drm_connector_state *old_conn_state) 787df0566a6SJani Nikula { 78846e61ee4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 78946e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 7902225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); 791c7104c38SVille Syrjälä struct intel_connector *connector = to_intel_connector(old_conn_state->connector); 7925eba7426SVille Syrjälä enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 793c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 794df0566a6SJani Nikula enum port port = encoder->port; 795df0566a6SJani Nikula 796179db7c1SJani Nikula if (!old_crtc_state->has_audio) 797179db7c1SJani Nikula return; 798179db7c1SJani Nikula 799c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on [CRTC:%d:%s]\n", 800c7104c38SVille Syrjälä connector->base.base.id, connector->base.name, 801c7104c38SVille Syrjälä encoder->base.base.id, encoder->base.name, 802c7104c38SVille Syrjälä crtc->base.base.id, crtc->base.name); 8031f31e35fSJani Nikula 80446e61ee4SVille Syrjälä if (i915->display.funcs.audio) 80546e61ee4SVille Syrjälä i915->display.funcs.audio->audio_codec_disable(encoder, 806df0566a6SJani Nikula old_crtc_state, 807df0566a6SJani Nikula old_conn_state); 808df0566a6SJani Nikula 80946e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 810c7104c38SVille Syrjälä 8115eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 812c7104c38SVille Syrjälä 813c7104c38SVille Syrjälä audio_state->encoder = NULL; 8145d986635SVille Syrjälä memset(audio_state->eld, 0, sizeof(audio_state->eld)); 815c7104c38SVille Syrjälä 81646e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 817df0566a6SJani Nikula 818df0566a6SJani Nikula if (acomp && acomp->base.audio_ops && 819df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify) { 8205eba7426SVille Syrjälä /* audio drivers expect cpu_transcoder = -1 to indicate Non-MST cases */ 821df0566a6SJani Nikula if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) 8225eba7426SVille Syrjälä cpu_transcoder = -1; 823df0566a6SJani Nikula acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr, 8245eba7426SVille Syrjälä (int)port, (int)cpu_transcoder); 825df0566a6SJani Nikula } 826df0566a6SJani Nikula 8275eba7426SVille Syrjälä intel_lpe_audio_notify(i915, cpu_transcoder, port, NULL, 0, false); 828df0566a6SJani Nikula } 829df0566a6SJani Nikula 83061a60df6SVille Syrjälä static void intel_acomp_get_config(struct intel_encoder *encoder, 83161a60df6SVille Syrjälä struct intel_crtc_state *crtc_state) 83261a60df6SVille Syrjälä { 83361a60df6SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 8345eba7426SVille Syrjälä enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; 83561a60df6SVille Syrjälä struct intel_audio_state *audio_state; 83661a60df6SVille Syrjälä 83761a60df6SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 83861a60df6SVille Syrjälä 8395eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 84061a60df6SVille Syrjälä 84161a60df6SVille Syrjälä if (audio_state->encoder) 84261a60df6SVille Syrjälä memcpy(crtc_state->eld, audio_state->eld, sizeof(audio_state->eld)); 84361a60df6SVille Syrjälä 84461a60df6SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 84561a60df6SVille Syrjälä } 84661a60df6SVille Syrjälä 84761a60df6SVille Syrjälä void intel_audio_codec_get_config(struct intel_encoder *encoder, 84861a60df6SVille Syrjälä struct intel_crtc_state *crtc_state) 84961a60df6SVille Syrjälä { 85061a60df6SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 85161a60df6SVille Syrjälä 85261a60df6SVille Syrjälä if (!crtc_state->has_audio) 85361a60df6SVille Syrjälä return; 85461a60df6SVille Syrjälä 85561a60df6SVille Syrjälä if (i915->display.funcs.audio) 85661a60df6SVille Syrjälä i915->display.funcs.audio->audio_codec_get_config(encoder, crtc_state); 85761a60df6SVille Syrjälä } 85861a60df6SVille Syrjälä 8590a108bcaSDave Airlie static const struct intel_audio_funcs g4x_audio_funcs = { 8600a108bcaSDave Airlie .audio_codec_enable = g4x_audio_codec_enable, 8610a108bcaSDave Airlie .audio_codec_disable = g4x_audio_codec_disable, 86261a60df6SVille Syrjälä .audio_codec_get_config = g4x_audio_codec_get_config, 8630a108bcaSDave Airlie }; 8640a108bcaSDave Airlie 8657e95cb09SVille Syrjälä static const struct intel_audio_funcs ibx_audio_funcs = { 8667e95cb09SVille Syrjälä .audio_codec_enable = ibx_audio_codec_enable, 8677e95cb09SVille Syrjälä .audio_codec_disable = ibx_audio_codec_disable, 86861a60df6SVille Syrjälä .audio_codec_get_config = intel_acomp_get_config, 8690a108bcaSDave Airlie }; 8700a108bcaSDave Airlie 8710a108bcaSDave Airlie static const struct intel_audio_funcs hsw_audio_funcs = { 8720a108bcaSDave Airlie .audio_codec_enable = hsw_audio_codec_enable, 8730a108bcaSDave Airlie .audio_codec_disable = hsw_audio_codec_disable, 87461a60df6SVille Syrjälä .audio_codec_get_config = intel_acomp_get_config, 8750a108bcaSDave Airlie }; 8760a108bcaSDave Airlie 877df0566a6SJani Nikula /** 878f47a0e35SJani Nikula * intel_audio_hooks_init - Set up chip specific audio hooks 87946e61ee4SVille Syrjälä * @i915: device private 880df0566a6SJani Nikula */ 88146e61ee4SVille Syrjälä void intel_audio_hooks_init(struct drm_i915_private *i915) 882df0566a6SJani Nikula { 88346e61ee4SVille Syrjälä if (IS_G4X(i915)) 88446e61ee4SVille Syrjälä i915->display.funcs.audio = &g4x_audio_funcs; 88531395fbaSVille Syrjälä else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915) || 88631395fbaSVille Syrjälä HAS_PCH_CPT(i915) || HAS_PCH_IBX(i915)) 8877e95cb09SVille Syrjälä i915->display.funcs.audio = &ibx_audio_funcs; 88846e61ee4SVille Syrjälä else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8) 88946e61ee4SVille Syrjälä i915->display.funcs.audio = &hsw_audio_funcs; 890df0566a6SJani Nikula } 891df0566a6SJani Nikula 892112a87c4SKai Vehmanen struct aud_ts_cdclk_m_n { 893112a87c4SKai Vehmanen u8 m; 894112a87c4SKai Vehmanen u16 n; 895112a87c4SKai Vehmanen }; 896112a87c4SKai Vehmanen 897112a87c4SKai Vehmanen void intel_audio_cdclk_change_pre(struct drm_i915_private *i915) 898112a87c4SKai Vehmanen { 899112a87c4SKai Vehmanen if (DISPLAY_VER(i915) >= 13) 900112a87c4SKai Vehmanen intel_de_rmw(i915, AUD_TS_CDCLK_M, AUD_TS_CDCLK_M_EN, 0); 901112a87c4SKai Vehmanen } 902112a87c4SKai Vehmanen 903112a87c4SKai Vehmanen static void get_aud_ts_cdclk_m_n(int refclk, int cdclk, struct aud_ts_cdclk_m_n *aud_ts) 904112a87c4SKai Vehmanen { 905091496e6SClint Taylor aud_ts->m = 60; 906112a87c4SKai Vehmanen aud_ts->n = cdclk * aud_ts->m / 24000; 907112a87c4SKai Vehmanen } 908112a87c4SKai Vehmanen 909112a87c4SKai Vehmanen void intel_audio_cdclk_change_post(struct drm_i915_private *i915) 910112a87c4SKai Vehmanen { 911112a87c4SKai Vehmanen struct aud_ts_cdclk_m_n aud_ts; 912112a87c4SKai Vehmanen 913112a87c4SKai Vehmanen if (DISPLAY_VER(i915) >= 13) { 914d51309b4SJani Nikula get_aud_ts_cdclk_m_n(i915->display.cdclk.hw.ref, i915->display.cdclk.hw.cdclk, &aud_ts); 915112a87c4SKai Vehmanen 916112a87c4SKai Vehmanen intel_de_write(i915, AUD_TS_CDCLK_N, aud_ts.n); 917112a87c4SKai Vehmanen intel_de_write(i915, AUD_TS_CDCLK_M, aud_ts.m | AUD_TS_CDCLK_M_EN); 918112a87c4SKai Vehmanen drm_dbg_kms(&i915->drm, "aud_ts_cdclk set to M=%u, N=%u\n", aud_ts.m, aud_ts.n); 919112a87c4SKai Vehmanen } 920112a87c4SKai Vehmanen } 921112a87c4SKai Vehmanen 92228a30b45SVille Syrjälä static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state, 92308e3ed3aSChris Wilson struct intel_crtc *crtc, 92428a30b45SVille Syrjälä bool enable) 92528a30b45SVille Syrjälä { 92628a30b45SVille Syrjälä struct intel_cdclk_state *cdclk_state; 92728a30b45SVille Syrjälä int ret; 92828a30b45SVille Syrjälä 92928a30b45SVille Syrjälä /* need to hold at least one crtc lock for the global state */ 93028a30b45SVille Syrjälä ret = drm_modeset_lock(&crtc->base.mutex, state->base.acquire_ctx); 93128a30b45SVille Syrjälä if (ret) 93228a30b45SVille Syrjälä return ret; 93328a30b45SVille Syrjälä 93428a30b45SVille Syrjälä cdclk_state = intel_atomic_get_cdclk_state(state); 93528a30b45SVille Syrjälä if (IS_ERR(cdclk_state)) 93628a30b45SVille Syrjälä return PTR_ERR(cdclk_state); 93728a30b45SVille Syrjälä 93828a30b45SVille Syrjälä cdclk_state->force_min_cdclk = enable ? 2 * 96000 : 0; 93928a30b45SVille Syrjälä 94028a30b45SVille Syrjälä return drm_atomic_commit(&state->base); 94128a30b45SVille Syrjälä } 94228a30b45SVille Syrjälä 94346e61ee4SVille Syrjälä static void glk_force_audio_cdclk(struct drm_i915_private *i915, 944df0566a6SJani Nikula bool enable) 945df0566a6SJani Nikula { 946df0566a6SJani Nikula struct drm_modeset_acquire_ctx ctx; 947df0566a6SJani Nikula struct drm_atomic_state *state; 94808e3ed3aSChris Wilson struct intel_crtc *crtc; 949df0566a6SJani Nikula int ret; 950df0566a6SJani Nikula 95146e61ee4SVille Syrjälä crtc = intel_first_crtc(i915); 95208e3ed3aSChris Wilson if (!crtc) 95308e3ed3aSChris Wilson return; 95408e3ed3aSChris Wilson 955df0566a6SJani Nikula drm_modeset_acquire_init(&ctx, 0); 95646e61ee4SVille Syrjälä state = drm_atomic_state_alloc(&i915->drm); 95746e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, !state)) 958df0566a6SJani Nikula return; 959df0566a6SJani Nikula 960df0566a6SJani Nikula state->acquire_ctx = &ctx; 96176ec6927SVille Syrjälä to_intel_atomic_state(state)->internal = true; 962df0566a6SJani Nikula 963df0566a6SJani Nikula retry: 96408e3ed3aSChris Wilson ret = glk_force_audio_cdclk_commit(to_intel_atomic_state(state), crtc, 96508e3ed3aSChris Wilson enable); 966df0566a6SJani Nikula if (ret == -EDEADLK) { 967df0566a6SJani Nikula drm_atomic_state_clear(state); 968df0566a6SJani Nikula drm_modeset_backoff(&ctx); 969df0566a6SJani Nikula goto retry; 970df0566a6SJani Nikula } 971df0566a6SJani Nikula 97246e61ee4SVille Syrjälä drm_WARN_ON(&i915->drm, ret); 973df0566a6SJani Nikula 974df0566a6SJani Nikula drm_atomic_state_put(state); 975df0566a6SJani Nikula 976df0566a6SJani Nikula drm_modeset_drop_locks(&ctx); 977df0566a6SJani Nikula drm_modeset_acquire_fini(&ctx); 978df0566a6SJani Nikula } 979df0566a6SJani Nikula 980df0566a6SJani Nikula static unsigned long i915_audio_component_get_power(struct device *kdev) 981df0566a6SJani Nikula { 98246e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(kdev); 983df0566a6SJani Nikula intel_wakeref_t ret; 984df0566a6SJani Nikula 985df0566a6SJani Nikula /* Catch potential impedance mismatches before they occur! */ 986df0566a6SJani Nikula BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long)); 987df0566a6SJani Nikula 98846e61ee4SVille Syrjälä ret = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK); 989df0566a6SJani Nikula 99046e61ee4SVille Syrjälä if (i915->display.audio.power_refcount++ == 0) { 99146e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 9) { 99246e61ee4SVille Syrjälä intel_de_write(i915, AUD_FREQ_CNTRL, 99346e61ee4SVille Syrjälä i915->display.audio.freq_cntrl); 99446e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, 99563855149SWambui Karuga "restored AUD_FREQ_CNTRL to 0x%x\n", 99646e61ee4SVille Syrjälä i915->display.audio.freq_cntrl); 99787c16945SKai Vehmanen } 99887c16945SKai Vehmanen 99987c16945SKai Vehmanen /* Force CDCLK to 2*BCLK as long as we need audio powered. */ 100046e61ee4SVille Syrjälä if (IS_GEMINILAKE(i915)) 100146e61ee4SVille Syrjälä glk_force_audio_cdclk(i915, true); 10021580d3cdSKai Vehmanen 100346e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 10) 10047c8d74e8SVille Syrjälä intel_de_rmw(i915, AUD_PIN_BUF_CTL, 10057c8d74e8SVille Syrjälä 0, AUD_PIN_BUF_ENABLE); 100687c16945SKai Vehmanen } 1007df0566a6SJani Nikula 1008df0566a6SJani Nikula return ret; 1009df0566a6SJani Nikula } 1010df0566a6SJani Nikula 1011df0566a6SJani Nikula static void i915_audio_component_put_power(struct device *kdev, 1012df0566a6SJani Nikula unsigned long cookie) 1013df0566a6SJani Nikula { 101446e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(kdev); 1015df0566a6SJani Nikula 1016df0566a6SJani Nikula /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */ 101746e61ee4SVille Syrjälä if (--i915->display.audio.power_refcount == 0) 101846e61ee4SVille Syrjälä if (IS_GEMINILAKE(i915)) 101946e61ee4SVille Syrjälä glk_force_audio_cdclk(i915, false); 1020df0566a6SJani Nikula 102146e61ee4SVille Syrjälä intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, cookie); 1022df0566a6SJani Nikula } 1023df0566a6SJani Nikula 1024df0566a6SJani Nikula static void i915_audio_component_codec_wake_override(struct device *kdev, 1025df0566a6SJani Nikula bool enable) 1026df0566a6SJani Nikula { 102746e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(kdev); 1028df0566a6SJani Nikula unsigned long cookie; 1029df0566a6SJani Nikula 103046e61ee4SVille Syrjälä if (DISPLAY_VER(i915) < 9) 1031df0566a6SJani Nikula return; 1032df0566a6SJani Nikula 1033df0566a6SJani Nikula cookie = i915_audio_component_get_power(kdev); 1034df0566a6SJani Nikula 1035df0566a6SJani Nikula /* 1036df0566a6SJani Nikula * Enable/disable generating the codec wake signal, overriding the 1037df0566a6SJani Nikula * internal logic to generate the codec wake to controller. 1038df0566a6SJani Nikula */ 10397c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_CHICKENBIT, 10407c8d74e8SVille Syrjälä SKL_AUD_CODEC_WAKE_SIGNAL, 0); 1041df0566a6SJani Nikula usleep_range(1000, 1500); 1042df0566a6SJani Nikula 1043df0566a6SJani Nikula if (enable) { 10447c8d74e8SVille Syrjälä intel_de_rmw(i915, HSW_AUD_CHICKENBIT, 10457c8d74e8SVille Syrjälä 0, SKL_AUD_CODEC_WAKE_SIGNAL); 1046df0566a6SJani Nikula usleep_range(1000, 1500); 1047df0566a6SJani Nikula } 1048df0566a6SJani Nikula 1049df0566a6SJani Nikula i915_audio_component_put_power(kdev, cookie); 1050df0566a6SJani Nikula } 1051df0566a6SJani Nikula 1052df0566a6SJani Nikula /* Get CDCLK in kHz */ 1053df0566a6SJani Nikula static int i915_audio_component_get_cdclk_freq(struct device *kdev) 1054df0566a6SJani Nikula { 105546e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(kdev); 1056df0566a6SJani Nikula 105746e61ee4SVille Syrjälä if (drm_WARN_ON_ONCE(&i915->drm, !HAS_DDI(i915))) 1058df0566a6SJani Nikula return -ENODEV; 1059df0566a6SJani Nikula 106046e61ee4SVille Syrjälä return i915->display.cdclk.hw.cdclk; 1061df0566a6SJani Nikula } 1062df0566a6SJani Nikula 1063df0566a6SJani Nikula /* 10645eba7426SVille Syrjälä * get the intel audio state according to the parameter port and cpu_transcoder 10655eba7426SVille Syrjälä * MST & (cpu_transcoder >= 0): return the audio.state[cpu_transcoder].encoder], 1066df0566a6SJani Nikula * when port is matched 10675eba7426SVille Syrjälä * MST & (cpu_transcoder < 0): this is invalid 10685eba7426SVille Syrjälä * Non-MST & (cpu_transcoder >= 0): only cpu_transcoder = 0 (the first device entry) 1069df0566a6SJani Nikula * will get the right intel_encoder with port matched 10705eba7426SVille Syrjälä * Non-MST & (cpu_transcoder < 0): get the right intel_encoder with port matched 1071df0566a6SJani Nikula */ 1072c7104c38SVille Syrjälä static struct intel_audio_state *find_audio_state(struct drm_i915_private *i915, 10735eba7426SVille Syrjälä int port, int cpu_transcoder) 1074df0566a6SJani Nikula { 1075df0566a6SJani Nikula /* MST */ 10765eba7426SVille Syrjälä if (cpu_transcoder >= 0) { 1077c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 1078734d06d2SVille Syrjälä struct intel_encoder *encoder; 1079734d06d2SVille Syrjälä 108046e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, 10815eba7426SVille Syrjälä cpu_transcoder >= ARRAY_SIZE(i915->display.audio.state))) 1082df0566a6SJani Nikula return NULL; 1083df0566a6SJani Nikula 10845eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 1085c7104c38SVille Syrjälä encoder = audio_state->encoder; 1086c7104c38SVille Syrjälä 1087734d06d2SVille Syrjälä if (encoder && encoder->port == port && 1088df0566a6SJani Nikula encoder->type == INTEL_OUTPUT_DP_MST) 1089c7104c38SVille Syrjälä return audio_state; 1090df0566a6SJani Nikula } 1091df0566a6SJani Nikula 1092df0566a6SJani Nikula /* Non-MST */ 10935eba7426SVille Syrjälä if (cpu_transcoder > 0) 1094df0566a6SJani Nikula return NULL; 1095df0566a6SJani Nikula 10965eba7426SVille Syrjälä for_each_cpu_transcoder(i915, cpu_transcoder) { 1097c7104c38SVille Syrjälä struct intel_audio_state *audio_state; 1098734d06d2SVille Syrjälä struct intel_encoder *encoder; 1099734d06d2SVille Syrjälä 11005eba7426SVille Syrjälä audio_state = &i915->display.audio.state[cpu_transcoder]; 1101c7104c38SVille Syrjälä encoder = audio_state->encoder; 1102df0566a6SJani Nikula 1103734d06d2SVille Syrjälä if (encoder && encoder->port == port && 1104734d06d2SVille Syrjälä encoder->type != INTEL_OUTPUT_DP_MST) 1105c7104c38SVille Syrjälä return audio_state; 1106df0566a6SJani Nikula } 1107df0566a6SJani Nikula 1108df0566a6SJani Nikula return NULL; 1109df0566a6SJani Nikula } 1110df0566a6SJani Nikula 1111df0566a6SJani Nikula static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, 11125eba7426SVille Syrjälä int cpu_transcoder, int rate) 1113df0566a6SJani Nikula { 111446e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(kdev); 111546e61ee4SVille Syrjälä struct i915_audio_component *acomp = i915->display.audio.component; 1116c7104c38SVille Syrjälä const struct intel_audio_state *audio_state; 1117df0566a6SJani Nikula struct intel_encoder *encoder; 1118df0566a6SJani Nikula struct intel_crtc *crtc; 1119df0566a6SJani Nikula unsigned long cookie; 1120df0566a6SJani Nikula int err = 0; 1121df0566a6SJani Nikula 112246e61ee4SVille Syrjälä if (!HAS_DDI(i915)) 1123df0566a6SJani Nikula return 0; 1124df0566a6SJani Nikula 1125df0566a6SJani Nikula cookie = i915_audio_component_get_power(kdev); 112646e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 1127df0566a6SJani Nikula 11285eba7426SVille Syrjälä audio_state = find_audio_state(i915, port, cpu_transcoder); 1129c7104c38SVille Syrjälä if (!audio_state) { 1130c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); 1131df0566a6SJani Nikula err = -ENODEV; 1132df0566a6SJani Nikula goto unlock; 1133df0566a6SJani Nikula } 1134df0566a6SJani Nikula 1135c7104c38SVille Syrjälä encoder = audio_state->encoder; 1136c7104c38SVille Syrjälä 1137c7104c38SVille Syrjälä /* FIXME stop using the legacy crtc pointer */ 1138df0566a6SJani Nikula crtc = to_intel_crtc(encoder->base.crtc); 1139df0566a6SJani Nikula 11405eba7426SVille Syrjälä /* port must be valid now, otherwise the cpu_transcoder will be invalid */ 1141df0566a6SJani Nikula acomp->aud_sample_rate[port] = rate; 1142df0566a6SJani Nikula 1143c7104c38SVille Syrjälä /* FIXME get rid of the crtc->config stuff */ 1144df0566a6SJani Nikula hsw_audio_config_update(encoder, crtc->config); 1145df0566a6SJani Nikula 1146df0566a6SJani Nikula unlock: 114746e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 1148df0566a6SJani Nikula i915_audio_component_put_power(kdev, cookie); 1149df0566a6SJani Nikula return err; 1150df0566a6SJani Nikula } 1151df0566a6SJani Nikula 1152df0566a6SJani Nikula static int i915_audio_component_get_eld(struct device *kdev, int port, 11535eba7426SVille Syrjälä int cpu_transcoder, bool *enabled, 1154df0566a6SJani Nikula unsigned char *buf, int max_bytes) 1155df0566a6SJani Nikula { 115646e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(kdev); 1157c7104c38SVille Syrjälä const struct intel_audio_state *audio_state; 1158c7104c38SVille Syrjälä int ret = 0; 1159df0566a6SJani Nikula 116046e61ee4SVille Syrjälä mutex_lock(&i915->display.audio.mutex); 1161df0566a6SJani Nikula 11625eba7426SVille Syrjälä audio_state = find_audio_state(i915, port, cpu_transcoder); 1163c7104c38SVille Syrjälä if (!audio_state) { 1164c7104c38SVille Syrjälä drm_dbg_kms(&i915->drm, "Not valid for port %c\n", port_name(port)); 116546e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 1166c7104c38SVille Syrjälä return -EINVAL; 1167df0566a6SJani Nikula } 1168df0566a6SJani Nikula 11695d986635SVille Syrjälä *enabled = audio_state->encoder != NULL; 1170df0566a6SJani Nikula if (*enabled) { 11715d986635SVille Syrjälä const u8 *eld = audio_state->eld; 1172c7104c38SVille Syrjälä 1173df0566a6SJani Nikula ret = drm_eld_size(eld); 1174df0566a6SJani Nikula memcpy(buf, eld, min(max_bytes, ret)); 1175df0566a6SJani Nikula } 1176df0566a6SJani Nikula 117746e61ee4SVille Syrjälä mutex_unlock(&i915->display.audio.mutex); 1178df0566a6SJani Nikula return ret; 1179df0566a6SJani Nikula } 1180df0566a6SJani Nikula 1181df0566a6SJani Nikula static const struct drm_audio_component_ops i915_audio_component_ops = { 1182df0566a6SJani Nikula .owner = THIS_MODULE, 1183df0566a6SJani Nikula .get_power = i915_audio_component_get_power, 1184df0566a6SJani Nikula .put_power = i915_audio_component_put_power, 1185df0566a6SJani Nikula .codec_wake_override = i915_audio_component_codec_wake_override, 1186df0566a6SJani Nikula .get_cdclk_freq = i915_audio_component_get_cdclk_freq, 1187df0566a6SJani Nikula .sync_audio_rate = i915_audio_component_sync_audio_rate, 1188df0566a6SJani Nikula .get_eld = i915_audio_component_get_eld, 1189df0566a6SJani Nikula }; 1190df0566a6SJani Nikula 1191df0566a6SJani Nikula static int i915_audio_component_bind(struct device *i915_kdev, 1192df0566a6SJani Nikula struct device *hda_kdev, void *data) 1193df0566a6SJani Nikula { 1194df0566a6SJani Nikula struct i915_audio_component *acomp = data; 119546e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); 1196df0566a6SJani Nikula int i; 1197df0566a6SJani Nikula 119846e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, acomp->base.ops || acomp->base.dev)) 1199df0566a6SJani Nikula return -EEXIST; 1200df0566a6SJani Nikula 120146e61ee4SVille Syrjälä if (drm_WARN_ON(&i915->drm, 12029a3b466bSPankaj Bharadiya !device_link_add(hda_kdev, i915_kdev, 12039a3b466bSPankaj Bharadiya DL_FLAG_STATELESS))) 1204df0566a6SJani Nikula return -ENOMEM; 1205df0566a6SJani Nikula 120646e61ee4SVille Syrjälä drm_modeset_lock_all(&i915->drm); 1207df0566a6SJani Nikula acomp->base.ops = &i915_audio_component_ops; 1208df0566a6SJani Nikula acomp->base.dev = i915_kdev; 1209df0566a6SJani Nikula BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); 1210df0566a6SJani Nikula for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) 1211df0566a6SJani Nikula acomp->aud_sample_rate[i] = 0; 121246e61ee4SVille Syrjälä i915->display.audio.component = acomp; 121346e61ee4SVille Syrjälä drm_modeset_unlock_all(&i915->drm); 1214df0566a6SJani Nikula 1215df0566a6SJani Nikula return 0; 1216df0566a6SJani Nikula } 1217df0566a6SJani Nikula 1218df0566a6SJani Nikula static void i915_audio_component_unbind(struct device *i915_kdev, 1219df0566a6SJani Nikula struct device *hda_kdev, void *data) 1220df0566a6SJani Nikula { 1221df0566a6SJani Nikula struct i915_audio_component *acomp = data; 122246e61ee4SVille Syrjälä struct drm_i915_private *i915 = kdev_to_i915(i915_kdev); 1223df0566a6SJani Nikula 122446e61ee4SVille Syrjälä drm_modeset_lock_all(&i915->drm); 1225df0566a6SJani Nikula acomp->base.ops = NULL; 1226df0566a6SJani Nikula acomp->base.dev = NULL; 122746e61ee4SVille Syrjälä i915->display.audio.component = NULL; 122846e61ee4SVille Syrjälä drm_modeset_unlock_all(&i915->drm); 1229df0566a6SJani Nikula 1230df0566a6SJani Nikula device_link_remove(hda_kdev, i915_kdev); 1231b4ed131dSJani Nikula 123246e61ee4SVille Syrjälä if (i915->display.audio.power_refcount) 123346e61ee4SVille Syrjälä drm_err(&i915->drm, "audio power refcount %d after unbind\n", 123446e61ee4SVille Syrjälä i915->display.audio.power_refcount); 1235df0566a6SJani Nikula } 1236df0566a6SJani Nikula 1237df0566a6SJani Nikula static const struct component_ops i915_audio_component_bind_ops = { 1238df0566a6SJani Nikula .bind = i915_audio_component_bind, 1239df0566a6SJani Nikula .unbind = i915_audio_component_unbind, 1240df0566a6SJani Nikula }; 1241df0566a6SJani Nikula 1242989634fbSKai Vehmanen #define AUD_FREQ_TMODE_SHIFT 14 1243989634fbSKai Vehmanen #define AUD_FREQ_4T 0 1244989634fbSKai Vehmanen #define AUD_FREQ_8T (2 << AUD_FREQ_TMODE_SHIFT) 1245989634fbSKai Vehmanen #define AUD_FREQ_PULLCLKS(x) (((x) & 0x3) << 11) 1246989634fbSKai Vehmanen #define AUD_FREQ_BCLK_96M BIT(4) 1247989634fbSKai Vehmanen 1248989634fbSKai Vehmanen #define AUD_FREQ_GEN12 (AUD_FREQ_8T | AUD_FREQ_PULLCLKS(0) | AUD_FREQ_BCLK_96M) 1249989634fbSKai Vehmanen #define AUD_FREQ_TGL_BROKEN (AUD_FREQ_8T | AUD_FREQ_PULLCLKS(2) | AUD_FREQ_BCLK_96M) 1250989634fbSKai Vehmanen 1251df0566a6SJani Nikula /** 1252df0566a6SJani Nikula * i915_audio_component_init - initialize and register the audio component 125346e61ee4SVille Syrjälä * @i915: i915 device instance 1254df0566a6SJani Nikula * 1255df0566a6SJani Nikula * This will register with the component framework a child component which 1256df0566a6SJani Nikula * will bind dynamically to the snd_hda_intel driver's corresponding master 1257df0566a6SJani Nikula * component when the latter is registered. During binding the child 1258df0566a6SJani Nikula * initializes an instance of struct i915_audio_component which it receives 1259df0566a6SJani Nikula * from the master. The master can then start to use the interface defined by 1260df0566a6SJani Nikula * this struct. Each side can break the binding at any point by deregistering 1261df0566a6SJani Nikula * its own component after which each side's component unbind callback is 1262df0566a6SJani Nikula * called. 1263df0566a6SJani Nikula * 1264df0566a6SJani Nikula * We ignore any error during registration and continue with reduced 1265df0566a6SJani Nikula * functionality (i.e. without HDMI audio). 1266df0566a6SJani Nikula */ 126746e61ee4SVille Syrjälä static void i915_audio_component_init(struct drm_i915_private *i915) 1268df0566a6SJani Nikula { 1269989634fbSKai Vehmanen u32 aud_freq, aud_freq_init; 1270df0566a6SJani Nikula 127146e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 9) { 127246e61ee4SVille Syrjälä aud_freq_init = intel_de_read(i915, AUD_FREQ_CNTRL); 1273989634fbSKai Vehmanen 127446e61ee4SVille Syrjälä if (DISPLAY_VER(i915) >= 12) 1275989634fbSKai Vehmanen aud_freq = AUD_FREQ_GEN12; 1276989634fbSKai Vehmanen else 1277989634fbSKai Vehmanen aud_freq = aud_freq_init; 1278989634fbSKai Vehmanen 1279c6b40ee3SKai-Heng Feng /* use BIOS provided value for TGL and RKL unless it is a known bad value */ 128046e61ee4SVille Syrjälä if ((IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915)) && 1281c6b40ee3SKai-Heng Feng aud_freq_init != AUD_FREQ_TGL_BROKEN) 1282989634fbSKai Vehmanen aud_freq = aud_freq_init; 1283989634fbSKai Vehmanen 128446e61ee4SVille Syrjälä drm_dbg_kms(&i915->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n", 1285989634fbSKai Vehmanen aud_freq, aud_freq_init); 1286989634fbSKai Vehmanen 128746e61ee4SVille Syrjälä i915->display.audio.freq_cntrl = aud_freq; 128887c16945SKai Vehmanen } 128987c16945SKai Vehmanen 1290112a87c4SKai Vehmanen /* init with current cdclk */ 129146e61ee4SVille Syrjälä intel_audio_cdclk_change_post(i915); 1292*fdd0b801SImre Deak } 1293*fdd0b801SImre Deak 1294*fdd0b801SImre Deak static void i915_audio_component_register(struct drm_i915_private *i915) 1295*fdd0b801SImre Deak { 1296*fdd0b801SImre Deak int ret; 1297*fdd0b801SImre Deak 1298*fdd0b801SImre Deak ret = component_add_typed(i915->drm.dev, 1299*fdd0b801SImre Deak &i915_audio_component_bind_ops, 1300*fdd0b801SImre Deak I915_COMPONENT_AUDIO); 1301*fdd0b801SImre Deak if (ret < 0) { 1302*fdd0b801SImre Deak drm_err(&i915->drm, 1303*fdd0b801SImre Deak "failed to add audio component (%d)\n", ret); 1304*fdd0b801SImre Deak /* continue with reduced functionality */ 1305*fdd0b801SImre Deak return; 1306*fdd0b801SImre Deak } 1307112a87c4SKai Vehmanen 130846e61ee4SVille Syrjälä i915->display.audio.component_registered = true; 1309df0566a6SJani Nikula } 1310df0566a6SJani Nikula 1311df0566a6SJani Nikula /** 1312df0566a6SJani Nikula * i915_audio_component_cleanup - deregister the audio component 131346e61ee4SVille Syrjälä * @i915: i915 device instance 1314df0566a6SJani Nikula * 1315df0566a6SJani Nikula * Deregisters the audio component, breaking any existing binding to the 1316df0566a6SJani Nikula * corresponding snd_hda_intel driver's master component. 1317df0566a6SJani Nikula */ 131846e61ee4SVille Syrjälä static void i915_audio_component_cleanup(struct drm_i915_private *i915) 1319df0566a6SJani Nikula { 132046e61ee4SVille Syrjälä if (!i915->display.audio.component_registered) 1321df0566a6SJani Nikula return; 1322df0566a6SJani Nikula 132346e61ee4SVille Syrjälä component_del(i915->drm.dev, &i915_audio_component_bind_ops); 132446e61ee4SVille Syrjälä i915->display.audio.component_registered = false; 1325df0566a6SJani Nikula } 1326df0566a6SJani Nikula 1327df0566a6SJani Nikula /** 1328df0566a6SJani Nikula * intel_audio_init() - Initialize the audio driver either using 1329df0566a6SJani Nikula * component framework or using lpe audio bridge 133046e61ee4SVille Syrjälä * @i915: the i915 drm device private data 1331df0566a6SJani Nikula * 1332df0566a6SJani Nikula */ 133346e61ee4SVille Syrjälä void intel_audio_init(struct drm_i915_private *i915) 1334df0566a6SJani Nikula { 133546e61ee4SVille Syrjälä if (intel_lpe_audio_init(i915) < 0) 133646e61ee4SVille Syrjälä i915_audio_component_init(i915); 1337df0566a6SJani Nikula } 1338df0566a6SJani Nikula 1339*fdd0b801SImre Deak void intel_audio_register(struct drm_i915_private *i915) 1340*fdd0b801SImre Deak { 1341*fdd0b801SImre Deak if (!i915->display.audio.lpe.platdev) 1342*fdd0b801SImre Deak i915_audio_component_register(i915); 1343*fdd0b801SImre Deak } 1344*fdd0b801SImre Deak 1345df0566a6SJani Nikula /** 1346df0566a6SJani Nikula * intel_audio_deinit() - deinitialize the audio driver 134746e61ee4SVille Syrjälä * @i915: the i915 drm device private data 1348df0566a6SJani Nikula * 1349df0566a6SJani Nikula */ 135046e61ee4SVille Syrjälä void intel_audio_deinit(struct drm_i915_private *i915) 1351df0566a6SJani Nikula { 135246e61ee4SVille Syrjälä if (i915->display.audio.lpe.platdev != NULL) 135346e61ee4SVille Syrjälä intel_lpe_audio_teardown(i915); 1354df0566a6SJani Nikula else 135546e61ee4SVille Syrjälä i915_audio_component_cleanup(i915); 1356df0566a6SJani Nikula } 1357