Skip to content

Commit

Permalink
drm/i915: setup bridge for HDMI LPE audio driver
Browse files Browse the repository at this point in the history
Enable support for HDMI LPE audio mode on Baytrail and
Cherrytrail when HDaudio controller is not detected

Setup minimum required resources during i915_driver_load:
1. Create a platform device to share MMIO/IRQ resources
2. Make the platform device child of i915 device for runtime PM.
3. Create IRQ chip to forward HDMI LPE audio irqs.

HDMI LPE audio driver (a standalone sound driver) probes the
LPE audio device and creates a new sound card.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Jerome Anand <jerome.anand@intel.com>
Acked-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Jerome Anand authored and Takashi Iwai committed Jan 25, 2017
1 parent 7a308bb commit eef5732
Show file tree
Hide file tree
Showing 10 changed files with 438 additions and 2 deletions.
9 changes: 9 additions & 0 deletions Documentation/gpu/i915.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,15 @@ Video BIOS Table (VBT)
.. kernel-doc:: drivers/gpu/drm/i915/intel_vbt_defs.h
:internal:

intel hdmi lpe audio support
----------------------------

.. kernel-doc:: drivers/gpu/drm/i915/intel_lpe_audio.c
:doc: LPE Audio integration for HDMI or DP playback

.. kernel-doc:: drivers/gpu/drm/i915/intel_lpe_audio.c
:internal:

Memory Management and Command Submission
========================================

Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ i915-y += intel_gvt.o
include $(src)/gvt/Makefile
endif

# LPE Audio for VLV and CHT
i915-y += intel_lpe_audio.o

obj-$(CONFIG_DRM_I915) += i915.o

CFLAGS_i915_trace_points.o := -I$(src)
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
if (IS_GEN5(dev_priv))
intel_gpu_ips_init(dev_priv);

i915_audio_component_init(dev_priv);
intel_audio_init(dev_priv);

/*
* Some ports require correctly set-up hpd registers for detection to
Expand All @@ -1156,7 +1156,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
*/
static void i915_driver_unregister(struct drm_i915_private *dev_priv)
{
i915_audio_component_cleanup(dev_priv);
intel_audio_deinit(dev_priv);

intel_gpu_ips_teardown();
acpi_video_unregister();
Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2136,6 +2136,12 @@ struct drm_i915_private {
/* Used to save the pipe-to-encoder mapping for audio */
struct intel_encoder *av_enc_map[I915_MAX_PIPES];

/* necessary resource sharing with HDMI LPE audio driver. */
struct {
struct platform_device *platdev;
int irq;
} lpe_audio;

/*
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
* will be rejected. Instead look for a better place.
Expand Down Expand Up @@ -3390,6 +3396,11 @@ extern int i915_restore_state(struct drm_device *dev);
void i915_setup_sysfs(struct drm_i915_private *dev_priv);
void i915_teardown_sysfs(struct drm_i915_private *dev_priv);

/* intel_lpe_audio.c */
int intel_lpe_audio_init(struct drm_i915_private *dev_priv);
void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv);
void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv);

/* intel_i2c.c */
extern int intel_setup_gmbus(struct drm_device *dev);
extern void intel_teardown_gmbus(struct drm_device *dev);
Expand Down
16 changes: 16 additions & 0 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,10 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
* signalled in iir */
valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);

if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT))
intel_lpe_audio_irq_handler(dev_priv);

/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
Expand Down Expand Up @@ -1973,6 +1977,11 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
* signalled in iir */
valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats);

if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT))
intel_lpe_audio_irq_handler(dev_priv);

/*
* VLV_IIR is single buffered, and reflects the level
* from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
Expand Down Expand Up @@ -2914,6 +2923,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
u32 pipestat_mask;
u32 enable_mask;
enum pipe pipe;
u32 val;

pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
PIPE_CRC_DONE_INTERRUPT_STATUS;
Expand All @@ -2930,6 +2940,12 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)

WARN_ON(dev_priv->irq_mask != ~0);

val = (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT);

enable_mask |= val;

dev_priv->irq_mask = ~enable_mask;

GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,9 @@ enum skl_disp_power_wells {
#define I915_ASLE_INTERRUPT (1<<0)
#define I915_BSD_USER_INTERRUPT (1<<25)

#define I915_HDMI_LPE_AUDIO_BASE (VLV_DISPLAY_BASE + 0x65000)
#define I915_HDMI_LPE_AUDIO_SIZE 0x1000

#define GEN6_BSD_RNCID _MMIO(0x12198)

#define GEN7_FF_THREAD_MODE _MMIO(0x20a0)
Expand Down
25 changes: 25 additions & 0 deletions drivers/gpu/drm/i915/intel_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,3 +931,28 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
dev_priv->audio_component_registered = false;
}

/**
* intel_audio_init() - Initialize the audio driver either using
* component framework or using lpe audio bridge
* @dev_priv: the i915 drm device private data
*
*/
void intel_audio_init(struct drm_i915_private *dev_priv)
{
if (intel_lpe_audio_init(dev_priv) < 0)
i915_audio_component_init(dev_priv);
}

/**
* intel_audio_deinit() - deinitialize the audio driver
* @dev_priv: the i915 drm device private data
*
*/
void intel_audio_deinit(struct drm_i915_private *dev_priv)
{
if ((dev_priv)->lpe_audio.platdev != NULL)
intel_lpe_audio_teardown(dev_priv);
else
i915_audio_component_cleanup(dev_priv);
}
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
void intel_audio_codec_disable(struct intel_encoder *encoder);
void i915_audio_component_init(struct drm_i915_private *dev_priv);
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
void intel_audio_init(struct drm_i915_private *dev_priv);
void intel_audio_deinit(struct drm_i915_private *dev_priv);

/* intel_display.c */
enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
Expand Down
Loading

0 comments on commit eef5732

Please sign in to comment.