mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-08-01 15:07:49 +00:00
Allwinner: Update HDMI audio patches
This commit is contained in:
parent
34fb3e0709
commit
7120f8fcc1
@ -6,7 +6,6 @@ Subject: [PATCH] AW H6 I2S WIP
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 31 ++++++++++++++++++++
|
||||
sound/soc/sunxi/sun4i-i2s.c | 12 ++++----
|
||||
3 files changed, 41 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
|
||||
@ -43,7 +42,7 @@ index 62a0eae77639..f1c53aec6523 100644
|
||||
|
||||
+ i2s1: i2s@5091000 {
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ compatible = "allwinner,sun8i-h3-i2s";
|
||||
+ compatible = "allwinner,sun50i-h6-i2s";
|
||||
+ reg = <0x05091000 0x1000>;
|
||||
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>;
|
||||
@ -65,37 +64,5 @@ index 62a0eae77639..f1c53aec6523 100644
|
||||
compatible = "allwinner,sun50i-h6-dw-hdmi";
|
||||
reg = <0x06000000 0x10000>;
|
||||
reg-io-width = <1>;
|
||||
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
|
||||
index d5ec1a20499d..f286b8bfcfb3 100644
|
||||
--- a/sound/soc/sunxi/sun4i-i2s.c
|
||||
+++ b/sound/soc/sunxi/sun4i-i2s.c
|
||||
@@ -108,12 +108,12 @@
|
||||
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0)
|
||||
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1)
|
||||
|
||||
-#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44
|
||||
+#define SUN8I_I2S_TX_CHAN_MAP_REG 0x48
|
||||
#define SUN8I_I2S_TX_CHAN_SEL_REG 0x34
|
||||
-#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12)
|
||||
-#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12)
|
||||
-#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4)
|
||||
-#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4)
|
||||
+#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(21, 20)
|
||||
+#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 20)
|
||||
+#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(15, 0)
|
||||
+#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 0)
|
||||
|
||||
#define SUN8I_I2S_RX_CHAN_SEL_REG 0x54
|
||||
#define SUN8I_I2S_RX_CHAN_MAP_REG 0x58
|
||||
@@ -946,7 +946,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
|
||||
.field_fmt_mode = REG_FIELD(SUN4I_I2S_CTRL_REG, 4, 5),
|
||||
.field_txchanmap = REG_FIELD(SUN8I_I2S_TX_CHAN_MAP_REG, 0, 31),
|
||||
.field_rxchanmap = REG_FIELD(SUN8I_I2S_RX_CHAN_MAP_REG, 0, 31),
|
||||
- .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 0, 2),
|
||||
+ .field_txchansel = REG_FIELD(SUN8I_I2S_TX_CHAN_SEL_REG, 16, 19),
|
||||
.field_rxchansel = REG_FIELD(SUN8I_I2S_RX_CHAN_SEL_REG, 0, 2),
|
||||
};
|
||||
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
@ -0,0 +1,77 @@
|
||||
From ab099efa81230670679a0aa8ad6aa9cb2ac748b4 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Sat, 14 Sep 2019 15:33:14 +0200
|
||||
Subject: [PATCH] clk: sunxi-ng: h6: Use sigma-delta modulation for audio PLL
|
||||
|
||||
Audio devices needs exact clock rates in order to correctly reproduce
|
||||
the sound. Until now, only integer factors were used to configure H6
|
||||
audio PLL which resulted in inexact rates. Fix that by adding support
|
||||
for fractional factors using sigma-delta modulation look-up table. It
|
||||
contains values for two most commonly used audio base frequencies.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
---
|
||||
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 21 +++++++++++++++------
|
||||
1 file changed, 15 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
|
||||
index d89353a3cdec..ed6338d74474 100644
|
||||
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
|
||||
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
|
||||
@@ -203,12 +203,21 @@ static struct ccu_nkmp pll_hsic_clk = {
|
||||
* hardcode it to match with the clock names.
|
||||
*/
|
||||
#define SUN50I_H6_PLL_AUDIO_REG 0x078
|
||||
+
|
||||
+static struct ccu_sdm_setting pll_audio_sdm_table[] = {
|
||||
+ { .rate = 541900800, .pattern = 0xc001288d, .m = 1, .n = 22 },
|
||||
+ { .rate = 589824000, .pattern = 0xc00126e9, .m = 1, .n = 24 },
|
||||
+};
|
||||
+
|
||||
static struct ccu_nm pll_audio_base_clk = {
|
||||
.enable = BIT(31),
|
||||
.lock = BIT(28),
|
||||
.n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
|
||||
.m = _SUNXI_CCU_DIV(1, 1), /* input divider */
|
||||
+ .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table,
|
||||
+ BIT(24), 0x178, BIT(31)),
|
||||
.common = {
|
||||
+ .features = CCU_FEATURE_SIGMA_DELTA_MOD,
|
||||
.reg = 0x078,
|
||||
.hw.init = CLK_HW_INIT("pll-audio-base", "osc24M",
|
||||
&ccu_nm_ops,
|
||||
@@ -753,12 +762,12 @@ static const struct clk_hw *clk_parent_pll_audio[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
- * The divider of pll-audio is fixed to 8 now, as pll-audio-4x has a
|
||||
- * fixed post-divider 2.
|
||||
+ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
|
||||
+ * rates can be set exactly in conjunction with sigma-delta modulation.
|
||||
*/
|
||||
static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
|
||||
clk_parent_pll_audio,
|
||||
- 8, 1, CLK_SET_RATE_PARENT);
|
||||
+ 24, 1, CLK_SET_RATE_PARENT);
|
||||
static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
|
||||
clk_parent_pll_audio,
|
||||
4, 1, CLK_SET_RATE_PARENT);
|
||||
@@ -1215,12 +1224,12 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/*
|
||||
- * Force the post-divider of pll-audio to 8 and the output divider
|
||||
- * of it to 1, to make the clock name represents the real frequency.
|
||||
+ * Force the post-divider of pll-audio to 12 and the output divider
|
||||
+ * of it to 2, so 24576000 and 22579200 rates can be set exactly.
|
||||
*/
|
||||
val = readl(reg + SUN50I_H6_PLL_AUDIO_REG);
|
||||
val &= ~(GENMASK(21, 16) | BIT(0));
|
||||
- writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG);
|
||||
+ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H6_PLL_AUDIO_REG);
|
||||
|
||||
/*
|
||||
* First clock parent (osc32K) is unusable for CEC. But since there
|
||||
--
|
||||
2.23.0
|
||||
|
4864
projects/Allwinner/patches/linux/0001-backport-from-5.4.patch
Normal file
4864
projects/Allwinner/patches/linux/0001-backport-from-5.4.patch
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
157
projects/Allwinner/patches/linux/0002-backport-from-5.5.patch
Normal file
157
projects/Allwinner/patches/linux/0002-backport-from-5.5.patch
Normal file
@ -0,0 +1,157 @@
|
||||
From c41784b042ac9cf97f2e871aceef3e06eff14140 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng-Yi Chiang <cychiang@chromium.org>
|
||||
Date: Mon, 2 Sep 2019 11:54:35 +0800
|
||||
Subject: [PATCH] drm: dw-hdmi-i2s: enable audio clock in audio_startup
|
||||
|
||||
In the designware databook, the sequence of enabling audio clock and
|
||||
setting format is not clearly specified.
|
||||
Currently, audio clock is enabled in the end of hw_param ops after
|
||||
setting format.
|
||||
|
||||
On some monitors, there is a possibility that audio does not come out.
|
||||
Fix this by enabling audio clock in audio_startup ops
|
||||
before hw_param ops setting format.
|
||||
|
||||
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
|
||||
Reviewed-by: Douglas Anderson <dianders@chromium.org>
|
||||
Reviewed-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
Tested-by: Douglas Anderson <dianders@chromium.org>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20190902035435.44463-1-cychiang@chromium.org
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
index 1d15cf9b6821..34d8e837555f 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
@@ -109,6 +109,14 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
|
||||
hdmi_write(audio, conf0, HDMI_AUD_CONF0);
|
||||
hdmi_write(audio, conf1, HDMI_AUD_CONF1);
|
||||
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int dw_hdmi_i2s_audio_startup(struct device *dev, void *data)
|
||||
+{
|
||||
+ struct dw_hdmi_i2s_audio_data *audio = data;
|
||||
+ struct dw_hdmi *hdmi = audio->hdmi;
|
||||
+
|
||||
dw_hdmi_audio_enable(hdmi);
|
||||
|
||||
return 0;
|
||||
@@ -153,6 +161,7 @@ static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
|
||||
|
||||
static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
|
||||
.hw_params = dw_hdmi_i2s_hw_params,
|
||||
+ .audio_startup = dw_hdmi_i2s_audio_startup,
|
||||
.audio_shutdown = dw_hdmi_i2s_audio_shutdown,
|
||||
.get_eld = dw_hdmi_i2s_get_eld,
|
||||
.get_dai_id = dw_hdmi_i2s_get_dai_id,
|
||||
--
|
||||
2.23.0
|
||||
|
||||
From 3250cdf938dce5447cf4f895bb3ec3b929a95e09 Mon Sep 17 00:00:00 2001
|
||||
From: Yakir Yang <ykk@rock-chips.com>
|
||||
Date: Wed, 11 Sep 2019 16:26:46 +0800
|
||||
Subject: [PATCH] drm: bridge/dw_hdmi: add audio sample channel status setting
|
||||
|
||||
When transmitting IEC60985 linear PCM audio, we configure the
|
||||
Aduio Sample Channel Status information in the IEC60958 frame.
|
||||
The status bit is already available in iec.status of hdmi_codec_params.
|
||||
|
||||
This fix the issue that audio does not come out on some monitors
|
||||
(e.g. LG 22CV241)
|
||||
|
||||
Note that these registers are only for interfaces:
|
||||
I2S audio interface, General Purpose Audio (GPA), or AHB audio DMA
|
||||
(AHBAUDDMA).
|
||||
For S/PDIF interface this information comes from the stream.
|
||||
|
||||
Currently this function dw_hdmi_set_channel_status is only called
|
||||
from dw-hdmi-i2s-audio in I2S setup.
|
||||
|
||||
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
|
||||
Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
|
||||
Reviewed-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
||||
Link: https://patchwork.freedesktop.org/patch/msgid/20190911082646.134347-1-cychiang@chromium.org
|
||||
---
|
||||
.../drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 1 +
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 20 +++++++++++++++++++
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 2 ++
|
||||
include/drm/bridge/dw_hdmi.h | 1 +
|
||||
4 files changed, 24 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
index 34d8e837555f..20f4f92dd866 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
@@ -102,6 +102,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
|
||||
}
|
||||
|
||||
dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
|
||||
+ dw_hdmi_set_channel_status(hdmi, hparms->iec.status);
|
||||
dw_hdmi_set_channel_count(hdmi, hparms->channels);
|
||||
dw_hdmi_set_channel_allocation(hdmi, hparms->cea.channel_allocation);
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index bd65d0479683..aa7efd4da1c8 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -582,6 +582,26 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk)
|
||||
return n;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * When transmitting IEC60958 linear PCM audio, these registers allow to
|
||||
+ * configure the channel status information of all the channel status
|
||||
+ * bits in the IEC60958 frame. For the moment this configuration is only
|
||||
+ * used when the I2S audio interface, General Purpose Audio (GPA),
|
||||
+ * or AHB audio DMA (AHBAUDDMA) interface is active
|
||||
+ * (for S/PDIF interface this information comes from the stream).
|
||||
+ */
|
||||
+void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi,
|
||||
+ u8 *channel_status)
|
||||
+{
|
||||
+ /*
|
||||
+ * Set channel status register for frequency and word length.
|
||||
+ * Use default values for other registers.
|
||||
+ */
|
||||
+ hdmi_writeb(hdmi, channel_status[3], HDMI_FC_AUDSCHNLS7);
|
||||
+ hdmi_writeb(hdmi, channel_status[4], HDMI_FC_AUDSCHNLS8);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_status);
|
||||
+
|
||||
static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
|
||||
unsigned long pixel_clk, unsigned int sample_rate)
|
||||
{
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
index 6988f12d89d9..fcff5059db24 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
|
||||
@@ -158,6 +158,8 @@
|
||||
#define HDMI_FC_SPDDEVICEINF 0x1062
|
||||
#define HDMI_FC_AUDSCONF 0x1063
|
||||
#define HDMI_FC_AUDSSTAT 0x1064
|
||||
+#define HDMI_FC_AUDSCHNLS7 0x106e
|
||||
+#define HDMI_FC_AUDSCHNLS8 0x106f
|
||||
#define HDMI_FC_DATACH0FILL 0x1070
|
||||
#define HDMI_FC_DATACH1FILL 0x1071
|
||||
#define HDMI_FC_DATACH2FILL 0x1072
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index cf528c289857..4b3e863c4f8a 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -156,6 +156,7 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense);
|
||||
|
||||
void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
|
||||
void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt);
|
||||
+void dw_hdmi_set_channel_status(struct dw_hdmi *hdmi, u8 *channel_status);
|
||||
void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca);
|
||||
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
|
||||
--
|
||||
2.23.0
|
||||
|
650
projects/Allwinner/patches/linux/0003-hdmi-improvements.patch
Normal file
650
projects/Allwinner/patches/linux/0003-hdmi-improvements.patch
Normal file
@ -0,0 +1,650 @@
|
||||
From 99b0611417b9864ae57b6646e143f748f80964c9 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 10:22:09 +0100
|
||||
Subject: [PATCH 01/15] drm: dw-hdmi: extract dw_hdmi_connector_update_edid()
|
||||
|
||||
Extract code that updates EDID into a dw_hdmi_connector_update_edid() helper,
|
||||
it will be called from dw_hdmi_connector_detect().
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index ab7968c..fb35ee9 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -2059,7 +2059,8 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
}
|
||||
|
||||
-static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
+static int dw_hdmi_connector_update_edid(struct drm_connector *connector,
|
||||
+ bool add_modes)
|
||||
{
|
||||
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
|
||||
connector);
|
||||
@@ -2078,7 +2079,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
|
||||
- ret = drm_add_edid_modes(connector, edid);
|
||||
+ if (add_modes)
|
||||
+ ret = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
} else {
|
||||
dev_dbg(hdmi->dev, "failed to get edid\n");
|
||||
@@ -2087,6 +2089,11 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
+{
|
||||
+ return dw_hdmi_connector_update_edid(connector, true);
|
||||
+}
|
||||
+
|
||||
static void dw_hdmi_connector_force(struct drm_connector *connector)
|
||||
{
|
||||
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From 834da8a94754f25fdfac1995cc7ea72e569e9fbd Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 11:38:43 +0100
|
||||
Subject: [PATCH 02/15] drm: dw-hdmi: move dw_hdmi_connector_detect()
|
||||
|
||||
Move dw_hdmi_connector_detect() it will call dw_hdmi_connector_update_edid().
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 30 +++++++++++++++---------------
|
||||
1 file changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index fb35ee9..eb9e5d8 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -2044,21 +2044,6 @@ static void dw_hdmi_update_phy_mask(struct dw_hdmi *hdmi)
|
||||
hdmi->rxsense);
|
||||
}
|
||||
|
||||
-static enum drm_connector_status
|
||||
-dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
-{
|
||||
- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
|
||||
- connector);
|
||||
-
|
||||
- mutex_lock(&hdmi->mutex);
|
||||
- hdmi->force = DRM_FORCE_UNSPECIFIED;
|
||||
- dw_hdmi_update_power(hdmi);
|
||||
- dw_hdmi_update_phy_mask(hdmi);
|
||||
- mutex_unlock(&hdmi->mutex);
|
||||
-
|
||||
- return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
-}
|
||||
-
|
||||
static int dw_hdmi_connector_update_edid(struct drm_connector *connector,
|
||||
bool add_modes)
|
||||
{
|
||||
@@ -2089,6 +2074,21 @@ static int dw_hdmi_connector_update_edid(struct drm_connector *connector,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static enum drm_connector_status
|
||||
+dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
+{
|
||||
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
|
||||
+ connector);
|
||||
+
|
||||
+ mutex_lock(&hdmi->mutex);
|
||||
+ hdmi->force = DRM_FORCE_UNSPECIFIED;
|
||||
+ dw_hdmi_update_power(hdmi);
|
||||
+ dw_hdmi_update_phy_mask(hdmi);
|
||||
+ mutex_unlock(&hdmi->mutex);
|
||||
+
|
||||
+ return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
+}
|
||||
+
|
||||
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
return dw_hdmi_connector_update_edid(connector, true);
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From f1d41eb5ac2193f2a6c4a746a9fac27c3bfe7af5 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 10:22:09 +0100
|
||||
Subject: [PATCH 03/15] drm: dw-hdmi: update CEC phys addr and EDID on HPD
|
||||
event
|
||||
|
||||
Update CEC phys addr and EDID on HPD event, fixes lost CEC phys addr and
|
||||
stale EDID when HDMI cable is unplugged/replugged or AVR is powered on/off.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 14 +++++++++-----
|
||||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index eb9e5d8..d079bde 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -2077,6 +2077,7 @@ static int dw_hdmi_connector_update_edid(struct drm_connector *connector,
|
||||
static enum drm_connector_status
|
||||
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
+ enum drm_connector_status status;
|
||||
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
|
||||
connector);
|
||||
|
||||
@@ -2086,7 +2087,14 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
||||
dw_hdmi_update_phy_mask(hdmi);
|
||||
mutex_unlock(&hdmi->mutex);
|
||||
|
||||
- return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
+ status = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||
+
|
||||
+ if (status == connector_status_connected)
|
||||
+ dw_hdmi_connector_update_edid(connector, false);
|
||||
+ else
|
||||
+ cec_notifier_set_phys_addr(hdmi->cec_notifier, CEC_PHYS_ADDR_INVALID);
|
||||
+
|
||||
+ return status;
|
||||
}
|
||||
|
||||
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
@@ -2301,10 +2309,6 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
||||
dw_hdmi_setup_rx_sense(hdmi,
|
||||
phy_stat & HDMI_PHY_HPD,
|
||||
phy_stat & HDMI_PHY_RX_SENSE);
|
||||
-
|
||||
- if ((phy_stat & (HDMI_PHY_RX_SENSE | HDMI_PHY_HPD)) == 0)
|
||||
- cec_notifier_set_phys_addr(hdmi->cec_notifier,
|
||||
- CEC_PHYS_ADDR_INVALID);
|
||||
}
|
||||
|
||||
if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From e20d93cd15aad779acfad254bac23d37ea7b7fe9 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 10:22:09 +0100
|
||||
Subject: [PATCH 04/15] Revert "drm/edid: make drm_edid_to_eld() static"
|
||||
|
||||
drm_edid_to_eld() is needed to update stale connector ELD on HPD event.
|
||||
|
||||
This reverts part of commit 79436a1c9bccf5e38cb6ea26e4e4b9283baf2e20.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/drm_edid.c | 5 +++--
|
||||
include/drm/drm_edid.h | 1 +
|
||||
2 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
|
||||
index d947789..cc71a3c 100644
|
||||
--- a/drivers/gpu/drm/drm_edid.c
|
||||
+++ b/drivers/gpu/drm/drm_edid.c
|
||||
@@ -3970,7 +3970,7 @@ static void clear_eld(struct drm_connector *connector)
|
||||
connector->audio_latency[1] = 0;
|
||||
}
|
||||
|
||||
-/*
|
||||
+/**
|
||||
* drm_edid_to_eld - build ELD from EDID
|
||||
* @connector: connector corresponding to the HDMI/DP sink
|
||||
* @edid: EDID to parse
|
||||
@@ -3978,7 +3978,7 @@ static void clear_eld(struct drm_connector *connector)
|
||||
* Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The
|
||||
* HDCP and Port_ID ELD fields are left for the graphics driver to fill in.
|
||||
*/
|
||||
-static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
||||
+void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
||||
{
|
||||
uint8_t *eld = connector->eld;
|
||||
u8 *cea;
|
||||
@@ -4063,6 +4063,7 @@ static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
||||
DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
|
||||
drm_eld_size(eld), total_sad_count);
|
||||
}
|
||||
+EXPORT_SYMBOL(drm_edid_to_eld);
|
||||
|
||||
/**
|
||||
* drm_edid_to_sad - extracts SADs from EDID
|
||||
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
|
||||
index 19b15fd..185870b 100644
|
||||
--- a/include/drm/drm_edid.h
|
||||
+++ b/include/drm/drm_edid.h
|
||||
@@ -333,6 +333,7 @@ struct drm_encoder;
|
||||
struct drm_connector;
|
||||
struct drm_display_mode;
|
||||
|
||||
+void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid);
|
||||
int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
|
||||
int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb);
|
||||
int drm_av_sync_delay(struct drm_connector *connector,
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From 901b76d639e09e7d829b4974c174ab8595310bcd Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 10:22:09 +0100
|
||||
Subject: [PATCH 05/15] drm: dw-hdmi: update ELD on HPD event
|
||||
|
||||
Update connector ELD on HPD event, fixes stale ELD when
|
||||
HDMI cable is unplugged/replugged or AVR is powered on/off.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index d079bde..f13ac2c 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -2066,6 +2066,8 @@ static int dw_hdmi_connector_update_edid(struct drm_connector *connector,
|
||||
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
|
||||
if (add_modes)
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
+ else
|
||||
+ drm_edid_to_eld(connector, edid);
|
||||
kfree(edid);
|
||||
} else {
|
||||
dev_dbg(hdmi->dev, "failed to get edid\n");
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From e77725c0dc43a3d8d8641dea4abfb92225bf6e72 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 10:22:09 +0100
|
||||
Subject: [PATCH 06/15] ASoC: hdmi-codec: add hdmi_codec_eld_notify()
|
||||
|
||||
Add helper that will notify userspace when ELD control has changed.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
include/sound/hdmi-codec.h | 2 ++
|
||||
sound/soc/codecs/hdmi-codec.c | 24 ++++++++++++++++++++----
|
||||
2 files changed, 22 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h
|
||||
index 9483c55..7cf66a4 100644
|
||||
--- a/include/sound/hdmi-codec.h
|
||||
+++ b/include/sound/hdmi-codec.h
|
||||
@@ -107,6 +107,8 @@ struct hdmi_codec_pdata {
|
||||
void *data;
|
||||
};
|
||||
|
||||
+void hdmi_codec_eld_notify(struct device *dev);
|
||||
+
|
||||
#define HDMI_CODEC_DRV_NAME "hdmi-audio-codec"
|
||||
|
||||
#endif /* __HDMI_CODEC_H__ */
|
||||
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
|
||||
index fb2f0ac..bfb1519 100644
|
||||
--- a/sound/soc/codecs/hdmi-codec.c
|
||||
+++ b/sound/soc/codecs/hdmi-codec.c
|
||||
@@ -285,6 +285,8 @@ struct hdmi_codec_priv {
|
||||
struct snd_pcm_chmap *chmap_info;
|
||||
unsigned int chmap_idx;
|
||||
struct mutex lock;
|
||||
+ struct snd_card *snd_card;
|
||||
+ struct snd_kcontrol *kctl;
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget hdmi_widgets[] = {
|
||||
@@ -648,7 +650,6 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
||||
{
|
||||
struct snd_soc_dai_driver *drv = dai->driver;
|
||||
struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
|
||||
- struct snd_kcontrol *kctl;
|
||||
struct snd_kcontrol_new hdmi_eld_ctl = {
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READ |
|
||||
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
|
||||
@@ -677,12 +678,27 @@ static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,
|
||||
hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
|
||||
|
||||
/* add ELD ctl with the device number corresponding to the PCM stream */
|
||||
- kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
|
||||
- if (!kctl)
|
||||
+ hcp->kctl = snd_ctl_new1(&hdmi_eld_ctl, dai->component);
|
||||
+ if (!hcp->kctl)
|
||||
return -ENOMEM;
|
||||
|
||||
- return snd_ctl_add(rtd->card->snd_card, kctl);
|
||||
+ hcp->snd_card = rtd->card->snd_card;
|
||||
+
|
||||
+ return snd_ctl_add(hcp->snd_card, hcp->kctl);
|
||||
+}
|
||||
+
|
||||
+void hdmi_codec_eld_notify(struct device *dev)
|
||||
+{
|
||||
+ struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
|
||||
+ struct snd_ctl_elem_id id;
|
||||
+
|
||||
+ if (!hcp->snd_card || !hcp->kctl)
|
||||
+ return;
|
||||
+
|
||||
+ id = hcp->kctl->id;
|
||||
+ snd_ctl_notify(hcp->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(hdmi_codec_eld_notify);
|
||||
|
||||
static int hdmi_dai_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From 2f1f2bdbc0f6d02235310e87c1de7a193dcda178 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 12:56:33 +0100
|
||||
Subject: [PATCH 07/15] drm: dw-hdmi: add dw_hdmi_update_eld() callback
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 15 +++++++++++++++
|
||||
include/drm/bridge/dw_hdmi.h | 2 ++
|
||||
2 files changed, 17 insertions(+)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
index f13ac2c..a7040c1 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
|
||||
@@ -188,6 +188,7 @@ struct dw_hdmi {
|
||||
struct regmap *regm;
|
||||
void (*enable_audio)(struct dw_hdmi *hdmi);
|
||||
void (*disable_audio)(struct dw_hdmi *hdmi);
|
||||
+ void (*update_eld)(struct device *dev, u8 *eld);
|
||||
|
||||
struct cec_notifier *cec_notifier;
|
||||
};
|
||||
@@ -613,6 +614,19 @@ void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
|
||||
|
||||
+static void dw_hdmi_update_eld(struct dw_hdmi *hdmi, u8 *eld)
|
||||
+{
|
||||
+ if (hdmi->audio && hdmi->update_eld)
|
||||
+ hdmi->update_eld(&hdmi->audio->dev, eld);
|
||||
+}
|
||||
+
|
||||
+void dw_hdmi_set_update_eld(struct dw_hdmi *hdmi,
|
||||
+ void (*update_eld)(struct device *dev, u8 *eld))
|
||||
+{
|
||||
+ hdmi->update_eld = update_eld;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(dw_hdmi_set_update_eld);
|
||||
+
|
||||
static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
|
||||
{
|
||||
switch (bus_format) {
|
||||
@@ -2068,6 +2082,7 @@ static int dw_hdmi_connector_update_edid(struct drm_connector *connector,
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
else
|
||||
drm_edid_to_eld(connector, edid);
|
||||
+ dw_hdmi_update_eld(hdmi, connector->eld);
|
||||
kfree(edid);
|
||||
} else {
|
||||
dev_dbg(hdmi->dev, "failed to get edid\n");
|
||||
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
|
||||
index 66e7077..323febe 100644
|
||||
--- a/include/drm/bridge/dw_hdmi.h
|
||||
+++ b/include/drm/bridge/dw_hdmi.h
|
||||
@@ -160,6 +160,8 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
|
||||
void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
|
||||
void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi);
|
||||
+void dw_hdmi_set_update_eld(struct dw_hdmi *hdmi,
|
||||
+ void (*update_eld)(struct device *dev, u8 *eld));
|
||||
|
||||
/* PHY configuration */
|
||||
void dw_hdmi_phy_i2c_set_addr(struct dw_hdmi *hdmi, u8 address);
|
||||
--
|
||||
2.14.1
|
||||
|
||||
|
||||
From 8a20ea0cfb4c6e97d2ccde1fc77e1f4cdd03e5d2 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 10:22:09 +0100
|
||||
Subject: [PATCH 08/15] drm: dw-hdmi-i2s: add .get_eld callback for ALSA SoC
|
||||
|
||||
Add get_eld() callback and call hdmi_codec_eld_notify() when ELD has changed.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 +
|
||||
.../gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 36 +++++++++++++++++++++-
|
||||
2 files changed, 36 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
index 5cbb71a..a397505 100644
|
||||
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
|
||||
@@ -84,6 +84,22 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
|
||||
dw_hdmi_audio_disable(hdmi);
|
||||
}
|
||||
|
||||
+static void dw_hdmi_i2s_update_eld(struct device *dev, u8 *eld)
|
||||
+{
|
||||
+ struct dw_hdmi_i2s_audio_data *audio = dev_get_platdata(dev);
|
||||
+ struct platform_device *hcpdev = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (!audio || !hcpdev)
|
||||
+ return;
|
||||
+
|
||||
+ if (!memcmp(audio->eld, eld, sizeof(audio->eld)))
|
||||
+ return;
|
||||
+
|
||||
+ memcpy(audio->eld, eld, sizeof(audio->eld));
|
||||
+
|
||||
+ hdmi_codec_eld_notify(&hcpdev->dev);
|
||||
+}
|
||||
+
|
||||
static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, uint8_t *buf,
|
||||
size_t len)
|
||||
{
|
||||
@@ -136,13 +165,18 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
|
||||
|
||||
dev_set_drvdata(&pdev->dev, platform);
|
||||
|
||||
+ dw_hdmi_set_update_eld(audio->hdmi, dw_hdmi_i2s_update_eld);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_dw_hdmi_remove(struct platform_device *pdev)
|
||||
{
|
||||
+ struct dw_hdmi_i2s_audio_data *audio = dev_get_platdata(&pdev->dev);
|
||||
struct platform_device *platform = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
+ dw_hdmi_set_update_eld(audio->hdmi, NULL);
|
||||
+
|
||||
platform_device_unregister(platform);
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.14.1
|
||||
|
||||
From e7b2f400507263f12872db06f4cd69bc80f62c2f Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 25 Mar 2018 22:17:06 +0200
|
||||
Subject: [PATCH 10/15] ASoC: hdmi-codec: fix channel allocation
|
||||
|
||||
---
|
||||
sound/soc/codecs/hdmi-codec.c | 113 +++++++++++++++++++-----------------------
|
||||
1 file changed, 52 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
|
||||
index bfb1519..47632a3 100644
|
||||
--- a/sound/soc/codecs/hdmi-codec.c
|
||||
+++ b/sound/soc/codecs/hdmi-codec.c
|
||||
@@ -202,78 +202,69 @@ static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {
|
||||
*/
|
||||
static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {
|
||||
{ .ca_id = 0x00, .n_ch = 2,
|
||||
- .mask = FL | FR},
|
||||
- /* 2.1 */
|
||||
- { .ca_id = 0x01, .n_ch = 4,
|
||||
- .mask = FL | FR | LFE},
|
||||
- /* Dolby Surround */
|
||||
+ .mask = FL | FR },
|
||||
+ { .ca_id = 0x03, .n_ch = 4,
|
||||
+ .mask = FL | FR | LFE | FC },
|
||||
{ .ca_id = 0x02, .n_ch = 4,
|
||||
.mask = FL | FR | FC },
|
||||
- /* surround51 */
|
||||
+ { .ca_id = 0x01, .n_ch = 4,
|
||||
+ .mask = FL | FR | LFE },
|
||||
{ .ca_id = 0x0b, .n_ch = 6,
|
||||
- .mask = FL | FR | LFE | FC | RL | RR},
|
||||
- /* surround40 */
|
||||
- { .ca_id = 0x08, .n_ch = 6,
|
||||
- .mask = FL | FR | RL | RR },
|
||||
- /* surround41 */
|
||||
- { .ca_id = 0x09, .n_ch = 6,
|
||||
- .mask = FL | FR | LFE | RL | RR },
|
||||
- /* surround50 */
|
||||
+ .mask = FL | FR | LFE | FC | RL | RR },
|
||||
{ .ca_id = 0x0a, .n_ch = 6,
|
||||
.mask = FL | FR | FC | RL | RR },
|
||||
- /* 6.1 */
|
||||
- { .ca_id = 0x0f, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | FC | RL | RR | RC },
|
||||
- /* surround71 */
|
||||
+ { .ca_id = 0x09, .n_ch = 6,
|
||||
+ .mask = FL | FR | LFE | RL | RR },
|
||||
+ { .ca_id = 0x08, .n_ch = 6,
|
||||
+ .mask = FL | FR | RL | RR },
|
||||
+ { .ca_id = 0x07, .n_ch = 6,
|
||||
+ .mask = FL | FR | LFE | FC | RC },
|
||||
+ { .ca_id = 0x06, .n_ch = 6,
|
||||
+ .mask = FL | FR | FC | RC },
|
||||
+ { .ca_id = 0x05, .n_ch = 6,
|
||||
+ .mask = FL | FR | LFE | RC },
|
||||
+ { .ca_id = 0x04, .n_ch = 6,
|
||||
+ .mask = FL | FR | RC },
|
||||
{ .ca_id = 0x13, .n_ch = 8,
|
||||
.mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },
|
||||
- /* others */
|
||||
- { .ca_id = 0x03, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | FC },
|
||||
- { .ca_id = 0x04, .n_ch = 8,
|
||||
- .mask = FL | FR | RC},
|
||||
- { .ca_id = 0x05, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | RC },
|
||||
- { .ca_id = 0x06, .n_ch = 8,
|
||||
- .mask = FL | FR | FC | RC },
|
||||
- { .ca_id = 0x07, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | FC | RC },
|
||||
- { .ca_id = 0x0c, .n_ch = 8,
|
||||
- .mask = FL | FR | RC | RL | RR },
|
||||
- { .ca_id = 0x0d, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | RL | RR | RC },
|
||||
- { .ca_id = 0x0e, .n_ch = 8,
|
||||
- .mask = FL | FR | FC | RL | RR | RC },
|
||||
- { .ca_id = 0x10, .n_ch = 8,
|
||||
- .mask = FL | FR | RL | RR | RLC | RRC },
|
||||
- { .ca_id = 0x11, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | RL | RR | RLC | RRC },
|
||||
+ { .ca_id = 0x1f, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
|
||||
{ .ca_id = 0x12, .n_ch = 8,
|
||||
.mask = FL | FR | FC | RL | RR | RLC | RRC },
|
||||
- { .ca_id = 0x14, .n_ch = 8,
|
||||
- .mask = FL | FR | FLC | FRC },
|
||||
- { .ca_id = 0x15, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | FLC | FRC },
|
||||
- { .ca_id = 0x16, .n_ch = 8,
|
||||
- .mask = FL | FR | FC | FLC | FRC },
|
||||
- { .ca_id = 0x17, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | FC | FLC | FRC },
|
||||
- { .ca_id = 0x18, .n_ch = 8,
|
||||
- .mask = FL | FR | RC | FLC | FRC },
|
||||
- { .ca_id = 0x19, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | RC | FLC | FRC },
|
||||
- { .ca_id = 0x1a, .n_ch = 8,
|
||||
- .mask = FL | FR | RC | FC | FLC | FRC },
|
||||
- { .ca_id = 0x1b, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | RC | FC | FLC | FRC },
|
||||
- { .ca_id = 0x1c, .n_ch = 8,
|
||||
- .mask = FL | FR | RL | RR | FLC | FRC },
|
||||
- { .ca_id = 0x1d, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | RL | RR | FLC | FRC },
|
||||
{ .ca_id = 0x1e, .n_ch = 8,
|
||||
.mask = FL | FR | FC | RL | RR | FLC | FRC },
|
||||
- { .ca_id = 0x1f, .n_ch = 8,
|
||||
- .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },
|
||||
+ { .ca_id = 0x11, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | RL | RR | RLC | RRC },
|
||||
+ { .ca_id = 0x1d, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | RL | RR | FLC | FRC },
|
||||
+ { .ca_id = 0x10, .n_ch = 8,
|
||||
+ .mask = FL | FR | RL | RR | RLC | RRC },
|
||||
+ { .ca_id = 0x1c, .n_ch = 8,
|
||||
+ .mask = FL | FR | RL | RR | FLC | FRC },
|
||||
+ { .ca_id = 0x0f, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | FC | RL | RR | RC },
|
||||
+ { .ca_id = 0x1b, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | RC | FC | FLC | FRC },
|
||||
+ { .ca_id = 0x0e, .n_ch = 8,
|
||||
+ .mask = FL | FR | FC | RL | RR | RC },
|
||||
+ { .ca_id = 0x1a, .n_ch = 8,
|
||||
+ .mask = FL | FR | RC | FC | FLC | FRC },
|
||||
+ { .ca_id = 0x0d, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | RL | RR | RC },
|
||||
+ { .ca_id = 0x19, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | RC | FLC | FRC },
|
||||
+ { .ca_id = 0x0c, .n_ch = 8,
|
||||
+ .mask = FL | FR | RC | RL | RR },
|
||||
+ { .ca_id = 0x18, .n_ch = 8,
|
||||
+ .mask = FL | FR | RC | FLC | FRC },
|
||||
+ { .ca_id = 0x17, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | FC | FLC | FRC },
|
||||
+ { .ca_id = 0x16, .n_ch = 8,
|
||||
+ .mask = FL | FR | FC | FLC | FRC },
|
||||
+ { .ca_id = 0x15, .n_ch = 8,
|
||||
+ .mask = FL | FR | LFE | FLC | FRC },
|
||||
+ { .ca_id = 0x14, .n_ch = 8,
|
||||
+ .mask = FL | FR | FLC | FRC },
|
||||
};
|
||||
|
||||
struct hdmi_codec_priv {
|
||||
--
|
||||
2.14.1
|
||||
|
||||
From 774d913eec1ba16c494dafefc626fa4fbd98fdac Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Sun, 16 Dec 2018 20:31:25 +0100
|
||||
Subject: [PATCH 15/15] fixup! drm: dw-hdmi: add dw_hdmi_update_eld() callback
|
||||
|
||||
---
|
||||
sound/soc/codecs/hdmi-codec.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
|
||||
index 47632a3..f5072dc 100644
|
||||
--- a/sound/soc/codecs/hdmi-codec.c
|
||||
+++ b/sound/soc/codecs/hdmi-codec.c
|
||||
@@ -683,7 +683,9 @@ void hdmi_codec_eld_notify(struct device *dev)
|
||||
struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);
|
||||
struct snd_ctl_elem_id id;
|
||||
|
||||
- if (!hcp->snd_card || !hcp->kctl)
|
||||
+ if (!hcp ||
|
||||
+ !hcp->snd_card ||
|
||||
+ !hcp->kctl)
|
||||
return;
|
||||
|
||||
id = hcp->kctl->id;
|
||||
--
|
||||
2.14.1
|
@ -0,0 +1,725 @@
|
||||
From b5cb1681a065bd03b0eb84ca243bc50ab0fa54c1 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue, 17 Sep 2019 17:55:07 +0200
|
||||
Subject: [PATCH] WIP: I2S improvements (to be mainlined)
|
||||
|
||||
Work done by Marcus Cooper (codekipper)
|
||||
---
|
||||
sound/soc/sunxi/sun4i-i2s.c | 454 ++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 412 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
|
||||
index d0a8d5810c0a..9a715a6bdbf9 100644
|
||||
--- a/sound/soc/sunxi/sun4i-i2s.c
|
||||
+++ b/sound/soc/sunxi/sun4i-i2s.c
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#define SUN4I_I2S_CTRL_REG 0x00
|
||||
#define SUN4I_I2S_CTRL_SDO_EN_MASK GENMASK(11, 8)
|
||||
-#define SUN4I_I2S_CTRL_SDO_EN(sdo) BIT(8 + (sdo))
|
||||
+#define SUN4I_I2S_CTRL_SDO_EN(lines) (((1 << (lines)) - 1) << 8)
|
||||
#define SUN4I_I2S_CTRL_MODE_MASK BIT(5)
|
||||
#define SUN4I_I2S_CTRL_MODE_SLAVE (1 << 5)
|
||||
#define SUN4I_I2S_CTRL_MODE_MASTER (0 << 5)
|
||||
@@ -48,6 +48,9 @@
|
||||
#define SUN4I_I2S_FMT0_FMT_I2S (0 << 0)
|
||||
|
||||
#define SUN4I_I2S_FMT1_REG 0x08
|
||||
+#define SUN4I_I2S_FMT1_REG_SEXT_MASK BIT(8)
|
||||
+#define SUN4I_I2S_FMT1_REG_SEXT(sext) ((sext) << 8)
|
||||
+
|
||||
#define SUN4I_I2S_FIFO_TX_REG 0x0c
|
||||
#define SUN4I_I2S_FIFO_RX_REG 0x10
|
||||
|
||||
@@ -97,33 +100,53 @@
|
||||
#define SUN8I_I2S_CTRL_MODE_PCM (0 << 4)
|
||||
|
||||
#define SUN8I_I2S_FMT0_LRCLK_POLARITY_MASK BIT(19)
|
||||
-#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19)
|
||||
-#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19)
|
||||
+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED (1 << 19)
|
||||
+#define SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL (0 << 19)
|
||||
#define SUN8I_I2S_FMT0_LRCK_PERIOD_MASK GENMASK(17, 8)
|
||||
#define SUN8I_I2S_FMT0_LRCK_PERIOD(period) ((period - 1) << 8)
|
||||
#define SUN8I_I2S_FMT0_BCLK_POLARITY_MASK BIT(7)
|
||||
-#define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7)
|
||||
-#define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7)
|
||||
+#define SUN8I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 7)
|
||||
+#define SUN8I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 7)
|
||||
+
|
||||
+#define SUN8I_I2S_FMT1_REG_SEXT_MASK GENMASK(5, 4)
|
||||
+#define SUN8I_I2S_FMT1_REG_SEXT(sext) ((sext) << 4)
|
||||
|
||||
#define SUN8I_I2S_INT_STA_REG 0x0c
|
||||
#define SUN8I_I2S_FIFO_TX_REG 0x20
|
||||
|
||||
#define SUN8I_I2S_CHAN_CFG_REG 0x30
|
||||
#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4)
|
||||
-#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4)
|
||||
+#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) (((chan) - 1) << 4)
|
||||
#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0)
|
||||
-#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1)
|
||||
+#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) ((chan) - 1)
|
||||
|
||||
#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44
|
||||
#define SUN8I_I2S_TX_CHAN_SEL_REG 0x34
|
||||
#define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12)
|
||||
-#define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12)
|
||||
+#define SUN8I_I2S_TX_CHAN_OFFSET(offset) ((offset) << 12)
|
||||
#define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4)
|
||||
#define SUN8I_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1) << 4)
|
||||
+#define SUN8I_I2S_TX_CHAN_SEL_MASK GENMASK(2, 0)
|
||||
+#define SUN8I_I2S_TX_CHAN_SEL(chan) ((chan) - 1)
|
||||
|
||||
#define SUN8I_I2S_RX_CHAN_SEL_REG 0x54
|
||||
#define SUN8I_I2S_RX_CHAN_MAP_REG 0x58
|
||||
|
||||
+/* Defines required for sun50i-h6 support */
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK GENMASK(21, 20)
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(offset) ((offset) << 20)
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_SEL_MASK GENMASK(19, 16)
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_SEL(chan) (((chan) - 1) << 16)
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0)
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << (num_chan)) - 1))
|
||||
+
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44
|
||||
+#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48
|
||||
+
|
||||
+#define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64
|
||||
+#define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68
|
||||
+#define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6C
|
||||
+
|
||||
struct sun4i_i2s;
|
||||
|
||||
/**
|
||||
@@ -156,7 +179,16 @@ struct sun4i_i2s_quirks {
|
||||
s8 (*get_wss)(const struct sun4i_i2s *, int);
|
||||
int (*set_chan_cfg)(const struct sun4i_i2s *,
|
||||
const struct snd_pcm_hw_params *);
|
||||
- int (*set_fmt)(const struct sun4i_i2s *, unsigned int);
|
||||
+ int (*set_fmt)(struct sun4i_i2s *, unsigned int);
|
||||
+ void (*set_fmt_sext)(const struct sun4i_i2s *, unsigned int);
|
||||
+ void (*set_txchanoffset)(const struct sun4i_i2s *, int);
|
||||
+ void (*set_rxchanoffset)(const struct sun4i_i2s *);
|
||||
+ void (*set_txchanen)(const struct sun4i_i2s *, int, int);
|
||||
+ void (*set_rxchanen)(const struct sun4i_i2s *, int);
|
||||
+ void (*set_txchansel)(const struct sun4i_i2s *, int, int);
|
||||
+ void (*set_rxchansel)(const struct sun4i_i2s *, int);
|
||||
+ void (*set_txchanmap)(const struct sun4i_i2s *, int, int);
|
||||
+ void (*set_rxchanmap)(const struct sun4i_i2s *, int);
|
||||
};
|
||||
|
||||
struct sun4i_i2s {
|
||||
@@ -169,6 +201,7 @@ struct sun4i_i2s {
|
||||
unsigned int mclk_freq;
|
||||
unsigned int slots;
|
||||
unsigned int slot_width;
|
||||
+ unsigned int offset;
|
||||
|
||||
struct snd_dmaengine_dai_dma_data capture_dma_data;
|
||||
struct snd_dmaengine_dai_dma_data playback_dma_data;
|
||||
@@ -354,6 +387,9 @@ static int sun4i_i2s_set_clk_rate(struct snd_soc_dai *dai,
|
||||
|
||||
regmap_field_write(i2s->field_clkdiv_mclk_en, 1);
|
||||
|
||||
+ /* Set sign extension to pad out LSB with 0 */
|
||||
+ i2s->variant->set_fmt_sext(i2s, 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -396,8 +432,8 @@ static int sun4i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
|
||||
unsigned int channels = params_channels(params);
|
||||
|
||||
/* Map the channels for playback and capture */
|
||||
- regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, 0x76543210);
|
||||
- regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, 0x00003210);
|
||||
+ i2s->variant->set_txchanmap(i2s, 0, 0x76543210);
|
||||
+ i2s->variant->set_rxchanmap(i2s, 0x3210);
|
||||
|
||||
/* Configure the channels */
|
||||
regmap_update_bits(i2s->regmap, SUN4I_I2S_TX_CHAN_SEL_REG,
|
||||
@@ -421,16 +457,12 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
|
||||
slots = i2s->slots;
|
||||
|
||||
/* Map the channels for playback and capture */
|
||||
- regmap_write(i2s->regmap, SUN8I_I2S_TX_CHAN_MAP_REG, 0x76543210);
|
||||
- regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, 0x76543210);
|
||||
+ i2s->variant->set_txchanmap(i2s, 0, 0x76543210);
|
||||
+ i2s->variant->set_rxchanmap(i2s, 0x3210);
|
||||
|
||||
/* Configure the channels */
|
||||
- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
|
||||
- SUN4I_I2S_CHAN_SEL_MASK,
|
||||
- SUN4I_I2S_CHAN_SEL(channels));
|
||||
- regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG,
|
||||
- SUN4I_I2S_CHAN_SEL_MASK,
|
||||
- SUN4I_I2S_CHAN_SEL(channels));
|
||||
+ i2s->variant->set_txchansel(i2s, 0, channels);
|
||||
+ i2s->variant->set_rxchansel(i2s, channels);
|
||||
|
||||
regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
|
||||
SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK,
|
||||
@@ -448,7 +480,10 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
- lrck_period = params_physical_width(params);
|
||||
+ if (i2s->slot_width)
|
||||
+ lrck_period = i2s->slot_width;
|
||||
+ else
|
||||
+ lrck_period = params_physical_width(params);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -466,6 +501,166 @@ static int sun8i_i2s_set_chan_cfg(const struct sun4i_i2s *i2s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void sun8i_i2s_set_txchanoffset(const struct sun4i_i2s *i2s, int output)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4),
|
||||
+ SUN8I_I2S_TX_CHAN_OFFSET_MASK,
|
||||
+ SUN8I_I2S_TX_CHAN_OFFSET(i2s->offset));
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_rxchanoffset(const struct sun4i_i2s *i2s)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN8I_I2S_TX_CHAN_OFFSET_MASK,
|
||||
+ SUN8I_I2S_TX_CHAN_OFFSET(i2s->offset));
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_txchanoffset(const struct sun4i_i2s *i2s, int output)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4),
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(i2s->offset));
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_rxchanoffset(const struct sun4i_i2s *i2s)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN50I_H6_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET_MASK,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL_OFFSET(i2s->offset));
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_txchanen(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4),
|
||||
+ SUN8I_I2S_TX_CHAN_EN_MASK,
|
||||
+ SUN8I_I2S_TX_CHAN_EN(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_rxchanen(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN8I_I2S_TX_CHAN_EN_MASK,
|
||||
+ SUN8I_I2S_TX_CHAN_EN(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_txchanen(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4),
|
||||
+ SUN50I_H6_I2S_TX_CHAN_EN_MASK,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_EN(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_rxchanen(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN50I_H6_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_EN_MASK,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_EN(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun4i_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ /* Configure the channels */
|
||||
+ regmap_write(i2s->regmap,
|
||||
+ SUN4I_I2S_TX_CHAN_SEL_REG,
|
||||
+ SUN4I_I2S_CHAN_SEL(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4),
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_MASK,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun4i_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ /* Configure the channels */
|
||||
+ regmap_write(i2s->regmap,
|
||||
+ SUN4I_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN4I_I2S_CHAN_SEL(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_MASK,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_txchansel(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_SEL_REG + (output * 4),
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL_MASK,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_rxchansel(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap,
|
||||
+ SUN50I_H6_I2S_RX_CHAN_SEL_REG,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL_MASK,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_SEL(channel));
|
||||
+}
|
||||
+
|
||||
+static void sun4i_i2s_set_txchanmap(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ regmap_write(i2s->regmap, SUN4I_I2S_TX_CHAN_MAP_REG, channel);
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_txchanmap(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_write(i2s->regmap,
|
||||
+ SUN8I_I2S_TX_CHAN_MAP_REG + (output * 4), channel);
|
||||
+}
|
||||
+
|
||||
+static void sun4i_i2s_set_rxchanmap(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_write(i2s->regmap, SUN4I_I2S_RX_CHAN_MAP_REG, channel);
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_rxchanmap(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_write(i2s->regmap, SUN8I_I2S_RX_CHAN_MAP_REG, channel);
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_txchanmap(const struct sun4i_i2s *i2s, int output,
|
||||
+ int channel)
|
||||
+{
|
||||
+ if (output >= 0 && output < 4)
|
||||
+ regmap_write(i2s->regmap,
|
||||
+ SUN50I_H6_I2S_TX_CHAN_MAP1_REG + (output * 8), channel);
|
||||
+}
|
||||
+
|
||||
+static void sun50i_h6_i2s_set_rxchanmap(const struct sun4i_i2s *i2s, int channel)
|
||||
+{
|
||||
+ regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, channel);
|
||||
+}
|
||||
+
|
||||
static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
@@ -477,6 +672,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
unsigned int slots = channels;
|
||||
int ret, sr, wss;
|
||||
u32 width;
|
||||
+ int lines;
|
||||
|
||||
if (i2s->slots)
|
||||
slots = i2s->slots;
|
||||
@@ -490,10 +686,82 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
+ if (channels > dai->driver->playback.channels_max ||
|
||||
+ channels < dai->driver->playback.channels_min) {
|
||||
+ dev_err(dai->dev, "Unsupported number of channels: %d\n",
|
||||
+ channels);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ lines = (channels + 1) / 2;
|
||||
+
|
||||
+ /* Enable the required output lines */
|
||||
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
|
||||
+ SUN4I_I2S_CTRL_SDO_EN_MASK,
|
||||
+ SUN4I_I2S_CTRL_SDO_EN(lines));
|
||||
+
|
||||
+ i2s->variant->set_txchanmap(i2s, 0, 0x10);
|
||||
+ i2s->variant->set_txchansel(i2s, 0, channels > 1 ? 2 : 1);
|
||||
+
|
||||
+ if (i2s->variant->set_txchanen)
|
||||
+ i2s->variant->set_txchanen(i2s, 0, 2);
|
||||
+
|
||||
+ if (i2s->variant->set_txchanoffset) {
|
||||
+ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
|
||||
+ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK,
|
||||
+ SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(channels));
|
||||
+
|
||||
+ if (channels > 2) {
|
||||
+ i2s->variant->set_txchanmap(i2s, 1, 0x32);
|
||||
+ i2s->variant->set_txchanoffset(i2s, 1);
|
||||
+ i2s->variant->set_txchansel(i2s, 1,
|
||||
+ channels > 3 ? 2 : 1);
|
||||
+ i2s->variant->set_txchanen(i2s, 1, 2);
|
||||
+ }
|
||||
+ if (channels > 4) {
|
||||
+ i2s->variant->set_txchanmap(i2s, 2, 0x54);
|
||||
+ i2s->variant->set_txchanoffset(i2s, 2);
|
||||
+ i2s->variant->set_txchansel(i2s, 2,
|
||||
+ channels > 5 ? 2 : 1);
|
||||
+ i2s->variant->set_txchanen(i2s, 2, 2);
|
||||
+ }
|
||||
+ if (channels > 6) {
|
||||
+ i2s->variant->set_txchanmap(i2s, 3, 0x76);
|
||||
+ i2s->variant->set_txchanoffset(i2s, 3);
|
||||
+ i2s->variant->set_txchansel(i2s, 3,
|
||||
+ channels > 6 ? 2 : 1);
|
||||
+ i2s->variant->set_txchanen(i2s, 3, 2);
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (channels > dai->driver->capture.channels_max ||
|
||||
+ channels < dai->driver->capture.channels_min) {
|
||||
+ dev_err(dai->dev, "Unsupported number of channels: %d\n",
|
||||
+ channels);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Map the channels for capture */
|
||||
+ i2s->variant->set_rxchanmap(i2s, 0x10);
|
||||
+ i2s->variant->set_rxchansel(i2s, channels);
|
||||
+
|
||||
+ if (i2s->variant->set_rxchanen)
|
||||
+ i2s->variant->set_rxchanen(i2s, channels);
|
||||
+
|
||||
+ if (i2s->variant->set_rxchanoffset)
|
||||
+ regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
|
||||
+ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK,
|
||||
+ SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(channels));
|
||||
+ }
|
||||
+
|
||||
switch (params_physical_width(params)) {
|
||||
case 16:
|
||||
width = DMA_SLAVE_BUSWIDTH_2_BYTES;
|
||||
break;
|
||||
+ case 32:
|
||||
+ width = DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
+ break;
|
||||
default:
|
||||
dev_err(dai->dev, "Unsupported physical sample width: %d\n",
|
||||
params_physical_width(params));
|
||||
@@ -516,7 +784,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||
slots, slot_width);
|
||||
}
|
||||
|
||||
-static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
|
||||
+static int sun4i_i2s_set_soc_fmt(struct sun4i_i2s *i2s,
|
||||
unsigned int fmt)
|
||||
{
|
||||
u32 val;
|
||||
@@ -589,11 +857,10 @@ static int sun4i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
|
||||
+static int sun8i_i2s_set_soc_fmt(struct sun4i_i2s *i2s,
|
||||
unsigned int fmt)
|
||||
{
|
||||
u32 mode, val;
|
||||
- u8 offset;
|
||||
|
||||
/*
|
||||
* DAI clock polarity
|
||||
@@ -632,27 +899,27 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
|
||||
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
|
||||
case SND_SOC_DAIFMT_DSP_A:
|
||||
mode = SUN8I_I2S_CTRL_MODE_PCM;
|
||||
- offset = 1;
|
||||
+ i2s->offset = 1;
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_DSP_B:
|
||||
mode = SUN8I_I2S_CTRL_MODE_PCM;
|
||||
- offset = 0;
|
||||
+ i2s->offset = 0;
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_I2S:
|
||||
mode = SUN8I_I2S_CTRL_MODE_LEFT;
|
||||
- offset = 1;
|
||||
+ i2s->offset = 1;
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_LEFT_J:
|
||||
mode = SUN8I_I2S_CTRL_MODE_LEFT;
|
||||
- offset = 0;
|
||||
+ i2s->offset = 0;
|
||||
break;
|
||||
|
||||
case SND_SOC_DAIFMT_RIGHT_J:
|
||||
mode = SUN8I_I2S_CTRL_MODE_RIGHT;
|
||||
- offset = 0;
|
||||
+ i2s->offset = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -661,12 +928,8 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
|
||||
|
||||
regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
|
||||
SUN8I_I2S_CTRL_MODE_MASK, mode);
|
||||
- regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG,
|
||||
- SUN8I_I2S_TX_CHAN_OFFSET_MASK,
|
||||
- SUN8I_I2S_TX_CHAN_OFFSET(offset));
|
||||
- regmap_update_bits(i2s->regmap, SUN8I_I2S_RX_CHAN_SEL_REG,
|
||||
- SUN8I_I2S_TX_CHAN_OFFSET_MASK,
|
||||
- SUN8I_I2S_TX_CHAN_OFFSET(offset));
|
||||
+ i2s->variant->set_txchanoffset(i2s, 0);
|
||||
+ i2s->variant->set_rxchanoffset(i2s);
|
||||
|
||||
/* DAI clock master masks */
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
@@ -691,6 +954,22 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void sun4i_i2s_set_fmt_sext(const struct sun4i_i2s *i2s,
|
||||
+ unsigned int sext)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
|
||||
+ SUN4I_I2S_FMT1_REG_SEXT_MASK,
|
||||
+ SUN4I_I2S_FMT1_REG_SEXT(sext));
|
||||
+}
|
||||
+
|
||||
+static void sun8i_i2s_set_fmt_sext(const struct sun4i_i2s *i2s,
|
||||
+ unsigned int sext)
|
||||
+{
|
||||
+ regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
|
||||
+ SUN8I_I2S_FMT1_REG_SEXT_MASK,
|
||||
+ SUN8I_I2S_FMT1_REG_SEXT(sext));
|
||||
+}
|
||||
+
|
||||
static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
|
||||
@@ -717,9 +996,9 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s)
|
||||
{
|
||||
/* Flush RX FIFO */
|
||||
- regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
|
||||
- SUN4I_I2S_FIFO_CTRL_FLUSH_RX,
|
||||
- SUN4I_I2S_FIFO_CTRL_FLUSH_RX);
|
||||
+ regmap_write_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
|
||||
+ SUN4I_I2S_FIFO_CTRL_FLUSH_RX,
|
||||
+ SUN4I_I2S_FIFO_CTRL_FLUSH_RX);
|
||||
|
||||
/* Clear RX counter */
|
||||
regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0);
|
||||
@@ -738,9 +1017,9 @@ static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s)
|
||||
static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
|
||||
{
|
||||
/* Flush TX FIFO */
|
||||
- regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
|
||||
- SUN4I_I2S_FIFO_CTRL_FLUSH_TX,
|
||||
- SUN4I_I2S_FIFO_CTRL_FLUSH_TX);
|
||||
+ regmap_write_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
|
||||
+ SUN4I_I2S_FIFO_CTRL_FLUSH_TX,
|
||||
+ SUN4I_I2S_FIFO_CTRL_FLUSH_TX);
|
||||
|
||||
/* Clear TX counter */
|
||||
regmap_write(i2s->regmap, SUN4I_I2S_TX_CNT_REG, 0);
|
||||
@@ -862,6 +1141,10 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
|
||||
+ SNDRV_PCM_FMTBIT_S20_LE | \
|
||||
+ SNDRV_PCM_FMTBIT_S24_LE)
|
||||
+
|
||||
static struct snd_soc_dai_driver sun4i_i2s_dai = {
|
||||
.probe = sun4i_i2s_dai_probe,
|
||||
.capture = {
|
||||
@@ -869,14 +1152,14 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = {
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
+ .formats = SUN4I_FORMATS,
|
||||
},
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 8,
|
||||
.rates = SNDRV_PCM_RATE_8000_192000,
|
||||
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
|
||||
+ .formats = SUN4I_FORMATS,
|
||||
},
|
||||
.ops = &sun4i_i2s_dai_ops,
|
||||
.symmetric_rates = 1,
|
||||
@@ -971,6 +1254,22 @@ static const struct reg_default sun8i_i2s_reg_defaults[] = {
|
||||
{ SUN8I_I2S_RX_CHAN_MAP_REG, 0x00000000 },
|
||||
};
|
||||
|
||||
+static const struct reg_default sun50i_i2s_reg_defaults[] = {
|
||||
+ { SUN4I_I2S_CTRL_REG, 0x00060000 },
|
||||
+ { SUN4I_I2S_FMT0_REG, 0x00000033 },
|
||||
+ { SUN4I_I2S_FMT1_REG, 0x00000030 },
|
||||
+ { SUN4I_I2S_FIFO_CTRL_REG, 0x000400f0 },
|
||||
+ { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 },
|
||||
+ { SUN4I_I2S_CLK_DIV_REG, 0x00000000 },
|
||||
+ { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 },
|
||||
+ { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 },
|
||||
+ { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 },
|
||||
+ { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 },
|
||||
+ { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 },
|
||||
+ { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 },
|
||||
+ { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 },
|
||||
+};
|
||||
+
|
||||
static const struct regmap_config sun4i_i2s_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
@@ -998,6 +1297,19 @@ static const struct regmap_config sun8i_i2s_regmap_config = {
|
||||
.volatile_reg = sun8i_i2s_volatile_reg,
|
||||
};
|
||||
|
||||
+static const struct regmap_config sun50i_i2s_regmap_config = {
|
||||
+ .reg_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .val_bits = 32,
|
||||
+ .max_register = SUN50I_H6_I2S_RX_CHAN_MAP1_REG,
|
||||
+ .cache_type = REGCACHE_FLAT,
|
||||
+ .reg_defaults = sun50i_i2s_reg_defaults,
|
||||
+ .num_reg_defaults = ARRAY_SIZE(sun50i_i2s_reg_defaults),
|
||||
+ .writeable_reg = sun4i_i2s_wr_reg,
|
||||
+ .readable_reg = sun8i_i2s_rd_reg,
|
||||
+ .volatile_reg = sun8i_i2s_volatile_reg,
|
||||
+};
|
||||
+
|
||||
static int sun4i_i2s_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct sun4i_i2s *i2s = dev_get_drvdata(dev);
|
||||
@@ -1077,6 +1389,11 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = {
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
.set_chan_cfg = sun4i_i2s_set_chan_cfg,
|
||||
.set_fmt = sun4i_i2s_set_soc_fmt,
|
||||
+ .set_fmt_sext = sun4i_i2s_set_fmt_sext,
|
||||
+ .set_txchansel = sun4i_i2s_set_txchansel,
|
||||
+ .set_rxchansel = sun4i_i2s_set_rxchansel,
|
||||
+ .set_txchanmap = sun4i_i2s_set_txchanmap,
|
||||
+ .set_rxchanmap = sun4i_i2s_set_rxchanmap,
|
||||
};
|
||||
|
||||
static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
|
||||
@@ -1095,6 +1412,11 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = {
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
.set_chan_cfg = sun4i_i2s_set_chan_cfg,
|
||||
.set_fmt = sun4i_i2s_set_soc_fmt,
|
||||
+ .set_fmt_sext = sun4i_i2s_set_fmt_sext,
|
||||
+ .set_txchansel = sun4i_i2s_set_txchansel,
|
||||
+ .set_rxchansel = sun4i_i2s_set_rxchansel,
|
||||
+ .set_txchanmap = sun4i_i2s_set_txchanmap,
|
||||
+ .set_rxchanmap = sun4i_i2s_set_rxchanmap,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1118,6 +1440,9 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = {
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
.set_chan_cfg = sun4i_i2s_set_chan_cfg,
|
||||
.set_fmt = sun4i_i2s_set_soc_fmt,
|
||||
+ .set_fmt_sext = sun4i_i2s_set_fmt_sext,
|
||||
+ .set_txchansel = sun4i_i2s_set_txchansel,
|
||||
+ .set_rxchansel = sun4i_i2s_set_rxchansel,
|
||||
};
|
||||
|
||||
static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
|
||||
@@ -1136,6 +1461,15 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = {
|
||||
.get_wss = sun8i_i2s_get_sr_wss,
|
||||
.set_chan_cfg = sun8i_i2s_set_chan_cfg,
|
||||
.set_fmt = sun8i_i2s_set_soc_fmt,
|
||||
+ .set_fmt_sext = sun8i_i2s_set_fmt_sext,
|
||||
+ .set_txchanoffset = sun8i_i2s_set_txchanoffset,
|
||||
+ .set_rxchanoffset = sun8i_i2s_set_rxchanoffset,
|
||||
+ .set_txchanen = sun8i_i2s_set_txchanen,
|
||||
+ .set_rxchanen = sun8i_i2s_set_rxchanen,
|
||||
+ .set_txchansel = sun8i_i2s_set_txchansel,
|
||||
+ .set_rxchansel = sun8i_i2s_set_rxchansel,
|
||||
+ .set_txchanmap = sun8i_i2s_set_txchanmap,
|
||||
+ .set_rxchanmap = sun8i_i2s_set_rxchanmap,
|
||||
};
|
||||
|
||||
static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
|
||||
@@ -1154,6 +1488,38 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = {
|
||||
.get_wss = sun4i_i2s_get_wss,
|
||||
.set_chan_cfg = sun4i_i2s_set_chan_cfg,
|
||||
.set_fmt = sun4i_i2s_set_soc_fmt,
|
||||
+ .set_fmt_sext = sun4i_i2s_set_fmt_sext,
|
||||
+ .set_txchansel = sun4i_i2s_set_txchansel,
|
||||
+ .set_rxchansel = sun4i_i2s_set_rxchansel,
|
||||
+ .set_txchanmap = sun4i_i2s_set_txchanmap,
|
||||
+ .set_rxchanmap = sun4i_i2s_set_rxchanmap,
|
||||
+};
|
||||
+
|
||||
+static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = {
|
||||
+ .has_reset = true,
|
||||
+ .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG,
|
||||
+ .sun4i_i2s_regmap = &sun50i_i2s_regmap_config,
|
||||
+ .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8),
|
||||
+ .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2),
|
||||
+ .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6),
|
||||
+ .bclk_dividers = sun8i_i2s_clk_div,
|
||||
+ .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
|
||||
+ .mclk_dividers = sun8i_i2s_clk_div,
|
||||
+ .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div),
|
||||
+ .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate,
|
||||
+ .get_sr = sun8i_i2s_get_sr_wss,
|
||||
+ .get_wss = sun8i_i2s_get_sr_wss,
|
||||
+ .set_chan_cfg = sun8i_i2s_set_chan_cfg,
|
||||
+ .set_fmt = sun8i_i2s_set_soc_fmt,
|
||||
+ .set_fmt_sext = sun8i_i2s_set_fmt_sext,
|
||||
+ .set_txchanoffset = sun50i_h6_i2s_set_txchanoffset,
|
||||
+ .set_rxchanoffset = sun50i_h6_i2s_set_rxchanoffset,
|
||||
+ .set_txchanen = sun50i_h6_i2s_set_txchanen,
|
||||
+ .set_rxchanen = sun50i_h6_i2s_set_rxchanen,
|
||||
+ .set_txchansel = sun50i_h6_i2s_set_txchansel,
|
||||
+ .set_rxchansel = sun50i_h6_i2s_set_rxchansel,
|
||||
+ .set_txchanmap = sun50i_h6_i2s_set_txchanmap,
|
||||
+ .set_rxchanmap = sun50i_h6_i2s_set_rxchanmap,
|
||||
};
|
||||
|
||||
static int sun4i_i2s_init_regmap_fields(struct device *dev,
|
||||
@@ -1325,6 +1691,10 @@ static const struct of_device_id sun4i_i2s_match[] = {
|
||||
.compatible = "allwinner,sun50i-a64-codec-i2s",
|
||||
.data = &sun50i_a64_codec_i2s_quirks,
|
||||
},
|
||||
+ {
|
||||
+ .compatible = "allwinner,sun50i-h6-i2s",
|
||||
+ .data = &sun50i_h6_i2s_quirks,
|
||||
+ },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sun4i_i2s_match);
|
||||
--
|
||||
2.23.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user