bcm27xx: sync 5.4 patches with RPi Foundation
authorÁlvaro Fernández Rojas <noltari@gmail.com>
Mon, 23 Mar 2020 07:48:08 +0000 (08:48 +0100)
committerÁlvaro Fernández Rojas <noltari@gmail.com>
Mon, 23 Mar 2020 07:48:08 +0000 (08:48 +0100)
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
17 files changed:
target/linux/bcm27xx/patches-5.4/950-0119-Add-rpi-poe-fan-driver.patch
target/linux/bcm27xx/patches-5.4/950-0475-gpio-ir-overlay-add-parameter-to-configure-signal-po.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0476-Add-support-for-merus-amp-soundcard-and-ma120x0p-cod.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0477-ARM-dts-bcm2711-Add-32-bit-PMU-compatibility.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0478-ARM-dts-bcm271x-Use-a53-pmu-drop-RPI364.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0479-net-bcmgenet-Clear-ID_MODE_DIS-in-EXT_RGMII_OOB_CTRL.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0480-drm-modes-parse_cmdline-Fix-possible-reference-past-.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0481-drm-modes-parse_cmdline-Make-various-char-pointers-c.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0482-drm-modes-parse_cmdline-Stop-parsing-extras-after-bp.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0483-drm-modes-parse_cmdline-Accept-extras-directly-after.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0484-drm-modes-parse_cmdline-Rework-drm_mode_parse_cmdlin.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0485-drm-modes-parse_cmdline-Add-freestanding-argument-to.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0486-drm-modes-parse_cmdline-Set-bpp-refresh_specified-af.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0487-drm-modes-parse_cmdline-Allow-specifying-stand-alone.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0488-drm-modes-parse_cmdline-Add-support-for-specifying-p.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0489-drm-modes-parse_cmdline-Remove-some-unnecessary-code.patch [new file with mode: 0644]
target/linux/bcm27xx/patches-5.4/950-0490-drm-modes-parse_cmdline-Explicitly-memset-the-passed.patch [new file with mode: 0644]

index 574e547de909927e7e69482473f1d3888bb51a34..8a1f57ad0156544ffe6018a04b2022be6c88db81 100644 (file)
@@ -108,7 +108,7 @@ Signed-off-by: Serge Schneider <serge@raspberrypi.org>
 +the fan to the user space through the hwmon sysfs interface.
 --- a/drivers/hwmon/Kconfig
 +++ b/drivers/hwmon/Kconfig
-@@ -1346,6 +1346,17 @@ config SENSORS_RASPBERRYPI_HWMON
+@@ -1356,6 +1356,17 @@ config SENSORS_RASPBERRYPI_HWMON
          This driver can also be built as a module. If so, the module
          will be called raspberrypi-hwmon.
  
@@ -128,7 +128,7 @@ Signed-off-by: Serge Schneider <serge@raspberrypi.org>
        depends on GPIOLIB || COMPILE_TEST
 --- a/drivers/hwmon/Makefile
 +++ b/drivers/hwmon/Makefile
-@@ -144,6 +144,7 @@ obj-$(CONFIG_SENSORS_PCF8591)      += pcf8591
+@@ -145,6 +145,7 @@ obj-$(CONFIG_SENSORS_PCF8591)      += pcf8591
  obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
  obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
  obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON)       += raspberrypi-hwmon.o
diff --git a/target/linux/bcm27xx/patches-5.4/950-0475-gpio-ir-overlay-add-parameter-to-configure-signal-po.patch b/target/linux/bcm27xx/patches-5.4/950-0475-gpio-ir-overlay-add-parameter-to-configure-signal-po.patch
new file mode 100644 (file)
index 0000000..cdd14f7
--- /dev/null
@@ -0,0 +1,45 @@
+From e253d03936265dc4ab8ae9ae89d2a885e80a45a6 Mon Sep 17 00:00:00 2001
+From: Matthias Reichl <hias@horus.com>
+Date: Fri, 6 Mar 2020 11:08:10 +0100
+Subject: [PATCH] gpio-ir-overlay: add parameter to configure signal
+ polarity (#3490)
+
+Standard IR receivers use inverted / active-low signalling
+and the gpio-ir overlay configures the GPIO appropriately
+as GPIO_ACTIVE_LOW (1).
+
+In order to support (rather rare) non-inverted / active-high
+signalling the GPIO needs to be configured as GPIO_ACTIVE_HIGH (0).
+
+Add an "invert" parameter to override this like in the gpio-ir-tx
+overlay.
+
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ arch/arm/boot/dts/overlays/README              | 4 ++++
+ arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 1 +
+ 2 files changed, 5 insertions(+)
+
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -754,6 +754,10 @@ Params: gpio_pin                Input pi
+         gpio_pull               Desired pull-up/down state (off, down, up)
+                                 Default is "up".
++        invert                  "1" = invert the input (active-low signalling).
++                                "0" = non-inverted input (active-high
++                                signalling). Default is "1".
++
+         rc-map-name             Default rc keymap (can also be changed by
+                                 ir-keytable), defaults to "rc-rc6-mce"
+--- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
++++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts
+@@ -42,6 +42,7 @@
+                                 <&gpio_ir_pins>,"brcm,pins:0",
+                                 <&gpio_ir_pins>,"reg:0";
+                 gpio_pull = <&gpio_ir_pins>,"brcm,pull:0";              // pull-up/down state
++                invert = <&gpio_ir>,"gpios:8";                          // 0 = active high input
+                 rc-map-name = <&gpio_ir>,"linux,rc-map-name";           // default rc map
+         };
diff --git a/target/linux/bcm27xx/patches-5.4/950-0476-Add-support-for-merus-amp-soundcard-and-ma120x0p-cod.patch b/target/linux/bcm27xx/patches-5.4/950-0476-Add-support-for-merus-amp-soundcard-and-ma120x0p-cod.patch
new file mode 100644 (file)
index 0000000..8e66bcc
--- /dev/null
@@ -0,0 +1,1589 @@
+From 76e0edf9676388c58bb5f0d7dda8eb8029926c6d Mon Sep 17 00:00:00 2001
+From: AMuszkat <ariel.muszkat@gmail.com>
+Date: Mon, 24 Feb 2020 22:56:59 +0100
+Subject: [PATCH] Add support for merus-amp soundcard and ma120x0p
+ codec
+
+correct checkpatch warnings and errors
+
+Signed-off-by: AMuszkat <ariel.muszkat@gmail.com>
+---
+ arch/arm/boot/dts/overlays/Makefile           |    1 +
+ arch/arm/boot/dts/overlays/README             |    6 +
+ .../boot/dts/overlays/merus-amp-overlay.dts   |   60 +
+ sound/soc/bcm/rpi-simple-soundcard.c          |   28 +
+ sound/soc/codecs/Kconfig                      |    8 +
+ sound/soc/codecs/Makefile                     |    2 +
+ sound/soc/codecs/ma120x0p.c                   | 1384 +++++++++++++++++
+ 7 files changed, 1489 insertions(+)
+ create mode 100644 arch/arm/boot/dts/overlays/merus-amp-overlay.dts
+ create mode 100644 sound/soc/codecs/ma120x0p.c
+
+--- a/arch/arm/boot/dts/overlays/Makefile
++++ b/arch/arm/boot/dts/overlays/Makefile
+@@ -103,6 +103,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \
+       mcp3202.dtbo \
+       mcp342x.dtbo \
+       media-center.dtbo \
++      merus-amp.dtbo \
+       midi-uart0.dtbo \
+       midi-uart1.dtbo \
+       miniuart-bt.dtbo \
+--- a/arch/arm/boot/dts/overlays/README
++++ b/arch/arm/boot/dts/overlays/README
+@@ -1662,6 +1662,12 @@ Params: speed                   Display
+                                 (default "off")
++Name:   merus-amp
++Info:   Configures the merus-amp audio card
++Load:   dtoverlay=merus-amp
++Params: <None>
++
++
+ Name:   midi-uart0
+ Info:   Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets
+         31.25kbaud, the frequency required for MIDI
+--- /dev/null
++++ b/arch/arm/boot/dts/overlays/merus-amp-overlay.dts
+@@ -0,0 +1,60 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Definitions for Infineon Merus-Amp
++/dts-v1/;
++/plugin/;
++#include <dt-bindings/pinctrl/bcm2835.h>
++#include <dt-bindings/gpio/gpio.h>
++
++
++/ {
++      compatible = "brcm,bcm2835";
++
++      fragment@0 {
++              target = <&i2s>;
++              __overlay__ {
++                      status = "okay";
++              };
++      };
++
++      fragment@1 {
++              target = <&gpio>;
++              __overlay__ {
++                      merus_amp_pins: merus_amp_pins {
++                              brcm,pins = <23>;
++                              brcm,function = <0>; /* in */
++                              brcm,pull = <2>; /* up */
++                      };
++              };
++      };
++
++      fragment@2 {
++              target = <&i2c1>;
++              __overlay__ {
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "okay";
++
++                      merus_amp: ma120x0p@20 {
++                              #sound-dai-cells = <0>;
++                              compatible = "ma,ma120x0p";
++                              reg = <0x20>;
++                              status = "okay";
++                              pinctrl-names = "default";
++                              pinctrl-0 = <&merus_amp_pins>;
++                              enable_gp-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
++                              mute_gp-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
++                              booster_gp-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
++                              error_gp-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
++                      };
++              };
++      };
++
++      fragment@3 {
++              target = <&sound>;
++              __overlay__ {
++                      compatible = "merus,merus-amp";
++                      i2s-controller = <&i2s>;
++                      status = "okay";
++              };
++      };
++};
+--- a/sound/soc/bcm/rpi-simple-soundcard.c
++++ b/sound/soc/bcm/rpi-simple-soundcard.c
+@@ -16,6 +16,10 @@
+  * adau1977-adc.c
+  * by Andrey Grodzovsky <andrey2805@gmail.com>
+  *
++ * merus-amp.c
++ * by Ariel Muszkat <ariel.muszkat@gmail.com>
++ *            Jorgen Kragh Jakobsen <jorgen.kraghjakobsen@infineon.com>
++ *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * version 2 as published by the Free Software Foundation.
+@@ -229,6 +233,28 @@ static struct snd_rpi_simple_drvdata drv
+       .fixed_bclk_ratio = 64,
+ };
++SND_SOC_DAILINK_DEFS(merus_amp,
++      DAILINK_COMP_ARRAY(COMP_EMPTY()),
++      DAILINK_COMP_ARRAY(COMP_CODEC("ma120x0p-amp", "ma120x0p.1-0020")),
++      DAILINK_COMP_ARRAY(COMP_EMPTY()));
++
++static struct snd_soc_dai_link snd_merus_amp_dai[] = {
++      {
++              .name           = "MerusAmp",
++              .stream_name    = "Merus Audio Amp",
++              .dai_fmt        = SND_SOC_DAIFMT_I2S |
++                                      SND_SOC_DAIFMT_NB_NF |
++                                      SND_SOC_DAIFMT_CBS_CFS,
++              SND_SOC_DAILINK_REG(merus_amp),
++      },
++};
++
++static struct snd_rpi_simple_drvdata drvdata_merus_amp = {
++      .card_name        = "snd_rpi_merus_amp",
++      .dai              = snd_merus_amp_dai,
++      .fixed_bclk_ratio = 64,
++};
++
+ static const struct of_device_id snd_rpi_simple_of_match[] = {
+       { .compatible = "adi,adau1977-adc",
+               .data = (void *) &drvdata_adau1977 },
+@@ -241,6 +267,8 @@ static const struct of_device_id snd_rpi
+       { .compatible = "hifiberry,hifiberry-dac",
+               .data = (void *) &drvdata_hifiberry_dac },
+       { .compatible = "rpi,rpi-dac", &drvdata_rpi_dac},
++      { .compatible = "merus,merus-amp",
++              .data = (void *) &drvdata_merus_amp },
+       {},
+ };
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -103,6 +103,7 @@ config SND_SOC_ALL_CODECS
+       select SND_SOC_LM4857 if I2C
+       select SND_SOC_LM49453 if I2C
+       select SND_SOC_LOCHNAGAR_SC if MFD_LOCHNAGAR
++      select SND_SOC_MA120X0P if I2C
+       select SND_SOC_MAX98088 if I2C
+       select SND_SOC_MAX98090 if I2C
+       select SND_SOC_MAX98095 if I2C
+@@ -732,6 +733,13 @@ config SND_SOC_LOCHNAGAR_SC
+         This driver support the sound card functionality of the Cirrus
+         Logic Lochnagar audio development board.
++config SND_SOC_MA120X0P
++      tristate "Infineon Merus(TM) MA120X0P Multilevel Class-D Audio amplifiers"
++      depends on I2C
++      help
++              Enable support for Infineon MA120X0P Multilevel Class-D audio power
++              amplifiers.
++
+ config SND_SOC_MADERA
+       tristate
+       default y if SND_SOC_CS47L15=y
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -99,6 +99,7 @@ snd-soc-l3-objs := l3.o
+ snd-soc-lm4857-objs := lm4857.o
+ snd-soc-lm49453-objs := lm49453.o
+ snd-soc-lochnagar-sc-objs := lochnagar-sc.o
++snd-soc-ma120x0p-objs := ma120x0p.o
+ snd-soc-madera-objs := madera.o
+ snd-soc-max9759-objs := max9759.o
+ snd-soc-max9768-objs := max9768.o
+@@ -386,6 +387,7 @@ obj-$(CONFIG_SND_SOC_L3)   += snd-soc-l3.o
+ obj-$(CONFIG_SND_SOC_LM4857)  += snd-soc-lm4857.o
+ obj-$(CONFIG_SND_SOC_LM49453)   += snd-soc-lm49453.o
+ obj-$(CONFIG_SND_SOC_LOCHNAGAR_SC)    += snd-soc-lochnagar-sc.o
++obj-$(CONFIG_SND_SOC_MA120X0P)   += snd-soc-ma120x0p.o
+ obj-$(CONFIG_SND_SOC_MADERA)  += snd-soc-madera.o
+ obj-$(CONFIG_SND_SOC_MAX9759) += snd-soc-max9759.o
+ obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
+--- /dev/null
++++ b/sound/soc/codecs/ma120x0p.c
+@@ -0,0 +1,1384 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * ASoC Driver for Infineon Merus(TM) ma120x0p multi-level class-D amplifier
++ *
++ * Authors:   Ariel Muszkat <ariel.muszkat@gmail.com>
++ * Jorgen Kragh Jakobsen <jorgen.kraghjakobsen@infineon.com>
++ *
++ * Copyright (C) 2019 Infineon Technologies AG
++ *
++ */
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm_runtime.h>
++#include <linux/i2c.h>
++#include <linux/of_device.h>
++#include <linux/spi/spi.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++#include <linux/gpio/consumer.h>
++#include <linux/gpio.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++#include <sound/initval.h>
++#include <sound/tlv.h>
++#include <linux/interrupt.h>
++
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/fs.h>
++#include <linux/uaccess.h>
++
++#ifndef _MA120X0P_
++#define _MA120X0P_
++//------------------------------------------------------------------manualPM---
++// Select Manual PowerMode control
++#define ma_manualpm__a 0
++#define ma_manualpm__len 1
++#define ma_manualpm__mask 0x40
++#define ma_manualpm__shift 0x06
++#define ma_manualpm__reset 0x00
++//--------------------------------------------------------------------pm_man---
++// manual selected power mode
++#define ma_pm_man__a 0
++#define ma_pm_man__len 2
++#define ma_pm_man__mask 0x30
++#define ma_pm_man__shift 0x04
++#define ma_pm_man__reset 0x03
++//------------------------------------------ ----------------------mthr_1to2---
++// mod. index threshold value for pm1=>pm2 change.
++#define ma_mthr_1to2__a 1
++#define ma_mthr_1to2__len 8
++#define ma_mthr_1to2__mask 0xff
++#define ma_mthr_1to2__shift 0x00
++#define ma_mthr_1to2__reset 0x3c
++//-----------------------------------------------------------------mthr_2to1---
++// mod. index threshold value for pm2=>pm1 change.
++#define ma_mthr_2to1__a 2
++#define ma_mthr_2to1__len 8
++#define ma_mthr_2to1__mask 0xff
++#define ma_mthr_2to1__shift 0x00
++#define ma_mthr_2to1__reset 0x32
++//-----------------------------------------------------------------mthr_2to3---
++// mod. index threshold value for pm2=>pm3 change.
++#define ma_mthr_2to3__a 3
++#define ma_mthr_2to3__len 8
++#define ma_mthr_2to3__mask 0xff
++#define ma_mthr_2to3__shift 0x00
++#define ma_mthr_2to3__reset 0x5a
++//-----------------------------------------------------------------mthr_3to2---
++// mod. index threshold value for pm3=>pm2 change.
++#define ma_mthr_3to2__a 4
++#define ma_mthr_3to2__len 8
++#define ma_mthr_3to2__mask 0xff
++#define ma_mthr_3to2__shift 0x00
++#define ma_mthr_3to2__reset 0x50
++//-------------------------------------------------------------pwmclkdiv_nom---
++// pwm default clock divider value
++#define ma_pwmclkdiv_nom__a 8
++#define ma_pwmclkdiv_nom__len 8
++#define ma_pwmclkdiv_nom__mask 0xff
++#define ma_pwmclkdiv_nom__shift 0x00
++#define ma_pwmclkdiv_nom__reset 0x26
++//--------- ----------------------------------------------------ocp_latch_en---
++// high to use permanently latching level-2 ocp
++#define ma_ocp_latch_en__a 10
++#define ma_ocp_latch_en__len 1
++#define ma_ocp_latch_en__mask 0x02
++#define ma_ocp_latch_en__shift 0x01
++#define ma_ocp_latch_en__reset 0x00
++//---------------------------------------------------------------lf_clamp_en---
++// high (default) to enable lf int2+3 clamping on clip
++#define ma_lf_clamp_en__a 10
++#define ma_lf_clamp_en__len 1
++#define ma_lf_clamp_en__mask 0x80
++#define ma_lf_clamp_en__shift 0x07
++#define ma_lf_clamp_en__reset 0x00
++//-------------------------------------------------------pmcfg_btl_b.modtype---
++//
++#define ma_pmcfg_btl_b__modtype__a 18
++#define ma_pmcfg_btl_b__modtype__len 2
++#define ma_pmcfg_btl_b__modtype__mask 0x18
++#define ma_pmcfg_btl_b__modtype__shift 0x03
++#define ma_pmcfg_btl_b__modtype__reset 0x02
++//-------------------------------------------------------pmcfg_btl_b.freqdiv---
++#define ma_pmcfg_btl_b__freqdiv__a 18
++#define ma_pmcfg_btl_b__freqdiv__len 2
++#define ma_pmcfg_btl_b__freqdiv__mask 0x06
++#define ma_pmcfg_btl_b__freqdiv__shift 0x01
++#define ma_pmcfg_btl_b__freqdiv__reset 0x01
++//----------------------------------------------------pmcfg_btl_b.lf_gain_ol---
++//
++#define ma_pmcfg_btl_b__lf_gain_ol__a 18
++#define ma_pmcfg_btl_b__lf_gain_ol__len 1
++#define ma_pmcfg_btl_b__lf_gain_ol__mask 0x01
++#define ma_pmcfg_btl_b__lf_gain_ol__shift 0x00
++#define ma_pmcfg_btl_b__lf_gain_ol__reset 0x01
++//-------------------------------------------------------pmcfg_btl_c.freqdiv---
++//
++#define ma_pmcfg_btl_c__freqdiv__a 19
++#define ma_pmcfg_btl_c__freqdiv__len 2
++#define ma_pmcfg_btl_c__freqdiv__mask 0x06
++#define ma_pmcfg_btl_c__freqdiv__shift 0x01
++#define ma_pmcfg_btl_c__freqdiv__reset 0x01
++//-------------------------------------------------------pmcfg_btl_c.modtype---
++//
++#define ma_pmcfg_btl_c__modtype__a 19
++#define ma_pmcfg_btl_c__modtype__len 2
++#define ma_pmcfg_btl_c__modtype__mask 0x18
++#define ma_pmcfg_btl_c__modtype__shift 0x03
++#define ma_pmcfg_btl_c__modtype__reset 0x01
++//----------------------------------------------------pmcfg_btl_c.lf_gain_ol---
++//
++#define ma_pmcfg_btl_c__lf_gain_ol__a 19
++#define ma_pmcfg_btl_c__lf_gain_ol__len 1
++#define ma_pmcfg_btl_c__lf_gain_ol__mask 0x01
++#define ma_pmcfg_btl_c__lf_gain_ol__shift 0x00
++#define ma_pmcfg_btl_c__lf_gain_ol__reset 0x00
++//-------------------------------------------------------pmcfg_btl_d.modtype---
++//
++#define ma_pmcfg_btl_d__modtype__a 20
++#define ma_pmcfg_btl_d__modtype__len 2
++#define ma_pmcfg_btl_d__modtype__mask 0x18
++#define ma_pmcfg_btl_d__modtype__shift 0x03
++#define ma_pmcfg_btl_d__modtype__reset 0x02
++//-------------------------------------------------------pmcfg_btl_d.freqdiv---
++//
++#define ma_pmcfg_btl_d__freqdiv__a 20
++#define ma_pmcfg_btl_d__freqdiv__len 2
++#define ma_pmcfg_btl_d__freqdiv__mask 0x06
++#define ma_pmcfg_btl_d__freqdiv__shift 0x01
++#define ma_pmcfg_btl_d__freqdiv__reset 0x02
++//----------------------------------------------------pmcfg_btl_d.lf_gain_ol---
++//
++#define ma_pmcfg_btl_d__lf_gain_ol__a 20
++#define ma_pmcfg_btl_d__lf_gain_ol__len 1
++#define ma_pmcfg_btl_d__lf_gain_ol__mask 0x01
++#define ma_pmcfg_btl_d__lf_gain_ol__shift 0x00
++#define ma_pmcfg_btl_d__lf_gain_ol__reset 0x00
++//------------ -------------------------------------------pmcfg_se_a.modtype---
++//
++#define ma_pmcfg_se_a__modtype__a 21
++#define ma_pmcfg_se_a__modtype__len 2
++#define ma_pmcfg_se_a__modtype__mask 0x18
++#define ma_pmcfg_se_a__modtype__shift 0x03
++#define ma_pmcfg_se_a__modtype__reset 0x01
++//--------------------------------------------------------pmcfg_se_a.freqdiv---
++//
++#define ma_pmcfg_se_a__freqdiv__a 21
++#define ma_pmcfg_se_a__freqdiv__len 2
++#define ma_pmcfg_se_a__freqdiv__mask 0x06
++#define ma_pmcfg_se_a__freqdiv__shift 0x01
++#define ma_pmcfg_se_a__freqdiv__reset 0x00
++//-----------------------------------------------------pmcfg_se_a.lf_gain_ol---
++//
++#define ma_pmcfg_se_a__lf_gain_ol__a 21
++#define ma_pmcfg_se_a__lf_gain_ol__len 1
++#define ma_pmcfg_se_a__lf_gain_ol__mask 0x01
++#define ma_pmcfg_se_a__lf_gain_ol__shift 0x00
++#define ma_pmcfg_se_a__lf_gain_ol__reset 0x01
++//-----------------------------------------------------pmcfg_se_b.lf_gain_ol---
++//
++#define ma_pmcfg_se_b__lf_gain_ol__a 22
++#define ma_pmcfg_se_b__lf_gain_ol__len 1
++#define ma_pmcfg_se_b__lf_gain_ol__mask 0x01
++#define ma_pmcfg_se_b__lf_gain_ol__shift 0x00
++#define ma_pmcfg_se_b__lf_gain_ol__reset 0x00
++//--------------------------------------------------------pmcfg_se_b.freqdiv---
++//
++#define ma_pmcfg_se_b__freqdiv__a 22
++#define ma_pmcfg_se_b__freqdiv__len 2
++#define ma_pmcfg_se_b__freqdiv__mask 0x06
++#define ma_pmcfg_se_b__freqdiv__shift 0x01
++#define ma_pmcfg_se_b__freqdiv__reset 0x01
++//--------------------------------------------------------pmcfg_se_b.modtype---
++//
++#define ma_pmcfg_se_b__modtype__a 22
++#define ma_pmcfg_se_b__modtype__len 2
++#define ma_pmcfg_se_b__modtype__mask 0x18
++#define ma_pmcfg_se_b__modtype__shift 0x03
++#define ma_pmcfg_se_b__modtype__reset 0x01
++//----------------------------------------------------------balwaitcount_pm1---
++// pm1 balancing period.
++#define ma_balwaitcount_pm1__a 23
++#define ma_balwaitcount_pm1__len 8
++#define ma_balwaitcount_pm1__mask 0xff
++#define ma_balwaitcount_pm1__shift 0x00
++#define ma_balwaitcount_pm1__reset 0x14
++//----------------------------------------------------------balwaitcount_pm2---
++// pm2 balancing period.
++#define ma_balwaitcount_pm2__a 24
++#define ma_balwaitcount_pm2__len 8
++#define ma_balwaitcount_pm2__mask 0xff
++#define ma_balwaitcount_pm2__shift 0x00
++#define ma_balwaitcount_pm2__reset 0x14
++//----------------------------------------------------------balwaitcount_pm3---
++// pm3 balancing period.
++#define ma_balwaitcount_pm3__a 25
++#define ma_balwaitcount_pm3__len 8
++#define ma_balwaitcount_pm3__mask 0xff
++#define ma_balwaitcount_pm3__shift 0x00
++#define ma_balwaitcount_pm3__reset 0x1a
++//-------------------------------------------------------------usespread_pm1---
++// pm1 pwm spread-spectrum mode on/off.
++#define ma_usespread_pm1__a 26
++#define ma_usespread_pm1__len 1
++#define ma_usespread_pm1__mask 0x40
++#define ma_usespread_pm1__shift 0x06
++#define ma_usespread_pm1__reset 0x00
++//---------------------------------------------------------------dtsteps_pm1---
++// pm1 dead time setting [10ns steps].
++#define ma_dtsteps_pm1__a 26
++#define ma_dtsteps_pm1__len 3
++#define ma_dtsteps_pm1__mask 0x38
++#define ma_dtsteps_pm1__shift 0x03
++#define ma_dtsteps_pm1__reset 0x04
++//---------------------------------------------------------------baltype_pm1---
++// pm1 balancing sensor scheme.
++#define ma_baltype_pm1__a 26
++#define ma_baltype_pm1__len 3
++#define ma_baltype_pm1__mask 0x07
++#define ma_baltype_pm1__shift 0x00
++#define ma_baltype_pm1__reset 0x00
++//-------------------------------------------------------------usespread_pm2---
++// pm2 pwm spread-spectrum mode on/off.
++#define ma_usespread_pm2__a 27
++#define ma_usespread_pm2__len 1
++#define ma_usespread_pm2__mask 0x40
++#define ma_usespread_pm2__shift 0x06
++#define ma_usespread_pm2__reset 0x00
++//---------------------------------------------------------------dtsteps_pm2---
++// pm2 dead time setting [10ns steps].
++#define ma_dtsteps_pm2__a 27
++#define ma_dtsteps_pm2__len 3
++#define ma_dtsteps_pm2__mask 0x38
++#define ma_dtsteps_pm2__shift 0x03
++#define ma_dtsteps_pm2__reset 0x03
++//---------------------------------------------------------------baltype_pm2---
++// pm2 balancing sensor scheme.
++#define ma_baltype_pm2__a 27
++#define ma_baltype_pm2__len 3
++#define ma_baltype_pm2__mask 0x07
++#define ma_baltype_pm2__shift 0x00
++#define ma_baltype_pm2__reset 0x01
++//-------------------------------------------------------------usespread_pm3---
++// pm3 pwm spread-spectrum mode on/off.
++#define ma_usespread_pm3__a 28
++#define ma_usespread_pm3__len 1
++#define ma_usespread_pm3__mask 0x40
++#define ma_usespread_pm3__shift 0x06
++#define ma_usespread_pm3__reset 0x00
++//---------------------------------------------------------------dtsteps_pm3---
++// pm3 dead time setting [10ns steps].
++#define ma_dtsteps_pm3__a 28
++#define ma_dtsteps_pm3__len 3
++#define ma_dtsteps_pm3__mask 0x38
++#define ma_dtsteps_pm3__shift 0x03
++#define ma_dtsteps_pm3__reset 0x01
++//---------------------------------------------------------------baltype_pm3---
++// pm3 balancing sensor scheme.
++#define ma_baltype_pm3__a 28
++#define ma_baltype_pm3__len 3
++#define ma_baltype_pm3__mask 0x07
++#define ma_baltype_pm3__shift 0x00
++#define ma_baltype_pm3__reset 0x03
++//-----------------------------------------------------------------pmprofile---
++// pm profile select. valid presets: 0-1-2-3-4. 5=> custom profile.
++#define ma_pmprofile__a 29
++#define ma_pmprofile__len 3
++#define ma_pmprofile__mask 0x07
++#define ma_pmprofile__shift 0x00
++#define ma_pmprofile__reset 0x00
++//-------------------------------------------------------------------pm3_man---
++// custom profile pm3 contents. 0=>a,  1=>b,  2=>c,  3=>d
++#define ma_pm3_man__a 30
++#define ma_pm3_man__len 2
++#define ma_pm3_man__mask 0x30
++#define ma_pm3_man__shift 0x04
++#define ma_pm3_man__reset 0x02
++//-------------------------------------------------------------------pm2_man---
++// custom profile pm2 contents. 0=>a,  1=>b,  2=>c,  3=>d
++#define ma_pm2_man__a 30
++#define ma_pm2_man__len 2
++#define ma_pm2_man__mask 0x0c
++#define ma_pm2_man__shift 0x02
++#define ma_pm2_man__reset 0x03
++//-------------------------------------------------------------------pm1_man---
++// custom profile pm1 contents. 0=>a,  1=>b,  2=>c,  3=>d
++#define ma_pm1_man__a 30
++#define ma_pm1_man__len 2
++#define ma_pm1_man__mask 0x03
++#define ma_pm1_man__shift 0x00
++#define ma_pm1_man__reset 0x03
++//-----------------------------------------------------------ocp_latch_clear---
++// low-high clears current ocp latched condition.
++#define ma_ocp_latch_clear__a 32
++#define ma_ocp_latch_clear__len 1
++#define ma_ocp_latch_clear__mask 0x80
++#define ma_ocp_latch_clear__shift 0x07
++#define ma_ocp_latch_clear__reset 0x00
++//-------------------------------------------------------------audio_in_mode---
++// audio input mode; 0-1-2-3-4-5
++#define ma_audio_in_mode__a 37
++#define ma_audio_in_mode__len 3
++#define ma_audio_in_mode__mask 0xe0
++#define ma_audio_in_mode__shift 0x05
++#define ma_audio_in_mode__reset 0x00
++//-----------------------------------------------------------------eh_dcshdn---
++// high to enable dc protection
++#define ma_eh_dcshdn__a 38
++#define ma_eh_dcshdn__len 1
++#define ma_eh_dcshdn__mask 0x04
++#define ma_eh_dcshdn__shift 0x02
++#define ma_eh_dcshdn__reset 0x01
++//---------------------------------------------------------audio_in_mode_ext---
++// if set,  audio_in_mode is controlled from audio_in_mode register. if not set
++//audio_in_mode is set from fuse bank setting
++#define ma_audio_in_mode_ext__a 39
++#define ma_audio_in_mode_ext__len 1
++#define ma_audio_in_mode_ext__mask 0x20
++#define ma_audio_in_mode_ext__shift 0x05
++#define ma_audio_in_mode_ext__reset 0x00
++//------------------------------------------------------------------eh_clear---
++// flip to clear error registers
++#define ma_eh_clear__a 45
++#define ma_eh_clear__len 1
++#define ma_eh_clear__mask 0x04
++#define ma_eh_clear__shift 0x02
++#define ma_eh_clear__reset 0x00
++//----------------------------------------------------------thermal_compr_en---
++// enable otw-contr.  input compression?
++#define ma_thermal_compr_en__a 45
++#define ma_thermal_compr_en__len 1
++#define ma_thermal_compr_en__mask 0x20
++#define ma_thermal_compr_en__shift 0x05
++#define ma_thermal_compr_en__reset 0x01
++//---------------------------------------------------------------system_mute---
++// 1 = mute system,  0 = normal operation
++#define ma_system_mute__a 45
++#define ma_system_mute__len 1
++#define ma_system_mute__mask 0x40
++#define ma_system_mute__shift 0x06
++#define ma_system_mute__reset 0x00
++//------------------------------------------------------thermal_compr_max_db---
++// audio limiter max thermal reduction
++#define ma_thermal_compr_max_db__a 46
++#define ma_thermal_compr_max_db__len 3
++#define ma_thermal_compr_max_db__mask 0x07
++#define ma_thermal_compr_max_db__shift 0x00
++#define ma_thermal_compr_max_db__reset 0x04
++//---------------------------------------------------------audio_proc_enable---
++// enable audio proc,  bypass if not enabled
++#define ma_audio_proc_enable__a 53
++#define ma_audio_proc_enable__len 1
++#define ma_audio_proc_enable__mask 0x08
++#define ma_audio_proc_enable__shift 0x03
++#define ma_audio_proc_enable__reset 0x00
++//--------------------------------------------------------audio_proc_release---
++// 00:slow,  01:normal,  10:fast
++#define ma_audio_proc_release__a 53
++#define ma_audio_proc_release__len 2
++#define ma_audio_proc_release__mask 0x30
++#define ma_audio_proc_release__shift 0x04
++#define ma_audio_proc_release__reset 0x00
++//---------------------------------------------------------audio_proc_attack---
++// 00:slow,  01:normal,  10:fast
++#define ma_audio_proc_attack__a 53
++#define ma_audio_proc_attack__len 2
++#define ma_audio_proc_attack__mask 0xc0
++#define ma_audio_proc_attack__shift 0x06
++#define ma_audio_proc_attack__reset 0x00
++//----------------------------------------------------------------i2s_format---
++// i2s basic data format,  000 = std. i2s,  001 = left justified (default)
++#define ma_i2s_format__a 53
++#define ma_i2s_format__len 3
++#define ma_i2s_format__mask 0x07
++#define ma_i2s_format__shift 0x00
++#define ma_i2s_format__reset 0x01
++//--------------------------------------------------audio_proc_limiterenable---
++// 1: enable limiter,  0: disable limiter
++#define ma_audio_proc_limiterenable__a 54
++#define ma_audio_proc_limiterenable__len 1
++#define ma_audio_proc_limiterenable__mask 0x40
++#define ma_audio_proc_limiterenable__shift 0x06
++#define ma_audio_proc_limiterenable__reset 0x00
++//-----------------------------------------------------------audio_proc_mute---
++// 1: mute,  0: unmute
++#define ma_audio_proc_mute__a 54
++#define ma_audio_proc_mute__len 1
++#define ma_audio_proc_mute__mask 0x80
++#define ma_audio_proc_mute__shift 0x07
++#define ma_audio_proc_mute__reset 0x00
++//---------------------------------------------------------------i2s_sck_pol---
++// i2s sck polarity cfg. 0 = rising edge data change
++#define ma_i2s_sck_pol__a 54
++#define ma_i2s_sck_pol__len 1
++#define ma_i2s_sck_pol__mask 0x01
++#define ma_i2s_sck_pol__shift 0x00
++#define ma_i2s_sck_pol__reset 0x01
++//-------------------------------------------------------------i2s_framesize---
++// i2s word length. 00 = 32bit,  01 = 24bit
++#define ma_i2s_framesize__a 54
++#define ma_i2s_framesize__len 2
++#define ma_i2s_framesize__mask 0x18
++#define ma_i2s_framesize__shift 0x03
++#define ma_i2s_framesize__reset 0x00
++//----------------------------------------------------------------i2s_ws_pol---
++// i2s ws polarity. 0 = low first
++#define ma_i2s_ws_pol__a 54
++#define ma_i2s_ws_pol__len 1
++#define ma_i2s_ws_pol__mask 0x02
++#define ma_i2s_ws_pol__shift 0x01
++#define ma_i2s_ws_pol__reset 0x00
++//-----------------------------------------------------------------i2s_order---
++// i2s word bit order. 0 = msb first
++#define ma_i2s_order__a 54
++#define ma_i2s_order__len 1
++#define ma_i2s_order__mask 0x04
++#define ma_i2s_order__shift 0x02
++#define ma_i2s_order__reset 0x00
++//------------------------------------------------------------i2s_rightfirst---
++// i2s l/r word order; 0 = left first
++#define ma_i2s_rightfirst__a 54
++#define ma_i2s_rightfirst__len 1
++#define ma_i2s_rightfirst__mask 0x20
++#define ma_i2s_rightfirst__shift 0x05
++#define ma_i2s_rightfirst__reset 0x00
++//-------------------------------------------------------------vol_db_master---
++// master volume db
++#define ma_vol_db_master__a 64
++#define ma_vol_db_master__len 8
++#define ma_vol_db_master__mask 0xff
++#define ma_vol_db_master__shift 0x00
++#define ma_vol_db_master__reset 0x18
++//------------------------------------------------------------vol_lsb_master---
++// master volume lsb 1/4 steps
++#define ma_vol_lsb_master__a 65
++#define ma_vol_lsb_master__len 2
++#define ma_vol_lsb_master__mask 0x03
++#define ma_vol_lsb_master__shift 0x00
++#define ma_vol_lsb_master__reset 0x00
++//----------------------------------------------------------------vol_db_ch0---
++// volume channel 0
++#define ma_vol_db_ch0__a 66
++#define ma_vol_db_ch0__len 8
++#define ma_vol_db_ch0__mask 0xff
++#define ma_vol_db_ch0__shift 0x00
++#define ma_vol_db_ch0__reset 0x18
++//----------------------------------------------------------------vol_db_ch1---
++// volume channel 1
++#define ma_vol_db_ch1__a 67
++#define ma_vol_db_ch1__len 8
++#define ma_vol_db_ch1__mask 0xff
++#define ma_vol_db_ch1__shift 0x00
++#define ma_vol_db_ch1__reset 0x18
++//----------------------------------------------------------------vol_db_ch2---
++// volume channel 2
++#define ma_vol_db_ch2__a 68
++#define ma_vol_db_ch2__len 8
++#define ma_vol_db_ch2__mask 0xff
++#define ma_vol_db_ch2__shift 0x00
++#define ma_vol_db_ch2__reset 0x18
++//----------------------------------------------------------------vol_db_ch3---
++// volume channel 3
++#define ma_vol_db_ch3__a 69
++#define ma_vol_db_ch3__len 8
++#define ma_vol_db_ch3__mask 0xff
++#define ma_vol_db_ch3__shift 0x00
++#define ma_vol_db_ch3__reset 0x18
++//---------------------------------------------------------------vol_lsb_ch0---
++// volume channel 1 - 1/4 steps
++#define ma_vol_lsb_ch0__a 70
++#define ma_vol_lsb_ch0__len 2
++#define ma_vol_lsb_ch0__mask 0x03
++#define ma_vol_lsb_ch0__shift 0x00
++#define ma_vol_lsb_ch0__reset 0x00
++//---------------------------------------------------------------vol_lsb_ch1---
++// volume channel 3 - 1/4 steps
++#define ma_vol_lsb_ch1__a 70
++#define ma_vol_lsb_ch1__len 2
++#define ma_vol_lsb_ch1__mask 0x0c
++#define ma_vol_lsb_ch1__shift 0x02
++#define ma_vol_lsb_ch1__reset 0x00
++//---------------------------------------------------------------vol_lsb_ch2---
++// volume channel 2 - 1/4 steps
++#define ma_vol_lsb_ch2__a 70
++#define ma_vol_lsb_ch2__len 2
++#define ma_vol_lsb_ch2__mask 0x30
++#define ma_vol_lsb_ch2__shift 0x04
++#define ma_vol_lsb_ch2__reset 0x00
++//---------------------------------------------------------------vol_lsb_ch3---
++// volume channel 3 - 1/4 steps
++#define ma_vol_lsb_ch3__a 70
++#define ma_vol_lsb_ch3__len 2
++#define ma_vol_lsb_ch3__mask 0xc0
++#define ma_vol_lsb_ch3__shift 0x06
++#define ma_vol_lsb_ch3__reset 0x00
++//----------------------------------------------------------------thr_db_ch0---
++// thr_db channel 0
++#define ma_thr_db_ch0__a 71
++#define ma_thr_db_ch0__len 8
++#define ma_thr_db_ch0__mask 0xff
++#define ma_thr_db_ch0__shift 0x00
++#define ma_thr_db_ch0__reset 0x18
++//----------------------------------------------------------------thr_db_ch1---
++// thr db ch1
++#define ma_thr_db_ch1__a 72
++#define ma_thr_db_ch1__len 8
++#define ma_thr_db_ch1__mask 0xff
++#define ma_thr_db_ch1__shift 0x00
++#define ma_thr_db_ch1__reset 0x18
++//----------------------------------------------------------------thr_db_ch2---
++// thr db ch2
++#define ma_thr_db_ch2__a 73
++#define ma_thr_db_ch2__len 8
++#define ma_thr_db_ch2__mask 0xff
++#define ma_thr_db_ch2__shift 0x00
++#define ma_thr_db_ch2__reset 0x18
++//----------------------------------------------------------------thr_db_ch3---
++// threshold db ch3
++#define ma_thr_db_ch3__a 74
++#define ma_thr_db_ch3__len 8
++#define ma_thr_db_ch3__mask 0xff
++#define ma_thr_db_ch3__shift 0x00
++#define ma_thr_db_ch3__reset 0x18
++//---------------------------------------------------------------thr_lsb_ch0---
++// thr lsb ch0
++#define ma_thr_lsb_ch0__a 75
++#define ma_thr_lsb_ch0__len 2
++#define ma_thr_lsb_ch0__mask 0x03
++#define ma_thr_lsb_ch0__shift 0x00
++#define ma_thr_lsb_ch0__reset 0x00
++//---------------------------------------------------------------thr_lsb_ch1---
++// thr lsb ch1
++#define ma_thr_lsb_ch1__a 75
++#define ma_thr_lsb_ch1__len 2
++#define ma_thr_lsb_ch1__mask 0x0c
++#define ma_thr_lsb_ch1__shift 0x02
++#define ma_thr_lsb_ch1__reset 0x00
++//---------------------------------------------------------------thr_lsb_ch2---
++// thr lsb ch2 1/4 db step
++#define ma_thr_lsb_ch2__a 75
++#define ma_thr_lsb_ch2__len 2
++#define ma_thr_lsb_ch2__mask 0x30
++#define ma_thr_lsb_ch2__shift 0x04
++#define ma_thr_lsb_ch2__reset 0x00
++//---------------------------------------------------------------thr_lsb_ch3---
++// threshold lsb ch3
++#define ma_thr_lsb_ch3__a 75
++#define ma_thr_lsb_ch3__len 2
++#define ma_thr_lsb_ch3__mask 0xc0
++#define ma_thr_lsb_ch3__shift 0x06
++#define ma_thr_lsb_ch3__reset 0x00
++//-----------------------------------------------------------dcu_mon0.pm_mon---
++// power mode monitor channel 0
++#define ma_dcu_mon0__pm_mon__a 96
++#define ma_dcu_mon0__pm_mon__len 2
++#define ma_dcu_mon0__pm_mon__mask 0x03
++#define ma_dcu_mon0__pm_mon__shift 0x00
++#define ma_dcu_mon0__pm_mon__reset 0x00
++//-----------------------------------------------------dcu_mon0.freqmode_mon---
++// frequence mode monitor channel 0
++#define ma_dcu_mon0__freqmode_mon__a 96
++#define ma_dcu_mon0__freqmode_mon__len 3
++#define ma_dcu_mon0__freqmode_mon__mask 0x70
++#define ma_dcu_mon0__freqmode_mon__shift 0x04
++#define ma_dcu_mon0__freqmode_mon__reset 0x00
++//-------------------------------------------------------dcu_mon0.pps_passed---
++// dcu0 pps completion indicator
++#define ma_dcu_mon0__pps_passed__a 96
++#define ma_dcu_mon0__pps_passed__len 1
++#define ma_dcu_mon0__pps_passed__mask 0x80
++#define ma_dcu_mon0__pps_passed__shift 0x07
++#define ma_dcu_mon0__pps_passed__reset 0x00
++//----------------------------------------------------------dcu_mon0.ocp_mon---
++// ocp monitor channel 0
++#define ma_dcu_mon0__ocp_mon__a 97
++#define ma_dcu_mon0__ocp_mon__len 1
++#define ma_dcu_mon0__ocp_mon__mask 0x01
++#define ma_dcu_mon0__ocp_mon__shift 0x00
++#define ma_dcu_mon0__ocp_mon__reset 0x00
++//--------------------------------------------------------dcu_mon0.vcfly1_ok---
++// cfly1 protection monitor channel 0.
++#define ma_dcu_mon0__vcfly1_ok__a 97
++#define ma_dcu_mon0__vcfly1_ok__len 1
++#define ma_dcu_mon0__vcfly1_ok__mask 0x02
++#define ma_dcu_mon0__vcfly1_ok__shift 0x01
++#define ma_dcu_mon0__vcfly1_ok__reset 0x00
++//--------------------------------------------------------dcu_mon0.vcfly2_ok---
++// cfly2 protection monitor channel 0.
++#define ma_dcu_mon0__vcfly2_ok__a 97
++#define ma_dcu_mon0__vcfly2_ok__len 1
++#define ma_dcu_mon0__vcfly2_ok__mask 0x04
++#define ma_dcu_mon0__vcfly2_ok__shift 0x02
++#define ma_dcu_mon0__vcfly2_ok__reset 0x00
++//----------------------------------------------------------dcu_mon0.pvdd_ok---
++// dcu0 pvdd monitor
++#define ma_dcu_mon0__pvdd_ok__a 97
++#define ma_dcu_mon0__pvdd_ok__len 1
++#define ma_dcu_mon0__pvdd_ok__mask 0x08
++#define ma_dcu_mon0__pvdd_ok__shift 0x03
++#define ma_dcu_mon0__pvdd_ok__reset 0x00
++//-----------------------------------------------------------dcu_mon0.vdd_ok---
++// dcu0 vdd monitor
++#define ma_dcu_mon0__vdd_ok__a 97
++#define ma_dcu_mon0__vdd_ok__len 1
++#define ma_dcu_mon0__vdd_ok__mask 0x10
++#define ma_dcu_mon0__vdd_ok__shift 0x04
++#define ma_dcu_mon0__vdd_ok__reset 0x00
++//-------------------------------------------------------------dcu_mon0.mute---
++// dcu0 mute monitor
++#define ma_dcu_mon0__mute__a 97
++#define ma_dcu_mon0__mute__len 1
++#define ma_dcu_mon0__mute__mask 0x20
++#define ma_dcu_mon0__mute__shift 0x05
++#define ma_dcu_mon0__mute__reset 0x00
++//------------------------------------------------------------dcu_mon0.m_mon---
++// m sense monitor channel 0
++#define ma_dcu_mon0__m_mon__a 98
++#define ma_dcu_mon0__m_mon__len 8
++#define ma_dcu_mon0__m_mon__mask 0xff
++#define ma_dcu_mon0__m_mon__shift 0x00
++#define ma_dcu_mon0__m_mon__reset 0x00
++//-----------------------------------------------------------dcu_mon1.pm_mon---
++// power mode monitor channel 1
++#define ma_dcu_mon1__pm_mon__a 100
++#define ma_dcu_mon1__pm_mon__len 2
++#define ma_dcu_mon1__pm_mon__mask 0x03
++#define ma_dcu_mon1__pm_mon__shift 0x00
++#define ma_dcu_mon1__pm_mon__reset 0x00
++//-----------------------------------------------------dcu_mon1.freqmode_mon---
++// frequence mode monitor channel 1
++#define ma_dcu_mon1__freqmode_mon__a 100
++#define ma_dcu_mon1__freqmode_mon__len 3
++#define ma_dcu_mon1__freqmode_mon__mask 0x70
++#define ma_dcu_mon1__freqmode_mon__shift 0x04
++#define ma_dcu_mon1__freqmode_mon__reset 0x00
++//-------------------------------------------------------dcu_mon1.pps_passed---
++// dcu1 pps completion indicator
++#define ma_dcu_mon1__pps_passed__a 100
++#define ma_dcu_mon1__pps_passed__len 1
++#define ma_dcu_mon1__pps_passed__mask 0x80
++#define ma_dcu_mon1__pps_passed__shift 0x07
++#define ma_dcu_mon1__pps_passed__reset 0x00
++//----------------------------------------------------------dcu_mon1.ocp_mon---
++// ocp monitor channel 1
++#define ma_dcu_mon1__ocp_mon__a 101
++#define ma_dcu_mon1__ocp_mon__len 1
++#define ma_dcu_mon1__ocp_mon__mask 0x01
++#define ma_dcu_mon1__ocp_mon__shift 0x00
++#define ma_dcu_mon1__ocp_mon__reset 0x00
++//--------------------------------------------------------dcu_mon1.vcfly1_ok---
++// cfly1 protcetion monitor channel 1
++#define ma_dcu_mon1__vcfly1_ok__a 101
++#define ma_dcu_mon1__vcfly1_ok__len 1
++#define ma_dcu_mon1__vcfly1_ok__mask 0x02
++#define ma_dcu_mon1__vcfly1_ok__shift 0x01
++#define ma_dcu_mon1__vcfly1_ok__reset 0x00
++//--------------------------------------------------------dcu_mon1.vcfly2_ok---
++// cfly2 protection monitor channel 1
++#define ma_dcu_mon1__vcfly2_ok__a 101
++#define ma_dcu_mon1__vcfly2_ok__len 1
++#define ma_dcu_mon1__vcfly2_ok__mask 0x04
++#define ma_dcu_mon1__vcfly2_ok__shift 0x02
++#define ma_dcu_mon1__vcfly2_ok__reset 0x00
++//----------------------------------------------------------dcu_mon1.pvdd_ok---
++// dcu1 pvdd monitor
++#define ma_dcu_mon1__pvdd_ok__a 101
++#define ma_dcu_mon1__pvdd_ok__len 1
++#define ma_dcu_mon1__pvdd_ok__mask 0x08
++#define ma_dcu_mon1__pvdd_ok__shift 0x03
++#define ma_dcu_mon1__pvdd_ok__reset 0x00
++//-----------------------------------------------------------dcu_mon1.vdd_ok---
++// dcu1 vdd monitor
++#define ma_dcu_mon1__vdd_ok__a 101
++#define ma_dcu_mon1__vdd_ok__len 1
++#define ma_dcu_mon1__vdd_ok__mask 0x10
++#define ma_dcu_mon1__vdd_ok__shift 0x04
++#define ma_dcu_mon1__vdd_ok__reset 0x00
++//-------------------------------------------------------------dcu_mon1.mute---
++// dcu1 mute monitor
++#define ma_dcu_mon1__mute__a 101
++#define ma_dcu_mon1__mute__len 1
++#define ma_dcu_mon1__mute__mask 0x20
++#define ma_dcu_mon1__mute__shift 0x05
++#define ma_dcu_mon1__mute__reset 0x00
++//------------------------------------------------------------dcu_mon1.m_mon---
++// m sense monitor channel 1
++#define ma_dcu_mon1__m_mon__a 102
++#define ma_dcu_mon1__m_mon__len 8
++#define ma_dcu_mon1__m_mon__mask 0xff
++#define ma_dcu_mon1__m_mon__shift 0x00
++#define ma_dcu_mon1__m_mon__reset 0x00
++//--------------------------------------------------------dcu_mon0.sw_enable---
++// dcu0 switch enable monitor
++#define ma_dcu_mon0__sw_enable__a 104
++#define ma_dcu_mon0__sw_enable__len 1
++#define ma_dcu_mon0__sw_enable__mask 0x40
++#define ma_dcu_mon0__sw_enable__shift 0x06
++#define ma_dcu_mon0__sw_enable__reset 0x00
++//--------------------------------------------------------dcu_mon1.sw_enable---
++// dcu1 switch enable monitor
++#define ma_dcu_mon1__sw_enable__a 104
++#define ma_dcu_mon1__sw_enable__len 1
++#define ma_dcu_mon1__sw_enable__mask 0x80
++#define ma_dcu_mon1__sw_enable__shift 0x07
++#define ma_dcu_mon1__sw_enable__reset 0x00
++//------------------------------------------------------------hvboot0_ok_mon---
++// hvboot0_ok for test/debug
++#define ma_hvboot0_ok_mon__a 105
++#define ma_hvboot0_ok_mon__len 1
++#define ma_hvboot0_ok_mon__mask 0x40
++#define ma_hvboot0_ok_mon__shift 0x06
++#define ma_hvboot0_ok_mon__reset 0x00
++//------------------------------------------------------------hvboot1_ok_mon---
++// hvboot1_ok for test/debug
++#define ma_hvboot1_ok_mon__a 105
++#define ma_hvboot1_ok_mon__len 1
++#define ma_hvboot1_ok_mon__mask 0x80
++#define ma_hvboot1_ok_mon__shift 0x07
++#define ma_hvboot1_ok_mon__reset 0x00
++//-----------------------------------------------------------------error_acc---
++// accumulated errors,  at and after triggering
++#define ma_error_acc__a 109
++#define ma_error_acc__len 8
++#define ma_error_acc__mask 0xff
++#define ma_error_acc__shift 0x00
++#define ma_error_acc__reset 0x00
++//-------------------------------------------------------------i2s_data_rate---
++// detected i2s data rate: 00/01/10 = x1/x2/x4
++#define ma_i2s_data_rate__a 116
++#define ma_i2s_data_rate__len 2
++#define ma_i2s_data_rate__mask 0x03
++#define ma_i2s_data_rate__shift 0x00
++#define ma_i2s_data_rate__reset 0x00
++//---------------------------------------------------------audio_in_mode_mon---
++// audio input mode monitor
++#define ma_audio_in_mode_mon__a 116
++#define ma_audio_in_mode_mon__len 3
++#define ma_audio_in_mode_mon__mask 0x1c
++#define ma_audio_in_mode_mon__shift 0x02
++#define ma_audio_in_mode_mon__reset 0x00
++//------------------------------------------------------------------msel_mon---
++// msel[2:0] monitor register
++#define ma_msel_mon__a 117
++#define ma_msel_mon__len 3
++#define ma_msel_mon__mask 0x07
++#define ma_msel_mon__shift 0x00
++#define ma_msel_mon__reset 0x00
++//---------------------------------------------------------------------error---
++// current error flag monitor reg - for app. ctrl.
++#define ma_error__a 124
++#define ma_error__len 8
++#define ma_error__mask 0xff
++#define ma_error__shift 0x00
++#define ma_error__reset 0x00
++//----------------------------------------------------audio_proc_limiter_mon---
++// b7-b4: channel 3-0 limiter active
++#define ma_audio_proc_limiter_mon__a 126
++#define ma_audio_proc_limiter_mon__len 4
++#define ma_audio_proc_limiter_mon__mask 0xf0
++#define ma_audio_proc_limiter_mon__shift 0x04
++#define ma_audio_proc_limiter_mon__reset 0x00
++//-------------------------------------------------------audio_proc_clip_mon---
++// b3-b0: channel 3-0 clipping monitor
++#define ma_audio_proc_clip_mon__a 126
++#define ma_audio_proc_clip_mon__len 4
++#define ma_audio_proc_clip_mon__mask 0x0f
++#define ma_audio_proc_clip_mon__shift 0x00
++#define ma_audio_proc_clip_mon__reset 0x00
++#endif
++
++#define SOC_ENUM_ERR(xname, xenum)\
++{     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
++      .access = SNDRV_CTL_ELEM_ACCESS_READ,\
++      .info = snd_soc_info_enum_double,\
++      .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double,\
++      .private_value = (unsigned long)&(xenum) }
++
++static struct i2c_client *i2c;
++
++struct ma120x0p_priv {
++      struct regmap *regmap;
++      int mclk_div;
++      struct snd_soc_component *component;
++      struct gpio_desc *enable_gpio;
++      struct gpio_desc *mute_gpio;
++      struct gpio_desc *booster_gpio;
++      struct gpio_desc *error_gpio;
++};
++
++static struct ma120x0p_priv *priv_data;
++
++//Used to share the IRQ number within this file
++static unsigned int irqNumber;
++
++// Function prototype for the custom IRQ handler function
++static irqreturn_t ma120x0p_irq_handler(int irq, void *data);
++
++//Alsa Controls
++static const char * const limenable_text[] = {"Bypassed", "Enabled"};
++static const char * const limatack_text[] = {"Slow", "Normal", "Fast"};
++static const char * const limrelease_text[] = {"Slow", "Normal", "Fast"};
++
++static const char * const err_flycap_text[] = {"Ok", "Error"};
++static const char * const err_overcurr_text[] = {"Ok", "Error"};
++static const char * const err_pllerr_text[] = {"Ok", "Error"};
++static const char * const err_pvddunder_text[] = {"Ok", "Error"};
++static const char * const err_overtempw_text[] = {"Ok", "Error"};
++static const char * const err_overtempe_text[] = {"Ok", "Error"};
++static const char * const err_pinlowimp_text[] = {"Ok", "Error"};
++static const char * const err_dcprot_text[] = {"Ok", "Error"};
++
++static const char * const pwr_mode_prof_text[] = {"PMF0", "PMF1", "PMF2",
++"PMF3", "PMF4"};
++
++static const struct soc_enum lim_enable_ctrl =
++      SOC_ENUM_SINGLE(ma_audio_proc_limiterenable__a,
++              ma_audio_proc_limiterenable__shift,
++              ma_audio_proc_limiterenable__len + 1,
++              limenable_text);
++static const struct soc_enum limatack_ctrl =
++      SOC_ENUM_SINGLE(ma_audio_proc_attack__a,
++              ma_audio_proc_attack__shift,
++              ma_audio_proc_attack__len + 1,
++              limatack_text);
++static const struct soc_enum limrelease_ctrl =
++      SOC_ENUM_SINGLE(ma_audio_proc_release__a,
++              ma_audio_proc_release__shift,
++              ma_audio_proc_release__len + 1,
++              limrelease_text);
++static const struct soc_enum err_flycap_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 0, 3, err_flycap_text);
++static const struct soc_enum err_overcurr_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 1, 3, err_overcurr_text);
++static const struct soc_enum err_pllerr_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 2, 3, err_pllerr_text);
++static const struct soc_enum err_pvddunder_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 3, 3, err_pvddunder_text);
++static const struct soc_enum err_overtempw_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 4, 3, err_overtempw_text);
++static const struct soc_enum err_overtempe_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 5, 3, err_overtempe_text);
++static const struct soc_enum err_pinlowimp_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 6, 3, err_pinlowimp_text);
++static const struct soc_enum err_dcprot_ctrl =
++      SOC_ENUM_SINGLE(ma_error__a, 7, 3, err_dcprot_text);
++static const struct soc_enum pwr_mode_prof_ctrl =
++      SOC_ENUM_SINGLE(ma_pmprofile__a, ma_pmprofile__shift, 5,
++              pwr_mode_prof_text);
++
++static const char * const pwr_mode_texts[] = {
++              "Dynamic power mode",
++              "Power mode 1",
++              "Power mode 2",
++              "Power mode 3",
++      };
++
++static const int pwr_mode_values[] = {
++              0x10,
++              0x50,
++              0x60,
++              0x70,
++      };
++
++static const SOC_VALUE_ENUM_SINGLE_DECL(pwr_mode_ctrl,
++      ma_pm_man__a, 0, 0x70,
++      pwr_mode_texts,
++      pwr_mode_values);
++
++static const DECLARE_TLV_DB_SCALE(ma120x0p_vol_tlv, -5000, 100,  0);
++static const DECLARE_TLV_DB_SCALE(ma120x0p_lim_tlv, -5000, 100,  0);
++static const DECLARE_TLV_DB_SCALE(ma120x0p_lr_tlv, -5000, 100,  0);
++
++static const struct snd_kcontrol_new ma120x0p_snd_controls[] = {
++      //Master Volume
++      SOC_SINGLE_RANGE_TLV("A.Mstr Vol Volume",
++              ma_vol_db_master__a, 0, 0x18, 0x4a, 1, ma120x0p_vol_tlv),
++
++      //L-R Volume ch0
++      SOC_SINGLE_RANGE_TLV("B.L Vol Volume",
++              ma_vol_db_ch0__a, 0, 0x18, 0x4a, 1, ma120x0p_lr_tlv),
++      SOC_SINGLE_RANGE_TLV("C.R Vol Volume",
++              ma_vol_db_ch1__a, 0, 0x18, 0x4a, 1, ma120x0p_lr_tlv),
++
++      //L-R Limiter Threshold ch0-ch1
++      SOC_DOUBLE_R_RANGE_TLV("D.Lim thresh Volume",
++              ma_thr_db_ch0__a, ma_thr_db_ch1__a, 0, 0x0e, 0x4a, 1,
++              ma120x0p_lim_tlv),
++
++      //Enum Switches/Selectors
++      //SOC_ENUM("E.AudioProc Mute", audioproc_mute_ctrl),
++      SOC_ENUM("F.Limiter Enable", lim_enable_ctrl),
++      SOC_ENUM("G.Limiter Attck", limatack_ctrl),
++      SOC_ENUM("H.Limiter Rls", limrelease_ctrl),
++
++      //Enum Error Monitor (read-only)
++      SOC_ENUM_ERR("I.Err flycap", err_flycap_ctrl),
++      SOC_ENUM_ERR("J.Err overcurr", err_overcurr_ctrl),
++      SOC_ENUM_ERR("K.Err pllerr", err_pllerr_ctrl),
++      SOC_ENUM_ERR("L.Err pvddunder", err_pvddunder_ctrl),
++      SOC_ENUM_ERR("M.Err overtempw", err_overtempw_ctrl),
++      SOC_ENUM_ERR("N.Err overtempe", err_overtempe_ctrl),
++      SOC_ENUM_ERR("O.Err pinlowimp", err_pinlowimp_ctrl),
++      SOC_ENUM_ERR("P.Err dcprot", err_dcprot_ctrl),
++
++      //Power modes profiles
++      SOC_ENUM("Q.PM Prof", pwr_mode_prof_ctrl),
++
++      // Power mode selection (Dynamic,1,2,3)
++      SOC_ENUM("R.Power Mode", pwr_mode_ctrl),
++};
++
++//Machine Driver
++static int ma120x0p_hw_params(struct snd_pcm_substream *substream,
++      struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
++{
++      u16 blen = 0x00;
++
++      struct snd_soc_component *component = dai->component;
++
++      priv_data->component = component;
++
++      switch (params_format(params)) {
++      case SNDRV_PCM_FORMAT_S16_LE:
++              blen = 0x10;
++              break;
++      case SNDRV_PCM_FORMAT_S24_LE:
++              blen = 0x00;
++              break;
++      case SNDRV_PCM_FORMAT_S32_LE:
++              blen = 0x00;
++              break;
++      default:
++              dev_err(dai->dev, "Unsupported word length: %u\n",
++              params_format(params));
++              return -EINVAL;
++      }
++
++      // set word length
++      snd_soc_component_update_bits(component, ma_i2s_framesize__a,
++              ma_i2s_framesize__mask, blen);
++
++      return 0;
++}
++
++static int ma120x0p_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
++{
++      int val = 0;
++
++      struct ma120x0p_priv *ma120x0p;
++
++      struct snd_soc_component *component = dai->component;
++
++      ma120x0p = snd_soc_component_get_drvdata(component);
++
++      if (mute)
++              val = 0;
++      else
++              val = 1;
++
++      gpiod_set_value_cansleep(priv_data->mute_gpio, val);
++
++      return 0;
++}
++
++static const struct snd_soc_dai_ops ma120x0p_dai_ops = {
++      .hw_params              =       ma120x0p_hw_params,
++      .mute_stream    =       ma120x0p_mute_stream,
++};
++
++static struct snd_soc_dai_driver ma120x0p_dai = {
++      .name           = "ma120x0p-amp",
++      .playback       =       {
++              .stream_name    = "Playback",
++              .channels_min   = 2,
++              .channels_max   = 2,
++              .rates = SNDRV_PCM_RATE_CONTINUOUS,
++              .rate_min = 44100,
++              .rate_max = 48000,
++              .formats = SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE
++      },
++      .ops        = &ma120x0p_dai_ops,
++};
++
++//Codec Driver
++static int ma120x0p_clear_err(struct snd_soc_component *component)
++{
++      int ret = 0;
++
++      struct ma120x0p_priv *ma120x0p;
++
++      ma120x0p = snd_soc_component_get_drvdata(component);
++
++      ret = snd_soc_component_update_bits(component,
++              ma_eh_clear__a, ma_eh_clear__mask, 0x00);
++      if (ret < 0)
++              return ret;
++
++      ret = snd_soc_component_update_bits(component,
++              ma_eh_clear__a, ma_eh_clear__mask, 0x04);
++      if (ret < 0)
++              return ret;
++
++      ret = snd_soc_component_update_bits(component,
++              ma_eh_clear__a, ma_eh_clear__mask, 0x00);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static void ma120x0p_remove(struct snd_soc_component *component)
++{
++      struct ma120x0p_priv *ma120x0p;
++
++      ma120x0p = snd_soc_component_get_drvdata(component);
++}
++
++static int ma120x0p_probe(struct snd_soc_component *component)
++{
++      struct ma120x0p_priv *ma120x0p;
++
++      int ret = 0;
++
++      i2c = container_of(component->dev, struct i2c_client, dev);
++
++      ma120x0p = snd_soc_component_get_drvdata(component);
++
++      //Reset error
++      ma120x0p_clear_err(component);
++      if (ret < 0)
++              return ret;
++
++      // set serial audio format I2S and enable audio processor
++      ret = snd_soc_component_write(component, ma_i2s_format__a, 0x08);
++      if (ret < 0)
++              return ret;
++
++      // Enable audio limiter
++      ret = snd_soc_component_update_bits(component,
++              ma_audio_proc_limiterenable__a,
++              ma_audio_proc_limiterenable__mask, 0x40);
++      if (ret < 0)
++              return ret;
++
++      // Set lim attack to fast
++      ret = snd_soc_component_update_bits(component,
++              ma_audio_proc_attack__a, ma_audio_proc_attack__mask, 0x80);
++      if (ret < 0)
++              return ret;
++
++      // Set lim attack to low
++      ret = snd_soc_component_update_bits(component,
++              ma_audio_proc_release__a, ma_audio_proc_release__mask, 0x00);
++      if (ret < 0)
++              return ret;
++
++      // set volume to 0dB
++      ret = snd_soc_component_write(component, ma_vol_db_master__a, 0x18);
++      if (ret < 0)
++              return ret;
++
++      // set ch0 lim thresh to -15dB
++      ret = snd_soc_component_write(component, ma_thr_db_ch0__a, 0x27);
++      if (ret < 0)
++              return ret;
++
++      // set ch1 lim thresh to -15dB
++      ret = snd_soc_component_write(component, ma_thr_db_ch1__a, 0x27);
++      if (ret < 0)
++              return ret;
++
++      //Check for errors
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x00, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x01, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x02, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x08, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x10, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x20, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x40, 0);
++      if (ret < 0)
++              return ret;
++      ret = snd_soc_component_test_bits(component, ma_error_acc__a, 0x80, 0);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static int ma120x0p_set_bias_level(struct snd_soc_component *component,
++      enum snd_soc_bias_level level)
++{
++      int ret = 0;
++
++      struct ma120x0p_priv *ma120x0p;
++
++      ma120x0p = snd_soc_component_get_drvdata(component);
++
++      switch (level) {
++      case SND_SOC_BIAS_ON:
++              break;
++
++      case SND_SOC_BIAS_PREPARE:
++              break;
++
++      case SND_SOC_BIAS_STANDBY:
++              ret = gpiod_get_value_cansleep(priv_data->enable_gpio);
++              if (ret != 0) {
++                      dev_err(component->dev, "Device ma120x0p disabled in STANDBY BIAS: %d\n",
++                      ret);
++                      return ret;
++              }
++              break;
++
++      case SND_SOC_BIAS_OFF:
++              break;
++      }
++
++      return 0;
++}
++
++static const struct snd_soc_dapm_widget ma120x0p_dapm_widgets[] = {
++      SND_SOC_DAPM_OUTPUT("OUT_A"),
++      SND_SOC_DAPM_OUTPUT("OUT_B"),
++};
++
++static const struct snd_soc_dapm_route ma120x0p_dapm_routes[] = {
++      { "OUT_B",  NULL, "Playback" },
++      { "OUT_A",  NULL, "Playback" },
++};
++
++static const struct snd_soc_component_driver ma120x0p_component_driver = {
++      .probe = ma120x0p_probe,
++      .remove = ma120x0p_remove,
++      .set_bias_level = ma120x0p_set_bias_level,
++      .dapm_widgets           = ma120x0p_dapm_widgets,
++      .num_dapm_widgets       = ARRAY_SIZE(ma120x0p_dapm_widgets),
++      .dapm_routes            = ma120x0p_dapm_routes,
++      .num_dapm_routes        = ARRAY_SIZE(ma120x0p_dapm_routes),
++      .controls = ma120x0p_snd_controls,
++      .num_controls = ARRAY_SIZE(ma120x0p_snd_controls),
++      .use_pmdown_time        = 1,
++      .endianness             = 1,
++      .non_legacy_dai_naming  = 1,
++};
++
++//I2C Driver
++static const struct reg_default ma120x0p_reg_defaults[] = {
++      {       0x01,   0x3c    },
++};
++
++static bool ma120x0p_reg_volatile(struct device *dev, unsigned int reg)
++{
++      switch (reg) {
++      case ma_error__a:
++                      return true;
++      default:
++                      return false;
++      }
++}
++
++static const struct of_device_id ma120x0p_of_match[] = {
++      { .compatible = "ma,ma120x0p", },
++      { }
++};
++
++MODULE_DEVICE_TABLE(of, ma120x0p_of_match);
++
++static struct regmap_config ma120x0p_regmap_config = {
++      .reg_bits = 8,
++      .val_bits = 8,
++
++      .max_register = 255,
++      .volatile_reg = ma120x0p_reg_volatile,
++
++      .cache_type = REGCACHE_RBTREE,
++      .reg_defaults = ma120x0p_reg_defaults,
++      .num_reg_defaults = ARRAY_SIZE(ma120x0p_reg_defaults),
++};
++
++static int ma120x0p_i2c_probe(struct i2c_client *i2c,
++      const struct i2c_device_id *id)
++{
++      int ret;
++
++      priv_data = devm_kzalloc(&i2c->dev, sizeof(*priv_data), GFP_KERNEL);
++      if (!priv_data)
++              return -ENOMEM;
++      i2c_set_clientdata(i2c, priv_data);
++
++      priv_data->regmap = devm_regmap_init_i2c(i2c, &ma120x0p_regmap_config);
++      if (IS_ERR(priv_data->regmap)) {
++              ret = PTR_ERR(priv_data->regmap);
++              return ret;
++      }
++
++      //Startup sequence
++
++      //Make sure the device is muted
++      priv_data->mute_gpio = devm_gpiod_get(&i2c->dev, "mute_gp",
++              GPIOD_OUT_LOW);
++      if (IS_ERR(priv_data->mute_gpio)) {
++              ret = PTR_ERR(priv_data->mute_gpio);
++              dev_err(&i2c->dev, "Failed to get mute gpio line: %d\n", ret);
++              return ret;
++      }
++      msleep(50);
++
++// MA120xx0P devices are usually powered by an integrated boost converter.
++// An option GPIO control line is provided to enable the booster properly and
++// in sync with the enable and mute GPIO lines.
++      priv_data->booster_gpio = devm_gpiod_get_optional(&i2c->dev,
++              "booster_gp", GPIOD_OUT_LOW);
++      if (IS_ERR(priv_data->booster_gpio)) {
++              ret = PTR_ERR(priv_data->booster_gpio);
++              dev_err(&i2c->dev,
++              "Failed to get booster enable gpio line: %d\n", ret);
++              return ret;
++      }
++      msleep(50);
++
++      //Enable booster and wait 200ms until stable PVDD
++      gpiod_set_value_cansleep(priv_data->booster_gpio, 1);
++      msleep(200);
++
++      //Enable ma120x0pp
++      priv_data->enable_gpio = devm_gpiod_get(&i2c->dev,
++              "enable_gp", GPIOD_OUT_LOW);
++      if (IS_ERR(priv_data->enable_gpio)) {
++              ret = PTR_ERR(priv_data->enable_gpio);
++              dev_err(&i2c->dev,
++              "Failed to get ma120x0p enable gpio line: %d\n", ret);
++              return ret;
++      }
++      msleep(50);
++
++      //Optional use of ma120x0pp error line as an interrupt trigger to
++      //platform GPIO.
++      //Get error input gpio ma120x0p
++      priv_data->error_gpio = devm_gpiod_get_optional(&i2c->dev,
++               "error_gp", GPIOD_IN);
++      if (IS_ERR(priv_data->error_gpio)) {
++              ret = PTR_ERR(priv_data->error_gpio);
++              dev_err(&i2c->dev,
++                      "Failed to get ma120x0p error gpio line: %d\n", ret);
++              return ret;
++      }
++
++      if (priv_data->error_gpio != NULL) {
++              irqNumber = gpiod_to_irq(priv_data->error_gpio);
++
++              ret = devm_request_threaded_irq(&i2c->dev,
++                       irqNumber, ma120x0p_irq_handler,
++                       NULL, IRQF_TRIGGER_FALLING,
++                       "ma120x0p", priv_data);
++              if (ret != 0)
++                      dev_warn(&i2c->dev, "Failed to request IRQ: %d\n",
++                              ret);
++      }
++
++      ret = devm_snd_soc_register_component(&i2c->dev,
++              &ma120x0p_component_driver, &ma120x0p_dai, 1);
++
++      return ret;
++}
++
++static irqreturn_t ma120x0p_irq_handler(int irq, void *data)
++{
++      gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
++      gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
++      return IRQ_HANDLED;
++}
++
++static int ma120x0p_i2c_remove(struct i2c_client *i2c)
++{
++      snd_soc_unregister_component(&i2c->dev);
++      i2c_set_clientdata(i2c, NULL);
++
++      gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
++      msleep(30);
++      gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
++      msleep(200);
++      gpiod_set_value_cansleep(priv_data->booster_gpio, 0);
++      msleep(200);
++
++      kfree(priv_data);
++
++      return 0;
++}
++
++static void ma120x0p_i2c_shutdown(struct i2c_client *i2c)
++{
++      snd_soc_unregister_component(&i2c->dev);
++      i2c_set_clientdata(i2c, NULL);
++
++      gpiod_set_value_cansleep(priv_data->mute_gpio, 0);
++      msleep(30);
++      gpiod_set_value_cansleep(priv_data->enable_gpio, 1);
++      msleep(200);
++      gpiod_set_value_cansleep(priv_data->booster_gpio, 0);
++      msleep(200);
++
++      kfree(priv_data);
++}
++
++static const struct i2c_device_id ma120x0p_i2c_id[] = {
++      { "ma120x0p", 0 },
++      { }
++};
++
++MODULE_DEVICE_TABLE(i2c, ma120x0p_i2c_id);
++
++static struct i2c_driver ma120x0p_i2c_driver = {
++      .driver = {
++              .name = "ma120x0p",
++              .owner = THIS_MODULE,
++              .of_match_table = ma120x0p_of_match,
++      },
++      .probe = ma120x0p_i2c_probe,
++      .remove = ma120x0p_i2c_remove,
++      .shutdown = ma120x0p_i2c_shutdown,
++      .id_table = ma120x0p_i2c_id
++};
++
++static int __init ma120x0p_modinit(void)
++{
++      int ret = 0;
++
++      ret = i2c_add_driver(&ma120x0p_i2c_driver);
++      if (ret != 0) {
++              pr_err("Failed to register MA120X0P I2C driver: %d\n", ret);
++              return ret;
++      }
++      return ret;
++}
++module_init(ma120x0p_modinit);
++
++static void __exit ma120x0p_exit(void)
++{
++      i2c_del_driver(&ma120x0p_i2c_driver);
++}
++module_exit(ma120x0p_exit);
++
++MODULE_AUTHOR("Ariel Muszkat ariel.muszkat@gmail.com>");
++MODULE_DESCRIPTION("ASoC driver for ma120x0p");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/bcm27xx/patches-5.4/950-0477-ARM-dts-bcm2711-Add-32-bit-PMU-compatibility.patch b/target/linux/bcm27xx/patches-5.4/950-0477-ARM-dts-bcm2711-Add-32-bit-PMU-compatibility.patch
new file mode 100644 (file)
index 0000000..f549e73
--- /dev/null
@@ -0,0 +1,27 @@
+From e25d9a93812847b4ddc9e883d0cd45b32f8e2f76 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Tue, 17 Mar 2020 16:39:07 +0000
+Subject: [PATCH] ARM: dts: bcm2711: Add 32-bit PMU compatibility
+
+The "arm" architecture has no support for the cortex-a72 as such, but
+the performance and measurement unit from the cortex-a15 seems to be
+compatible.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2711-rpi.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/arm/boot/dts/bcm2711-rpi.dtsi
++++ b/arch/arm/boot/dts/bcm2711-rpi.dtsi
+@@ -12,6 +12,10 @@
+               sd_poll_once = <&emmc2>, "non-removable?";
+       };
++      arm-pmu {
++              compatible = "arm,cortex-a72-pmu", "arm,cortex-a15-pmu";
++      };
++
+       v3dbus {
+               compatible = "simple-bus";
+               #address-cells = <1>;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0478-ARM-dts-bcm271x-Use-a53-pmu-drop-RPI364.patch b/target/linux/bcm27xx/patches-5.4/950-0478-ARM-dts-bcm271x-Use-a53-pmu-drop-RPI364.patch
new file mode 100644 (file)
index 0000000..9504bb3
--- /dev/null
@@ -0,0 +1,67 @@
+From 70b0d5d07426e1b9c34ddd6ab4ee99b8c2fb81a6 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.com>
+Date: Thu, 19 Mar 2020 10:04:46 +0000
+Subject: [PATCH] ARM: dts: bcm271x: Use a53 pmu, drop RPI364
+
+The upstream bcm2837.dtsi uses cortex-a53-pmu, so we can do the same
+but with a fallback to the cortex-a7-pmu which is supported by the
+32-bit kernel.
+
+Now that we're using the natural fallback mechanism of compatible
+strings, the RPI364 macro no longer serves any purpose - remove it.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.com>
+---
+ arch/arm/boot/dts/bcm2710.dtsi                        | 6 +-----
+ arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts      | 2 --
+ arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dts | 2 --
+ arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts      | 2 --
+ arch/arm64/boot/dts/broadcom/bcm2710-rpi-cm3.dts      | 2 --
+ arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts      | 2 --
+ 6 files changed, 1 insertion(+), 15 deletions(-)
+
+--- a/arch/arm/boot/dts/bcm2710.dtsi
++++ b/arch/arm/boot/dts/bcm2710.dtsi
+@@ -5,11 +5,7 @@
+       compatible = "brcm,bcm2837", "brcm,bcm2836";
+       arm-pmu {
+-#ifdef RPI364
+-              compatible = "arm,armv8-pmuv3", "arm,cortex-a7-pmu";
+-#else
+-              compatible = "arm,cortex-a7-pmu";
+-#endif
++              compatible = "arm,cortex-a53-pmu", "arm,cortex-a7-pmu";
+       };
+       soc {
+--- a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts
++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-2-b.dts
+@@ -1,3 +1 @@
+-#define RPI364
+-
+ #include "../../../../arm/boot/dts/bcm2710-rpi-2-b.dts"
+--- a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dts
++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dts
+@@ -1,3 +1 @@
+-#define RPI364
+-
+ #include "../../../../arm/boot/dts/bcm2710-rpi-3-b-plus.dts"
+--- a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts
++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dts
+@@ -1,3 +1 @@
+-#define RPI364
+-
+ #include "../../../../arm/boot/dts/bcm2710-rpi-3-b.dts"
+--- a/arch/arm64/boot/dts/broadcom/bcm2710-rpi-cm3.dts
++++ b/arch/arm64/boot/dts/broadcom/bcm2710-rpi-cm3.dts
+@@ -1,3 +1 @@
+-#define RPI364
+-
+ #include "../../../../arm/boot/dts/bcm2710-rpi-cm3.dts"
+--- a/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-4-b.dts
+@@ -1,3 +1 @@
+-#define RPI364
+-
+ #include "../../../../arm/boot/dts/bcm2711-rpi-4-b.dts"
diff --git a/target/linux/bcm27xx/patches-5.4/950-0479-net-bcmgenet-Clear-ID_MODE_DIS-in-EXT_RGMII_OOB_CTRL.patch b/target/linux/bcm27xx/patches-5.4/950-0479-net-bcmgenet-Clear-ID_MODE_DIS-in-EXT_RGMII_OOB_CTRL.patch
new file mode 100644 (file)
index 0000000..9d80904
--- /dev/null
@@ -0,0 +1,32 @@
+From cff8c5c2a95a4afd65bfa3198258d03bc790cddb Mon Sep 17 00:00:00 2001
+From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Date: Tue, 25 Feb 2020 14:11:59 +0100
+Subject: [PATCH] net: bcmgenet: Clear ID_MODE_DIS in
+ EXT_RGMII_OOB_CTRL when not needed
+
+commit 402482a6a78e5c61d8a2ec6311fc5b4aca392cd6 upstream.
+
+Outdated Raspberry Pi 4 firmware might configure the external PHY as
+rgmii although the kernel currently sets it as rgmii-rxid. This makes
+connections unreliable as ID_MODE_DIS is left enabled. To avoid this,
+explicitly clear that bit whenever we don't need it.
+
+Fixes: da38802211cc ("net: bcmgenet: Add RGMII_RXID support")
+Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Matthias Reichl <hias@horus.com>
+---
+ drivers/net/ethernet/broadcom/genet/bcmmii.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
+@@ -292,6 +292,7 @@ int bcmgenet_mii_config(struct net_devic
+        */
+       if (priv->ext_phy) {
+               reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
++              reg &= ~ID_MODE_DIS;
+               reg |= id_mode_dis;
+               if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
+                       reg |= RGMII_MODE_EN_V123;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0480-drm-modes-parse_cmdline-Fix-possible-reference-past-.patch b/target/linux/bcm27xx/patches-5.4/950-0480-drm-modes-parse_cmdline-Fix-possible-reference-past-.patch
new file mode 100644 (file)
index 0000000..1617a45
--- /dev/null
@@ -0,0 +1,141 @@
+From fade8b3cf37785297b4f8a9bbd13ab107208af5a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:22 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Fix possible reference past
+ end of string
+
+Commit 8582e244e5fe72d2e9ace186fa8f3ed3bb4122e1 upstream.
+
+Before this commit, if the last option of a video=... option is for
+example "rotate" without a "=<value>" after it then delim will point to
+the terminating 0 of the string, and value which is sets to <delim + 1>
+will point one position past the end of the string.
+
+This commit fixes this by enforcing that the contents of delim equals '='
+as it should be for options which take a value, this check is done in a
+new drm_mode_parse_cmdline_int helper function which factors out the
+common integer parsing code for all the options which take an int.
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-1-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 68 ++++++++++++++++---------------------
+ 1 file changed, 30 insertions(+), 38 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1568,11 +1568,34 @@ static int drm_mode_parse_cmdline_res_mo
+       return 0;
+ }
++static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
++{
++      const char *value;
++      char *endp;
++
++      /*
++       * delim must point to the '=', otherwise it is a syntax error and
++       * if delim points to the terminating zero, then delim + 1 wil point
++       * past the end of the string.
++       */
++      if (*delim != '=')
++              return -EINVAL;
++
++      value = delim + 1;
++      *int_ret = simple_strtol(value, &endp, 10);
++
++      /* Make sure we have parsed something */
++      if (endp == value)
++              return -EINVAL;
++
++      return 0;
++}
++
+ static int drm_mode_parse_cmdline_options(char *str, size_t len,
+                                         const struct drm_connector *connector,
+                                         struct drm_cmdline_mode *mode)
+ {
+-      unsigned int rotation = 0;
++      unsigned int deg, margin, rotation = 0;
+       char *sep = str;
+       while ((sep = strchr(sep, ','))) {
+@@ -1588,13 +1611,7 @@ static int drm_mode_parse_cmdline_option
+               }
+               if (!strncmp(option, "rotate", delim - option)) {
+-                      const char *value = delim + 1;
+-                      unsigned int deg;
+-
+-                      deg = simple_strtol(value, &sep, 10);
+-
+-                      /* Make sure we have parsed something */
+-                      if (sep == value)
++                      if (drm_mode_parse_cmdline_int(delim, &deg))
+                               return -EINVAL;
+                       switch (deg) {
+@@ -1619,57 +1636,32 @@ static int drm_mode_parse_cmdline_option
+                       }
+               } else if (!strncmp(option, "reflect_x", delim - option)) {
+                       rotation |= DRM_MODE_REFLECT_X;
+-                      sep = delim;
+               } else if (!strncmp(option, "reflect_y", delim - option)) {
+                       rotation |= DRM_MODE_REFLECT_Y;
+-                      sep = delim;
+               } else if (!strncmp(option, "margin_right", delim - option)) {
+-                      const char *value = delim + 1;
+-                      unsigned int margin;
+-
+-                      margin = simple_strtol(value, &sep, 10);
+-
+-                      /* Make sure we have parsed something */
+-                      if (sep == value)
++                      if (drm_mode_parse_cmdline_int(delim, &margin))
+                               return -EINVAL;
+                       mode->tv_margins.right = margin;
+               } else if (!strncmp(option, "margin_left", delim - option)) {
+-                      const char *value = delim + 1;
+-                      unsigned int margin;
+-
+-                      margin = simple_strtol(value, &sep, 10);
+-
+-                      /* Make sure we have parsed something */
+-                      if (sep == value)
++                      if (drm_mode_parse_cmdline_int(delim, &margin))
+                               return -EINVAL;
+                       mode->tv_margins.left = margin;
+               } else if (!strncmp(option, "margin_top", delim - option)) {
+-                      const char *value = delim + 1;
+-                      unsigned int margin;
+-
+-                      margin = simple_strtol(value, &sep, 10);
+-
+-                      /* Make sure we have parsed something */
+-                      if (sep == value)
++                      if (drm_mode_parse_cmdline_int(delim, &margin))
+                               return -EINVAL;
+                       mode->tv_margins.top = margin;
+               } else if (!strncmp(option, "margin_bottom", delim - option)) {
+-                      const char *value = delim + 1;
+-                      unsigned int margin;
+-
+-                      margin = simple_strtol(value, &sep, 10);
+-
+-                      /* Make sure we have parsed something */
+-                      if (sep == value)
++                      if (drm_mode_parse_cmdline_int(delim, &margin))
+                               return -EINVAL;
+                       mode->tv_margins.bottom = margin;
+               } else {
+                       return -EINVAL;
+               }
++              sep = delim;
+       }
+       mode->rotation_reflection = rotation;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0481-drm-modes-parse_cmdline-Make-various-char-pointers-c.patch b/target/linux/bcm27xx/patches-5.4/950-0481-drm-modes-parse_cmdline-Make-various-char-pointers-c.patch
new file mode 100644 (file)
index 0000000..ef8c161
--- /dev/null
@@ -0,0 +1,50 @@
+From 250363a413cd08e723789e1b8821608ff5eebfe6 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:23 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Make various char pointers
+ const
+
+Commit 83e14ea3a64f00897cc31974d3ae4e27e5a7405b upstream.
+
+We are not supposed to modify the passed in string, make char pointers
+used in drm_mode_parse_cmdline_options() const char * where possible.
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-2-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1591,15 +1591,15 @@ static int drm_mode_parse_cmdline_int(co
+       return 0;
+ }
+-static int drm_mode_parse_cmdline_options(char *str, size_t len,
++static int drm_mode_parse_cmdline_options(const char *str, size_t len,
+                                         const struct drm_connector *connector,
+                                         struct drm_cmdline_mode *mode)
+ {
+       unsigned int deg, margin, rotation = 0;
+-      char *sep = str;
++      const char *sep = str;
+       while ((sep = strchr(sep, ','))) {
+-              char *delim, *option;
++              const char *delim, *option;
+               option = sep + 1;
+               delim = strchr(option, '=');
+@@ -1718,8 +1718,8 @@ bool drm_mode_parse_command_line_for_con
+       bool named_mode = false, parse_extras = false;
+       unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
+       unsigned int mode_end = 0;
+-      char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
+-      char *options_ptr = NULL;
++      const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
++      const char *options_ptr = NULL;
+       char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
+       int ret;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0482-drm-modes-parse_cmdline-Stop-parsing-extras-after-bp.patch b/target/linux/bcm27xx/patches-5.4/950-0482-drm-modes-parse_cmdline-Stop-parsing-extras-after-bp.patch
new file mode 100644 (file)
index 0000000..1128ac0
--- /dev/null
@@ -0,0 +1,95 @@
+From 0e7c5e80d8d310a881d723a426762e8822d5bf35 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:24 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Stop parsing extras after
+ bpp / refresh at ', '
+
+Commit c2ed3e941901810ad3d55ce1935fa22c5007fee4 upstream.
+
+Before this commit it was impossible to add an extra mode argument after
+a bpp or refresh specifier, combined with an option, e.g.
+video=HDMI-1:720x480-24e,rotate=180 would not work, either the "e" to
+force enable would need to be dropped or the ",rotate=180", otherwise
+the mode_option would not be accepted.
+
+This commit fixes this by fixing the length calculation if extras_ptr
+is set to stop the extra parsing at the start of the options (stop at the
+',' options_ptr points to).
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-3-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c                   | 10 ++++---
+ .../gpu/drm/selftests/drm_cmdline_selftests.h |  1 +
+ .../drm/selftests/test-drm_cmdline_parser.c   | 26 +++++++++++++++++++
+ 3 files changed, 33 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1721,7 +1721,7 @@ bool drm_mode_parse_command_line_for_con
+       const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
+       const char *options_ptr = NULL;
+       char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
+-      int ret;
++      int i, len, ret;
+ #ifdef CONFIG_FB
+       if (!mode_option)
+@@ -1841,9 +1841,11 @@ bool drm_mode_parse_command_line_for_con
+       else if (refresh_ptr)
+               extra_ptr = refresh_end_ptr;
+-      if (extra_ptr &&
+-          extra_ptr != options_ptr) {
+-              int len = strlen(name) - (extra_ptr - name);
++      if (extra_ptr) {
++              if (options_ptr)
++                      len = options_ptr - extra_ptr;
++              else
++                      len = strlen(extra_ptr);
+               ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
+                                                  connector, mode);
+--- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
++++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+@@ -60,3 +60,4 @@ cmdline_test(drm_cmdline_test_vmirror)
+ cmdline_test(drm_cmdline_test_margin_options)
+ cmdline_test(drm_cmdline_test_multiple_options)
+ cmdline_test(drm_cmdline_test_invalid_option)
++cmdline_test(drm_cmdline_test_bpp_extra_and_option)
+--- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
++++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
+@@ -992,6 +992,32 @@ static int drm_cmdline_test_invalid_opti
+       return 0;
+ }
++static int drm_cmdline_test_bpp_extra_and_option(void *ignored)
++{
++      struct drm_cmdline_mode mode = { };
++
++      FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24e,rotate=180",
++                                                         &no_connector,
++                                                         &mode));
++      FAIL_ON(!mode.specified);
++      FAIL_ON(mode.xres != 720);
++      FAIL_ON(mode.yres != 480);
++      FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
++
++      FAIL_ON(mode.refresh_specified);
++
++      FAIL_ON(!mode.bpp_specified);
++      FAIL_ON(mode.bpp != 24);
++
++      FAIL_ON(mode.rb);
++      FAIL_ON(mode.cvt);
++      FAIL_ON(mode.interlace);
++      FAIL_ON(mode.margins);
++      FAIL_ON(mode.force != DRM_FORCE_ON);
++
++      return 0;
++}
++
+ #include "drm_selftest.c"
+ static int __init test_drm_cmdline_init(void)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0483-drm-modes-parse_cmdline-Accept-extras-directly-after.patch b/target/linux/bcm27xx/patches-5.4/950-0483-drm-modes-parse_cmdline-Accept-extras-directly-after.patch
new file mode 100644 (file)
index 0000000..79cfa56
--- /dev/null
@@ -0,0 +1,77 @@
+From bc4d8c5519c74b9bdf4d35369ba76bac01be8ca2 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:25 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Accept extras directly
+ after mode combined with options
+
+Commit cfb0881b8f621b656a9e23b31944a5db94cf5842 upstream.
+
+Before this commit it was impossible to combine an extra mode argument
+specified directly after the resolution with an option, e.g.
+video=HDMI-1:720x480e,rotate=180 would not work, either the "e" to force
+enable would need to be dropped or the ",rotate=180", otherwise the
+mode_option would not be accepted.
+
+This commit fixes this by setting parse_extras to true in this case, so
+that drm_mode_parse_cmdline_res_mode() parses the extra arguments directly
+after the resolution.
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-4-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c                   |  1 +
+ .../gpu/drm/selftests/drm_cmdline_selftests.h |  1 +
+ .../drm/selftests/test-drm_cmdline_parser.c   | 24 +++++++++++++++++++
+ 3 files changed, 26 insertions(+)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1794,6 +1794,7 @@ bool drm_mode_parse_command_line_for_con
+               mode_end = refresh_off;
+       } else if (options_ptr) {
+               mode_end = options_off;
++              parse_extras = true;
+       } else {
+               mode_end = strlen(name);
+               parse_extras = true;
+--- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
++++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+@@ -61,3 +61,4 @@ cmdline_test(drm_cmdline_test_margin_opt
+ cmdline_test(drm_cmdline_test_multiple_options)
+ cmdline_test(drm_cmdline_test_invalid_option)
+ cmdline_test(drm_cmdline_test_bpp_extra_and_option)
++cmdline_test(drm_cmdline_test_extra_and_option)
+--- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
++++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
+@@ -1018,6 +1018,30 @@ static int drm_cmdline_test_bpp_extra_an
+       return 0;
+ }
++static int drm_cmdline_test_extra_and_option(void *ignored)
++{
++      struct drm_cmdline_mode mode = { };
++
++      FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480e,rotate=180",
++                                                         &no_connector,
++                                                         &mode));
++      FAIL_ON(!mode.specified);
++      FAIL_ON(mode.xres != 720);
++      FAIL_ON(mode.yres != 480);
++      FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
++
++      FAIL_ON(mode.refresh_specified);
++      FAIL_ON(mode.bpp_specified);
++
++      FAIL_ON(mode.rb);
++      FAIL_ON(mode.cvt);
++      FAIL_ON(mode.interlace);
++      FAIL_ON(mode.margins);
++      FAIL_ON(mode.force != DRM_FORCE_ON);
++
++      return 0;
++}
++
+ #include "drm_selftest.c"
+ static int __init test_drm_cmdline_init(void)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0484-drm-modes-parse_cmdline-Rework-drm_mode_parse_cmdlin.patch b/target/linux/bcm27xx/patches-5.4/950-0484-drm-modes-parse_cmdline-Rework-drm_mode_parse_cmdlin.patch
new file mode 100644 (file)
index 0000000..0cf2939
--- /dev/null
@@ -0,0 +1,76 @@
+From 5b6257773b43e7a7b28f86359d2e9ebe15346b78 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:26 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Rework
+ drm_mode_parse_cmdline_options()
+
+Commit 739b200c2edcaaa7a86f37b0c11db57956433dfb upstream.
+
+Refactor drm_mode_parse_cmdline_options() so that it takes a pointer
+to the first option, rather then a pointer to the ',' before the first
+option.
+
+This is a preparation patch for allowing parsing of stand-alone options
+without a mode before them, e.g.: video=HDMI-1:margin_right=14,...
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-5-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1591,23 +1591,21 @@ static int drm_mode_parse_cmdline_int(co
+       return 0;
+ }
+-static int drm_mode_parse_cmdline_options(const char *str, size_t len,
++static int drm_mode_parse_cmdline_options(const char *str,
+                                         const struct drm_connector *connector,
+                                         struct drm_cmdline_mode *mode)
+ {
+       unsigned int deg, margin, rotation = 0;
+-      const char *sep = str;
++      const char *delim, *option, *sep;
+-      while ((sep = strchr(sep, ','))) {
+-              const char *delim, *option;
+-
+-              option = sep + 1;
++      option = str;
++      do {
+               delim = strchr(option, '=');
+               if (!delim) {
+                       delim = strchr(option, ',');
+                       if (!delim)
+-                              delim = str + len;
++                              delim = option + strlen(option);
+               }
+               if (!strncmp(option, "rotate", delim - option)) {
+@@ -1661,8 +1659,9 @@ static int drm_mode_parse_cmdline_option
+               } else {
+                       return -EINVAL;
+               }
+-              sep = delim;
+-      }
++              sep = strchr(delim, ',');
++              option = sep + 1;
++      } while (sep);
+       mode->rotation_reflection = rotation;
+@@ -1855,9 +1854,7 @@ bool drm_mode_parse_command_line_for_con
+       }
+       if (options_ptr) {
+-              int len = strlen(name) - (options_ptr - name);
+-
+-              ret = drm_mode_parse_cmdline_options(options_ptr, len,
++              ret = drm_mode_parse_cmdline_options(options_ptr + 1,
+                                                    connector, mode);
+               if (ret)
+                       return false;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0485-drm-modes-parse_cmdline-Add-freestanding-argument-to.patch b/target/linux/bcm27xx/patches-5.4/950-0485-drm-modes-parse_cmdline-Add-freestanding-argument-to.patch
new file mode 100644 (file)
index 0000000..ac37b72
--- /dev/null
@@ -0,0 +1,49 @@
+From d3c76025a7de614fade5ffcaa8c1d88d8d64213e Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:27 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Add freestanding argument
+ to drm_mode_parse_cmdline_options()
+
+Commit 99e2716e053734b70434502867be24d20a3e2d84 upstream.
+
+Add a freestanding function argument to drm_mode_parse_cmdline_options()
+similar to how drm_mode_parse_cmdline_extra() already has this.
+
+This is a preparation patch for allowing parsing of stand-alone options
+without a mode before them, e.g.: video=HDMI-1:margin_right=14,...
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-6-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1592,6 +1592,7 @@ static int drm_mode_parse_cmdline_int(co
+ }
+ static int drm_mode_parse_cmdline_options(const char *str,
++                                        bool freestanding,
+                                         const struct drm_connector *connector,
+                                         struct drm_cmdline_mode *mode)
+ {
+@@ -1663,6 +1664,9 @@ static int drm_mode_parse_cmdline_option
+               option = sep + 1;
+       } while (sep);
++      if (rotation && freestanding)
++              return -EINVAL;
++
+       mode->rotation_reflection = rotation;
+       return 0;
+@@ -1855,6 +1859,7 @@ bool drm_mode_parse_command_line_for_con
+       if (options_ptr) {
+               ret = drm_mode_parse_cmdline_options(options_ptr + 1,
++                                                   false,
+                                                    connector, mode);
+               if (ret)
+                       return false;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0486-drm-modes-parse_cmdline-Set-bpp-refresh_specified-af.patch b/target/linux/bcm27xx/patches-5.4/950-0486-drm-modes-parse_cmdline-Set-bpp-refresh_specified-af.patch
new file mode 100644 (file)
index 0000000..7f0c629
--- /dev/null
@@ -0,0 +1,64 @@
+From 5b7efd2fa0c75164373d6faf28fec4b89065d39c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:28 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Set bpp/refresh_specified
+ after successful parsing
+
+Commit 6a2d163756545aa3180d7851d5f8322b865e72be upstream.
+
+drm_connector_get_cmdline_mode() calls
+drm_mode_parse_command_line_for_connector() with &connector->cmdline_mode
+as mode argument, so anything which we store in the mode arguments gets
+kept even if we return false.
+
+Avoid storing a possibly false-postive bpp/refresh_specified setting
+in connector->cmdline_mode by moving the setting of these to after
+successful parsing of the bpp/refresh parts of the video= argument.
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-7-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1771,10 +1771,8 @@ bool drm_mode_parse_command_line_for_con
+       /* Try to locate the bpp and refresh specifiers, if any */
+       bpp_ptr = strchr(name, '-');
+-      if (bpp_ptr) {
++      if (bpp_ptr)
+               bpp_off = bpp_ptr - name;
+-              mode->bpp_specified = true;
+-      }
+       refresh_ptr = strchr(name, '@');
+       if (refresh_ptr) {
+@@ -1782,7 +1780,6 @@ bool drm_mode_parse_command_line_for_con
+                       return false;
+               refresh_off = refresh_ptr - name;
+-              mode->refresh_specified = true;
+       }
+       /* Locate the start of named options */
+@@ -1825,6 +1822,8 @@ bool drm_mode_parse_command_line_for_con
+               ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
+               if (ret)
+                       return false;
++
++              mode->bpp_specified = true;
+       }
+       if (refresh_ptr) {
+@@ -1832,6 +1831,8 @@ bool drm_mode_parse_command_line_for_con
+                                                    &refresh_end_ptr, mode);
+               if (ret)
+                       return false;
++
++              mode->refresh_specified = true;
+       }
+       /*
diff --git a/target/linux/bcm27xx/patches-5.4/950-0487-drm-modes-parse_cmdline-Allow-specifying-stand-alone.patch b/target/linux/bcm27xx/patches-5.4/950-0487-drm-modes-parse_cmdline-Allow-specifying-stand-alone.patch
new file mode 100644 (file)
index 0000000..301ad57
--- /dev/null
@@ -0,0 +1,247 @@
+From b3212eba63b541206e12c8dc31fc0d99d916b210 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:29 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Allow specifying
+ stand-alone options
+
+Commit 7b1cce760afe38b40f0989cdf10b2190dccf9815 upstream.
+
+Some options which can be specified on the commandline, such as
+margin_right=..., margin_left=..., etc. are applied not only to the
+specified mode, but to all modes. As such it would be nice if the user
+can simply say e.g.
+video=HDMI-1:margin_right=14,margin_left=24,margin_bottom=36,margin_top=42
+
+This commit refactors drm_mode_parse_command_line_for_connector() to
+add support for this, and as a nice side effect also cleans up the
+function a bit.
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-8-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c                   | 92 +++++++------------
+ .../gpu/drm/selftests/drm_cmdline_selftests.h |  2 +
+ .../drm/selftests/test-drm_cmdline_parser.c   | 50 ++++++++++
+ 3 files changed, 86 insertions(+), 58 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1677,17 +1677,6 @@ static const char * const drm_named_mode
+       "PAL",
+ };
+-static bool drm_named_mode_is_in_whitelist(const char *mode, unsigned int size)
+-{
+-      int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++)
+-              if (!strncmp(mode, drm_named_modes_whitelist[i], size))
+-                      return true;
+-
+-      return false;
+-}
+-
+ /**
+  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
+  * @mode_option: optional per connector mode option
+@@ -1718,7 +1707,7 @@ bool drm_mode_parse_command_line_for_con
+                                              struct drm_cmdline_mode *mode)
+ {
+       const char *name;
+-      bool named_mode = false, parse_extras = false;
++      bool freestanding = false, parse_extras = false;
+       unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
+       unsigned int mode_end = 0;
+       const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
+@@ -1738,49 +1727,14 @@ bool drm_mode_parse_command_line_for_con
+       name = mode_option;
+-      /*
+-       * This is a bit convoluted. To differentiate between the
+-       * named modes and poorly formatted resolutions, we need a
+-       * bunch of things:
+-       *   - We need to make sure that the first character (which
+-       *     would be our resolution in X) is a digit.
+-       *   - If not, then it's either a named mode or a force on/off.
+-       *     To distinguish between the two, we need to run the
+-       *     extra parsing function, and if not, then we consider it
+-       *     a named mode.
+-       *
+-       * If this isn't enough, we should add more heuristics here,
+-       * and matching unit-tests.
+-       */
+-      if (!isdigit(name[0]) && name[0] != 'x') {
+-              unsigned int namelen = strlen(name);
+-
+-              /*
+-               * Only the force on/off options can be in that case,
+-               * and they all take a single character.
+-               */
+-              if (namelen == 1) {
+-                      ret = drm_mode_parse_cmdline_extra(name, namelen, true,
+-                                                         connector, mode);
+-                      if (!ret)
+-                              return true;
+-              }
+-
+-              named_mode = true;
+-      }
+-
+       /* Try to locate the bpp and refresh specifiers, if any */
+       bpp_ptr = strchr(name, '-');
+       if (bpp_ptr)
+               bpp_off = bpp_ptr - name;
+       refresh_ptr = strchr(name, '@');
+-      if (refresh_ptr) {
+-              if (named_mode)
+-                      return false;
+-
++      if (refresh_ptr)
+               refresh_off = refresh_ptr - name;
+-      }
+       /* Locate the start of named options */
+       options_ptr = strchr(name, ',');
+@@ -1800,23 +1754,45 @@ bool drm_mode_parse_command_line_for_con
+               parse_extras = true;
+       }
+-      if (named_mode) {
+-              if (mode_end + 1 > DRM_DISPLAY_MODE_LEN)
+-                      return false;
+-
+-              if (!drm_named_mode_is_in_whitelist(name, mode_end))
+-                      return false;
++      /* First check for a named mode */
++      for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
++              ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
++              if (ret == mode_end) {
++                      if (refresh_ptr)
++                              return false; /* named + refresh is invalid */
++
++                      strcpy(mode->name, drm_named_modes_whitelist[i]);
++                      mode->specified = true;
++                      break;
++              }
++      }
+-              strscpy(mode->name, name, mode_end + 1);
+-      } else {
++      /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
++      if (!mode->specified && isdigit(name[0])) {
+               ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
+                                                     parse_extras,
+                                                     connector,
+                                                     mode);
+               if (ret)
+                       return false;
++
++              mode->specified = true;
++      }
++
++      /* No mode? Check for freestanding extras and/or options */
++      if (!mode->specified) {
++              unsigned int len = strlen(mode_option);
++
++              if (bpp_ptr || refresh_ptr)
++                      return false; /* syntax error */
++
++              if (len == 1 || (len >= 2 && mode_option[1] == ','))
++                      extra_ptr = mode_option;
++              else
++                      options_ptr = mode_option - 1;
++
++              freestanding = true;
+       }
+-      mode->specified = true;
+       if (bpp_ptr) {
+               ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
+@@ -1852,7 +1828,7 @@ bool drm_mode_parse_command_line_for_con
+               else
+                       len = strlen(extra_ptr);
+-              ret = drm_mode_parse_cmdline_extra(extra_ptr, len, false,
++              ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
+                                                  connector, mode);
+               if (ret)
+                       return false;
+@@ -1860,7 +1836,7 @@ bool drm_mode_parse_command_line_for_con
+       if (options_ptr) {
+               ret = drm_mode_parse_cmdline_options(options_ptr + 1,
+-                                                   false,
++                                                   freestanding,
+                                                    connector, mode);
+               if (ret)
+                       return false;
+--- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
++++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+@@ -62,3 +62,5 @@ cmdline_test(drm_cmdline_test_multiple_o
+ cmdline_test(drm_cmdline_test_invalid_option)
+ cmdline_test(drm_cmdline_test_bpp_extra_and_option)
+ cmdline_test(drm_cmdline_test_extra_and_option)
++cmdline_test(drm_cmdline_test_freestanding_options)
++cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
+--- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
++++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
+@@ -1042,6 +1042,56 @@ static int drm_cmdline_test_extra_and_op
+       return 0;
+ }
++static int drm_cmdline_test_freestanding_options(void *ignored)
++{
++      struct drm_cmdline_mode mode = { };
++
++      FAIL_ON(!drm_mode_parse_command_line_for_connector("margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
++                                                         &no_connector,
++                                                         &mode));
++      FAIL_ON(mode.specified);
++      FAIL_ON(mode.refresh_specified);
++      FAIL_ON(mode.bpp_specified);
++
++      FAIL_ON(mode.tv_margins.right != 14);
++      FAIL_ON(mode.tv_margins.left != 24);
++      FAIL_ON(mode.tv_margins.bottom != 36);
++      FAIL_ON(mode.tv_margins.top != 42);
++
++      FAIL_ON(mode.rb);
++      FAIL_ON(mode.cvt);
++      FAIL_ON(mode.interlace);
++      FAIL_ON(mode.margins);
++      FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
++
++      return 0;
++}
++
++static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored)
++{
++      struct drm_cmdline_mode mode = { };
++
++      FAIL_ON(!drm_mode_parse_command_line_for_connector("e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
++                                                         &no_connector,
++                                                         &mode));
++      FAIL_ON(mode.specified);
++      FAIL_ON(mode.refresh_specified);
++      FAIL_ON(mode.bpp_specified);
++
++      FAIL_ON(mode.tv_margins.right != 14);
++      FAIL_ON(mode.tv_margins.left != 24);
++      FAIL_ON(mode.tv_margins.bottom != 36);
++      FAIL_ON(mode.tv_margins.top != 42);
++
++      FAIL_ON(mode.rb);
++      FAIL_ON(mode.cvt);
++      FAIL_ON(mode.interlace);
++      FAIL_ON(mode.margins);
++      FAIL_ON(mode.force != DRM_FORCE_ON);
++
++      return 0;
++}
++
+ #include "drm_selftest.c"
+ static int __init test_drm_cmdline_init(void)
diff --git a/target/linux/bcm27xx/patches-5.4/950-0488-drm-modes-parse_cmdline-Add-support-for-specifying-p.patch b/target/linux/bcm27xx/patches-5.4/950-0488-drm-modes-parse_cmdline-Add-support-for-specifying-p.patch
new file mode 100644 (file)
index 0000000..2938200
--- /dev/null
@@ -0,0 +1,157 @@
+From 7d395633947fa6595a117f40e0f27ba87be77d6c Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:30 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Add support for specifying
+ panel_orientation (v2)
+
+Commit 4e7a4a6fbdc669c44e6079f9d5eb25673749455f upstream.
+
+Sometimes we want to override a connector's panel_orientation from the
+kernel commandline. Either for testing and for special cases, e.g. a kiosk
+like setup which uses a TV mounted in portrait mode.
+
+Users can already specify a "rotate" option through a video= kernel cmdline
+option. But that only supports 0/180 degrees (see drm_client_modeset TODO)
+and only works for in kernel modeset clients, not for userspace kms users.
+
+The "panel-orientation" connector property OTOH does support 90/270 degrees
+as it leaves dealing with the rotation up to userspace and this does work
+for userspace kms clients (at least those which support this property).
+
+Changes in v2:
+-Add missing ':' after @panel_orientation (reported by kbuild test robot)
+
+BugLink: https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/83
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-9-hdegoede@redhat.com
+---
+ Documentation/fb/modedb.rst                   |  3 ++
+ drivers/gpu/drm/drm_modes.c                   | 32 +++++++++++++++++++
+ .../gpu/drm/selftests/drm_cmdline_selftests.h |  1 +
+ .../drm/selftests/test-drm_cmdline_parser.c   | 22 +++++++++++++
+ include/drm/drm_connector.h                   |  8 +++++
+ 5 files changed, 66 insertions(+)
+
+--- a/Documentation/fb/modedb.rst
++++ b/Documentation/fb/modedb.rst
+@@ -65,6 +65,9 @@ Valid options are::
+   - reflect_y (boolean): Perform an axial symmetry on the Y axis
+   - rotate (integer): Rotate the initial framebuffer by x
+     degrees. Valid values are 0, 90, 180 and 270.
++  - panel_orientation, one of "normal", "upside_down", "left_side_up", or
++    "right_side_up". For KMS drivers only, this sets the "panel orientation"
++    property on the kms connector as hint for kms users.
+ -----------------------------------------------------------------------------
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1591,6 +1591,33 @@ static int drm_mode_parse_cmdline_int(co
+       return 0;
+ }
++static int drm_mode_parse_panel_orientation(const char *delim,
++                                          struct drm_cmdline_mode *mode)
++{
++      const char *value;
++
++      if (*delim != '=')
++              return -EINVAL;
++
++      value = delim + 1;
++      delim = strchr(value, ',');
++      if (!delim)
++              delim = value + strlen(value);
++
++      if (!strncmp(value, "normal", delim - value))
++              mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
++      else if (!strncmp(value, "upside_down", delim - value))
++              mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
++      else if (!strncmp(value, "left_side_up", delim - value))
++              mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
++      else if (!strncmp(value, "right_side_up", delim - value))
++              mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
++      else
++              return -EINVAL;
++
++      return 0;
++}
++
+ static int drm_mode_parse_cmdline_options(const char *str,
+                                         bool freestanding,
+                                         const struct drm_connector *connector,
+@@ -1657,6 +1684,9 @@ static int drm_mode_parse_cmdline_option
+                               return -EINVAL;
+                       mode->tv_margins.bottom = margin;
++              } else if (!strncmp(option, "panel_orientation", delim - option)) {
++                      if (drm_mode_parse_panel_orientation(delim, mode))
++                              return -EINVAL;
+               } else {
+                       return -EINVAL;
+               }
+@@ -1715,6 +1745,8 @@ bool drm_mode_parse_command_line_for_con
+       char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
+       int i, len, ret;
++      mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
++
+ #ifdef CONFIG_FB
+       if (!mode_option)
+               mode_option = fb_mode_option;
+--- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
++++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+@@ -64,3 +64,4 @@ cmdline_test(drm_cmdline_test_bpp_extra_
+ cmdline_test(drm_cmdline_test_extra_and_option)
+ cmdline_test(drm_cmdline_test_freestanding_options)
+ cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
++cmdline_test(drm_cmdline_test_panel_orientation)
+--- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
++++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
+@@ -1092,6 +1092,28 @@ static int drm_cmdline_test_freestanding
+       return 0;
+ }
++static int drm_cmdline_test_panel_orientation(void *ignored)
++{
++      struct drm_cmdline_mode mode = { };
++
++      FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down",
++                                                         &no_connector,
++                                                         &mode));
++      FAIL_ON(mode.specified);
++      FAIL_ON(mode.refresh_specified);
++      FAIL_ON(mode.bpp_specified);
++
++      FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP);
++
++      FAIL_ON(mode.rb);
++      FAIL_ON(mode.cvt);
++      FAIL_ON(mode.interlace);
++      FAIL_ON(mode.margins);
++      FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
++
++      return 0;
++}
++
+ #include "drm_selftest.c"
+ static int __init test_drm_cmdline_init(void)
+--- a/include/drm/drm_connector.h
++++ b/include/drm/drm_connector.h
+@@ -1066,6 +1066,14 @@ struct drm_cmdline_mode {
+       unsigned int rotation_reflection;
+       /**
++       * @panel_orientation:
++       *
++       * drm-connector "panel orientation" property override value,
++       * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set.
++       */
++      enum drm_panel_orientation panel_orientation;
++
++      /**
+        * @tv_margins: TV margins to apply to the mode.
+        */
+       struct drm_connector_tv_margins tv_margins;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0489-drm-modes-parse_cmdline-Remove-some-unnecessary-code.patch b/target/linux/bcm27xx/patches-5.4/950-0489-drm-modes-parse_cmdline-Remove-some-unnecessary-code.patch
new file mode 100644 (file)
index 0000000..ce80f19
--- /dev/null
@@ -0,0 +1,38 @@
+From 339666068713986cfe1456175dd8a7514f6ed2ab Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:31 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Remove some unnecessary
+ code (v2)
+
+Commit 5b926617cdef41ce0696e09834991194b1759e28 upstream.
+
+fb_get_options() will return fb_mode_option if no video=<connector-name>
+argument is present on the kernel commandline, so there is no need to also
+do this in drm_mode_parse_command_line_for_connector() as our only caller
+uses fb_get_options() to get the mode_option argument.
+
+Changes in v2:
+-Split out the changes dealing with the initialization of the mode struct
+ into a separate patch
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-10-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1747,11 +1747,6 @@ bool drm_mode_parse_command_line_for_con
+       mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
+-#ifdef CONFIG_FB
+-      if (!mode_option)
+-              mode_option = fb_mode_option;
+-#endif
+-
+       if (!mode_option) {
+               mode->specified = false;
+               return false;
diff --git a/target/linux/bcm27xx/patches-5.4/950-0490-drm-modes-parse_cmdline-Explicitly-memset-the-passed.patch b/target/linux/bcm27xx/patches-5.4/950-0490-drm-modes-parse_cmdline-Explicitly-memset-the-passed.patch
new file mode 100644 (file)
index 0000000..6c17d89
--- /dev/null
@@ -0,0 +1,41 @@
+From d89b3f22cf7b6bba8081f6d16c9087019fdcf586 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 18 Nov 2019 16:51:32 +0100
+Subject: [PATCH] drm/modes: parse_cmdline: Explicitly memset the
+ passed in drm_cmdline_mode struct
+
+Commit d1fe276b5115f0d581c3cfe6154633b3547e8aab upstream.
+
+Instead of only setting mode->specified on false on an early exit and
+leaving e.g. mode->bpp_specified and mode->refresh_specified as is,
+lets be consistent and just zero out the entire passed in struct at
+the top of drm_mode_parse_command_line_for_connector()
+
+Changes in v3:
+-Drop "mode->specified = false;" line instead of the "return false;" (oops)
+ This crasher was reported-by: kernel test robot <lkp@intel.com>
+
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-11-hdegoede@redhat.com
+---
+ drivers/gpu/drm/drm_modes.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/drm_modes.c
++++ b/drivers/gpu/drm/drm_modes.c
+@@ -1745,12 +1745,11 @@ bool drm_mode_parse_command_line_for_con
+       char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
+       int i, len, ret;
++      memset(mode, 0, sizeof(*mode));
+       mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
+-      if (!mode_option) {
+-              mode->specified = false;
++      if (!mode_option)
+               return false;
+-      }
+       name = mode_option;