Fix errors in HDMI sound for Allwinner A10-A31

https://github.com/armbian/build/pull/2096
This commit is contained in:
Igor Pecovnik 2021-02-22 09:30:13 +01:00
parent 04670580ea
commit d1bed529fa
2 changed files with 36 additions and 34 deletions

View File

@ -32,7 +32,7 @@ index 37e90e42943f..ca2ab5d53dd4 100644
@@ -23,6 +23,17 @@ config DRM_SUN4I_HDMI
Choose this option if you have an Allwinner SoC with an HDMI
controller.
+config DRM_SUN4I_HDMI_AUDIO
+ bool "Allwinner A10 HDMI Audio Support"
+ default y
@ -54,7 +54,7 @@ index 0d04f2447b01..492bfd28ad2e 100644
@@ -5,6 +5,9 @@ sun4i-frontend-y += sun4i_frontend.o
sun4i-drm-y += sun4i_drv.o
sun4i-drm-y += sun4i_framebuffer.o
+ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
+sun4i-drm-hdmi-y += sun4i_hdmi_audio.o
+endif
@ -68,7 +68,7 @@ index 7ad3f06c127e..28621d289655 100644
@@ -42,7 +42,32 @@
#define SUN4I_HDMI_VID_TIMING_POL_VSYNC BIT(1)
#define SUN4I_HDMI_VID_TIMING_POL_HSYNC BIT(0)
+#define SUN4I_HDMI_AUDIO_CTRL_REG 0x040
+#define SUN4I_HDMI_AUDIO_CTRL_ENABLE BIT(31)
+#define SUN4I_HDMI_AUDIO_CTRL_RESET BIT(30)
@ -95,13 +95,13 @@ index 7ad3f06c127e..28621d289655 100644
+
#define SUN4I_HDMI_AVI_INFOFRAME_REG(n) (0x080 + (n))
+#define SUN4I_HDMI_AUDIO_INFOFRAME_REG(n) (0x0a0 + (n))
#define SUN4I_HDMI_PAD_CTRL0_REG 0x200
#define SUN4I_HDMI_PAD_CTRL0_BIASEN BIT(31)
@@ -242,6 +267,11 @@ struct sun4i_hdmi_variant {
bool ddc_fifo_has_dir;
};
+struct sun4i_hdmi_audio {
+ struct snd_soc_card *card;
+ u8 channels;
@ -113,17 +113,17 @@ index 7ad3f06c127e..28621d289655 100644
@@ -283,9 +313,14 @@ struct sun4i_hdmi {
struct regmap_field *field_ddc_sda_en;
struct regmap_field *field_ddc_sck_en;
+
struct sun4i_drv *drv;
bool hdmi_monitor;
+ bool hdmi_audio;
+
+ struct sun4i_hdmi_audio audio;
+
struct cec_adapter *cec_adap;
const struct sun4i_hdmi_variant *variant;
@@ -294,5 +329,7 @@ struct sun4i_hdmi {
int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk);
@ -131,7 +131,7 @@ index 7ad3f06c127e..28621d289655 100644
int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi);
+int sun4i_hdmi_audio_create(struct sun4i_hdmi *hdmi);
+void sun4i_hdmi_audio_destroy(struct sun4i_hdmi *hdmi);
#endif /* _SUN4I_HDMI_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_audio.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_audio.c
new file mode 100644
@ -596,18 +596,19 @@ index 68d4644ac2dc..4cd35c97c503 100644
@@ -23,6 +23,8 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
+#include <sound/soc.h>
+
#include "sun4i_backend.h"
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
@@ -87,6 +89,10 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
@@ -87,6 +89,11 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
+#ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
+ sun4i_hdmi_audio_destroy(hdmi);
+ if (hdmi->hdmi_audio)
+ sun4i_hdmi_audio_destroy(hdmi);
+#endif
+
val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
@ -615,7 +616,7 @@ index 68d4644ac2dc..4cd35c97c503 100644
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
@@ -114,6 +120,11 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
+
+#ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
@ -623,12 +624,12 @@ index 68d4644ac2dc..4cd35c97c503 100644
+ DRM_ERROR("Couldn't create the HDMI audio adapter\n");
+#endif
}
static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
@@ -218,6 +229,9 @@ static int sun4i_hdmi_get_modes(struct drm_connector *connector)
if (!edid)
return 0;
+#ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
+ hdmi->hdmi_audio = drm_detect_monitor_audio(edid);
+#endif

View File

@ -32,7 +32,7 @@ index 37e90e42943f..ca2ab5d53dd4 100644
@@ -23,6 +23,17 @@ config DRM_SUN4I_HDMI
Choose this option if you have an Allwinner SoC with an HDMI
controller.
+config DRM_SUN4I_HDMI_AUDIO
+ bool "Allwinner A10 HDMI Audio Support"
+ default y
@ -54,7 +54,7 @@ index 0d04f2447b01..492bfd28ad2e 100644
@@ -5,6 +5,9 @@ sun4i-frontend-y += sun4i_frontend.o
sun4i-drm-y += sun4i_drv.o
sun4i-drm-y += sun4i_framebuffer.o
+ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
+sun4i-drm-hdmi-y += sun4i_hdmi_audio.o
+endif
@ -68,7 +68,7 @@ index 7ad3f06c127e..28621d289655 100644
@@ -42,7 +42,32 @@
#define SUN4I_HDMI_VID_TIMING_POL_VSYNC BIT(1)
#define SUN4I_HDMI_VID_TIMING_POL_HSYNC BIT(0)
+#define SUN4I_HDMI_AUDIO_CTRL_REG 0x040
+#define SUN4I_HDMI_AUDIO_CTRL_ENABLE BIT(31)
+#define SUN4I_HDMI_AUDIO_CTRL_RESET BIT(30)
@ -95,13 +95,13 @@ index 7ad3f06c127e..28621d289655 100644
+
#define SUN4I_HDMI_AVI_INFOFRAME_REG(n) (0x080 + (n))
+#define SUN4I_HDMI_AUDIO_INFOFRAME_REG(n) (0x0a0 + (n))
#define SUN4I_HDMI_PAD_CTRL0_REG 0x200
#define SUN4I_HDMI_PAD_CTRL0_BIASEN BIT(31)
@@ -242,6 +267,11 @@ struct sun4i_hdmi_variant {
bool ddc_fifo_has_dir;
};
+struct sun4i_hdmi_audio {
+ struct snd_soc_card *card;
+ u8 channels;
@ -113,17 +113,17 @@ index 7ad3f06c127e..28621d289655 100644
@@ -283,9 +313,14 @@ struct sun4i_hdmi {
struct regmap_field *field_ddc_sda_en;
struct regmap_field *field_ddc_sck_en;
+
struct sun4i_drv *drv;
bool hdmi_monitor;
+ bool hdmi_audio;
+
+ struct sun4i_hdmi_audio audio;
+
struct cec_adapter *cec_adap;
const struct sun4i_hdmi_variant *variant;
@@ -294,5 +329,7 @@ struct sun4i_hdmi {
int sun4i_ddc_create(struct sun4i_hdmi *hdmi, struct clk *clk);
@ -131,7 +131,7 @@ index 7ad3f06c127e..28621d289655 100644
int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi);
+int sun4i_hdmi_audio_create(struct sun4i_hdmi *hdmi);
+void sun4i_hdmi_audio_destroy(struct sun4i_hdmi *hdmi);
#endif /* _SUN4I_HDMI_H_ */
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_audio.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_audio.c
new file mode 100644
@ -596,18 +596,19 @@ index 68d4644ac2dc..4cd35c97c503 100644
@@ -23,6 +23,8 @@
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
+#include <sound/soc.h>
+
#include "sun4i_backend.h"
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
@@ -87,6 +89,10 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
@@ -87,6 +89,11 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
+#ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
+ sun4i_hdmi_audio_destroy(hdmi);
+ if (hdmi->hdmi_audio)
+ sun4i_hdmi_audio_destroy(hdmi);
+#endif
+
val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
@ -615,7 +616,7 @@ index 68d4644ac2dc..4cd35c97c503 100644
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
@@ -114,6 +120,11 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
+
+#ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
@ -623,12 +624,12 @@ index 68d4644ac2dc..4cd35c97c503 100644
+ DRM_ERROR("Couldn't create the HDMI audio adapter\n");
+#endif
}
static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
@@ -218,6 +229,9 @@ static int sun4i_hdmi_get_modes(struct drm_connector *connector)
if (!edid)
return 0;
+#ifdef CONFIG_DRM_SUN4I_HDMI_AUDIO
+ hdmi->hdmi_audio = drm_detect_monitor_audio(edid);
+#endif