* [PATCH 02/10] ASoC: sunxi: Add support for A23/A33/H3 codec's analog path controls
From: Chen-Yu Tsai @ 2016-11-12 6:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161112064648.26779-1-wens@csie.org>
The internal codec on A23/A33/H3 is split into 2 parts. The
analog path controls are routed through an embedded custom register
bus accessed through the PRCM block.
The SoCs share a common set of inputs, outputs, and audio paths.
The following table lists the differences.
----------------------------------------
| Feature \ SoC | A23 | A33 | H3 |
----------------------------------------
| Headphone | v | v | |
----------------------------------------
| Line Out | | | v |
----------------------------------------
| Phone In/Out | v | v | |
----------------------------------------
Add an ASoC component driver for it. This should be tied to the codec
audio card as an auxiliary device. This patch adds the commont paths
and controls, and variant specific headphone out and line out.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
sound/soc/sunxi/Kconfig | 8 +
sound/soc/sunxi/Makefile | 1 +
sound/soc/sunxi/sun8i-codec-analog.c | 665 +++++++++++++++++++++++++++++++++++
3 files changed, 674 insertions(+)
create mode 100644 sound/soc/sunxi/sun8i-codec-analog.c
diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
index dd2368297fd3..6c344e16aca4 100644
--- a/sound/soc/sunxi/Kconfig
+++ b/sound/soc/sunxi/Kconfig
@@ -9,6 +9,14 @@ config SND_SUN4I_CODEC
Select Y or M to add support for the Codec embedded in the Allwinner
A10 and affiliated SoCs.
+config SND_SUN8I_CODEC_ANALOG
+ tristate "Allwinner sun8i Codec Analog Controls Support"
+ depends on MACH_SUN8I || COMPILE_TEST
+ select REGMAP
+ help
+ Say Y or M if you want to add support for the analog controls for
+ the codec embedded in newer Allwinner SoCs.
+
config SND_SUN4I_I2S
tristate "Allwinner A10 I2S Support"
select SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
index 604c7b842837..241c0df9ca0c 100644
--- a/sound/soc/sunxi/Makefile
+++ b/sound/soc/sunxi/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
+obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c
new file mode 100644
index 000000000000..222bbd440b1e
--- /dev/null
+++ b/sound/soc/sunxi/sun8i-codec-analog.c
@@ -0,0 +1,665 @@
+/*
+ * This driver supports the analog controls for the internal codec
+ * found in Allwinner's A31s, A23, A33 and H3 SoCs.
+ *
+ * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+/* Codec analog control register offsets and bit fields */
+#define SUN8I_ADDA_HP_VOLC 0x00
+#define SUN8I_ADDA_HP_VOLC_PA_CLK_GATE 7
+#define SUN8I_ADDA_HP_VOLC_HP_VOL 0
+#define SUN8I_ADDA_LOMIXSC 0x01
+#define SUN8I_ADDA_LOMIXSC_MIC1 6
+#define SUN8I_ADDA_LOMIXSC_MIC2 5
+#define SUN8I_ADDA_LOMIXSC_PHONE 4
+#define SUN8I_ADDA_LOMIXSC_PHONEN 3
+#define SUN8I_ADDA_LOMIXSC_LINEINL 2
+#define SUN8I_ADDA_LOMIXSC_DACL 1
+#define SUN8I_ADDA_LOMIXSC_DACR 0
+#define SUN8I_ADDA_ROMIXSC 0x02
+#define SUN8I_ADDA_ROMIXSC_MIC1 6
+#define SUN8I_ADDA_ROMIXSC_MIC2 5
+#define SUN8I_ADDA_ROMIXSC_PHONE 4
+#define SUN8I_ADDA_ROMIXSC_PHONEP 3
+#define SUN8I_ADDA_ROMIXSC_LINEINR 2
+#define SUN8I_ADDA_ROMIXSC_DACR 1
+#define SUN8I_ADDA_ROMIXSC_DACL 0
+#define SUN8I_ADDA_DAC_PA_SRC 0x03
+#define SUN8I_ADDA_DAC_PA_SRC_DACAREN 7
+#define SUN8I_ADDA_DAC_PA_SRC_DACALEN 6
+#define SUN8I_ADDA_DAC_PA_SRC_RMIXEN 5
+#define SUN8I_ADDA_DAC_PA_SRC_LMIXEN 4
+#define SUN8I_ADDA_DAC_PA_SRC_RHPPAMUTE 3
+#define SUN8I_ADDA_DAC_PA_SRC_LHPPAMUTE 2
+#define SUN8I_ADDA_DAC_PA_SRC_RHPIS 1
+#define SUN8I_ADDA_DAC_PA_SRC_LHPIS 0
+#define SUN8I_ADDA_PHONEIN_GCTRL 0x04
+#define SUN8I_ADDA_PHONEIN_GCTRL_PHONEPG 4
+#define SUN8I_ADDA_PHONEIN_GCTRL_PHONENG 0
+#define SUN8I_ADDA_LINEIN_GCTRL 0x05
+#define SUN8I_ADDA_LINEIN_GCTRL_LINEING 4
+#define SUN8I_ADDA_LINEIN_GCTRL_PHONEG 0
+#define SUN8I_ADDA_MICIN_GCTRL 0x06
+#define SUN8I_ADDA_MICIN_GCTRL_MIC1G 4
+#define SUN8I_ADDA_MICIN_GCTRL_MIC2G 0
+#define SUN8I_ADDA_PAEN_HP_CTRL 0x07
+#define SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN 7
+#define SUN8I_ADDA_PAEN_HP_CTRL_LINEOUTEN 7 /* H3 specific */
+#define SUN8I_ADDA_PAEN_HP_CTRL_HPCOM_FC 5
+#define SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN 4
+#define SUN8I_ADDA_PAEN_HP_CTRL_PA_ANTI_POP_CTRL 2
+#define SUN8I_ADDA_PAEN_HP_CTRL_LTRNMUTE 1
+#define SUN8I_ADDA_PAEN_HP_CTRL_RTLNMUTE 0
+#define SUN8I_ADDA_PHONEOUT_CTRL 0x08
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTG 5
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUTEN 4
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_MIC1 3
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_MIC2 2
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_RMIX 1
+#define SUN8I_ADDA_PHONEOUT_CTRL_PHONEOUT_LMIX 0
+#define SUN8I_ADDA_PHONE_GAIN_CTRL 0x09
+#define SUN8I_ADDA_PHONE_GAIN_CTRL_LINEOUT_VOL 3
+#define SUN8I_ADDA_PHONE_GAIN_CTRL_PHONEPREG 0
+#define SUN8I_ADDA_MIC2G_CTRL 0x0a
+#define SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN 7
+#define SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST 4
+#define SUN8I_ADDA_MIC2G_CTRL_LINEOUTLEN 3
+#define SUN8I_ADDA_MIC2G_CTRL_LINEOUTREN 2
+#define SUN8I_ADDA_MIC2G_CTRL_LINEOUTLSRC 1
+#define SUN8I_ADDA_MIC2G_CTRL_LINEOUTRSRC 0
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL 0x0b
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIASEN 7
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN 6
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIAS_MODE 5
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN 3
+#define SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1BOOST 0
+#define SUN8I_ADDA_LADCMIXSC 0x0c
+#define SUN8I_ADDA_LADCMIXSC_MIC1 6
+#define SUN8I_ADDA_LADCMIXSC_MIC2 5
+#define SUN8I_ADDA_LADCMIXSC_PHONE 4
+#define SUN8I_ADDA_LADCMIXSC_PHONEN 3
+#define SUN8I_ADDA_LADCMIXSC_LINEINL 2
+#define SUN8I_ADDA_LADCMIXSC_OMIXRL 1
+#define SUN8I_ADDA_LADCMIXSC_OMIXRR 0
+#define SUN8I_ADDA_RADCMIXSC 0x0d
+#define SUN8I_ADDA_RADCMIXSC_MIC1 6
+#define SUN8I_ADDA_RADCMIXSC_MIC2 5
+#define SUN8I_ADDA_RADCMIXSC_PHONE 4
+#define SUN8I_ADDA_RADCMIXSC_PHONEP 3
+#define SUN8I_ADDA_RADCMIXSC_LINEINR 2
+#define SUN8I_ADDA_RADCMIXSC_OMIXR 1
+#define SUN8I_ADDA_RADCMIXSC_OMIXL 0
+#define SUN8I_ADDA_RES 0x0e
+#define SUN8I_ADDA_RES_MMICBIAS_SEL 4
+#define SUN8I_ADDA_RES_PA_ANTI_POP_CTRL 0
+#define SUN8I_ADDA_ADC_AP_EN 0x0f
+#define SUN8I_ADDA_ADC_AP_EN_ADCREN 7
+#define SUN8I_ADDA_ADC_AP_EN_ADCLEN 6
+#define SUN8I_ADDA_ADC_AP_EN_ADCG 0
+
+/* Analog control register access bits */
+#define ADDA_PR 0x0 /* PRCM base + 0x1c0 */
+#define ADDA_PR_RESET BIT(28)
+#define ADDA_PR_WRITE BIT(24)
+#define ADDA_PR_ADDR_SHIFT 16
+#define ADDA_PR_ADDR_MASK GENMASK(4, 0)
+#define ADDA_PR_DATA_IN_SHIFT 8
+#define ADDA_PR_DATA_IN_MASK GENMASK(7, 0)
+#define ADDA_PR_DATA_OUT_SHIFT 0
+#define ADDA_PR_DATA_OUT_MASK GENMASK(7, 0)
+
+/* regmap access bits */
+static int adda_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ void __iomem *base = (void __iomem *)context;
+ u32 tmp;
+
+ /* De-assert reset */
+ writel(readl(base) | ADDA_PR_RESET, base);
+
+ /* Clear write bit */
+ writel(readl(base) & ~ADDA_PR_WRITE, base);
+
+ /* Set register address */
+ tmp = readl(base);
+ tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT);
+ tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT;
+ writel(tmp, base);
+
+ /* Read back value */
+ *val = readl(base) & ADDA_PR_DATA_OUT_MASK;
+
+ return 0;
+}
+
+static int adda_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ void __iomem *base = (void __iomem *)context;
+ u32 tmp;
+
+ /* De-assert reset */
+ writel(readl(base) | ADDA_PR_RESET, base);
+
+ /* Set register address */
+ tmp = readl(base);
+ tmp &= ~(ADDA_PR_ADDR_MASK << ADDA_PR_ADDR_SHIFT);
+ tmp |= (reg & ADDA_PR_ADDR_MASK) << ADDA_PR_ADDR_SHIFT;
+ writel(tmp, base);
+
+ /* Set data to write */
+ tmp = readl(base);
+ tmp &= ~(ADDA_PR_DATA_IN_MASK << ADDA_PR_DATA_IN_SHIFT);
+ tmp |= (val & ADDA_PR_DATA_IN_MASK) << ADDA_PR_DATA_IN_SHIFT;
+ writel(tmp, base);
+
+ /* Set write bit to signal a write */
+ writel(readl(base) | ADDA_PR_WRITE, base);
+
+ /* Clear write bit */
+ writel(readl(base) & ~ADDA_PR_WRITE, base);
+
+ return 0;
+}
+
+static const struct regmap_config adda_pr_regmap_cfg = {
+ .name = "adda-pr",
+ .reg_bits = 5,
+ .reg_stride = 1,
+ .val_bits = 8,
+ .reg_read = adda_reg_read,
+ .reg_write = adda_reg_write,
+ .fast_io = true,
+ .max_register = 24,
+};
+
+/* mixer controls */
+static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = {
+ SOC_DAPM_DOUBLE_R("DAC Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_LOMIXSC_DACL, 1, 0),
+ SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_LOMIXSC_DACR, 1, 0),
+ SOC_DAPM_DOUBLE_R("Line In Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_LOMIXSC_LINEINL, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mic1 Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_LOMIXSC_MIC1, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mic2 Playback Switch",
+ SUN8I_ADDA_LOMIXSC,
+ SUN8I_ADDA_ROMIXSC,
+ SUN8I_ADDA_LOMIXSC_MIC2, 1, 0),
+};
+
+/* ADC mixer controls */
+static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = {
+ SOC_DAPM_DOUBLE_R("Mixer Capture Switch",
+ SUN8I_ADDA_LADCMIXSC,
+ SUN8I_ADDA_RADCMIXSC,
+ SUN8I_ADDA_LADCMIXSC_OMIXRL, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch",
+ SUN8I_ADDA_LADCMIXSC,
+ SUN8I_ADDA_RADCMIXSC,
+ SUN8I_ADDA_LADCMIXSC_OMIXRR, 1, 0),
+ SOC_DAPM_DOUBLE_R("Line In Capture Switch",
+ SUN8I_ADDA_LADCMIXSC,
+ SUN8I_ADDA_RADCMIXSC,
+ SUN8I_ADDA_LADCMIXSC_LINEINL, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mic1 Capture Switch",
+ SUN8I_ADDA_LADCMIXSC,
+ SUN8I_ADDA_RADCMIXSC,
+ SUN8I_ADDA_LADCMIXSC_MIC1, 1, 0),
+ SOC_DAPM_DOUBLE_R("Mic2 Capture Switch",
+ SUN8I_ADDA_LADCMIXSC,
+ SUN8I_ADDA_RADCMIXSC,
+ SUN8I_ADDA_LADCMIXSC_MIC2, 1, 0),
+};
+
+/* volume / mute controls */
+static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale,
+ -450, 150, 0);
+static const DECLARE_TLV_DB_RANGE(sun8i_codec_mic_gain_scale,
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
+);
+
+static const struct snd_kcontrol_new sun8i_codec_common_controls[] = {
+ /* Mixer pre-gains */
+ SOC_SINGLE_TLV("Line In Playback Volume", SUN8I_ADDA_LINEIN_GCTRL,
+ SUN8I_ADDA_LINEIN_GCTRL_LINEING,
+ 0x7, 0, sun8i_codec_out_mixer_pregain_scale),
+ SOC_SINGLE_TLV("Mic1 Playback Volume", SUN8I_ADDA_MICIN_GCTRL,
+ SUN8I_ADDA_MICIN_GCTRL_MIC1G,
+ 0x7, 0, sun8i_codec_out_mixer_pregain_scale),
+ SOC_SINGLE_TLV("Mic2 Playback Volume",
+ SUN8I_ADDA_MICIN_GCTRL, SUN8I_ADDA_MICIN_GCTRL_MIC2G,
+ 0x7, 0, sun8i_codec_out_mixer_pregain_scale),
+
+ /* Microphone Amp boost gains */
+ SOC_SINGLE_TLV("Mic1 Boost Volume", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
+ SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1BOOST, 0x7, 0,
+ sun8i_codec_mic_gain_scale),
+ SOC_SINGLE_TLV("Mic2 Boost Volume", SUN8I_ADDA_MIC2G_CTRL,
+ SUN8I_ADDA_MIC2G_CTRL_MIC2BOOST, 0x7, 0,
+ sun8i_codec_mic_gain_scale),
+
+ /* ADC */
+ SOC_SINGLE_TLV("ADC Gain Capture Volume", SUN8I_ADDA_ADC_AP_EN,
+ SUN8I_ADDA_ADC_AP_EN_ADCG, 0x7, 0,
+ sun8i_codec_out_mixer_pregain_scale),
+};
+
+static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = {
+ /* ADC */
+ SND_SOC_DAPM_ADC("Left ADC", NULL, SUN8I_ADDA_ADC_AP_EN,
+ SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0),
+ SND_SOC_DAPM_ADC("Right ADC", NULL, SUN8I_ADDA_ADC_AP_EN,
+ SUN8I_ADDA_ADC_AP_EN_ADCREN, 0),
+
+ /* DAC */
+ SND_SOC_DAPM_DAC("Left DAC", NULL, SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_DACALEN, 0),
+ SND_SOC_DAPM_DAC("Right DAC", NULL, SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_DACAREN, 0),
+ /*
+ * Due to this component and the codec belonging to separate DAPM
+ * contexts, we need to manually link the above widgets to their
+ * stream widgets@the card level.
+ */
+
+ /* Line In */
+ SND_SOC_DAPM_INPUT("LINEIN"),
+
+ /* Microphone inputs */
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+
+ /* Microphone Bias */
+ SND_SOC_DAPM_SUPPLY("MBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
+ SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MMICBIASEN,
+ 0, NULL, 0),
+
+ /* Mic input path */
+ SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
+ SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN8I_ADDA_MIC2G_CTRL,
+ SUN8I_ADDA_MIC2G_CTRL_MIC2AMPEN, 0, NULL, 0),
+
+ /* Mixers */
+ SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0,
+ sun8i_codec_mixer_controls,
+ ARRAY_SIZE(sun8i_codec_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right Mixer", SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_RMIXEN, 0,
+ sun8i_codec_mixer_controls,
+ ARRAY_SIZE(sun8i_codec_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN8I_ADDA_ADC_AP_EN,
+ SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0,
+ sun8i_codec_adc_mixer_controls,
+ ARRAY_SIZE(sun8i_codec_adc_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN8I_ADDA_ADC_AP_EN,
+ SUN8I_ADDA_ADC_AP_EN_ADCREN, 0,
+ sun8i_codec_adc_mixer_controls,
+ ARRAY_SIZE(sun8i_codec_adc_mixer_controls)),
+};
+
+static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = {
+ /* Microphone Routes */
+ { "Mic1 Amplifier", NULL, "MIC1"},
+ { "Mic2 Amplifier", NULL, "MIC2"},
+
+ /* Left Mixer Routes */
+ { "Left Mixer", "DAC Playback Switch", "Left DAC" },
+ { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" },
+ { "Left Mixer", "Line In Playback Switch", "LINEIN" },
+ { "Left Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
+ { "Left Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
+
+ /* Right Mixer Routes */
+ { "Right Mixer", "DAC Playback Switch", "Right DAC" },
+ { "Right Mixer", "DAC Reversed Playback Switch", "Left DAC" },
+ { "Right Mixer", "Line In Playback Switch", "LINEIN" },
+ { "Right Mixer", "Mic1 Playback Switch", "Mic1 Amplifier" },
+ { "Right Mixer", "Mic2 Playback Switch", "Mic2 Amplifier" },
+
+ /* Left ADC Mixer Routes */
+ { "Left ADC Mixer", "Mixer Capture Switch", "Left Mixer" },
+ { "Left ADC Mixer", "Mixer Reversed Capture Switch", "Right Mixer" },
+ { "Left ADC Mixer", "Line In Capture Switch", "LINEIN" },
+ { "Left ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
+ { "Left ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
+
+ /* Right ADC Mixer Routes */
+ { "Right ADC Mixer", "Mixer Capture Switch", "Right Mixer" },
+ { "Right ADC Mixer", "Mixer Reversed Capture Switch", "Left Mixer" },
+ { "Right ADC Mixer", "Line In Capture Switch", "LINEIN" },
+ { "Right ADC Mixer", "Mic1 Capture Switch", "Mic1 Amplifier" },
+ { "Right ADC Mixer", "Mic2 Capture Switch", "Mic2 Amplifier" },
+
+ /* ADC Routes */
+ { "Left ADC", NULL, "Left ADC Mixer" },
+ { "Right ADC", NULL, "Right ADC Mixer" },
+};
+
+/* headphone specific controls, widgets, and routes */
+static const DECLARE_TLV_DB_SCALE(sun8i_codec_hp_vol_scale, -6300, 100, 1);
+static const struct snd_kcontrol_new sun8i_codec_headphone_controls[] = {
+ SOC_SINGLE_TLV("Headphone Playback Volume",
+ SUN8I_ADDA_HP_VOLC,
+ SUN8I_ADDA_HP_VOLC_HP_VOL, 0x3f, 0,
+ sun8i_codec_hp_vol_scale),
+ SOC_DOUBLE("Headphone Playback Switch",
+ SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_LHPPAMUTE,
+ SUN8I_ADDA_DAC_PA_SRC_RHPPAMUTE, 1, 0),
+};
+
+static const char * const sun8i_codec_hp_src_enum_text[] = {
+ "DAC", "Mixer",
+};
+
+static SOC_ENUM_DOUBLE_DECL(sun8i_codec_hp_src_enum,
+ SUN8I_ADDA_DAC_PA_SRC,
+ SUN8I_ADDA_DAC_PA_SRC_LHPIS,
+ SUN8I_ADDA_DAC_PA_SRC_RHPIS,
+ sun8i_codec_hp_src_enum_text);
+
+static const struct snd_kcontrol_new sun8i_codec_hp_src[] = {
+ SOC_DAPM_ENUM("Headphone Source Playback Route",
+ sun8i_codec_hp_src_enum),
+};
+
+static const struct snd_soc_dapm_widget sun8i_codec_headphone_widgets[] = {
+ SND_SOC_DAPM_MUX("Headphone Source Playback Route",
+ SND_SOC_NOPM, 0, 0, sun8i_codec_hp_src),
+ SND_SOC_DAPM_OUT_DRV("Headphone Amp", SUN8I_ADDA_PAEN_HP_CTRL,
+ SUN8I_ADDA_PAEN_HP_CTRL_HPPAEN, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HPCOM Protection", SUN8I_ADDA_PAEN_HP_CTRL,
+ SUN8I_ADDA_PAEN_HP_CTRL_COMPTEN, 0, NULL, 0),
+ SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPCOM", SUN8I_ADDA_PAEN_HP_CTRL,
+ SUN8I_ADDA_PAEN_HP_CTRL_HPCOM_FC, 0x3, 0x3, 0),
+ SND_SOC_DAPM_OUTPUT("HP"),
+};
+
+static const struct snd_soc_dapm_route sun8i_codec_headphone_routes[] = {
+ { "Headphone Source Playback Route", "DAC", "Left DAC" },
+ { "Headphone Source Playback Route", "DAC", "Right DAC" },
+ { "Headphone Source Playback Route", "Mixer", "Left Mixer" },
+ { "Headphone Source Playback Route", "Mixer", "Right Mixer" },
+ { "Headphone Amp", NULL, "Headphone Source Playback Route" },
+ { "HPCOM", NULL, "HPCOM Protection" },
+ { "HP", NULL, "Headphone Amp" },
+};
+
+static int sun8i_codec_add_headphone(struct snd_soc_component *cmpnt)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
+ struct device *dev = cmpnt->dev;
+ int ret;
+
+ ret = snd_soc_add_component_controls(cmpnt,
+ sun8i_codec_headphone_controls,
+ ARRAY_SIZE(sun8i_codec_headphone_controls));
+ if (ret) {
+ dev_err(dev, "Failed to add Headphone controls: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_headphone_widgets,
+ ARRAY_SIZE(sun8i_codec_headphone_widgets));
+ if (ret) {
+ dev_err(dev, "Failed to add Headphone DAPM widgets: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_headphone_routes,
+ ARRAY_SIZE(sun8i_codec_headphone_routes));
+ if (ret) {
+ dev_err(dev, "Failed to add Headphone DAPM routes: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* hmic specific widget */
+static const struct snd_soc_dapm_widget sun8i_codec_hmic_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("HBIAS", SUN8I_ADDA_MIC1G_MICBIAS_CTRL,
+ SUN8I_ADDA_MIC1G_MICBIAS_CTRL_HMICBIASEN,
+ 0, NULL, 0),
+};
+
+static int sun8i_codec_add_hmic(struct snd_soc_component *cmpnt)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
+ struct device *dev = cmpnt->dev;
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_hmic_widgets,
+ ARRAY_SIZE(sun8i_codec_hmic_widgets));
+ if (ret)
+ dev_err(dev, "Failed to add Mic3 DAPM widgets: %d\n", ret);
+
+ return ret;
+}
+
+/* line out specific controls, widgets and routes */
+static const DECLARE_TLV_DB_RANGE(sun8i_codec_lineout_vol_scale,
+ 0, 1, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+ 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
+);
+static const struct snd_kcontrol_new sun8i_codec_lineout_controls[] = {
+ SOC_SINGLE_TLV("Line Out Playback Volume",
+ SUN8I_ADDA_PHONE_GAIN_CTRL,
+ SUN8I_ADDA_PHONE_GAIN_CTRL_LINEOUT_VOL, 0x1f, 0,
+ sun8i_codec_lineout_vol_scale),
+ SOC_DOUBLE("Line Out Playback Switch",
+ SUN8I_ADDA_MIC2G_CTRL,
+ SUN8I_ADDA_MIC2G_CTRL_LINEOUTLEN,
+ SUN8I_ADDA_MIC2G_CTRL_LINEOUTREN, 1, 0),
+};
+
+static const char * const sun8i_codec_lineout_src_enum_text[] = {
+ "Stereo", "Mono Differential",
+};
+
+static SOC_ENUM_DOUBLE_DECL(sun8i_codec_lineout_src_enum,
+ SUN8I_ADDA_MIC2G_CTRL,
+ SUN8I_ADDA_MIC2G_CTRL_LINEOUTLSRC,
+ SUN8I_ADDA_MIC2G_CTRL_LINEOUTRSRC,
+ sun8i_codec_lineout_src_enum_text);
+
+static const struct snd_kcontrol_new sun8i_codec_lineout_src[] = {
+ SOC_DAPM_ENUM("Line Out Source Playback Route",
+ sun8i_codec_lineout_src_enum),
+};
+
+static const struct snd_soc_dapm_widget sun8i_codec_lineout_widgets[] = {
+ SND_SOC_DAPM_MUX("Line Out Source Playback Route",
+ SND_SOC_NOPM, 0, 0, sun8i_codec_lineout_src),
+ /* It is unclear if this is a buffer or gate, model it as a supply */
+ SND_SOC_DAPM_SUPPLY("Line Out Enable", SUN8I_ADDA_PAEN_HP_CTRL,
+ SUN8I_ADDA_PAEN_HP_CTRL_LINEOUTEN, 0, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("LINEOUT"),
+};
+
+static const struct snd_soc_dapm_route sun8i_codec_lineout_routes[] = {
+ { "Line Out Source Playback Route", "Stereo", "Left Mixer" },
+ { "Line Out Source Playback Route", "Stereo", "Right Mixer" },
+ { "Line Out Source Playback Route", "Mono Differential", "Left Mixer" },
+ { "Line Out Source Playback Route", "Mono Differential", "Right Mixer" },
+ { "LINEOUT", NULL, "Line Out Source Playback Route" },
+ { "LINEOUT", NULL, "Line Out Enable", },
+};
+
+static int sun8i_codec_add_lineout(struct snd_soc_component *cmpnt)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt);
+ struct device *dev = cmpnt->dev;
+ int ret;
+
+ ret = snd_soc_add_component_controls(cmpnt,
+ sun8i_codec_lineout_controls,
+ ARRAY_SIZE(sun8i_codec_lineout_controls));
+ if (ret) {
+ dev_err(dev, "Failed to add Line Out controls: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_lineout_widgets,
+ ARRAY_SIZE(sun8i_codec_lineout_widgets));
+ if (ret) {
+ dev_err(dev, "Failed to add Line Out DAPM widgets: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_lineout_routes,
+ ARRAY_SIZE(sun8i_codec_lineout_routes));
+ if (ret) {
+ dev_err(dev, "Failed to add Line Out DAPM routes: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+struct sun8i_codec_analog_quirks {
+ bool has_headphone;
+ bool has_hmic;
+ bool has_lineout;
+};
+
+static const struct sun8i_codec_analog_quirks sun8i_a23_quirks = {
+ .has_headphone = true,
+ .has_hmic = true,
+};
+
+static const struct sun8i_codec_analog_quirks sun8i_h3_quirks = {
+ .has_lineout = true,
+};
+
+static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt)
+{
+ struct device *dev = cmpnt->dev;
+ const struct sun8i_codec_analog_quirks *quirks;
+ int ret;
+
+ /*
+ * This would never return NULL unless someone directly registers a
+ * platform device matching this driver's name, without specifying a
+ * device tree node.
+ */
+ quirks = of_device_get_match_data(dev);
+
+ /* Add controls, widgets, and routes for individual features */
+
+ if (quirks->has_headphone) {
+ ret = sun8i_codec_add_headphone(cmpnt);
+ if (ret)
+ return ret;
+ }
+
+ if (quirks->has_hmic) {
+ sun8i_codec_add_hmic(cmpnt);
+ if (ret)
+ return ret;
+ }
+
+ if (quirks->has_lineout) {
+ ret = sun8i_codec_add_lineout(cmpnt);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_component_driver sun8i_codec_analog_cmpnt_drv = {
+ .controls = sun8i_codec_common_controls,
+ .num_controls = ARRAY_SIZE(sun8i_codec_common_controls),
+ .dapm_widgets = sun8i_codec_common_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_common_widgets),
+ .dapm_routes = sun8i_codec_common_routes,
+ .num_dapm_routes = ARRAY_SIZE(sun8i_codec_common_routes),
+ .probe = sun8i_codec_analog_cmpnt_probe,
+};
+
+static const struct of_device_id sun8i_codec_analog_of_match[] = {
+ {
+ .compatible = "allwinner,sun8i-a23-codec-analog",
+ .data = &sun8i_a23_quirks,
+ },
+ {
+ .compatible = "allwinner,sun8i-h3-codec-analog",
+ .data = &sun8i_h3_quirks,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_codec_analog_of_match);
+
+static int sun8i_codec_analog_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct regmap *regmap;
+ void __iomem *base;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base)) {
+ dev_err(&pdev->dev, "Failed to map the registers\n");
+ return PTR_ERR(base);
+ }
+
+ regmap = devm_regmap_init(&pdev->dev, NULL, base, &adda_pr_regmap_cfg);
+ if (IS_ERR(regmap)) {
+ dev_err(&pdev->dev, "Failed to create regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ return devm_snd_soc_register_component(&pdev->dev,
+ &sun8i_codec_analog_cmpnt_drv,
+ NULL, 0);
+}
+
+static struct platform_driver sun8i_codec_analog_driver = {
+ .driver = {
+ .name = "sun8i-codec-analog",
+ .of_match_table = sun8i_codec_analog_of_match,
+ },
+ .probe = sun8i_codec_analog_probe,
+};
+module_platform_driver(sun8i_codec_analog_driver);
+
+MODULE_DESCRIPTION("Allwinner internal codec analog controls driver");
+MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sun8i-codec-analog");
--
2.10.2
^ permalink raw reply related
* [PATCH 01/10] ASoC: sunxi: Add bindings for A23/A33/H3 codec's analog path controls
From: Chen-Yu Tsai @ 2016-11-12 6:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161112064648.26779-1-wens@csie.org>
The internal codec on A23/A33/H3 is split into 2 parts. The
analog path controls are routed through an embedded custom register
bus accessed through the PRCM block.
The SoCs share a common set of inputs, outputs, and audio paths.
The following table lists the differences.
----------------------------------------
| Feature \ SoC | A23 | A33 | H3 |
----------------------------------------
| Headphone | v | v | |
----------------------------------------
| Line Out | | | v |
----------------------------------------
| Phone In/Out | v | v | |
----------------------------------------
Add a binding for this hardware.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
.../devicetree/bindings/sound/sun8i-codec-analog.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
diff --git a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
new file mode 100644
index 000000000000..779b735781ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
@@ -0,0 +1,16 @@
+* Allwinner Codec Analog Controls
+
+Required properties:
+- compatible: must be one of the following compatibles:
+ - "allwinner,sun8i-a23-codec-analog"
+ - "allwinner,sun8i-h3-codec-analog"
+
+Required properties if not a sub-node of the PRCM node:
+- reg: must contain the registers location and length
+
+Example:
+prcm: prcm at 01f01400 {
+ codec_analog: codec-analog {
+ compatible = "allwinner,sun8i-a23-codec-analog";
+ };
+};
--
2.10.2
^ permalink raw reply related
* [PATCH 00/10] ASoC: sunxi: Add support for audio codec in A23/H3 SoCs
From: Chen-Yu Tsai @ 2016-11-12 6:46 UTC (permalink / raw)
To: linux-arm-kernel
Hi everyone,
This series adds support for the audio codec found in Allwinner A23 and
H3 SoCs. The design and data paths are similar to the audio codec found
in earlier SoCs such as the A31. The analog audio paths are symmetrical
with left/right channels and down-mix selectors for mono differential
output.
What deviates from previous SoCs is that the analog path controls have
been moved to a separate control bus, accessed through a message box
like register interface in the PRCM block. This necessitates writing
a separate component driver for it, which is then tied into the sound
card as an ASoC auxiliary device.
Patches 1 and 2 add the binding and driver for the analog path control
block. This is the more complete version. Previously I provided a not
fully tested version to Mylene Josserand from Free Electrons to use
with the A33. Their version was then trimmed down and switched to
SOC_DAPM_SINGLE controls. Mine implements all the commonly used paths,
and uses the new stereo SOC_DAPM_DOUBLE controls. I also have a separate
patch for "Phone In" in case anyone wants to test them. It is not included
as my hardware does not use that input.
As for the A33, the analog controls are exactly the same as the A23, so
this driver can be reused, but the PCM and DAI bits are completely
different.
Patch 3 adds the analog path controls block to the sun6i-prcm driver as
a sub-device, for the A23. The H3 currently does not use the PRCM driver.
Patch 4 adds PCM and card support for the A23 codec to the sun4i-codec
driver.
Patch 5 adds a device node for the analog path controls block to the A23
dtsi.
Patch 6 adds a device node for the audio codec, and the phandle for the
analog path controls block to the A23 dtsi.
Patch 7 enables the audio codec for the A23 Q8 tablets. On these tablets
the headphone output is driven in DC coupled, or "direct drive", mode.
Patch 8 adds PCM and card support for the H3 codec to the sun4i-codec
driver.
Patch 9 adds device nodes for the audio codec and analog path controls
block to the H3 dtsi.
Patch 10 enables the audio codec on the Orange Pi PC. The audio output
jack on the board is tied to the line out pins on the SoC.
Please take a look and let me know what you think.
In addition, the sun4i-codec driver is getting pretty large. Maybe we
want to split the different parts into different files?
Regards
ChenYu
Chen-Yu Tsai (10):
ASoC: sunxi: Add bindings for A23/A33/H3 codec's analog path controls
ASoC: sunxi: Add support for A23/A33/H3 codec's analog path controls
mfd: sun6i-prcm: Add codec analog controls sub-device for Allwinner
A23
ASoC: sun4i-codec: Add support for A23 codec
ARM: dts: sun8i: Add codec analog path controls node in PRCM for
A23/A33
ARM: dts: sun8i-a23: Add device node for internal audio codec
ARM: dts: sun8i-a23: q8-tablet: Enable internal audio codec
ASoC: sun4i-codec: Add support for H3 codec
ARM: dts: sun8i-h3: Add device nodes for audio codec and its analog
controls
ARM: dts: sun8i-h3: orange-pi-pc: Enable audio codec
.../devicetree/bindings/sound/sun4i-codec.txt | 14 +-
.../bindings/sound/sun8i-codec-analog.txt | 16 +
arch/arm/boot/dts/sun8i-a23-a33.dtsi | 4 +
arch/arm/boot/dts/sun8i-a23-q8-tablet.dts | 23 +
arch/arm/boot/dts/sun8i-a23.dtsi | 16 +
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 +
arch/arm/boot/dts/sun8i-h3.dtsi | 19 +
drivers/mfd/sun6i-prcm.c | 17 +
sound/soc/sunxi/Kconfig | 8 +
sound/soc/sunxi/Makefile | 1 +
sound/soc/sunxi/sun4i-codec.c | 179 ++++++
sound/soc/sunxi/sun8i-codec-analog.c | 665 +++++++++++++++++++++
12 files changed, 968 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
create mode 100644 sound/soc/sunxi/sun8i-codec-analog.c
--
2.10.2
^ permalink raw reply
* [PATCH RFC] mm: Add debug_virt_to_phys()
From: Will Deacon @ 2016-11-12 5:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161112004449.30566-1-f.fainelli@gmail.com>
On Fri, Nov 11, 2016 at 04:44:43PM -0800, Florian Fainelli wrote:
> When CONFIG_DEBUG_VM is turned on, virt_to_phys() maps to
> debug_virt_to_phys() which helps catch vmalloc space addresses being
> passed. This is helpful in debugging bogus drivers that just assume
> linear mappings all over the place.
>
> For ARM, ARM64, Unicore32 and Microblaze, the architectures define
> __virt_to_phys() as being the functional implementation of the address
> translation, so we special case the debug stub to call into
> __virt_to_phys directly.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> arch/arm/include/asm/memory.h | 4 ++++
> arch/arm64/include/asm/memory.h | 4 ++++
> include/asm-generic/memory_model.h | 4 ++++
> mm/debug.c | 15 +++++++++++++++
> 4 files changed, 27 insertions(+)
What's the interaction between this and the DEBUG_VIRTUAL patches from Laura?
http://lkml.kernel.org/r/20161102210054.16621-7-labbott at redhat.com
They seem to be tackling the exact same problem afaict.
Will
^ permalink raw reply
* [PATCH] ARM: dts: vfxxx: Enable DMA for DSPI2 and DSPI3
From: maitysanchayan at gmail.com @ 2016-11-12 5:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5BAE=6pE9DMGhXTMm5CeLh+DmhSqGtdSYHf8+yyZkfEVQ@mail.gmail.com>
On 16-11-11 20:46:12, Fabio Estevam wrote:
> On Thu, Nov 10, 2016 at 9:45 AM, Sanchayan Maity
> <maitysanchayan@gmail.com> wrote:
> > Enable DMA for DSPI2 and DSPI3 on Vybrid.
>
> You missed your Signed-off-by line.
Argh...Sorry about that...Will send a follow patch with this fixed.
- Sanchayan.
^ permalink raw reply
* [PATCH v6 4/9] drm/hisilicon/hibmc: Add plane for DE
From: Rongrong Zou @ 2016-11-12 5:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOw6vb+kibtOkViwB4+gEn=+u14esSoNVavhrasNxtrCoWhyJQ@mail.gmail.com>
? 2016/11/11 5:53, Sean Paul ??:
> On Fri, Oct 28, 2016 at 3:27 AM, Rongrong Zou <zourongrong@gmail.com> wrote:
>> Add plane funcs and helper funcs for DE.
>>
>> Signed-off-by: Rongrong Zou <zourongrong@gmail.com>
>> ---
>> drivers/gpu/drm/hisilicon/hibmc/Kconfig | 1 +
>> drivers/gpu/drm/hisilicon/hibmc/Makefile | 2 +-
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 170 ++++++++++++++++++++++++
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h | 29 ++++
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 51 ++++++-
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 5 +
>> drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 6 +
>> 7 files changed, 261 insertions(+), 3 deletions(-)
>> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>>
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> index bcb8c18..380622a 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
>> @@ -1,6 +1,7 @@
>> config DRM_HISI_HIBMC
>> tristate "DRM Support for Hisilicon Hibmc"
>> depends on DRM && PCI
>> + select DRM_KMS_HELPER
>> select DRM_TTM
>>
>> help
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> index 810a37e..72e107e 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
>> @@ -1,5 +1,5 @@
>> ccflags-y := -Iinclude/drm
>> -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
>> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_fbdev.o hibmc_drm_power.o hibmc_ttm.o
>>
>> obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o
>> #obj-y += hibmc-drm.o
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>> new file mode 100644
>> index 0000000..9c1a68c
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
>> @@ -0,0 +1,170 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + * Rongrong Zou <zourongrong@huawei.com>
>> + * Rongrong Zou <zourongrong@gmail.com>
>> + * Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + */
>> +
>> +#include <drm/drm_atomic.h>
>> +#include <drm/drm_atomic_helper.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_plane_helper.h>
>> +
>> +#include "hibmc_drm_drv.h"
>> +#include "hibmc_drm_regs.h"
>> +#include "hibmc_drm_power.h"
>> +
>> +/* ---------------------------------------------------------------------- */
>
> Remove
ok, will do, thanks.
>
>> +
>> +static int hibmc_plane_atomic_check(struct drm_plane *plane,
>> + struct drm_plane_state *state)
>> +{
>> + struct drm_framebuffer *fb = state->fb;
>> + struct drm_crtc *crtc = state->crtc;
>> + struct drm_crtc_state *crtc_state;
>> + u32 src_x = state->src_x >> 16;
>> + u32 src_y = state->src_y >> 16;
>> + u32 src_w = state->src_w >> 16;
>> + u32 src_h = state->src_h >> 16;
>> + int crtc_x = state->crtc_x;
>> + int crtc_y = state->crtc_y;
>> + u32 crtc_w = state->crtc_w;
>> + u32 crtc_h = state->crtc_h;
>
> I don't think you gain anything with the crtc_* vars
It would work well, but looks redundant and not simple enough,
will delete them, thanks.
>
>> +
>> + if (!crtc || !fb)
>> + return 0;
>> +
>> + crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
>> + if (IS_ERR(crtc_state))
>> + return PTR_ERR(crtc_state);
>> +
>> + if (src_w != crtc_w || src_h != crtc_h) {
>> + DRM_ERROR("Scale not support!!!\n");
>
> I like the enthusiasm, but I think DRM_DEBUG_ATOMIC would be better
I'm sorry, can you explain why here should be an DRM_DEBUG_ATOMIC,
when this condition is hit, it is really an error and atomic_commit will
abort with failure.
>
>> + return -EINVAL;
>> + }
>> +
>> + if (src_x + src_w > fb->width ||
>> + src_y + src_h > fb->height)
>
> These should be already covered in drm_atomic_plane_check
understood, thanks.
>
>> + return -EINVAL;
>> +
>> + if (crtc_x < 0 || crtc_y < 0)
>
> Print DRM_DEBUG_ATOMIC message here
agreed. thanks.
>
>> + return -EINVAL;
>> +
>> + if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
>> + crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
>
> DRM_DEBUG_ATOMIC here too
ditto.
>
>> + return -EINVAL;
>> +
>> + return 0;
>> +}
>> +
>> +static void hibmc_plane_atomic_update(struct drm_plane *plane,
>> + struct drm_plane_state *old_state)
>> +{
>> + struct drm_plane_state *state = plane->state;
>> + u32 reg;
>> + int ret;
>> + u64 gpu_addr = 0;
>> + unsigned int line_l;
>> + struct hibmc_drm_device *hidev =
>> + (struct hibmc_drm_device *)plane->dev->dev_private;
>> +
>
> nit: extra line
will delete, thanks.
>> + struct hibmc_framebuffer *hibmc_fb;
>> + struct hibmc_bo *bo;
>> +
>> + hibmc_fb = to_hibmc_framebuffer(state->fb);
>> + bo = gem_to_hibmc_bo(hibmc_fb->obj);
>> + ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
>> + if (ret)
>
> Print error
agreed, thanks.
>
>> + return;
>> +
>> + hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
>
> Check return value
ok, thanks.
>
>> + if (ret) {
>> + ttm_bo_unreserve(&bo->bo);
>> + return;
>> + }
>> +
>> + ttm_bo_unreserve(&bo->bo);
>
> Move this up before the conditional so you don't have to call it in
> both branches
understood, thanks.
>
>> +
>> + writel(gpu_addr, hidev->mmio + HIBMC_CRT_FB_ADDRESS);
>> +
>> + reg = state->fb->width * (state->fb->bits_per_pixel >> 3);
>> + /* now line_pad is 16 */
>> + reg = PADDING(16, reg);
>> +
>> + line_l = state->fb->width * state->fb->bits_per_pixel / 8;
>
> above, you >> 3. here you / 8, pick one?
i prefer /8 because it is more readable to human, although it is less effective
in executing.
>
>> + line_l = PADDING(16, line_l);
>> + writel((HIBMC_CRT_FB_WIDTH_WIDTH(reg) & HIBMC_CRT_FB_WIDTH_WIDTH_MASK) |
>> + (HIBMC_CRT_FB_WIDTH_OFFS(line_l) & HIBMC_CRT_FB_WIDTH_OFFS_MASK),
>> + hidev->mmio + HIBMC_CRT_FB_WIDTH);
>> +
>> + /* SET PIXEL FORMAT */
>> + reg = readl(hidev->mmio + HIBMC_CRT_DISP_CTL);
>> + reg = reg & ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
>> + reg = reg | (HIBMC_CRT_DISP_CTL_FORMAT(state->fb->bits_per_pixel >> 4) &
>> + HIBMC_CRT_DISP_CTL_FORMAT_MASK);
>> + writel(reg, hidev->mmio + HIBMC_CRT_DISP_CTL);
>> +}
>> +
>> +static void hibmc_plane_atomic_disable(struct drm_plane *plane,
>> + struct drm_plane_state *old_state)
>> +{
>> +}
>
> The caller checks for NULL, no need to stub
thanks for pointing it out,
will remove.
Regards,
Rongrong.
>
>> +
>> +static const u32 channel_formats1[] = {
>> + DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
>> + DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
>> + DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
>> + DRM_FORMAT_ABGR8888
>> +};
>> +
>> +static struct drm_plane_funcs hibmc_plane_funcs = {
>> + .update_plane = drm_atomic_helper_update_plane,
>> + .disable_plane = drm_atomic_helper_disable_plane,
>> + .set_property = drm_atomic_helper_plane_set_property,
>> + .destroy = drm_plane_cleanup,
>> + .reset = drm_atomic_helper_plane_reset,
>> + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
>> + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
>> +};
>> +
>> +static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
>> + .atomic_check = hibmc_plane_atomic_check,
>> + .atomic_update = hibmc_plane_atomic_update,
>> + .atomic_disable = hibmc_plane_atomic_disable,
>> +};
>> +
>> +int hibmc_plane_init(struct hibmc_drm_device *hidev)
>> +{
>> + struct drm_device *dev = hidev->dev;
>> + struct drm_plane *plane = &hidev->plane;
>> + int ret = 0;
>> +
>> + /*
>> + * plane init
>> + * TODO: Now only support primary plane, overlay planes
>> + * need to do.
>> + */
>> + ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
>> + channel_formats1,
>> + ARRAY_SIZE(channel_formats1),
>> + DRM_PLANE_TYPE_PRIMARY,
>> + NULL);
>> + if (ret) {
>> + DRM_ERROR("fail to init plane!!!\n");
>> + return ret;
>> + }
>> +
>> + drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
>> + return 0;
>> +}
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>> new file mode 100644
>> index 0000000..4ce0d7b
>> --- /dev/null
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.h
>> @@ -0,0 +1,29 @@
>> +/* Hisilicon Hibmc SoC drm driver
>> + *
>> + * Based on the bochs drm driver.
>> + *
>> + * Copyright (c) 2016 Huawei Limited.
>> + *
>> + * Author:
>> + * Rongrong Zou <zourongrong@huawei.com>
>> + * Rongrong Zou <zourongrong@gmail.com>
>> + * Jianhua Li <lijianhua@huawei.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + */
>> +
>> +#ifndef HIBMC_DRM_DE_H
>> +#define HIBMC_DRM_DE_H
>> +
>> +struct panel_pll {
>> + unsigned long M;
>> + unsigned long N;
>> + unsigned long OD;
>> + unsigned long POD;
>> +};
>> +
>> +#endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> index 5ac7a7e..7d96583 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
>> @@ -18,6 +18,7 @@
>>
>> #include <linux/module.h>
>> #include <linux/console.h>
>> +#include <drm/drm_crtc_helper.h>
>>
>> #include "hibmc_drm_drv.h"
>> #include "hibmc_drm_regs.h"
>> @@ -47,8 +48,8 @@ static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
>> }
>>
>> static struct drm_driver hibmc_driver = {
>> - .driver_features = DRIVER_GEM,
>> -
>> + .driver_features = DRIVER_GEM | DRIVER_MODESET |
>> + DRIVER_ATOMIC,
>> .fops = &hibmc_fops,
>> .name = "hibmc",
>> .date = "20160828",
>> @@ -70,6 +71,7 @@ static int hibmc_pm_suspend(struct device *dev)
>> struct drm_device *drm_dev = pci_get_drvdata(pdev);
>> struct hibmc_drm_device *hidev = drm_dev->dev_private;
>>
>> + drm_kms_helper_poll_disable(drm_dev);
>> drm_fb_helper_set_suspend_unlocked(&hidev->fbdev->helper, 1);
>>
>> return 0;
>> @@ -81,7 +83,9 @@ static int hibmc_pm_resume(struct device *dev)
>> struct drm_device *drm_dev = pci_get_drvdata(pdev);
>> struct hibmc_drm_device *hidev = drm_dev->dev_private;
>>
>> + drm_helper_resume_force_mode(drm_dev);
>> drm_fb_helper_set_suspend_unlocked(&hidev->fbdev->helper, 0);
>> + drm_kms_helper_poll_enable(drm_dev);
>>
>> return 0;
>> }
>> @@ -91,6 +95,41 @@ static int hibmc_pm_resume(struct device *dev)
>> hibmc_pm_resume)
>> };
>>
>> +static int hibmc_kms_init(struct hibmc_drm_device *hidev)
>> +{
>> + int ret;
>> +
>> + drm_mode_config_init(hidev->dev);
>> + hidev->mode_config_initialized = true;
>> +
>> + hidev->dev->mode_config.min_width = 0;
>> + hidev->dev->mode_config.min_height = 0;
>> + hidev->dev->mode_config.max_width = 1920;
>> + hidev->dev->mode_config.max_height = 1440;
>> +
>> + hidev->dev->mode_config.fb_base = hidev->fb_base;
>> + hidev->dev->mode_config.preferred_depth = 24;
>> + hidev->dev->mode_config.prefer_shadow = 0;
>> +
>> + hidev->dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
>> +
>> + ret = hibmc_plane_init(hidev);
>> + if (ret) {
>> + DRM_ERROR("fail to init plane!!!\n");
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void hibmc_kms_fini(struct hibmc_drm_device *hidev)
>> +{
>> + if (hidev->mode_config_initialized) {
>> + drm_mode_config_cleanup(hidev->dev);
>> + hidev->mode_config_initialized = false;
>> + }
>> +}
>> +
>> static int hibmc_hw_config(struct hibmc_drm_device *hidev)
>> {
>> unsigned int reg;
>> @@ -183,6 +222,7 @@ static int hibmc_unload(struct drm_device *dev)
>> struct hibmc_drm_device *hidev = dev->dev_private;
>>
>> hibmc_fbdev_fini(hidev);
>> + hibmc_kms_fini(hidev);
>> hibmc_mm_fini(hidev);
>> hibmc_hw_fini(hidev);
>> dev->dev_private = NULL;
>> @@ -208,6 +248,13 @@ static int hibmc_load(struct drm_device *dev, unsigned long flags)
>> if (ret)
>> goto err;
>>
>> + ret = hibmc_kms_init(hidev);
>> + if (ret)
>> + goto err;
>> +
>> + /* reset all the states of crtc/plane/encoder/connector */
>> + drm_mode_config_reset(dev);
>> +
>> ret = hibmc_fbdev_init(hidev);
>> if (ret)
>> goto err;
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> index a40e9a7..49e39d2 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
>> @@ -45,6 +45,8 @@ struct hibmc_drm_device {
>>
>> /* drm */
>> struct drm_device *dev;
>> + struct drm_plane plane;
>> + bool mode_config_initialized;
>>
>> /* ttm */
>> struct {
>> @@ -82,6 +84,7 @@ static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
>>
>> #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
>>
>> +int hibmc_plane_init(struct hibmc_drm_device *hidev);
>> int hibmc_fbdev_init(struct hibmc_drm_device *hidev);
>> void hibmc_fbdev_fini(struct hibmc_drm_device *hidev);
>>
>> @@ -102,4 +105,6 @@ int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
>> u32 handle, u64 *offset);
>> int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
>>
>> +extern const struct drm_mode_config_funcs hibmc_mode_funcs;
>> +
>> #endif
>> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>> index 9822f62..beb4d76 100644
>> --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
>> @@ -554,3 +554,9 @@ struct hibmc_framebuffer *
>> }
>> return &hibmc_fb->fb;
>> }
>> +
>> +const struct drm_mode_config_funcs hibmc_mode_funcs = {
>> + .atomic_check = drm_atomic_helper_check,
>> + .atomic_commit = drm_atomic_helper_commit,
>> + .fb_create = hibmc_user_framebuffer_create,
>> +};
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> _______________________________________________
> linuxarm mailing list
> linuxarm at huawei.com
> http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm
>
> .
>
^ permalink raw reply
* [PATCH v2 2/9] arm64: dts: rockchip: add pd_sd power node for rk3399
From: Shawn Lin @ 2016-11-12 4:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478697721-2323-3-git-send-email-wxt@rock-chips.com>
Hi Caesar,
On 2016/11/9 21:21, Caesar Wang wrote:
> From: zhangqing <zhangqing@rock-chips.com>
>
> 1.add pd node for RK3399 Soc
> 2.create power domain tree
> 3.add qos node for domain
> 4.add the pd_sd consumers node
I'm no sure if it is worth spliting out a seperated
patch as it looks to me that you was doing 4 things within
one patch, but anyway
Tested-by: Shawn Lin <shawn.lin@rock-chips.com>
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> Signed-off-by: Caesar Wang <wxt@rock-chips.com>
> ---
>
> Changes in v2:
> - v1 on https://patchwork.kernel.org/patch/9322553/
> - Reviewed-on: https://chromium-review.googlesource.com/386483
> - Verified on ChromeOS kernel4.4
>
> arch/arm64/boot/dts/rockchip/rk3399.dtsi | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index b401176..e5b5b3d 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -253,6 +253,7 @@
> <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
> clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
> fifo-depth = <0x100>;
> + power-domains = <&power RK3399_PD_SD>;
> status = "disabled";
> };
>
> @@ -691,6 +692,11 @@
> status = "disabled";
> };
>
> + qos_sd: qos at ffa74000 {
> + compatible = "syscon";
> + reg = <0x0 0xffa74000 0x0 0x20>;
> + };
> +
> qos_emmc: qos at ffa58000 {
> compatible = "syscon";
> reg = <0x0 0xffa58000 0x0 0x20>;
> @@ -839,6 +845,12 @@
> clocks = <&cru ACLK_GMAC>;
> pm_qos = <&qos_gmac>;
> };
> + pd_sd at RK3399_PD_SD {
> + reg = <RK3399_PD_SD>;
> + clocks = <&cru HCLK_SDMMC>,
> + <&cru SCLK_SDMMC>;
> + pm_qos = <&qos_sd>;
> + };
> pd_vio at RK3399_PD_VIO {
> reg = <RK3399_PD_VIO>;
> #address-cells = <1>;
>
--
Best Regards
Shawn Lin
^ permalink raw reply
* [PATCH v2 1/9] arm64: dts: rockchip: add eMMC's power domain support for rk3399
From: Shawn Lin @ 2016-11-12 4:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478697721-2323-2-git-send-email-wxt@rock-chips.com>
On 2016/11/9 21:21, Caesar Wang wrote:
> From: Ziyuan Xu <xzy.xu@rock-chips.com>
>
> Control power domain for eMMC via genpd to reduce power consumption.
>
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
> Signed-off-by: Ziyuan Xu <xzy.xu@rock-chips.com>
> Signed-off-by: Caesar Wang <wxt@rock-chips.com>
It was verified on my rk3399 evb with kernel4.4, so
free feel to add my tag,
Tested-by: Shawn Lin <shawn.lin@rock-chips.com>
BTW, it seems my reply is bounced form Yakir's address, so please
remove him from CC list if he changed his mail address.
> ---
>
> Changes in v2:
> - Reviewed-on: https://chromium-review.googlesource.com/376558
> - Verified on ChromeOS kernel4.4
>
> arch/arm64/boot/dts/rockchip/rk3399.dtsi | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> index cbb7f8b..b401176 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
> @@ -269,6 +269,7 @@
> #clock-cells = <0>;
> phys = <&emmc_phy>;
> phy-names = "phy_arasan";
> + power-domains = <&power RK3399_PD_EMMC>;
> status = "disabled";
> };
>
> @@ -690,6 +691,11 @@
> status = "disabled";
> };
>
> + qos_emmc: qos at ffa58000 {
> + compatible = "syscon";
> + reg = <0x0 0xffa58000 0x0 0x20>;
> + };
> +
> qos_gmac: qos at ffa5c000 {
> compatible = "syscon";
> reg = <0x0 0xffa5c000 0x0 0x20>;
> @@ -823,6 +829,11 @@
> };
>
> /* These power domains are grouped by VD_LOGIC */
> + pd_emmc at RK3399_PD_EMMC {
> + reg = <RK3399_PD_EMMC>;
> + clocks = <&cru ACLK_EMMC>;
> + pm_qos = <&qos_emmc>;
> + };
> pd_gmac at RK3399_PD_GMAC {
> reg = <RK3399_PD_GMAC>;
> clocks = <&cru ACLK_GMAC>;
>
--
Best Regards
Shawn Lin
^ permalink raw reply
* [PATCH RFC] mm: Add debug_virt_to_phys()
From: Florian Fainelli @ 2016-11-12 3:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.20.1611112034520.1618@knanqh.ubzr>
Le 11/11/2016 ? 17:49, Nicolas Pitre a ?crit :
> On Fri, 11 Nov 2016, Florian Fainelli wrote:
>
>> When CONFIG_DEBUG_VM is turned on, virt_to_phys() maps to
>> debug_virt_to_phys() which helps catch vmalloc space addresses being
>> passed. This is helpful in debugging bogus drivers that just assume
>> linear mappings all over the place.
>>
>> For ARM, ARM64, Unicore32 and Microblaze, the architectures define
>> __virt_to_phys() as being the functional implementation of the address
>> translation, so we special case the debug stub to call into
>> __virt_to_phys directly.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> arch/arm/include/asm/memory.h | 4 ++++
>> arch/arm64/include/asm/memory.h | 4 ++++
>> include/asm-generic/memory_model.h | 4 ++++
>> mm/debug.c | 15 +++++++++++++++
>> 4 files changed, 27 insertions(+)
>>
>> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
>> index 76cbd9c674df..448dec9b8b00 100644
>> --- a/arch/arm/include/asm/memory.h
>> +++ b/arch/arm/include/asm/memory.h
>> @@ -260,11 +260,15 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
>> * translation for translating DMA addresses. Use the driver
>> * DMA support - see dma-mapping.h.
>> */
>> +#ifndef CONFIG_DEBUG_VM
>> #define virt_to_phys virt_to_phys
>> static inline phys_addr_t virt_to_phys(const volatile void *x)
>> {
>> return __virt_to_phys((unsigned long)(x));
>> }
>> +#else
>> +#define virt_to_phys debug_virt_to_phys
>> +#endif
> [...]
>
> Why don't you do something more like:
>
> static inline phys_addr_t virt_to_phys(const volatile void *x)
> {
> + debug_virt_to_phys(x);
> return __virt_to_phys((unsigned long)(x));
> }
>
> [...]
>
> static inline void debug_virt_to_phys(const void *address)
> {
> #ifdef CONFIG_DEBUG_VM
> BUG_ON(is_vmalloc_addr(address));
> #endif
> }
>
> ?
This is how I started doing it initially, but to get the
is_vmalloc_addr() definition, we need to include linux/mm.h and then
everything falls apart because of the include and dependencies chain. We
could open code the is_vmalloc_addr() check because that's simple
enough, but we still need VMALLOC_START and VMALLOC_END and to get there
we need to include pgtable.h, and there are still some inclusion
problems in doing so.
The other reason was to avoid putting the same checks in architecture
specific code, except for those like ARM/ARM64/Unicore32/Microblaze
where I could not find a simple way to undefined virt_to_phys and
redefine it to debug_virt_to_phys.
Do you see an other way around this? Thanks!
--
Florian
^ permalink raw reply
* [PATCH V6 2/3] ACPI: Add support for ResourceSource/IRQ domain mapping
From: agustinv at codeaurora.org @ 2016-11-12 3:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5825C8A2.3040302@linaro.org>
Hey Lorenzo, Hanjun,
On 2016-11-11 08:33, Hanjun Guo wrote:
> Hi Lorenzo,
>
> On 11/11/2016 01:58 AM, Lorenzo Pieralisi wrote:
>> On Thu, Nov 10, 2016 at 10:02:35AM -0500, agustinv at codeaurora.org
>> wrote:
>>> Hey Hanjun,
>>>
>>> On 2016-11-09 21:36, Hanjun Guo wrote:
>>>> Hi Marc, Rafael, Lorenzo,
>>>>
>>>> Since we agreed to add a probe deferral if we failed to get irq
>>>> resources which mirroring the DT does (patch 1 in this patch set),
>>>> I think the last blocker to make things work both for Agustin and
>>>> me [1] is this patch, which makes the interrupt producer and
>>>> consumer
>>>> work in ACPI, we have two different solution for one thing, we'd
>>>> happy
>>>> to work together for one solution, could you give some suggestions
>>>> please?
>>>>
>>>> [1]:
>>>> https://mail-archive.com/linux-kernel at vger.kernel.org/msg1257419.html
>>>>
>>>> Agustin, I have some comments below.
>>>>
>>>> On 2016/10/29 4:48, Agustin Vega-Frias wrote:
>>>>> This allows irqchip drivers to associate an ACPI DSDT device to
>>>>> an IRQ domain and provides support for using the ResourceSource
>>>>> in Extended IRQ Resources to find the domain and map the IRQs
>>>>> specified on that domain.
>>>>>
>>>>> Signed-off-by: Agustin Vega-Frias <agustinv@codeaurora.org>
>>>>> ---
>>>>> drivers/acpi/Makefile | 1 +
>>>>> drivers/acpi/irqdomain.c | 119
>>>>> +++++++++++++++++++++++++++++++++++++++++++++++
>>>>
>>>> Could we just reuse the gsi.c and not introduce a new
>>>> file, probably we can change the gsi.c to irqdomain.c
>>>> or something similar, then reuse the code in gsi.c.
>>>
>>> I was thinking just that after we chatted off-list.
>>
>> Yes, that's a fair point.
>>
>>> I might revisit and see what I come up with given that we already
>>> have
>>> a device argument and we could pass the IRQ source there.
>>
>> I agree with the approach taken by this patch, I do not like much
>> passing around struct acpi_resource_source *source (in particular
>> the dummy struct) I do not think it is needed, I will comment on
>> the code.
>
> thanks for your time to have a look:)
>
>>
>> Hopefully there is not any buggy FW out there that does use the
>> resource source inappropriately otherwise we will notice on x86/ia64
>> (ie you can't blame FW if it breaks the kernel) but I suspect the
>> only way to find out is by trying, the patch has to go through
>> Rafael's
>> review anyway before getting there so it is fine.
>
> I think we can avoid that by not touching the logic that x86/ia64
> already used, but only adding interrupt producer/consumer function.
I looked at this more today and implemented a new patch that I plan to
test over the weekend, but I wanted to let you know the approach I am
pursuing.
On the new patch use of ResourceSource when parsing ACPI Extended IRQ
Resources is conditional on CONFIG_ACPI_GENERIC_GSI. The reason for this
is two fold:
1. Since we wanted to reduce duplication and place the new APIs on the
same source file as acpi_register_gsi, which is already under that
config flag.
2. So the patch does not have effect on platforms not using the generic
GSI support, including x86/ia64.
If support for this is needed outside platforms using the generic GSI
implementation, we can move these APIs out to their own source file
and eliminate the CONFIG_ACPI_GENERIC_GSI conditionality.
I'll send the new patch, hopefully some time tomorrow, but please let
me know if you have concerns with this approach.
Thanks,
Agustin
--
Qualcomm Datacenter Technologies, Inc. on behalf of the Qualcomm
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a
Linux Foundation Collaborative Project.
^ permalink raw reply
* [RFC 00/17] clk: Add per-controller locks to fix deadlocks
From: Stephen Boyd @ 2016-11-12 2:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7933d51e-92a8-ca6d-84f0-70b22fe17568@samsung.com>
On 11/04, Marek Szyprowski wrote:
> Hi Stephen,
>
> Krzysztof has left Samsung, but we would like to continue this task, because
> the ABBA dead-locks related to global prepare lock becomes more and more
> problematic for us to workaround.
Hmm. Ok. Thanks for the info.
>
> On 2016-09-09 02:24, Stephen Boyd wrote:
>
> >So I'm not very fond of this design because the locking scheme is
> >pretty much out of the hands of the framework and can be easily
> >broken.
>
> Well, switching from a single global lock to more granular locking
> is always a good approach. Please note that the global lock sooner
> or later became a serious bottleneck if one wants to make somehow
> more aggressive power management and clock gating.
I'm not so sure switching from a global lock to a more granular
lock is _always_ a great idea. Sometimes simpler code is better,
even if it doesn't scale to a million clk nodes. The largest
systems I've seen only have clocks in the hundreds, and a
majority of those aren't rate changing in parallel, so it's not
like we're suffering from VFS type scalability problems here with
tens of thousands of inodes.
That isn't to say I don't agree there's a scalability problem
here, but I'd like to actually see numbers to prove that there's
some sort of scalability problem before making drastic changes.
>
> > I'm biased of course, because I'd prefer we go with my
> >wwmutex design of per-clk locks[1]. Taking locks in any order
> >works fine there, and we resolve quite a few long standing
> >locking problems that we have while improving scalability. The
> >problem there is that we don't get the recursive mutex design
> >(maybe that's a benefit!).
>
> Do you have any plan to continue working on your approach? per-clk
> wwmutex looks like an overkill on the first glance, but that's probably
> the only working solution if you want to get rid of recursive locks.
> I'm still not really convinced that we really need wwmutex here,
> especially if it is possible to guarantee the same order of locking
> operations inside the clock core. This requires a bit of cooperation
> from clock providers (with proper documentation and a list of
> DO/DON'T it shouldn't be that hard).
So far I haven't gotten around to resurrecting the wwmutex stuff.
If you have interest in doing it that's great. Having a locking
scheme with rules of DO/DON'T sounds brittle to me, unless it can
be automated to find problems. I know that I'm not going to spend
time policing that.
>
> >Once a clk_op reenters the framework
> >with consumer APIs and tries to grab the same lock we deadlock.
> >This is why I've been slowly splitting consumers from providers
> >so we can easily identify these cases. If we had something like
> >coordinated clk rate switching, we could get rid of clk_ops
> >reentering the framework and avoid this problem (and we really do
> >need to do that).
>
> I'm not sure that this makes really sense split consumers and
> providers. You will get recursive calls to clk core anyway with
> consumers calls if you are implementing i2c clock, for which an i2c
> bus driver does it's own clock gating (i2c controller uses
> consumer clk api).
>
>
I suppose this is a different topic. Regardless of the recursive
call or not, we can easily see that a clk consumer is also a clk
provider and just knowing that is useful. Once we know that, we
can look to see if they're calling clk consumer APIs from their
provider callbacks which is not desired because it makes it
impossible to get rid of the recursive lock design. If the lock
is per-clock, then recursion doesn't happen when the provider is
also a consumer. If it does, that's bad and lockdep should tell
us.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH RFC] mm: Add debug_virt_to_phys()
From: Nicolas Pitre @ 2016-11-12 1:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161112004449.30566-1-f.fainelli@gmail.com>
On Fri, 11 Nov 2016, Florian Fainelli wrote:
> When CONFIG_DEBUG_VM is turned on, virt_to_phys() maps to
> debug_virt_to_phys() which helps catch vmalloc space addresses being
> passed. This is helpful in debugging bogus drivers that just assume
> linear mappings all over the place.
>
> For ARM, ARM64, Unicore32 and Microblaze, the architectures define
> __virt_to_phys() as being the functional implementation of the address
> translation, so we special case the debug stub to call into
> __virt_to_phys directly.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> arch/arm/include/asm/memory.h | 4 ++++
> arch/arm64/include/asm/memory.h | 4 ++++
> include/asm-generic/memory_model.h | 4 ++++
> mm/debug.c | 15 +++++++++++++++
> 4 files changed, 27 insertions(+)
>
> diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
> index 76cbd9c674df..448dec9b8b00 100644
> --- a/arch/arm/include/asm/memory.h
> +++ b/arch/arm/include/asm/memory.h
> @@ -260,11 +260,15 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
> * translation for translating DMA addresses. Use the driver
> * DMA support - see dma-mapping.h.
> */
> +#ifndef CONFIG_DEBUG_VM
> #define virt_to_phys virt_to_phys
> static inline phys_addr_t virt_to_phys(const volatile void *x)
> {
> return __virt_to_phys((unsigned long)(x));
> }
> +#else
> +#define virt_to_phys debug_virt_to_phys
> +#endif
[...]
Why don't you do something more like:
static inline phys_addr_t virt_to_phys(const volatile void *x)
{
+ debug_virt_to_phys(x);
return __virt_to_phys((unsigned long)(x));
}
[...]
static inline void debug_virt_to_phys(const void *address)
{
#ifdef CONFIG_DEBUG_VM
BUG_ON(is_vmalloc_addr(address));
#endif
}
?
Nicolas
^ permalink raw reply
* [PATCH] PCI: enable extended tags support for PCIe endpoints
From: Sinan Kaya @ 2016-11-12 1:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161111205801.GC9868@bhelgaas-glaptop.roam.corp.google.com>
On 11/11/2016 3:58 PM, Bjorn Helgaas wrote:
>> I should have checked the capability here before trying to enable it.
>> > I'll post a follow up patch on this.
>> >
>> > Is there any other feedback?
> If this were completely safe to enable for every device that supported
> it, why would there be an enable bit in Device Control?
reading from the ECN here.
https://pcisig.com/sites/default/files/specification_documents/ECN_Extended_Tag_Enable_Default_05Sept2008_final.pdf
The initial value is implementation specific and functions are allowed
to set it to 1 by default.
>
> I don't know anything about extended tags, but it worries me a little
> when there's a "go-fast" switch and no explanation about when and why
> we might need to go slo
Based on my observation, extended tags increase the number of reads that
can be queued up back to back downstream. Otherwise, the requests will not
make progress until 1 tag out of 32 gets available.
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH RFC] mm: Add debug_virt_to_phys()
From: Florian Fainelli @ 2016-11-12 0:44 UTC (permalink / raw)
To: linux-arm-kernel
When CONFIG_DEBUG_VM is turned on, virt_to_phys() maps to
debug_virt_to_phys() which helps catch vmalloc space addresses being
passed. This is helpful in debugging bogus drivers that just assume
linear mappings all over the place.
For ARM, ARM64, Unicore32 and Microblaze, the architectures define
__virt_to_phys() as being the functional implementation of the address
translation, so we special case the debug stub to call into
__virt_to_phys directly.
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/include/asm/memory.h | 4 ++++
arch/arm64/include/asm/memory.h | 4 ++++
include/asm-generic/memory_model.h | 4 ++++
mm/debug.c | 15 +++++++++++++++
4 files changed, 27 insertions(+)
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 76cbd9c674df..448dec9b8b00 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -260,11 +260,15 @@ static inline unsigned long __phys_to_virt(phys_addr_t x)
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
*/
+#ifndef CONFIG_DEBUG_VM
#define virt_to_phys virt_to_phys
static inline phys_addr_t virt_to_phys(const volatile void *x)
{
return __virt_to_phys((unsigned long)(x));
}
+#else
+#define virt_to_phys debug_virt_to_phys
+#endif
#define phys_to_virt phys_to_virt
static inline void *phys_to_virt(phys_addr_t x)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index b71086d25195..c9e436b28523 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -186,11 +186,15 @@ extern u64 kimage_voffset;
* translation for translating DMA addresses. Use the driver
* DMA support - see dma-mapping.h.
*/
+#ifndef CONFIG_DEBUG_VM
#define virt_to_phys virt_to_phys
static inline phys_addr_t virt_to_phys(const volatile void *x)
{
return __virt_to_phys((unsigned long)(x));
}
+#else
+#define virt_to_phys debug_virt_to_phys
+#endif
#define phys_to_virt phys_to_virt
static inline void *phys_to_virt(phys_addr_t x)
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
index 5148150cc80b..426085757258 100644
--- a/include/asm-generic/memory_model.h
+++ b/include/asm-generic/memory_model.h
@@ -80,6 +80,10 @@
#define page_to_pfn __page_to_pfn
#define pfn_to_page __pfn_to_page
+#ifdef CONFIG_DEBUG_VM
+unsigned long debug_virt_to_phys(volatile void *address);
+#endif /* CONFIG_DEBUG_VM */
+
#endif /* __ASSEMBLY__ */
#endif
diff --git a/mm/debug.c b/mm/debug.c
index 9feb699c5d25..72b2ca9b11f4 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -161,4 +161,19 @@ void dump_mm(const struct mm_struct *mm)
);
}
+#include <asm/memory.h>
+#include <linux/mm.h>
+
+unsigned long debug_virt_to_phys(volatile void *address)
+{
+ BUG_ON(is_vmalloc_addr((const void *)address));
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_UNICORE32) || \
+ defined(CONFIG_MICROBLAZE)
+ return __virt_to_phys(address);
+#else
+ return virt_to_phys(address);
+#endif
+}
+EXPORT_SYMBOL(debug_virt_to_phys);
+
#endif /* CONFIG_DEBUG_VM */
--
2.9.3
^ permalink raw reply related
* [PATCH] pci: layerscape: add LS1046a support
From: Bjorn Helgaas @ 2016-11-11 22:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477399016-22826-1-git-send-email-Minghuan.Lian@nxp.com>
On Tue, Oct 25, 2016 at 08:36:56PM +0800, Minghuan Lian wrote:
> From: "mingkai.hu at nxp.com" <mingkai.hu@nxp.com>
>
> 1. LS1046a PCIe controller has a different LUT_DBG offset.
> Available "lut_dbg" is added to ls_pcie_drvdata to describe
> this difference.
> 2. Match LS1046 PCIe compatible
>
> Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
> Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com>
Applied to pci/host-layerscape for v4.10, thanks!
I removed the now-unused PCIE_LUT_DBG definition for you.
> ---
> Documentation/devicetree/bindings/pci/layerscape-pci.txt | 1 +
> drivers/pci/host/pci-layerscape.c | 13 ++++++++++++-
> 2 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/pci/layerscape-pci.txt b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
> index 41e9f55..ee1c72d5 100644
> --- a/Documentation/devicetree/bindings/pci/layerscape-pci.txt
> +++ b/Documentation/devicetree/bindings/pci/layerscape-pci.txt
> @@ -15,6 +15,7 @@ Required properties:
> - compatible: should contain the platform identifier such as:
> "fsl,ls1021a-pcie", "snps,dw-pcie"
> "fsl,ls2080a-pcie", "fsl,ls2085a-pcie", "snps,dw-pcie"
> + "fsl,ls1046a-pcie"
> - reg: base addresses and lengths of the PCIe controller
> - interrupts: A list of interrupt outputs of the controller. Must contain an
> entry for each entry in the interrupt-names property.
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index 958187f..8cebf9a 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -41,6 +41,7 @@
> struct ls_pcie_drvdata {
> u32 lut_offset;
> u32 ltssm_shift;
> + u32 lut_dbg;
> struct pcie_host_ops *ops;
> };
>
> @@ -134,7 +135,7 @@ static int ls_pcie_link_up(struct pcie_port *pp)
> struct ls_pcie *pcie = to_ls_pcie(pp);
> u32 state;
>
> - state = (ioread32(pcie->lut + PCIE_LUT_DBG) >>
> + state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
> pcie->drvdata->ltssm_shift) &
> LTSSM_STATE_MASK;
>
> @@ -196,18 +197,28 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp,
> static struct ls_pcie_drvdata ls1043_drvdata = {
> .lut_offset = 0x10000,
> .ltssm_shift = 24,
> + .lut_dbg = 0x7fc,
> + .ops = &ls_pcie_host_ops,
> +};
> +
> +static struct ls_pcie_drvdata ls1046_drvdata = {
> + .lut_offset = 0x80000,
> + .ltssm_shift = 24,
> + .lut_dbg = 0x407fc,
> .ops = &ls_pcie_host_ops,
> };
>
> static struct ls_pcie_drvdata ls2080_drvdata = {
> .lut_offset = 0x80000,
> .ltssm_shift = 0,
> + .lut_dbg = 0x7fc,
> .ops = &ls_pcie_host_ops,
> };
>
> static const struct of_device_id ls_pcie_of_match[] = {
> { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
> { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
> + { .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
> { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
> { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
> { },
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] ARM: dts: vfxxx: Enable DMA for DSPI2 and DSPI3
From: Fabio Estevam @ 2016-11-11 22:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161110114505.17618-1-maitysanchayan@gmail.com>
On Thu, Nov 10, 2016 at 9:45 AM, Sanchayan Maity
<maitysanchayan@gmail.com> wrote:
> Enable DMA for DSPI2 and DSPI3 on Vybrid.
You missed your Signed-off-by line.
^ permalink raw reply
* [PATCH] i.MX: Kconfig: Drop errata 769419 for Vybrid
From: Fabio Estevam @ 2016-11-11 22:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478709850-9361-1-git-send-email-andrew.smirnov@gmail.com>
On Wed, Nov 9, 2016 at 2:44 PM, Andrey Smirnov <andrew.smirnov@gmail.com> wrote:
> According to the datasheet, VF610 uses revision r3p2 of the L2C-310
> block, same as i.MX6Q+, which does not require a software workaround for
> ARM errata 769419.
>
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
^ permalink raw reply
* PM regression with LED changes in next-20161109
From: Pavel Machek @ 2016-11-11 22:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d7ddbbb0-b99c-14a3-f462-3534b5ec67e6@redhat.com>
Hi!
Reason #1:
> >>Hmm. So userland can read the LED state, and it can get _some_ value
> >>back, but it can not know if it is current state or not.
> Why a dedicated file? Are we going to mirror brightness here
> wrt r/w (show/store) behavior ? If not userspace now needs
> 2 open fds which is not really nice. If we are and we are
> not going to use poll for something else on brightness itself
> then why not just poll directly on brightness ?
Reason #1 is above.
Reason #2 is "if userspace sees brightness file, it can not know if
the notifications on change actually work or not".
Reason #3 is that you broke Tony's system. Polling does not make sense
when trigger such as "CPU in use" is active.
Reason #4 is that there are really two brightnesses:
1) maximum brightness trigger is going to use
2) current brightness
Currently writing to "brightness" file changes 1), but reading returns
2) when available.
So, feel free to propose better interface. One that solves #1..#4
above.
Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161111/f0be8d93/attachment.sig>
^ permalink raw reply
* PM regression with LED changes in next-20161109
From: Pavel Machek @ 2016-11-11 22:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f7c9b2be-0003-f342-a4c7-802532faa424@gmail.com>
Hi!
> >Hmm. So userland can read the LED state, and it can get _some_ value
> >back, but it can not know if it is current state or not.
> >
> >I don't think that's a good interface. I see it is from 2008... is
> >someone using it? Maybe it is too late for revert.
>
> I can imagine it being used in flash LED use case. E.g. one
> could use oneshot trigger to trigger flash strobe, and then
> he could periodically read brightness file to check, for whatever
> reason, whether the flash is strobing.
I'm pretty sure nobody does that for flah strobe.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161111/e6116c19/attachment.sig>
^ permalink raw reply
* [PATCH v7] soc: qcom: add l2 cache perf events driver
From: Leeder, Neil @ 2016-11-11 21:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109181652.GK17771@arm.com>
Hi Will,
On 11/9/2016 1:16 PM, Will Deacon wrote:
> On Wed, Nov 09, 2016 at 05:54:13PM +0000, Mark Rutland wrote:
>> On Fri, Oct 28, 2016 at 04:50:13PM -0400, Neil Leeder wrote:
>>> + struct perf_event *events[MAX_L2_CTRS];
>>> + struct l2cache_pmu *l2cache_pmu;
>>> + DECLARE_BITMAP(used_counters, MAX_L2_CTRS);
>>> + DECLARE_BITMAP(used_groups, L2_EVT_GROUP_MAX + 1);
>>> + int group_to_counter[L2_EVT_GROUP_MAX + 1];
>>> + int irq;
>>> + /* The CPU that is used for collecting events on this cluster */
>>> + int on_cpu;
>>> + /* All the CPUs associated with this cluster */
>>> + cpumask_t cluster_cpus;
>>
>> I'm still uncertain about aggregating all cluster PMUs into a larger
>> PMU, given the cluster PMUs are logically independent (at least in terms
>> of the programming model).
>>
>> However, from what I understand the x86 uncore PMU drivers aggregate
>> symmetric instances of uncore PMUs (and also aggregate across packages
>> to the same logical PMU).
>>
>> Whatever we do, it would be nice for the uncore drivers to align on a
>> common behaviour (and I think we're currently going the oppposite route
>> with Cavium's uncore PMU). Will, thoughts?
>
> I'm not a big fan of aggregating this stuff. Ultimately, the user in the
> driving seat of perf is going to need some knowledge about the toplogy of
> the system in order to perform sensible profiling using an uncore PMU.
> If the kernel tries to present a single, unified PMU then we paint ourselves
> into a corner when the hardware isn't as symmetric as we want it to be
> (big/little on the CPU side is the extreme example of this). If we want
> to be consistent, then exposing each uncore unit as a separate PMU is
> the way to go. That doesn't mean we can't aggregate the components of a
> distributed PMU (e.g. the CCN or the SMMU), but we don't want to aggregate
> at the programming interface/IP block level.
>
> We could consider exposing some topology information in sysfs if that's
> seen as an issue with the non-aggregated case.
>
> Will
So is there a use-case for individual uncore PMUs when they can't be
used in task mode or per-cpu?
The main (only?) use will be in system mode, in which case surely it
makes sense to provide a single aggregated count?
With individual PMUs exposed there will be potentially dozens of nodes
for userspace to collect from which would make perf command-line usage
unwieldy at best.
Neil
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH -next] PCI: xilinx-nwl: Add missing of_node_put() in nwl_pcie_init_irq_domain()
From: Bjorn Helgaas @ 2016-11-11 21:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476716297-31808-1-git-send-email-weiyj.lk@gmail.com>
On Mon, Oct 17, 2016 at 02:58:17PM +0000, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> This node pointer is returned by of_get_next_child() with refcount
> incremented in this function. of_node_put() on it before exitting
> this function on error.
>
> This is detected by Coccinelle semantic patch.
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Applied to pci/host-xilinx for v.10, thanks!
> ---
> drivers/pci/host/pcie-xilinx-nwl.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c
> index 43eaa4a..c16b26c 100644
> --- a/drivers/pci/host/pcie-xilinx-nwl.c
> +++ b/drivers/pci/host/pcie-xilinx-nwl.c
> @@ -535,6 +535,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie)
>
> if (!pcie->legacy_irq_domain) {
> dev_err(dev, "failed to create IRQ domain\n");
> + of_node_put(legacy_intc_node);
> return -ENOMEM;
> }
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH -next] PCI: xilinx: Add missing of_node_put() in xilinx_pcie_init_irq_domain()
From: Bjorn Helgaas @ 2016-11-11 21:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476716344-1050-1-git-send-email-weiyj.lk@gmail.com>
On Mon, Oct 17, 2016 at 02:59:04PM +0000, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> This node pointer is returned by of_get_next_child() with refcount
> incremented in this function. of_node_put() on it before exitting
> this function on error.
>
> This is detected by Coccinelle semantic patch.
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Applied to pci/host-xilinx for v4.10, thanks!
See below for another possible issue.
> ---
> drivers/pci/host/pcie-xilinx.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
> index c8616fa..7100ee5 100644
> --- a/drivers/pci/host/pcie-xilinx.c
> +++ b/drivers/pci/host/pcie-xilinx.c
> @@ -529,6 +529,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
> port);
> if (!port->leg_domain) {
> dev_err(dev, "Failed to get a INTx IRQ domain\n");
> + of_node_put(pcie_intc_node);
> return -ENODEV;
> }
>
> @@ -540,6 +541,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
> &xilinx_pcie_msi_chip);
> if (!port->msi_domain) {
> dev_err(dev, "Failed to get a MSI IRQ domain\n");
> + of_node_put(pcie_intc_node);
We also leak port->leg_domain here, don't we?
> return -ENODEV;
> }
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH -next] PCI: rockchip: Add missing of_node_put() in rockchip_pcie_init_irq_domain()
From: Bjorn Helgaas @ 2016-11-11 21:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476716242-31684-1-git-send-email-weiyj.lk@gmail.com>
On Mon, Oct 17, 2016 at 02:57:22PM +0000, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> This node pointer is returned by of_get_next_child() with refcount
> incremented in this function. of_node_put() on it before exitting
> this function on error.
>
> This is detected by Coccinelle semantic patch.
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Applied with Shawn's ack to pci/host-rockchip for v4.10, thanks!
> ---
> drivers/pci/host/pcie-rockchip.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
> index e0b22da..ab88859 100644
> --- a/drivers/pci/host/pcie-rockchip.c
> +++ b/drivers/pci/host/pcie-rockchip.c
> @@ -949,6 +949,7 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip)
> &intx_domain_ops, rockchip);
> if (!rockchip->irq_domain) {
> dev_err(dev, "failed to get a INTx IRQ domain\n");
> + of_node_put(intc);
> return -EINVAL;
> }
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH -next] PCI: layerscape: Remove redundant dev_err call in ls_pcie_probe()
From: Bjorn Helgaas @ 2016-11-11 21:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476716140-30608-1-git-send-email-weiyj.lk@gmail.com>
On Mon, Oct 17, 2016 at 02:55:40PM +0000, Wei Yongjun wrote:
> From: Wei Yongjun <weiyongjun1@huawei.com>
>
> There is a error message within devm_ioremap_resource
> already, so remove the dev_err call to avoid redundant
> error message.
>
> Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Applied to pci/host-layerscape for v4.10, thanks!
> ---
> drivers/pci/host/pci-layerscape.c | 4 +---
> 1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
> index 2cb7315..bbd3d23 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -251,10 +251,8 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
>
> dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
> pcie->pp.dbi_base = devm_ioremap_resource(dev, dbi_base);
> - if (IS_ERR(pcie->pp.dbi_base)) {
> - dev_err(dev, "missing *regs* space\n");
> + if (IS_ERR(pcie->pp.dbi_base))
> return PTR_ERR(pcie->pp.dbi_base);
> - }
>
> pcie->drvdata = match->data;
> pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [GIT PULL 2/2] SoCFPGA defconfig updates for v4.10
From: Dinh Nguyen @ 2016-11-11 20:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161111205915.22173-1-dinguyen@kernel.org>
Hi Arnd, Kevin, and Olof:
Please pull these defconfig updates for v4.10.
Thanks,
Dinh
The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git tags/socfpga_defconfig_updates_for_v4.10
for you to fetch changes up to cab004fa972f06b236ba6b592bbb0512d5c6c158:
ARM: socfpga_defconfig: enable FS configs to support Angstrom filesystem (2016-11-09 08:11:31 -0600)
----------------------------------------------------------------
SoCFPGA defconfig updates for v4.10
- enable QSPI, HIGHMEM, FPGA bridge and device-tree overlays
- enable AUTOFS4 and NFS file system support
----------------------------------------------------------------
Alan Tull (1):
ARM: socfpga: updates for socfpga_defconfig
Dinh Nguyen (2):
ARM: socfpga_defconfig: Enable HIGHMEM
ARM: socfpga_defconfig: enable FS configs to support Angstrom filesystem
Steffen Trumtrar (1):
ARM: socfpga: defconfig: enable qspi
arch/arm/configs/socfpga_defconfig | 15 +++++++++++++++
1 file changed, 15 insertions(+)
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox