summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/bridge/dw_hdmi.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-11-07 16:01:45 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-10-09 17:14:12 +0100
commit7ed6c665e19d4c0456d01c01147e82563c482c4d (patch)
treeed6bb0a14799b8161e45ddc97cf2cce5032b5f45 /drivers/gpu/drm/bridge/dw_hdmi.c
parentaeac23bda87fd98049352d3bc27a1cb80445e7a0 (diff)
drm: bridge/dw_hdmi-ahb-audio: add audio driver
Add ALSA based HDMI AHB audio driver for dw_hdmi. The only buffer format supported by the hardware is its own special IEC958 based format, which is not compatible with any ALSA format. To avoid doing too much data manipulation within the driver, we support only ALSAs IEC958 LE and 24-bit PCM formats for 2 to 6 channels, which we convert to its hardware format. A more desirable solution would be to have this conversion in userspace, but ALSA does not appear to allow such transformations outside of libasound itself. Reviewed-by: Takashi Iwai <tiwai@suse.de> Tested-by: Fabio Estevam <fabio.estevam@freescale.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/bridge/dw_hdmi.c')
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 7a130f6fdb3d..d61a9fb46c6d 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -28,6 +28,7 @@
#include <drm/bridge/dw_hdmi.h>
#include "dw_hdmi.h"
+#include "dw_hdmi-audio.h"
#define HDMI_EDID_LEN 512
@@ -104,6 +105,7 @@ struct dw_hdmi {
struct drm_encoder *encoder;
struct drm_bridge *bridge;
+ struct platform_device *audio;
enum dw_hdmi_devtype dev_type;
struct device *dev;
struct clk *isfr_clk;
@@ -1732,7 +1734,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
{
struct drm_device *drm = data;
struct device_node *np = dev->of_node;
+ struct platform_device_info pdevinfo;
struct device_node *ddc_node;
+ struct dw_hdmi_audio_data audio;
struct dw_hdmi *hdmi;
int ret;
u32 val = 1;
@@ -1860,6 +1864,23 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
hdmi_writeb(hdmi, ~(HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE),
HDMI_IH_MUTE_PHY_STAT0);
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ pdevinfo.parent = dev;
+ pdevinfo.id = PLATFORM_DEVID_AUTO;
+
+ if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
+ audio.phys = iores->start;
+ audio.base = hdmi->regs;
+ audio.irq = irq;
+ audio.hdmi = hdmi;
+
+ pdevinfo.name = "dw-hdmi-ahb-audio";
+ pdevinfo.data = &audio;
+ pdevinfo.size_data = sizeof(audio);
+ pdevinfo.dma_mask = DMA_BIT_MASK(32);
+ hdmi->audio = platform_device_register_full(&pdevinfo);
+ }
+
dev_set_drvdata(dev, hdmi);
return 0;
@@ -1877,6 +1898,9 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
{
struct dw_hdmi *hdmi = dev_get_drvdata(dev);
+ if (hdmi->audio && !IS_ERR(hdmi->audio))
+ platform_device_unregister(hdmi->audio);
+
/* Disable all interrupts */
hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);