* Re: [PATCH v3 3/5] RISC-V: Fix unsupported isa string info.
From: Atish Patra @ 2019-08-07 17:31 UTC (permalink / raw)
To: paul.walmsley@sifive.com
Cc: info@metux.net, allison@lohutok.net, palmer@sifive.com,
aou@eecs.berkeley.edu, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, tglx@linutronix.de,
daniel.lezcano@linaro.org, Anup Patel, mark.rutland@arm.com,
johan@kernel.org, robh+dt@kernel.org, gregkh@linuxfoundation.org,
tiny.windzz@gmail.com, gary@garyguo.net,
linux-riscv@lists.infradead.org
In-Reply-To: <alpine.DEB.2.21.9999.1908061818360.13971@viisi.sifive.com>
On Tue, 2019-08-06 at 18:26 -0700, Paul Walmsley wrote:
> On Wed, 7 Aug 2019, Atish Patra wrote:
>
> > On Tue, 2019-08-06 at 16:27 -0700, Paul Walmsley wrote:
> >
> > > Seems like the "su" should be dropped from mandatory_ext. What
> > > do you
> > > think?
> > >
> >
> > Yup. As DT binding only mention imafdc, mandatory extensions should
> > contain only that and just consider "su" extensions are considered
> > as
> > implicit as we are running Linux.
>
> Discussing this with Andrew and Palmer, it looks like "su" is
> currently
> non-compliant. Section 22.6 of the user-level specification states
> that
> the "s" character indicates that a longer standard supervisor
> extension
> name will follow. So far I don't think any of these have been
> defined.
>
> > Do you think QEMU DT should be updated to reflect that ?
>
> Yes.
>
> > > There's no Kconfig option by this name, and we're requiring
> > > compressed
> >
> > Sorry. This was a typo. It should have been CONFIG_RISCV_ISA_C.
> >
> > > instruction support as part of the RISC-V Linux baseline. Could
> > > you
> > > share the rationale behind this?
> >
> > I think I added this check at the config file. Looking at the
> > Kconfig,
> > RISCV_ISA_C is always enabled. So we can drop this.
>
> OK great. Do you want to resend an updated patch, or would you like
> me to
> fix it up here?
>
I am sending the patch right now. We can remove the 'S' mode check as
palmer have already sent the QEMU patch as well, .
Regards,
Atish
> I'll also send a patch to drop CONFIG_RISCV_ISA_C.
>
>
> - Paul
^ permalink raw reply
* Re: [PATCH 5/6] tty: serial: Add linflexuart driver for S32V234
From: Stefan-gabriel Mirea @ 2019-08-07 17:05 UTC (permalink / raw)
To: gregkh@linuxfoundation.org
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, corbet@lwn.net,
catalin.marinas@arm.com, linux-doc@vger.kernel.org,
Larisa Ileana Grigore, linux-kernel@vger.kernel.org, Leo Li,
Cosmin Stefan Stoica, robh+dt@kernel.org,
linux-serial@vger.kernel.org, jslaby@suse.com,
shawnguo@kernel.org, will@kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190807165646.GA6584@kroah.com>
On 8/7/2019 7:56 PM, gregkh@linuxfoundation.org wrote:
> On Wed, Aug 07, 2019 at 04:42:17PM +0000, Stefan-gabriel Mirea wrote:
>> On 8/6/2019 9:40 PM, gregkh@linuxfoundation.org wrote:
>>> On Tue, Aug 06, 2019 at 05:11:17PM +0000, Stefan-gabriel Mirea wrote:
<snip>
>>>> Other than that, I do not see anything wrong with the addition of a
>>>> define in serial_core.h for this purpose (which is also what most of the
>>>> serial drivers do, including amba-pl011.c, mentioned in
>>>> Documentation/driver-api/serial/driver.rst as providing the reference
>>>> implementation), so please be more specific.
>>>
>>> I am getting tired of dealing with merge issues with that list, and no
>>> one seems to be able to find where they are really needed for userspace,
>>> especially for new devices. What happens if you do not have use it?
>>
>> I see. If I drop its usage completely and leave 'type' from the
>> uart_port as 0, uart_port_startup() will fail when finding that
>> uport->type == PORT_UNKNOWN at [1] (there may be other effects as well,
>> e.g. due to the check in uart_configure_port[2]).
>>
>> So I suppose that I need to define some nonzero 'PORT_KNOWN' macro in
>> the driver and use that one internally for 'type'. Is my understanding
>> correct? Will there be any problems if I define it to a positive integer
>> which is already assigned to another driver, according to serial_core.h?
>
> Ugh, ok, that's messy, nevermind. Keep the #define in there, I will try
> to figure out how to move all of these at once sometime in the future...
>
> sorry for the noise.
No problem, thank you for your time.
Regards,
Stefan
^ permalink raw reply
* [PATCH v5 4/4] net: phy: realtek: Add LED configuration support for RTL8211E
From: Matthias Kaehlcke @ 2019-08-07 17:04 UTC (permalink / raw)
To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
Florian Fainelli, Heiner Kallweit
Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
Matthias Kaehlcke
In-Reply-To: <20190807170449.205378-1-mka@chromium.org>
Add a .config_led hook which is called by the PHY core when
configuration data for a PHY LED is available. Each LED can be
configured to be solid 'off, solid 'on' for certain (or all)
link speeds or to blink on RX/TX activity.
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v5:
- use 'config_leds' driver callback instead of requesting the DT
configuration
- added support for trigger 'none'
- always disable EEE LED mode when a LED is configured. We have no
device data struct to keep track of its state, the number of LEDs
is limited, so the overhead of disabling it multiple times (once for
each LED that is configured) during initialization is negligible
- print warning when disabling EEE LED mode fails
- updated commit message (previous subject was 'net: phy: realtek:
configure RTL8211E LEDs')
Changes in v4:
- use the generic PHY LED binding
- keep default/current configuration if none is specified
- added rtl8211e_disable_eee_led_mode()
- was previously in separate patch, however since we always want to
disable EEE LED mode when a LED configuration is specified it makes
sense to just add the function here.
- don't call phy_restore_page() in rtl8211e_config_leds() if
selection of the extended page failed.
- use phydev_warn() instead of phydev_err() if LED configuration
fails since we don't bail out
- use hex number to specify page for consistency
- add hex number to comment about ext page 44 to facilitate searching
Changes in v3:
- sanity check led-modes values
- set LACR bits in a more readable way
- use phydev_err() instead of dev_err()
- log an error if LED configuration fails
Changes in v2:
- patch added to the series
---
drivers/net/phy/realtek.c | 101 +++++++++++++++++++++++++++++++++++++-
1 file changed, 100 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index a5b3708dc4d8..5064ad732443 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -9,8 +9,9 @@
* Copyright (c) 2004 Freescale Semiconductor, Inc.
*/
#include <linux/bitops.h>
-#include <linux/phy.h>
+#include <linux/bits.h>
#include <linux/module.h>
+#include <linux/phy.h>
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX BIT(13)
@@ -26,6 +27,18 @@
#define RTL821x_EXT_PAGE_SELECT 0x1e
#define RTL821x_PAGE_SELECT 0x1f
+/* RTL8211E page 5 */
+#define RTL8211E_EEE_LED_MODE1 0x05
+#define RTL8211E_EEE_LED_MODE2 0x06
+
+/* RTL8211E extension page 44 (0x2c) */
+#define RTL8211E_LACR 0x1a
+#define RLT8211E_LACR_LEDACTCTRL_SHIFT 4
+#define RTL8211E_LCR 0x1c
+
+#define LACR_MASK(led) BIT(4 + led)
+#define LCR_MASK(led) GENMASK((led * 4) + 2, led * 4)
+
#define RTL8211F_INSR 0x1d
#define RTL8211F_TX_DELAY BIT(8)
@@ -83,6 +96,91 @@ static int rtl8211x_modify_ext_paged(struct phy_device *phydev, int page,
return phy_restore_page(phydev, oldpage, ret);
}
+static void rtl8211e_disable_eee_led_mode(struct phy_device *phydev)
+{
+ int oldpage;
+ int err = 0;
+
+ oldpage = phy_select_page(phydev, 5);
+ if (oldpage < 0)
+ goto out;
+
+ /* write magic values to disable EEE LED mode */
+ err = __phy_write(phydev, RTL8211E_EEE_LED_MODE1, 0x8b82);
+ if (err)
+ goto out;
+
+ err = __phy_write(phydev, RTL8211E_EEE_LED_MODE2, 0x052b);
+
+out:
+ if (err)
+ phydev_warn(phydev, "failed to disable EEE LED mode: %d\n", err);
+
+ phy_restore_page(phydev, oldpage, err);
+}
+
+static int rtl8211e_config_led(struct phy_device *phydev, int led,
+ struct phy_led_config *cfg)
+{
+ u16 lacr_bits = 0, lcr_bits = 0;
+ int oldpage, ret;
+
+ switch (cfg->trigger.t) {
+ case PHY_LED_TRIGGER_LINK:
+ lcr_bits = 7 << (led * 4);
+ break;
+
+ case PHY_LED_TRIGGER_LINK_10M:
+ lcr_bits = 1 << (led * 4);
+ break;
+
+ case PHY_LED_TRIGGER_LINK_100M:
+ lcr_bits = 2 << (led * 4);
+ break;
+
+ case PHY_LED_TRIGGER_LINK_1G:
+ lcr_bits |= 4 << (led * 4);
+ break;
+
+ case PHY_LED_TRIGGER_NONE:
+ break;
+
+ default:
+ phydev_warn(phydev,
+ "unknown trigger for LED%d: %d\n",
+ led, cfg->trigger.t);
+ return -EINVAL;
+ }
+
+ if (cfg->trigger.activity)
+ lacr_bits = BIT(RLT8211E_LACR_LEDACTCTRL_SHIFT + led);
+
+ rtl8211e_disable_eee_led_mode(phydev);
+
+ oldpage = rtl8211x_select_ext_page(phydev, 0x2c);
+ if (oldpage < 0) {
+ phydev_err(phydev, "failed to select extended page: %d\n", oldpage);
+ return oldpage;
+ }
+
+ ret = __phy_modify(phydev, RTL8211E_LACR,
+ LACR_MASK(led), lacr_bits);
+ if (ret) {
+ phydev_err(phydev, "failed to write LACR reg: %d\n",
+ ret);
+ goto err;
+ }
+
+ ret = __phy_modify(phydev, RTL8211E_LCR,
+ LCR_MASK(led), lcr_bits);
+ if (ret)
+ phydev_err(phydev, "failed to write LCR reg: %d\n",
+ ret);
+
+err:
+ return phy_restore_page(phydev, oldpage, ret);
+}
+
static int rtl8201_ack_interrupt(struct phy_device *phydev)
{
int err;
@@ -330,6 +428,7 @@ static struct phy_driver realtek_drvs[] = {
.config_init = &rtl8211e_config_init,
.ack_interrupt = &rtl821x_ack_interrupt,
.config_intr = &rtl8211e_config_intr,
+ .config_led = &rtl8211e_config_led,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = rtl821x_read_page,
--
2.22.0.770.g0f2c4a37fd-goog
^ permalink raw reply related
* [PATCH v5 3/4] net: phy: realtek: Add helpers for accessing RTL8211x extension pages
From: Matthias Kaehlcke @ 2019-08-07 17:04 UTC (permalink / raw)
To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
Florian Fainelli, Heiner Kallweit
Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
Matthias Kaehlcke
In-Reply-To: <20190807170449.205378-1-mka@chromium.org>
Some RTL8211x PHYs have extension pages, which can be accessed
after selecting a page through a custom method. Add a function to
modify bits in a register of an extension page and a helper for
selecting an ext page. Use rtl8211x_modify_ext_paged() in
rtl8211e_config_init() instead of doing things 'manually'.
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v5:
- renamed 'rtl8211e_<action>_ext_page' to 'rtl8211x_<action>_ext_page'
- updated commit message
Changes in v4:
- don't add constant RTL8211E_EXT_PAGE, it's only used once,
use a literal instead
- pass 'oldpage' to phy_restore_page() in rtl8211e_select_ext_page(),
not 'page'
- return 'oldpage' in rtl8211e_select_ext_page()
- use __phy_modify() in rtl8211e_modify_ext_paged() instead of
reimplementing __phy_modify_changed()
- in rtl8211e_modify_ext_paged() return directly when
rtl8211e_select_ext_page() fails
Changes in v3:
- use the new function in rtl8211e_config_init() instead of
doing things 'manually'
- use existing RTL8211E_EXT_PAGE instead of adding a new define
- updated commit message
Changes in v2:
- use phy_select_page() and phy_restore_page(), get rid of
rtl8211e_restore_page()
- s/rtl821e_select_ext_page/rtl8211e_select_ext_page/
- updated commit message
---
drivers/net/phy/realtek.c | 47 +++++++++++++++++++++++++++------------
1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index a669945eb829..a5b3708dc4d8 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -53,6 +53,36 @@ static int rtl821x_write_page(struct phy_device *phydev, int page)
return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
}
+static int rtl8211x_select_ext_page(struct phy_device *phydev, int page)
+{
+ int ret, oldpage;
+
+ oldpage = phy_select_page(phydev, 7);
+ if (oldpage < 0)
+ return oldpage;
+
+ ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, page);
+ if (ret)
+ return phy_restore_page(phydev, oldpage, ret);
+
+ return oldpage;
+}
+
+static int rtl8211x_modify_ext_paged(struct phy_device *phydev, int page,
+ u32 regnum, u16 mask, u16 set)
+{
+ int ret = 0;
+ int oldpage;
+
+ oldpage = rtl8211x_select_ext_page(phydev, page);
+ if (oldpage < 0)
+ return oldpage;
+
+ ret = __phy_modify(phydev, regnum, mask, set);
+
+ return phy_restore_page(phydev, oldpage, ret);
+}
+
static int rtl8201_ack_interrupt(struct phy_device *phydev)
{
int err;
@@ -184,7 +214,6 @@ static int rtl8211f_config_init(struct phy_device *phydev)
static int rtl8211e_config_init(struct phy_device *phydev)
{
- int ret = 0, oldpage;
u16 val;
/* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
@@ -213,19 +242,9 @@ static int rtl8211e_config_init(struct phy_device *phydev)
* 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
* for details).
*/
- oldpage = phy_select_page(phydev, 0x7);
- if (oldpage < 0)
- goto err_restore_page;
-
- ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
- if (ret)
- goto err_restore_page;
-
- ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
- val);
-
-err_restore_page:
- return phy_restore_page(phydev, oldpage, ret);
+ return rtl8211x_modify_ext_paged(phydev, 0xa4, 0x1c,
+ RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
+ val);
}
static int rtl8211b_suspend(struct phy_device *phydev)
--
2.22.0.770.g0f2c4a37fd-goog
^ permalink raw reply related
* [PATCH v5 2/4] net: phy: Add support for generic LED configuration through the DT
From: Matthias Kaehlcke @ 2019-08-07 17:04 UTC (permalink / raw)
To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
Florian Fainelli, Heiner Kallweit
Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
Matthias Kaehlcke
In-Reply-To: <20190807170449.205378-1-mka@chromium.org>
For PHYs with a device tree node look for LED trigger configuration
using the generic binding, if it exists try to apply it via the new
driver hook .config_led.
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v5:
- add callback to configure a LED to the PHY driver, instead of
having the driver retrieve the DT data
- use new trigger names
- added support for trigger 'none'
- release DT nodes after use
- renamed 'PHY_LED_LINK_*' to 'PHY_LED_TRIGGER_LINK_*'
- added anonymous struct to struct phy_led_config to track
'activity' in a separate flag. this could be changed to 'flags' if
needed/desired.
- updated commit message (previous subject was 'net: phy: Add
function to retrieve LED configuration from the DT')
Changes in v4:
- patch added to the series
---
drivers/net/phy/phy_device.c | 72 ++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 22 +++++++++++
2 files changed, 94 insertions(+)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 6b5cb87f3866..6f85fdf72af0 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -29,6 +29,7 @@
#include <linux/phy_led_triggers.h>
#include <linux/mdio.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <linux/uaccess.h>
MODULE_DESCRIPTION("PHY library");
@@ -1064,6 +1065,75 @@ static int phy_poll_reset(struct phy_device *phydev)
return 0;
}
+static void of_phy_config_leds(struct phy_device *phydev)
+{
+ struct device_node *np, *child;
+ struct phy_led_config cfg;
+ const char *trigger;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO) || !phydev->drv->config_led)
+ return;
+
+ np = of_find_node_by_name(phydev->mdio.dev.of_node, "leds");
+ if (!np)
+ return;
+
+ for_each_child_of_node(np, child) {
+ u32 led;
+
+ if (of_property_read_u32(child, "reg", &led))
+ goto skip_config;
+
+ ret = of_property_read_string(child, "linux,default-trigger",
+ &trigger);
+ if (ret)
+ trigger = "none";
+
+ memset(&cfg, 0, sizeof(cfg));
+
+ if (!strcmp(trigger, "none")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_NONE;
+ } else if (!strcmp(trigger, "phy-link")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK;
+ } else if (!strcmp(trigger, "phy-link-10m")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_10M;
+ } else if (!strcmp(trigger, "phy-link-100m")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_100M;
+ } else if (!strcmp(trigger, "phy-link-1g")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_1G;
+ } else if (!strcmp(trigger, "phy-link-10g")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_10G;
+ } else if (!strcmp(trigger, "phy-link-activity")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK;
+ cfg.trigger.activity = true;
+ } else if (!strcmp(trigger, "phy-link-10m-activity")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_10M;
+ cfg.trigger.activity = true;
+ } else if (!strcmp(trigger, "phy-link-100m-activity")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_100M;
+ cfg.trigger.activity = true;
+ } else if (!strcmp(trigger, "phy-link-1g-activity")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_1G;
+ cfg.trigger.activity = true;
+ } else if (!strcmp(trigger, "phy-link-10g-activity")) {
+ cfg.trigger.t = PHY_LED_TRIGGER_LINK_10G;
+ cfg.trigger.activity = true;
+ } else {
+ phydev_warn(phydev, "trigger '%s' for LED%d is invalid\n",
+ trigger, led);
+ goto skip_config;
+ }
+
+ phydev->drv->config_led(phydev, led, &cfg);
+
+ skip_config:
+ of_node_put(child);
+ }
+
+ of_node_put(np);
+}
+
int phy_init_hw(struct phy_device *phydev)
{
int ret = 0;
@@ -1087,6 +1157,8 @@ int phy_init_hw(struct phy_device *phydev)
if (phydev->drv->config_init)
ret = phydev->drv->config_init(phydev);
+ of_phy_config_leds(phydev);
+
return ret;
}
EXPORT_SYMBOL(phy_init_hw);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 462b90b73f93..3a07390fc5e9 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -325,6 +325,24 @@ struct phy_c45_device_ids {
u32 device_ids[8];
};
+/* Triggers for PHY LEDs */
+enum phy_led_trigger {
+ PHY_LED_TRIGGER_NONE,
+ PHY_LED_TRIGGER_LINK,
+ PHY_LED_TRIGGER_LINK_10M,
+ PHY_LED_TRIGGER_LINK_100M,
+ PHY_LED_TRIGGER_LINK_1G,
+ PHY_LED_TRIGGER_LINK_10G,
+};
+
+/* Configuration of a single PHY LED */
+struct phy_led_config {
+ struct {
+ enum phy_led_trigger t;
+ bool activity;
+ } trigger;
+};
+
/* phy_device: An instance of a PHY
*
* drv: Pointer to the driver for this PHY instance
@@ -626,6 +644,10 @@ struct phy_driver {
struct ethtool_tunable *tuna,
const void *data);
int (*set_loopback)(struct phy_device *dev, bool enable);
+
+ /* Configure a PHY LED */
+ int (*config_led)(struct phy_device *dev, int led,
+ struct phy_led_config *cfg);
};
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)
--
2.22.0.770.g0f2c4a37fd-goog
^ permalink raw reply related
* [PATCH v5 1/4] dt-bindings: net: phy: Add subnode for LED configuration
From: Matthias Kaehlcke @ 2019-08-07 17:04 UTC (permalink / raw)
To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
Florian Fainelli, Heiner Kallweit
Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
Matthias Kaehlcke
In-Reply-To: <20190807170449.205378-1-mka@chromium.org>
The LED behavior of some Ethernet PHYs is configurable. Add an
optional 'leds' subnode with a child node for each LED to be
configured. The binding aims to be compatible with the common
LED binding (see devicetree/bindings/leds/common.txt).
A LED can be configured to be:
- 'on' when a link is active, some PHYs allow configuration for
certain link speeds
speeds
- 'off'
- blink on RX/TX activity, some PHYs allow configuration for
certain link speeds
For the configuration to be effective it needs to be supported by
the hardware and the corresponding PHY driver.
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
Changes in v5:
- renamed triggers from 'phy_link_<speed>_active' to 'phy-link-<speed>'
- added entries for 'phy-link-<speed>-activity'
- added 'phy-link' and 'phy-link-activity' for triggers with any link
speed
- added entry for trigger 'none'
Changes in v4:
- patch added to the series
---
.../devicetree/bindings/net/ethernet-phy.yaml | 59 +++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
index f70f18ff821f..98ba320f828b 100644
--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
@@ -153,6 +153,50 @@ properties:
Delay after the reset was deasserted in microseconds. If
this property is missing the delay will be skipped.
+patternProperties:
+ "^leds$":
+ type: object
+ description:
+ Subnode with configuration of the PHY LEDs.
+
+ patternProperties:
+ "^led@[0-9]+$":
+ type: object
+ description:
+ Subnode with the configuration of a single PHY LED.
+
+ properties:
+ reg:
+ description:
+ The ID number of the LED, typically corresponds to a hardware ID.
+ $ref: "/schemas/types.yaml#/definitions/uint32"
+
+ linux,default-trigger:
+ description:
+ This parameter, if present, is a string specifying the trigger
+ assigned to the LED. Supported triggers are:
+ "none" - LED will be solid off
+ "phy-link" - LED will be solid on when a link is active
+ "phy-link-10m" - LED will be solid on when a 10Mb/s link is active
+ "phy-link-100m" - LED will be solid on when a 100Mb/s link is active
+ "phy-link-1g" - LED will be solid on when a 1Gb/s link is active
+ "phy-link-10g" - LED will be solid on when a 10Gb/s link is active
+ "phy-link-activity" - LED will be on when link is active and blink
+ off with activity.
+ "phy-link-10m-activity" - LED will be on when 10Mb/s link is active
+ and blink off with activity.
+ "phy-link-100m-activity" - LED will be on when 100Mb/s link is
+ active and blink off with activity.
+ "phy-link-1g-activity" - LED will be on when 1Gb/s link is active
+ and blink off with activity.
+ "phy-link-10g-activity" - LED will be on when 10Gb/s link is active
+ and blink off with activity.
+
+ $ref: "/schemas/types.yaml#/definitions/string"
+
+ required:
+ - reg
+
required:
- reg
@@ -173,5 +217,20 @@ examples:
reset-gpios = <&gpio1 4 1>;
reset-assert-us = <1000>;
reset-deassert-us = <2000>;
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ linux,default-trigger = "phy-link-1g";
+ };
+
+ led@1 {
+ reg = <1>;
+ linux,default-trigger = "phy-link-100m-activity";
+ };
+ };
};
};
--
2.22.0.770.g0f2c4a37fd-goog
^ permalink raw reply related
* [PATCH v5 0/4] net: phy: Add support for DT configuration of PHY LEDs and use it for RTL8211E
From: Matthias Kaehlcke @ 2019-08-07 17:04 UTC (permalink / raw)
To: David S . Miller, Rob Herring, Mark Rutland, Andrew Lunn,
Florian Fainelli, Heiner Kallweit
Cc: netdev, devicetree, linux-kernel, Douglas Anderson,
Matthias Kaehlcke
This series adds a generic binding to configure PHY LEDs through
the device tree, and phylib support for reading the information
from the DT. PHY drivers that support the generic binding should
implement the new hook .config_led.
Enable DT configuration of the RTL8211E LEDs by implementing the
.config_led hook of the driver. Certain registers of the RTL8211E
can only be accessed through a vendor specific extended page
mechanism. Extended pages need to be accessed for the LED
configuration. This series adds helpers to facilitate accessing
extended pages.
(subject updated, was "net: phy: realtek: Enable configuration
of RTL8211E LEDs")
Matthias Kaehlcke (4):
dt-bindings: net: phy: Add subnode for LED configuration
net: phy: Add support for generic LED configuration through the DT
net: phy: realtek: Add helpers for accessing RTL8211x extension pages
net: phy: realtek: Add LED configuration support for RTL8211E
.../devicetree/bindings/net/ethernet-phy.yaml | 59 +++++++
drivers/net/phy/phy_device.c | 72 +++++++++
drivers/net/phy/realtek.c | 148 ++++++++++++++++--
include/linux/phy.h | 22 +++
4 files changed, 286 insertions(+), 15 deletions(-)
--
2.22.0.770.g0f2c4a37fd-goog
^ permalink raw reply
* Re: [PATCH 5/6] tty: serial: Add linflexuart driver for S32V234
From: gregkh @ 2019-08-07 16:56 UTC (permalink / raw)
To: Stefan-gabriel Mirea
Cc: corbet@lwn.net, robh+dt@kernel.org, mark.rutland@arm.com,
catalin.marinas@arm.com, will@kernel.org, shawnguo@kernel.org,
Leo Li, jslaby@suse.com, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linux-serial@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Cosmin Stefan Stoica,
Larisa Ileana Grigore
In-Reply-To: <VI1PR0402MB2863C4406C06B0BDA3581822DFD40@VI1PR0402MB2863.eurprd04.prod.outlook.com>
On Wed, Aug 07, 2019 at 04:42:17PM +0000, Stefan-gabriel Mirea wrote:
> On 8/6/2019 9:40 PM, gregkh@linuxfoundation.org wrote:
> > On Tue, Aug 06, 2019 at 05:11:17PM +0000, Stefan-gabriel Mirea wrote:
> >> On 8/5/2019 6:31 PM, gregkh@linuxfoundation.org wrote:
> >>> On Fri, Aug 02, 2019 at 07:47:23PM +0000, Stefan-gabriel Mirea wrote:
> >>>>
> >>>> +/* Freescale Linflex UART */
> >>>> +#define PORT_LINFLEXUART 121
> >>>
> >>> Do you really need this modified?
> >>
> >> Hello Greg,
> >>
> >> This macro is meant to be assigned to port->type in the config_port
> >> method from uart_ops, in order for verify_port to know if the received
> >> serial_struct structure was really targeted for a LINFlex port. It
> >> needs to be defined outside, to avoid "collisions" with other drivers.
> >
> > Yes, I know what it goes to, but does anyone in userspace actually use
> > it?
>
> No, we do not use it from userspace, but kept the pattern only for
> conformance.
>
> >> Other than that, I do not see anything wrong with the addition of a
> >> define in serial_core.h for this purpose (which is also what most of the
> >> serial drivers do, including amba-pl011.c, mentioned in
> >> Documentation/driver-api/serial/driver.rst as providing the reference
> >> implementation), so please be more specific.
> >
> > I am getting tired of dealing with merge issues with that list, and no
> > one seems to be able to find where they are really needed for userspace,
> > especially for new devices. What happens if you do not have use it?
>
> I see. If I drop its usage completely and leave 'type' from the
> uart_port as 0, uart_port_startup() will fail when finding that
> uport->type == PORT_UNKNOWN at [1] (there may be other effects as well,
> e.g. due to the check in uart_configure_port[2]).
>
> So I suppose that I need to define some nonzero 'PORT_KNOWN' macro in
> the driver and use that one internally for 'type'. Is my understanding
> correct? Will there be any problems if I define it to a positive integer
> which is already assigned to another driver, according to serial_core.h?
Ugh, ok, that's messy, nevermind. Keep the #define in there, I will try
to figure out how to move all of these at once sometime in the future...
sorry for the noise.
greg k-h
^ permalink raw reply
* Re: [PATCH v2 4/4] dt-bindings: iio: adc: Add AD7606B ADC documentation
From: Peter Meerwald-Stadler @ 2019-08-07 16:41 UTC (permalink / raw)
To: Beniamin Bia
Cc: jic23, lars, Michael.Hennerich, linux-iio, devicetree,
biabeniamin
In-Reply-To: <20190807133137.11185-4-beniamin.bia@analog.com>
On Wed, 7 Aug 2019, Beniamin Bia wrote:
minor comment below
> Documentation for AD7606B Analog to Digital Converter and software
> mode was added.
>
> Signed-off-by: Beniamin Bia <beniamin.bia@analog.com>
> ---
> Changes in v2:
> -nothing changed
>
> Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
> index 509dbe9c84d2..2afe31747a70 100644
> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
> @@ -13,6 +13,7 @@ maintainers:
> description: |
> Analog Devices AD7606 Simultaneous Sampling ADC
> https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf
> + https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf
> https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf
>
> properties:
> @@ -22,6 +23,7 @@ properties:
> - adi,ad7606-8
> - adi,ad7606-6
> - adi,ad7606-4
> + - adi,ad7606b
> - adi,ad7616
>
> reg:
> @@ -87,7 +89,7 @@ properties:
>
> adi,sw-mode:
> description:
> - Software mode of operation, so far available only for ad7616.
> + Software mode of operation, so far available only for ad7616 and ad7606B.
how about ad7606b to match the properties above?
> It is enabled when all three oversampling mode pins are connected to
> high level. The device is configured by the corresponding registers. If the
> adi,oversampling-ratio-gpios property is defined, then the driver will set the
>
--
Peter Meerwald-Stadler
Mobile: +43 664 24 44 418
^ permalink raw reply
* [PATCH v3 5/5] dt-bindings: dsp: fsl: Add DSP core binding support
From: Daniel Baluta @ 2019-08-07 16:42 UTC (permalink / raw)
To: daniel.baluta, shawnguo
Cc: aisheng.dong, anson.huang, devicetree, festevam, kernel,
leonard.crestez, linux-arm-kernel, linux-imx, linux-kernel,
m.felsch, mark.rutland, paul.olaru, peng.fan, robh+dt,
shengjiu.wang, sound-open-firmware, pierre-louis.bossart, l.stach
In-Reply-To: <20190807164258.8306-1-daniel.baluta@nxp.com>
This describes the DSP device tree node.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/dsp/fsl,dsp.yaml | 88 +++++++++++++++++++
1 file changed, 88 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
diff --git a/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
new file mode 100644
index 000000000000..24b9fd64e3eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/dsp/fsl,dsp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX8 DSP core
+
+maintainers:
+ - Daniel Baluta <daniel.baluta@nxp.com>
+
+description: |
+ Some boards from i.MX8 family contain a DSP core used for
+ advanced pre- and post- audio processing.
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8qxp-dsp
+
+ reg:
+ description: Should contain register location and length
+
+ clocks:
+ items:
+ - description: ipg clock
+ - description: ocram clock
+ - description: core clock
+
+ clock-names:
+ items:
+ - const: ipg
+ - const: ocram
+ - const: core
+
+ power-domains:
+ description:
+ List of phandle and PM domain specifier as documented in
+ Documentation/devicetree/bindings/power/power_domain.txt
+ maxItems: 4
+
+ mboxes:
+ description:
+ List of <&phandle type channel> - 2 channels for TXDB, 2 channels for RXDB
+ (see mailbox/fsl,mu.txt)
+ maxItems: 4
+
+ mbox-names:
+ items:
+ - const: txdb0
+ - const: txdb1
+ - const: rxdb0
+ - const: rxdb1
+
+ memory-region:
+ description:
+ phandle to a node describing reserved memory (System RAM memory)
+ used by DSP (see bindings/reserved-memory/reserved-memory.txt)
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - power-domains
+ - mboxes
+ - mbox-names
+ - memory-region
+
+examples:
+ - |
+ #include <dt-bindings/firmware/imx/rsrc.h>
+ #include <dt-bindings/clock/imx8-clock.h>
+ dsp@596e8000 {
+ compatbile = "fsl,imx8qxp-dsp";
+ reg = <0x596e8000 0x88000>;
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_DSP_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>;
+ clock-names = "ipg", "ocram", "core";
+ power-domains = <&pd IMX_SC_R_MU_13A>,
+ <&pd IMX_SC_R_MU_13B>,
+ <&pd IMX_SC_R_DSP>,
+ <&pd IMX_SC_R_DSP_RAM>;
+ mbox-names = "txdb0", "txdb1", "rxdb0", "rxdb1";
+ mboxes = <&lsio_mu13 2 0>, <&lsio_mu13 2 1>, <&lsio_mu13 3 0>, <&lsio_mu13 3 1>;
+ };
--
2.17.1
^ permalink raw reply related
* [PATCH v3 4/5] arm64: dts: imx8qxp: Add DSP DT node
From: Daniel Baluta @ 2019-08-07 16:42 UTC (permalink / raw)
To: daniel.baluta, shawnguo
Cc: aisheng.dong, anson.huang, devicetree, festevam, kernel,
leonard.crestez, linux-arm-kernel, linux-imx, linux-kernel,
m.felsch, mark.rutland, paul.olaru, peng.fan, robh+dt,
shengjiu.wang, sound-open-firmware, pierre-louis.bossart, l.stach
In-Reply-To: <20190807164258.8306-1-daniel.baluta@nxp.com>
This includes DSP reserved memory, ADMA DSP device and DSP MU
communication channels description.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts | 4 +++
arch/arm64/boot/dts/freescale/imx8qxp.dtsi | 32 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
index bfdada2db176..19468058e6ae 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -230,3 +230,7 @@
>;
};
};
+
+&adma_dsp {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
index 05fa0b7f36bb..b6c408fb2b7f 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
@@ -113,6 +113,17 @@
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ dsp_reserved: dsp@92400000 {
+ reg = <0 0x92400000 0 0x2000000>;
+ no-map;
+ };
+ };
+
pmu {
compatible = "arm,armv8-pmuv3";
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
@@ -204,6 +215,27 @@
#clock-cells = <1>;
};
+ adma_dsp: dsp@596e8000 {
+ compatible = "fsl,imx8qxp-dsp";
+ reg = <0x596e8000 0x88000>;
+ clocks = <&adma_lpcg IMX_ADMA_LPCG_DSP_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_OCRAM_IPG_CLK>,
+ <&adma_lpcg IMX_ADMA_LPCG_DSP_CORE_CLK>;
+ clock-names = "ipg", "ocram", "core";
+ power-domains = <&pd IMX_SC_R_MU_13A>,
+ <&pd IMX_SC_R_MU_13B>,
+ <&pd IMX_SC_R_DSP>,
+ <&pd IMX_SC_R_DSP_RAM>;
+ mbox-names = "txdb0", "txdb1",
+ "rxdb0", "rxdb1";
+ mboxes = <&lsio_mu13 2 0>,
+ <&lsio_mu13 2 1>,
+ <&lsio_mu13 3 0>,
+ <&lsio_mu13 3 1>;
+ memory-region = <&dsp_reserved>;
+ status = "disabled";
+ };
+
adma_lpuart0: serial@5a060000 {
compatible = "fsl,imx8qxp-lpuart", "fsl,imx7ulp-lpuart";
reg = <0x5a060000 0x1000>;
--
2.17.1
^ permalink raw reply related
* [PATCH v3 3/5] ASoC: SOF: topology: Add dummy support for i.MX8 DAIs
From: Daniel Baluta @ 2019-08-07 16:42 UTC (permalink / raw)
To: daniel.baluta, shawnguo
Cc: aisheng.dong, anson.huang, devicetree, festevam, kernel,
leonard.crestez, linux-arm-kernel, linux-imx, linux-kernel,
m.felsch, mark.rutland, paul.olaru, peng.fan, robh+dt,
shengjiu.wang, sound-open-firmware, pierre-louis.bossart, l.stach
In-Reply-To: <20190807164258.8306-1-daniel.baluta@nxp.com>
Add dummy support for SAI/ESAI digital audio interface
IPs found on i.MX8 boards.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
include/sound/sof/dai.h | 2 ++
include/uapi/sound/sof/tokens.h | 8 ++++++++
sound/soc/sof/topology.c | 30 ++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h
index 3d174e20aa53..ec3b5c080537 100644
--- a/include/sound/sof/dai.h
+++ b/include/sound/sof/dai.h
@@ -50,6 +50,8 @@ enum sof_ipc_dai_type {
SOF_DAI_INTEL_DMIC, /**< Intel DMIC */
SOF_DAI_INTEL_HDA, /**< Intel HD/A */
SOF_DAI_INTEL_SOUNDWIRE, /**< Intel SoundWire */
+ SOF_DAI_IMX_SAI, /**< i.MX SAI */
+ SOF_DAI_IMX_ESAI, /**< i.MX ESAI */
};
/* general purpose DAI configuration */
diff --git a/include/uapi/sound/sof/tokens.h b/include/uapi/sound/sof/tokens.h
index 6435240cef13..8f996857fb24 100644
--- a/include/uapi/sound/sof/tokens.h
+++ b/include/uapi/sound/sof/tokens.h
@@ -106,4 +106,12 @@
/* for backward compatibility */
#define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE
+/* SAI */
+#define SOF_TKN_IMX_SAI_FIRST_TOKEN 1000
+/* TODO: Add SAI tokens */
+
+/* ESAI */
+#define SOF_TKN_IMX_ESAI_FIRST_TOKEN 1100
+/* TODO: Add ESAI tokens */
+
#endif
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 30b5638622dd..e3761657ecc0 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -346,6 +346,8 @@ static const struct sof_dai_types sof_dais[] = {
{"SSP", SOF_DAI_INTEL_SSP},
{"HDA", SOF_DAI_INTEL_HDA},
{"DMIC", SOF_DAI_INTEL_DMIC},
+ {"SAI", SOF_DAI_IMX_SAI},
+ {"ESAI", SOF_DAI_IMX_ESAI},
};
static enum sof_ipc_dai_type find_dai(const char *name)
@@ -2516,6 +2518,26 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, int index,
return ret;
}
+static int sof_link_sai_load(struct snd_soc_component *scomp, int index,
+ struct snd_soc_dai_link *link,
+ struct snd_soc_tplg_link_config *cfg,
+ struct snd_soc_tplg_hw_config *hw_config,
+ struct sof_ipc_dai_config *config)
+{
+ /*TODO: Add implementation */
+ return 0;
+}
+
+static int sof_link_esai_load(struct snd_soc_component *scomp, int index,
+ struct snd_soc_dai_link *link,
+ struct snd_soc_tplg_link_config *cfg,
+ struct snd_soc_tplg_hw_config *hw_config,
+ struct sof_ipc_dai_config *config)
+{
+ /*TODO: Add implementation */
+ return 0;
+}
+
static int sof_link_dmic_load(struct snd_soc_component *scomp, int index,
struct snd_soc_dai_link *link,
struct snd_soc_tplg_link_config *cfg,
@@ -2840,6 +2862,14 @@ static int sof_link_load(struct snd_soc_component *scomp, int index,
ret = sof_link_hda_load(scomp, index, link, cfg, hw_config,
&config);
break;
+ case SOF_DAI_IMX_SAI:
+ ret = sof_link_sai_load(scomp, index, link, cfg, hw_config,
+ &config);
+ break;
+ case SOF_DAI_IMX_ESAI:
+ ret = sof_link_esai_load(scomp, index, link, cfg, hw_config,
+ &config);
+ break;
default:
dev_err(sdev->dev, "error: invalid DAI type %d\n", config.type);
ret = -EINVAL;
--
2.17.1
^ permalink raw reply related
* [PATCH v3 2/5] ASoC: SOF: imx: Add i.MX8 HW support
From: Daniel Baluta @ 2019-08-07 16:42 UTC (permalink / raw)
To: daniel.baluta, shawnguo
Cc: aisheng.dong, anson.huang, devicetree, festevam, kernel,
leonard.crestez, linux-arm-kernel, linux-imx, linux-kernel,
m.felsch, mark.rutland, paul.olaru, peng.fan, robh+dt,
shengjiu.wang, sound-open-firmware, pierre-louis.bossart, l.stach
In-Reply-To: <20190807164258.8306-1-daniel.baluta@nxp.com>
Add support for the audio DSP hardware found on NXP i.MX8 platform.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
sound/soc/sof/Kconfig | 1 +
sound/soc/sof/Makefile | 1 +
sound/soc/sof/imx/Kconfig | 22 +++
sound/soc/sof/imx/Makefile | 4 +
sound/soc/sof/imx/imx8.c | 394 +++++++++++++++++++++++++++++++++++++
5 files changed, 422 insertions(+)
create mode 100644 sound/soc/sof/imx/Kconfig
create mode 100644 sound/soc/sof/imx/Makefile
create mode 100644 sound/soc/sof/imx/imx8.c
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 73c455dacab5..cc592bcadae7 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -181,6 +181,7 @@ config SND_SOC_SOF_PROBE_WORK_QUEUE
When selected, the probe is handled in two steps, for example to
avoid lockdeps if request_module is used in the probe.
+source "sound/soc/sof/imx/Kconfig"
source "sound/soc/sof/intel/Kconfig"
source "sound/soc/sof/xtensa/Kconfig"
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index f605a02257e7..a37dbfabfa3b 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -20,4 +20,5 @@ obj-$(CONFIG_SND_SOC_SOF_OF) += sof-of-dev.o
obj-$(CONFIG_SND_SOC_SOF_PCI) += sof-pci-dev.o
obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/
+obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/
obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/
diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig
new file mode 100644
index 000000000000..fd73d8402dbf
--- /dev/null
+++ b/sound/soc/sof/imx/Kconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+
+config SND_SOC_SOF_IMX_TOPLEVEL
+ bool "SOF support for NXP i.MX audio DSPs"
+ depends on ARM64 && SND_SOC_SOF_OF || COMPILE_TEST
+ help
+ This adds support for Sound Open Firmware for NXP i.MX platforms.
+ Say Y if you have such a device.
+ If unsure select "N".
+
+if SND_SOC_SOF_IMX_TOPLEVEL
+
+config SND_SOC_SOF_IMX8
+ tristate "SOF support for i.MX8"
+ depends on IMX_SCU
+ depends on IMX_DSP
+ help
+ This adds support for Sound Open Firmware for NXP i.MX8 platforms
+ Say Y if you have such a device.
+ If unsure select "N".
+
+endif ## SND_SOC_SOF_IMX_IMX_TOPLEVEL
diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile
new file mode 100644
index 000000000000..6ef908e8c807
--- /dev/null
+++ b/sound/soc/sof/imx/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+snd-sof-imx8-objs := imx8.o
+
+obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o
diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c
new file mode 100644
index 000000000000..9869d783c31e
--- /dev/null
+++ b/sound/soc/sof/imx/imx8.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+//
+// Copyright 2019 NXP
+//
+// Author: Daniel Baluta <daniel.baluta@nxp.com>
+//
+// Hardware interface for audio DSP on i.MX8
+
+#include <linux/firmware.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/pm_domain.h>
+
+#include <linux/module.h>
+#include <sound/sof.h>
+#include <sound/sof/xtensa.h>
+#include <linux/firmware/imx/ipc.h>
+#include <linux/firmware/imx/dsp.h>
+
+#include <linux/firmware/imx/svc/misc.h>
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include "../ops.h"
+
+/* DSP memories */
+#define IRAM_OFFSET 0x10000
+#define IRAM_SIZE (2 * 1024)
+#define DRAM0_OFFSET 0x0
+#define DRAM0_SIZE (32 * 1024)
+#define DRAM1_OFFSET 0x8000
+#define DRAM1_SIZE (32 * 1024)
+#define SYSRAM_OFFSET 0x18000
+#define SYSRAM_SIZE (256 * 1024)
+#define SYSROM_OFFSET 0x58000
+#define SYSROM_SIZE (192 * 1024)
+
+#define RESET_VECTOR_VADDR 0x596f8000
+
+#define MBOX_OFFSET 0x800000
+#define MBOX_SIZE 0x1000
+
+struct imx8_priv {
+ struct device *dev;
+ struct snd_sof_dev *sdev;
+
+ /* DSP IPC handler */
+ struct imx_dsp_ipc *dsp_ipc;
+ struct platform_device *ipc_dev;
+
+ /* System Controller IPC handler */
+ struct imx_sc_ipc *sc_ipc;
+
+ /* Power domain handling */
+ int num_domains;
+ struct device **pd_dev;
+ struct device_link **link;
+
+};
+
+static void imx8_get_reply(struct snd_sof_dev *sdev)
+{
+ struct snd_sof_ipc_msg *msg = sdev->msg;
+ struct sof_ipc_reply reply;
+ int ret = 0;
+
+ if (!msg) {
+ dev_warn(sdev->dev, "unexpected ipc interrupt\n");
+ return;
+ }
+
+ /* get reply */
+ sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
+
+ if (reply.error < 0) {
+ memcpy(msg->reply_data, &reply, sizeof(reply));
+ ret = reply.error;
+ } else {
+ /* reply has correct size? */
+ if (reply.hdr.size != msg->reply_size) {
+ dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
+ msg->reply_size, reply.hdr.size);
+ ret = -EINVAL;
+ }
+
+ /* read the message */
+ if (msg->reply_size > 0)
+ sof_mailbox_read(sdev, sdev->host_box.offset,
+ msg->reply_data, msg->reply_size);
+ }
+
+ msg->reply_error = ret;
+}
+
+static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev)
+{
+ return MBOX_OFFSET;
+}
+
+static int imx8_get_window_offset(struct snd_sof_dev *sdev, u32 id)
+{
+ return MBOX_OFFSET;
+}
+
+void imx8_dsp_handle_reply(struct imx_dsp_ipc *ipc)
+{
+ struct imx8_priv *priv = imx_dsp_get_data(ipc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sdev->ipc_lock, flags);
+ imx8_get_reply(priv->sdev);
+ snd_sof_ipc_reply(priv->sdev, 0);
+ spin_unlock_irqrestore(&priv->sdev->ipc_lock, flags);
+}
+
+void imx8_dsp_handle_request(struct imx_dsp_ipc *ipc)
+{
+ struct imx8_priv *priv = imx_dsp_get_data(ipc);
+
+ snd_sof_ipc_msgs_rx(priv->sdev);
+}
+
+struct imx_dsp_ops dsp_ops = {
+ .handle_reply = imx8_dsp_handle_reply,
+ .handle_request = imx8_dsp_handle_request,
+};
+
+static int imx8_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
+{
+ struct imx8_priv *priv = (struct imx8_priv *)sdev->private;
+
+ sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+ msg->msg_size);
+ imx_dsp_ring_doorbell(priv->dsp_ipc, 0);
+
+ return 0;
+}
+
+/*
+ * DSP control.
+ */
+static int imx8_run(struct snd_sof_dev *sdev)
+{
+ int ret;
+ struct imx8_priv *dsp_priv = (struct imx8_priv *)sdev->private;
+
+ ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
+ IMX_SC_C_OFS_SEL, 1);
+ if (ret < 0) {
+ dev_err(sdev->dev, "Error system address offset source select\n");
+ return ret;
+ }
+
+ ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
+ IMX_SC_C_OFS_AUDIO, 0x80);
+ if (ret < 0) {
+ dev_err(sdev->dev, "Error system address offset of AUDIO\n");
+ return ret;
+ }
+
+ ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
+ IMX_SC_C_OFS_PERIPH, 0x5A);
+ if (ret < 0) {
+ dev_err(sdev->dev, "Error system address offset of PERIPH %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = imx_sc_misc_set_control(dsp_priv->sc_ipc, IMX_SC_R_DSP,
+ IMX_SC_C_OFS_IRQ, 0x51);
+ if (ret < 0) {
+ dev_err(sdev->dev, "Error system address offset of IRQ\n");
+ return ret;
+ }
+
+ imx_sc_pm_cpu_start(dsp_priv->sc_ipc, IMX_SC_R_DSP, true,
+ RESET_VECTOR_VADDR);
+
+ return 0;
+}
+
+static int imx8_probe(struct snd_sof_dev *sdev)
+{
+ struct platform_device *pdev =
+ container_of(sdev->dev, struct platform_device, dev);
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *res_node;
+ struct resource *mmio;
+ struct imx8_priv *priv;
+ struct resource res;
+ u32 base, size;
+ int ret = 0;
+ int i;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ sdev->private = priv;
+ priv->dev = sdev->dev;
+ priv->sdev = sdev;
+
+ /* power up device associated power domains */
+ priv->num_domains = of_count_phandle_with_args(np, "power-domains",
+ "#power-domain-cells");
+ if (priv->num_domains < 0) {
+ dev_err(sdev->dev, "no power-domains property in %pOF\n", np);
+ return priv->num_domains;
+ }
+
+ priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains,
+ sizeof(*priv->pd_dev), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains,
+ sizeof(*priv->link), GFP_KERNEL);
+ if (!priv->link)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->num_domains; i++) {
+ priv->pd_dev[i] = dev_pm_domain_attach_by_id(&pdev->dev, i);
+ if (IS_ERR(priv->pd_dev[i])) {
+ ret = PTR_ERR(priv->pd_dev[i]);
+ goto exit_unroll_pm;
+ }
+ priv->link[i] = device_link_add(&pdev->dev, priv->pd_dev[i],
+ DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_RPM_ACTIVE);
+ if (IS_ERR(priv->link[i])) {
+ ret = PTR_ERR(priv->link[i]);
+ dev_pm_domain_detach(priv->pd_dev[i], false);
+ goto exit_unroll_pm;
+ }
+ }
+
+ ret = imx_scu_get_handle(&priv->sc_ipc);
+ if (ret) {
+ dev_err(sdev->dev, "Cannot obtain SCU handle (err = %d)\n",
+ ret);
+ goto exit_unroll_pm;
+ }
+
+ priv->ipc_dev = platform_device_register_data(sdev->dev, "imx-dsp",
+ PLATFORM_DEVID_NONE,
+ pdev, sizeof(*pdev));
+ if (IS_ERR(priv->ipc_dev)) {
+ ret = PTR_ERR(priv->ipc_dev);
+ goto exit_unroll_pm;
+ }
+
+ priv->dsp_ipc = dev_get_drvdata(&priv->ipc_dev->dev);
+ if (!priv->dsp_ipc) {
+ /* DSP IPC driver not probed yet, try later */
+ ret = -EPROBE_DEFER;
+ dev_err(sdev->dev, "Failed to get drvdata\n");
+ goto exit_pdev_unregister;
+ }
+
+ imx_dsp_set_data(priv->dsp_ipc, priv);
+ priv->dsp_ipc->ops = &dsp_ops;
+
+ /* DSP base */
+ mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (mmio) {
+ base = mmio->start;
+ size = resource_size(mmio);
+ } else {
+ dev_err(sdev->dev, "error: failed to get DSP base at idx 0\n");
+ ret = -EINVAL;
+ goto exit_pdev_unregister;
+ }
+
+ sdev->bar[SOF_FW_BLK_TYPE_IRAM] = devm_ioremap(sdev->dev, base, size);
+ if (!sdev->bar[SOF_FW_BLK_TYPE_IRAM]) {
+ dev_err(sdev->dev, "failed to ioremap base 0x%x size 0x%x\n",
+ base, size);
+ ret = -ENODEV;
+ goto exit_pdev_unregister;
+ }
+ sdev->mmio_bar = SOF_FW_BLK_TYPE_IRAM;
+
+ res_node = of_parse_phandle(np, "memory-region", 0);
+ if (!res_node) {
+ dev_err(&pdev->dev, "failed to get memory region node\n");
+ ret = -ENODEV;
+ goto exit_pdev_unregister;
+ }
+
+ ret = of_address_to_resource(res_node, 0, &res);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get reserved region address\n");
+ goto exit_pdev_unregister;
+ }
+
+ sdev->bar[SOF_FW_BLK_TYPE_SRAM] = devm_ioremap_wc(sdev->dev, res.start,
+ res.end - res.start +
+ 1);
+ if (IS_ERR(sdev->bar[SOF_FW_BLK_TYPE_SRAM])) {
+ dev_err(sdev->dev, "failed to ioremap mem 0x%x size 0x%x\n",
+ base, size);
+ ret = PTR_ERR(sdev->bar[SOF_FW_BLK_TYPE_SRAM]);
+ goto exit_pdev_unregister;
+ }
+ sdev->mailbox_bar = SOF_FW_BLK_TYPE_SRAM;
+
+ return 0;
+
+exit_pdev_unregister:
+ platform_device_unregister(priv->ipc_dev);
+exit_unroll_pm:
+ while (--i >= 0) {
+ device_link_del(priv->link[i]);
+ dev_pm_domain_detach(priv->pd_dev[i], false);
+ }
+
+ return ret;
+}
+
+static int imx8_remove(struct snd_sof_dev *sdev)
+{
+ int i;
+ struct imx8_priv *priv = (struct imx8_priv *)sdev->private;
+
+ platform_device_unregister(priv->ipc_dev);
+
+ for (i = 0; i < priv->num_domains; i++) {
+ device_link_del(priv->link[i]);
+ dev_pm_domain_detach(priv->pd_dev[i], false);
+ }
+
+ return 0;
+}
+
+/* on i.MX8 there is 1 to 1 match between type and BAR idx */
+int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type)
+{
+ return type;
+}
+
+void imx8_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ void *p, size_t sz)
+{
+ sof_mailbox_read(sdev, sdev->dsp_box.offset, p, sz);
+}
+
+int imx8_ipc_pcm_params(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ const struct sof_ipc_pcm_params_reply *reply)
+{
+ return 0;
+}
+
+static struct snd_soc_dai_driver imx8_dai[] = {
+{
+ .name = "esai-port",
+},
+};
+
+/* i.MX8 ops */
+struct snd_sof_dsp_ops sof_imx8_ops = {
+ /* probe and remove */
+ .probe = imx8_probe,
+ .remove = imx8_remove,
+ /* DSP core boot */
+ .run = imx8_run,
+
+ /* Block IO */
+ .block_read = sof_block_read,
+ .block_write = sof_block_write,
+
+ /* ipc */
+ .send_msg = imx8_send_msg,
+ .fw_ready = sof_fw_ready,
+ .get_mailbox_offset = imx8_get_mailbox_offset,
+ .get_window_offset = imx8_get_window_offset,
+
+ .ipc_msg_data = imx8_ipc_msg_data,
+ .ipc_pcm_params = imx8_ipc_pcm_params,
+
+ /* module loading */
+ .load_module = snd_sof_parse_module_memcpy,
+ .get_bar_index = imx8_get_bar_index,
+ /* firmware loading */
+ .load_firmware = snd_sof_load_firmware_memcpy,
+
+ /* DAI drivers */
+ .drv = imx8_dai,
+ .num_drv = 1, /* we have only 1 ESAI interface on i.MX8 */
+};
+EXPORT_SYMBOL(sof_imx8_ops);
+
+MODULE_LICENSE("Dual BSD/GPL");
--
2.17.1
^ permalink raw reply related
* [PATCH v3 1/5] ASoC: SOF: Add OF DSP device support
From: Daniel Baluta @ 2019-08-07 16:42 UTC (permalink / raw)
To: daniel.baluta, shawnguo
Cc: aisheng.dong, anson.huang, devicetree, festevam, kernel,
leonard.crestez, linux-arm-kernel, linux-imx, linux-kernel,
m.felsch, mark.rutland, paul.olaru, peng.fan, robh+dt,
shengjiu.wang, sound-open-firmware, pierre-louis.bossart, l.stach
In-Reply-To: <20190807164258.8306-1-daniel.baluta@nxp.com>
Add support for device tree based SOF DSP devices.
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
---
sound/soc/sof/Kconfig | 10 +++
sound/soc/sof/Makefile | 3 +
sound/soc/sof/sof-of-dev.c | 143 +++++++++++++++++++++++++++++++++++++
3 files changed, 156 insertions(+)
create mode 100644 sound/soc/sof/sof-of-dev.c
diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 5b41628ad722..73c455dacab5 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -36,6 +36,16 @@ config SND_SOC_SOF_ACPI
Say Y if you need this option
If unsure select "N".
+config SND_SOC_SOF_OF
+ tristate "SOF OF enumeration support"
+ depends on OF || COMPILE_TEST
+ select SND_SOC_SOF
+ select SND_SOC_SOF_OPTIONS
+ help
+ This adds support for Device Tree enumeration. This option is
+ required to enable i.MX8 devices.
+ Say Y if you need this option. If unsure select "N".
+
config SND_SOC_SOF_OPTIONS
tristate
help
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile
index 33c3ded2b7e2..f605a02257e7 100644
--- a/sound/soc/sof/Makefile
+++ b/sound/soc/sof/Makefile
@@ -7,6 +7,8 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\
snd-sof-pci-objs := sof-pci-dev.o
snd-sof-acpi-objs := sof-acpi-dev.o
+snd-sof-of-objs := sof-of-dev.o
+
snd-sof-nocodec-objs := nocodec.o
obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o
@@ -14,6 +16,7 @@ obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o
obj-$(CONFIG_SND_SOC_SOF_ACPI) += sof-acpi-dev.o
+obj-$(CONFIG_SND_SOC_SOF_OF) += sof-of-dev.o
obj-$(CONFIG_SND_SOC_SOF_PCI) += sof-pci-dev.o
obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/
diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c
new file mode 100644
index 000000000000..28a9692974e5
--- /dev/null
+++ b/sound/soc/sof/sof-of-dev.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+//
+// Copyright 2019 NXP
+//
+// Author: Daniel Baluta <daniel.baluta@nxp.com>
+//
+
+#include <linux/firmware.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <sound/sof.h>
+
+#include "ops.h"
+
+extern struct snd_sof_dsp_ops sof_imx8_ops;
+
+/* platform specific devices */
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8)
+static struct sof_dev_desc sof_of_imx8qxp_desc = {
+ .default_fw_path = "imx/sof",
+ .default_tplg_path = "imx/sof-tplg",
+ .nocodec_fw_filename = "sof-imx8.ri",
+ .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
+ .ops = &sof_imx8_ops,
+};
+#endif
+
+static const struct dev_pm_ops sof_of_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume)
+ SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
+ NULL)
+};
+
+static void sof_of_probe_complete(struct device *dev)
+{
+ /* allow runtime_pm */
+ pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_enable(dev);
+}
+
+static int sof_of_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct sof_dev_desc *desc;
+ /*TODO: create a generic snd_soc_xxx_mach */
+ struct snd_soc_acpi_mach *mach;
+ struct snd_sof_pdata *sof_pdata;
+ const struct snd_sof_dsp_ops *ops;
+ int ret;
+
+ dev_info(&pdev->dev, "DT DSP detected");
+
+ sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL);
+ if (!sof_pdata)
+ return -ENOMEM;
+
+ desc = device_get_match_data(dev);
+ if (!desc)
+ return -ENODEV;
+
+ /* get ops for platform */
+ ops = desc->ops;
+ if (!ops) {
+ dev_err(dev, "error: no matching DT descriptor ops\n");
+ return -ENODEV;
+ }
+
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
+ /* force nocodec mode */
+ dev_warn(dev, "Force to use nocodec mode\n");
+ mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
+ if (!mach)
+ return -ENOMEM;
+ ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
+ if (ret < 0)
+ return ret;
+#else
+ /* TODO: implement case where we actually have a codec */
+ return -ENODEV;
+#endif
+
+ if (mach)
+ mach->mach_params.platform = dev_name(dev);
+
+ sof_pdata->machine = mach;
+ sof_pdata->desc = desc;
+ sof_pdata->dev = &pdev->dev;
+ sof_pdata->platform = dev_name(dev);
+
+ /* TODO: read alternate fw and tplg filenames from DT */
+ sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path;
+ sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path;
+
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
+ /* set callback to enable runtime_pm */
+ sof_pdata->sof_probe_complete = sof_of_probe_complete;
+#endif
+ /* call sof helper for DSP hardware probe */
+ ret = snd_sof_device_probe(dev, sof_pdata);
+ if (ret) {
+ dev_err(dev, "error: failed to probe DSP hardware\n");
+ return ret;
+ }
+
+#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
+ sof_of_probe_complete(dev);
+#endif
+
+ return ret;
+}
+
+static int sof_of_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ /* call sof helper for DSP hardware remove */
+ snd_sof_device_remove(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id sof_of_ids[] = {
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8)
+ { .compatible = "fsl,imx8qxp-dsp", .data = &sof_of_imx8qxp_desc},
+#endif
+ { }
+};
+MODULE_DEVICE_TABLE(of, sof_of_ids);
+
+/* DT driver definition */
+static struct platform_driver snd_sof_of_driver = {
+ .probe = sof_of_probe,
+ .remove = sof_of_remove,
+ .driver = {
+ .name = "sof-audio-of",
+ .pm = &sof_of_pm,
+ .of_match_table = sof_of_ids,
+ },
+};
+module_platform_driver(snd_sof_of_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
--
2.17.1
^ permalink raw reply related
* [PATCH v3 0/5] Add DSP node for i.MX8QXP board to be used by DSP SOF driver
From: Daniel Baluta @ 2019-08-07 16:42 UTC (permalink / raw)
To: daniel.baluta, shawnguo
Cc: aisheng.dong, anson.huang, devicetree, festevam, kernel,
leonard.crestez, linux-arm-kernel, linux-imx, linux-kernel,
m.felsch, mark.rutland, paul.olaru, peng.fan, robh+dt,
shengjiu.wang, sound-open-firmware, pierre-louis.bossart, l.stach
i.MX 8QXP boards feature an Hifi4 DSP from Tensilica.
This patch series aims on adding the DT node describing the DSP,
but it also contains the Linux SOF DSP driver code that will use the DT node
for easier review.
Note that we switched to the new yaml format for bindings documentation.
The DSP will run SOF Firmware [1]. Patches 1,2,3 are adding support
for Linux DSP driver are already sent for review to SOF folks [2]
Ideally, patches 4/5 and 5/5 will go upstream through Shawn's tree
while 1-3/5 will go upstream via Pierre's tree -> ASoC tree.
Mind that SOF DSP support depends on IMX DSP communication protocol
up for review here: https://lkml.org/lkml/2019/8/1/260
Shawn, can you pick this up first?
Symbol dependencies are hopefully set correct so even if one of
the patches is not in a tree the compilation will not fail because
the symbols depending on that patches will not be selected.
[1] https://github.com/thesofproject/sof
[2] https://github.com/thesofproject/linux/pull/1048/commits
Daniel Baluta (5):
ASoC: SOF: Add OF DSP device support
ASoC: SOF: imx: Add i.MX8 HW support
ASoC: SOF: topology: Add dummy support for i.MX8 DAIs
arm64: dts: imx8qxp: Add DSP DT node
dt-bindings: dsp: fsl: Add DSP core binding support
.../devicetree/bindings/dsp/fsl,dsp.yaml | 88 ++++
arch/arm64/boot/dts/freescale/imx8qxp-mek.dts | 4 +
arch/arm64/boot/dts/freescale/imx8qxp.dtsi | 32 ++
include/sound/sof/dai.h | 2 +
include/uapi/sound/sof/tokens.h | 8 +
sound/soc/sof/Kconfig | 11 +
sound/soc/sof/Makefile | 4 +
sound/soc/sof/imx/Kconfig | 22 +
sound/soc/sof/imx/Makefile | 4 +
sound/soc/sof/imx/imx8.c | 394 ++++++++++++++++++
sound/soc/sof/sof-of-dev.c | 143 +++++++
sound/soc/sof/topology.c | 30 ++
12 files changed, 742 insertions(+)
create mode 100644 Documentation/devicetree/bindings/dsp/fsl,dsp.yaml
create mode 100644 sound/soc/sof/imx/Kconfig
create mode 100644 sound/soc/sof/imx/Makefile
create mode 100644 sound/soc/sof/imx/imx8.c
create mode 100644 sound/soc/sof/sof-of-dev.c
--
2.17.1
^ permalink raw reply
* Re: [PATCH 5/6] tty: serial: Add linflexuart driver for S32V234
From: Stefan-gabriel Mirea @ 2019-08-07 16:42 UTC (permalink / raw)
To: gregkh@linuxfoundation.org
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, corbet@lwn.net,
catalin.marinas@arm.com, linux-doc@vger.kernel.org,
Larisa Ileana Grigore, linux-kernel@vger.kernel.org, Leo Li,
Cosmin Stefan Stoica, robh+dt@kernel.org,
linux-serial@vger.kernel.org, jslaby@suse.com,
shawnguo@kernel.org, will@kernel.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190806184042.GA26041@kroah.com>
On 8/6/2019 9:40 PM, gregkh@linuxfoundation.org wrote:
> On Tue, Aug 06, 2019 at 05:11:17PM +0000, Stefan-gabriel Mirea wrote:
>> On 8/5/2019 6:31 PM, gregkh@linuxfoundation.org wrote:
>>> On Fri, Aug 02, 2019 at 07:47:23PM +0000, Stefan-gabriel Mirea wrote:
>>>>
>>>> +/* Freescale Linflex UART */
>>>> +#define PORT_LINFLEXUART 121
>>>
>>> Do you really need this modified?
>>
>> Hello Greg,
>>
>> This macro is meant to be assigned to port->type in the config_port
>> method from uart_ops, in order for verify_port to know if the received
>> serial_struct structure was really targeted for a LINFlex port. It
>> needs to be defined outside, to avoid "collisions" with other drivers.
>
> Yes, I know what it goes to, but does anyone in userspace actually use
> it?
No, we do not use it from userspace, but kept the pattern only for
conformance.
>> Other than that, I do not see anything wrong with the addition of a
>> define in serial_core.h for this purpose (which is also what most of the
>> serial drivers do, including amba-pl011.c, mentioned in
>> Documentation/driver-api/serial/driver.rst as providing the reference
>> implementation), so please be more specific.
>
> I am getting tired of dealing with merge issues with that list, and no
> one seems to be able to find where they are really needed for userspace,
> especially for new devices. What happens if you do not have use it?
I see. If I drop its usage completely and leave 'type' from the
uart_port as 0, uart_port_startup() will fail when finding that
uport->type == PORT_UNKNOWN at [1] (there may be other effects as well,
e.g. due to the check in uart_configure_port[2]).
So I suppose that I need to define some nonzero 'PORT_KNOWN' macro in
the driver and use that one internally for 'type'. Is my understanding
correct? Will there be any problems if I define it to a positive integer
which is already assigned to another driver, according to serial_core.h?
Regards,
Stefan
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/serial/serial_core.c?h=v5.3-rc1#n188
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/serial/serial_core.c?h=v5.3-rc1#n2348
^ permalink raw reply
* Re: [PATCH v3 8/8] PCI: dw: Add support for PCI_PROBE_ONLY/PCI_REASSIGN_ALL_BUS flags
From: Lorenzo Pieralisi @ 2019-08-07 16:36 UTC (permalink / raw)
To: Jonathan Chocron
Cc: bhelgaas, jingoohan1, gustavo.pimentel, robh+dt, mark.rutland,
dwmw, benh, alisaidi, ronenk, barakw, talel, hanochu, hhhawa,
linux-pci, linux-kernel, devicetree
In-Reply-To: <20190723092711.11786-4-jonnyc@amazon.com>
On Tue, Jul 23, 2019 at 12:27:11PM +0300, Jonathan Chocron wrote:
> This basically aligns the usage of PCI_PROBE_ONLY and
> PCI_REASSIGN_ALL_BUS in dw_pcie_host_init() with the logic in
> pci_host_common_probe().
>
> Now it will be possible to control via the devicetree whether to just
> probe the PCI bus (in cases where FW already configured it) or to fully
> configure it.
>
> Signed-off-by: Jonathan Chocron <jonnyc@amazon.com>
> ---
> .../pci/controller/dwc/pcie-designware-host.c | 23 +++++++++++++++----
> 1 file changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index d2ca748e4c85..0a294d8aa21a 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -342,6 +342,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
> if (!bridge)
> return -ENOMEM;
>
> + of_pci_check_probe_only();
> +
> ret = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
> &bridge->windows, &pp->io_base);
> if (ret)
> @@ -474,6 +476,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
>
> pp->root_bus_nr = pp->busn->start;
>
> + /* Do not reassign bus nums if probe only */
> + if (!pci_has_flag(PCI_PROBE_ONLY))
> + pci_add_flags(PCI_REASSIGN_ALL_BUS);
This changes the default for bus reassignment on all DWC host (that are
!PCI_PROBE_ONLY), we should drop this line, it can trigger regressions.
If we still want to merge it as a separate change we must test it on all
DWC host bridges to make sure it does not trigger any issues with
current set-ups, that's not going to be easy though.
Lorenzo
> +
> bridge->dev.parent = dev;
> bridge->sysdata = pp;
> bridge->busnr = pp->root_bus_nr;
> @@ -490,11 +496,20 @@ int dw_pcie_host_init(struct pcie_port *pp)
> if (pp->ops->scan_bus)
> pp->ops->scan_bus(pp);
>
> - pci_bus_size_bridges(pp->root_bus);
> - pci_bus_assign_resources(pp->root_bus);
> + /*
> + * We insert PCI resources into the iomem_resource and
> + * ioport_resource trees in either pci_bus_claim_resources()
> + * or pci_bus_assign_resources().
> + */
> + if (pci_has_flag(PCI_PROBE_ONLY)) {
> + pci_bus_claim_resources(pp->root_bus);
> + } else {
> + pci_bus_size_bridges(pp->root_bus);
> + pci_bus_assign_resources(pp->root_bus);
>
> - list_for_each_entry(child, &pp->root_bus->children, node)
> - pcie_bus_configure_settings(child);
> + list_for_each_entry(child, &pp->root_bus->children, node)
> + pcie_bus_configure_settings(child);
> + }
>
> pci_bus_add_devices(pp->root_bus);
> return 0;
> --
> 2.17.1
>
^ permalink raw reply
* Re: [PATCH 0/6] hwspinlock: allow sharing of hwspinlocks
From: Suman Anna @ 2019-08-07 16:19 UTC (permalink / raw)
To: Fabien DESSENNE, Bjorn Andersson
Cc: Ohad Ben-Cohen, Mark Rutland, Alexandre TORGUE, Jonathan Corbet,
linux-doc@vger.kernel.org, linux-remoteproc@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
Rob Herring, Maxime Coquelin,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org, Benjamin GAIGNARD
In-Reply-To: <02329102-5571-c6c1-b78c-693747133f0e@st.com>
Hi Fabien,
On 8/7/19 3:39 AM, Fabien DESSENNE wrote:
> Hi
>
> On 06/08/2019 11:30 PM, Suman Anna wrote:
>> On 8/6/19 1:21 PM, Bjorn Andersson wrote:
>>> On Tue 06 Aug 10:38 PDT 2019, Suman Anna wrote:
>>>
>>>> Hi Fabien,
>>>>
>>>> On 8/5/19 12:46 PM, Bjorn Andersson wrote:
>>>>> On Mon 05 Aug 01:48 PDT 2019, Fabien DESSENNE wrote:
>>>>>
>>>>>> On 01/08/2019 9:14 PM, Bjorn Andersson wrote:
>>>>>>> On Wed 13 Mar 08:50 PDT 2019, Fabien Dessenne wrote:
>>> [..]
>>>>>> B/ This would introduce some inconsistency between the two 'request' API
>>>>>> which are hwspin_lock_request() and hwspin_lock_request_specific().
>>>>>> hwspin_lock_request() looks for an unused lock, so requests for an exclusive
>>>>>> usage. On the other side, request_specific() would request shared locks.
>>>>>> Worst the following sequence can transform an exclusive usage into a shared
>>>>>>
>>>>> There is already an inconsistency in between these; as with above any
>>>>> system that uses both request() and request_specific() will be suffering
>>>>> from intermittent failures due to probe ordering.
>>>>>
>>>>>> one:
>>>>>> -hwspin_lock_request() -> returns Id#0 (exclusive)
>>>>>> -hwspin_lock_request() -> returns Id#1 (exclusive)
>>>>>> -hwspin_lock_request_specific(0) -> returns Id#0 and makes Id#0 shared
>>>>>> Honestly I am not sure that this is a real issue, but it's better to have it
>>>>>> in mind before we take ay decision
>>>> Wouldn't it be actually simpler to just introduce a new specific API
>>>> variant for this, similar to the reset core for example (it uses a
>>>> separate exclusive API), without having to modify the bindings at all.
>>>> It is just a case of your driver using the right API, and the core can
>>>> be modified to use the additional tag semantics based on the API. It
>>>> should avoid any confusion with say using a different second cell value
>>>> for the same lock in two different nodes.
>>>>
>>> But this implies that there is an actual need to hold these locks
>>> exclusively. Given that they are (except for the raw case) all wrapped
>>> by Linux locking primitives there shouldn't be a problem sharing a lock
>>> (except possibly for the raw case).
>> Yes agreed, the HWLOCK_RAW and HWLOCK_IN_ATOMIC cases are unprotected. I
>> am still trying to understand better the usecase to see if the same lock
>> is being multiplexed for different protection contexts, or if all of
>> them are protecting the same context.
>
>
> Here are two different examples that explain the need for changes.
> In both cases the Linux clients are talking to a single entity on the
> remote-side.
>
> Example 1:
> exti: interrupt-controller@5000d000 {
> compatible = "st,stm32mp1-exti", "syscon";
> interrupt-controller;
> #interrupt-cells = <2>;
> reg = <0x5000d000 0x400>;
> hwlocks = <&hsem 1>;
> };
> The two drivers (stm32mp1-exti and syscon) refer to the same hwlock.
> With the current hwspinlock implementation, only the first driver succeeds
> in requesting (hwspin_lock_request_specific) the hwlock. The second request
> fails.
> Here, we really need to share the hwlock between the two drivers.
> Note: hardware spinlock support for regmap was 'recently' introduced in 4.15
> see https://lore.kernel.org/patchwork/patch/845941/
>
>
>
> Example 2:
> Here it is more a question of optimization : we want to save the number of
> hwlocks used to protect resources, using an unique hwlock to protect all
> pinctrl resources:
> pinctrl: pin-controller@50002000 {
> compatible = "st,stm32mp157-pinctrl";
> ranges = <0 0x50002000 0xa400>;
> hwlocks = <&hsem 0 1>;
>
> pinctrl_z: pin-controller-z@54004000 {
> compatible = "st,stm32mp157-z-pinctrl";
> ranges = <0 0x54004000 0x400>;
> pins-are-numbered;
> hwlocks = <&hsem 0 1>;
Thanks for the examples.
>
>>
>>> I agree that we shouldn't specify this property in DT - if anything it
>>> should be a variant of the API.
>
>
> If we decide to add a 'shared' API, then, what about the generic regmap
> driver?
>
> In the context of above example1, this would require to update the
> regmap driver.
>
> But would this be acceptable for any driver using syscon/regmap?
>
>
> I think it is better to keep the existing API (modifying it so it always
> allows
>
> hwlocks sharing, so no need for bindings update) than adding another API.
For your usecases, you would definitely need the syscon/regmap behavior
to be shared right. Whether we introduce a 'shared' API or an
'exclusive' API and change the current API behavior to shared, it is
definitely a case-by-case usage scenario for the existing drivers and
usage right. The main contention point is what to do with the
unprotected usecases like Bjorn originally pointed out.
regards
Suman
>
>
>
>>>
>>>> If you are sharing a hwlock on the Linux side, surely your driver should
>>>> be aware that it is a shared lock. The tag can be set during the first
>>>> request API, and you look through both tags when giving out a handle.
>>>>
>>> Why would the driver need to know about it?
>> Just the semantics if we were to support single user vs multiple users
>> on Linux-side to even get a handle. Your point is that this may be moot
>> since we have protection anyway other than the raw cases. But we need to
>> be able to have the same API work across all cases.
>>
>> So far, it had mostly been that there would be one user on Linux
>> competing with other equivalent peer entities on different processors.
>> It is not common to have multiple users since these protection schemes
>> are usually needed only at the lowest levels of a stack, so the
>> exclusive handle stuff had been sufficient.
>>
>>>> Obviously, the hwspin_lock_request() API usage semantics always had the
>>>> implied additional need for communicating the lock id to the other peer
>>>> entity, so a realistic usage is most always the specific API variant. I
>>>> doubt this API would be of much use for the shared driver usage. This
>>>> also implies that the client user does not care about specifying a lock
>>>> in DT.
>>>>
>>> Afaict if the lock are shared then there shouldn't be a problem with
>>> some clients using the request API and others request_specific(). As any
>>> collisions would simply mean that there are more contention on the lock.
>>>
>>> With the current exclusive model that is not possible and the success of
>>> the request_specific will depend on probe order.
>>>
>>> But perhaps it should be explicitly prohibited to use both APIs on the
>>> same hwspinlock instance?
>> Yeah, they are meant to be complimentary usage, though I doubt we will
>> ever have any realistic users for the generic API if we haven't had a
>> usage so far. I had posted a concept of reserved locks long back [1] to
>> keep away certain locks from the generic requestor, but dropped it since
>> we did not have an actual use-case needing it.
>>
>> regards
>> Suman
>>
>> [1] https://lwn.net/Articles/611944/
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support
From: Pierre-Louis Bossart @ 2019-08-07 16:01 UTC (permalink / raw)
To: Daniel Baluta
Cc: Mark Rutland, Aisheng Dong, Peng Fan, Anson Huang,
Devicetree List, Daniel Baluta, S.j. Wang, Marco Felsch,
Linux Kernel Mailing List, Paul Olaru, Rob Herring, dl-linux-imx,
Pengutronix Kernel Team, Shawn Guo, Leonard Crestez,
Fabio Estevam, linux-arm-kernel, sound-open-firmware
In-Reply-To: <CAEnQRZARFQjutkvW3_xkQAQznNm8c5jSjtAG715VtrZnDxztoA@mail.gmail.com>
On 8/7/19 10:29 AM, Daniel Baluta wrote:
> On Tue, Jul 23, 2019 at 6:19 PM Pierre-Louis Bossart
> <pierre-louis.bossart@linux.intel.com> wrote:
>>
>>
>>> diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
>>> index 61b97fc55bb2..2aa3a1cdf60c 100644
>>> --- a/sound/soc/sof/Kconfig
>>> +++ b/sound/soc/sof/Kconfig
>>> @@ -36,6 +36,15 @@ config SND_SOC_SOF_ACPI
>>> Say Y if you need this option
>>> If unsure select "N".
>>>
>>> +config SND_SOC_SOF_DT
>>> + tristate "SOF DT enumeration support"
>>> + select SND_SOC_SOF
>>> + select SND_SOC_SOF_OPTIONS
>>> + help
>>> + This adds support for Device Tree enumeration. This option is
>>> + required to enable i.MX8 devices.
>>> + Say Y if you need this option. If unsure select "N".
>>> +
>>
>> [snip]
>>
>>> diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig
>>> index fff64a9970f0..fa35994a79c4 100644
>>> --- a/sound/soc/sof/imx/Kconfig
>>> +++ b/sound/soc/sof/imx/Kconfig
>>> @@ -12,6 +12,7 @@ if SND_SOC_SOF_IMX_TOPLEVEL
>>>
>>> config SND_SOC_SOF_IMX8
>>> tristate "SOF support for i.MX8"
>>> + select SND_SOC_SOF_DT
>>
>> This looks upside down. You should select SOF_DT first then include the
>> NXP stuff.
>
> One more thing: So this should be 'depends on SND_SOC_SOF_DT' right?
I would do this:
config SND_SOC_SOF_DT
tristate "SOF DT enumeration support"
depends on OF # or whatever the top-level DT dependency is
select SND_SOC_SOF
select SND_SOC_SOF_OPTIONS
config SND_SOC_SOF_IMX_TOPLEVEL
bool "SOF support for NXP i.MX audio DSPs"
depends on ARM64 && SND_SOC_SOF_DT || COMPILE_TEST
if SND_SOC_SOF_IMX_TOPLEVEL
config SND_SOC_SOF_IMX8
tristate "SOF support for i.MX8"
In other words push the dependencies at a higher level.
^ permalink raw reply
* Re: [PATCH v8 00/14] Rockchip ISP1 Driver
From: Sakari Ailus @ 2019-08-07 15:37 UTC (permalink / raw)
To: Helen Koike
Cc: linux-rockchip, devicetree, eddie.cai.linux, mchehab, heiko,
jacob2.chen, jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
laurent.pinchart, kernel, ezequiel, linux-media, linux-arm-kernel,
zhengsq
In-Reply-To: <20190730184256.30338-1-helen.koike@collabora.com>
On Tue, Jul 30, 2019 at 03:42:42PM -0300, Helen Koike wrote:
> Hello,
>
> I'm re-sending a new version of ISP(Camera) v4l2 driver for rockchip
> rk3399 SoC.
>
> I didn't change much from the last version, just applying the
> suggestions made in the previous one.
>
> This patchset is also available at:
> https://gitlab.collabora.com/koike/linux/tree/rockchip/isp/v8
>
> Libcamera patched to work with this version:
> https://gitlab.collabora.com/koike/libcamera
> (also sent to the mailing list)
>
> I tested on the rockpi 4 with a rpi v1.3 sensor and also with the
> Scarlet Chromebook.
Could you also post media-ctl -p printout e.g. as a reply to the cover
letter?
Thanks.
--
Sakari Ailus
sakari.ailus@linux.intel.com
^ permalink raw reply
* Re: [PATCH v3 3/5] RISC-V: Fix unsupported isa string info.
From: Palmer Dabbelt @ 2019-08-07 15:37 UTC (permalink / raw)
To: Paul Walmsley
Cc: mark.rutland, devicetree, aou, tiny.windzz, Greg KH,
daniel.lezcano, linux-kernel, johan, Atish Patra, Anup Patel,
robh+dt, gary, tglx, info, linux-riscv, allison
In-Reply-To: <alpine.DEB.2.21.9999.1908061818360.13971@viisi.sifive.com>
On Tue, 06 Aug 2019 18:26:08 PDT (-0700), Paul Walmsley wrote:
> On Wed, 7 Aug 2019, Atish Patra wrote:
>
>> On Tue, 2019-08-06 at 16:27 -0700, Paul Walmsley wrote:
>>
>> > Seems like the "su" should be dropped from mandatory_ext. What do you
>> > think?
>> >
>>
>> Yup. As DT binding only mention imafdc, mandatory extensions should
>> contain only that and just consider "su" extensions are considered as
>> implicit as we are running Linux.
>
> Discussing this with Andrew and Palmer, it looks like "su" is currently
> non-compliant. Section 22.6 of the user-level specification states that
> the "s" character indicates that a longer standard supervisor extension
> name will follow. So far I don't think any of these have been defined.
>
>> Do you think QEMU DT should be updated to reflect that ?
>
> Yes.
https://lists.nongnu.org/archive/html/qemu-riscv/2019-08/msg00141.html
>
>> > There's no Kconfig option by this name, and we're requiring
>> > compressed
>>
>> Sorry. This was a typo. It should have been CONFIG_RISCV_ISA_C.
>>
>> > instruction support as part of the RISC-V Linux baseline. Could you
>> > share the rationale behind this?
>>
>> I think I added this check at the config file. Looking at the Kconfig,
>> RISCV_ISA_C is always enabled. So we can drop this.
>
> OK great. Do you want to resend an updated patch, or would you like me to
> fix it up here?
>
> I'll also send a patch to drop CONFIG_RISCV_ISA_C.
>
>
> - Paul
^ permalink raw reply
* Re: [PATCH v8 09/14] media: rkisp1: add rockchip isp1 core driver
From: Sakari Ailus @ 2019-08-07 15:36 UTC (permalink / raw)
To: Helen Koike
Cc: linux-rockchip, devicetree, eddie.cai.linux, mchehab, heiko,
jacob2.chen, jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
laurent.pinchart, kernel, ezequiel, linux-media, linux-arm-kernel,
zhengsq, Jacob Chen, Allon Huang
In-Reply-To: <20190730184256.30338-10-helen.koike@collabora.com>
Hi Helen,
On Tue, Jul 30, 2019 at 03:42:51PM -0300, Helen Koike wrote:
...
> +static int rkisp1_fwnode_parse(struct device *dev,
> + struct v4l2_fwnode_endpoint *vep,
> + struct v4l2_async_subdev *asd)
> +{
> + struct sensor_async_subdev *s_asd =
> + container_of(asd, struct sensor_async_subdev, asd);
> +
> + if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
> + dev_err(dev, "Only CSI2 bus type is currently supported\n");
> + return -EINVAL;
> + }
> +
> + if (vep->base.port != 0) {
> + dev_err(dev, "The ISP has only port 0\n");
> + return -EINVAL;
> + }
> +
> + s_asd->mbus.type = vep->bus_type;
> + s_asd->mbus.flags = vep->bus.mipi_csi2.flags;
> + s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
> +
> + switch (vep->bus.mipi_csi2.num_data_lanes) {
> + case 1:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_1_LANE;
> + break;
> + case 2:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_2_LANE;
> + break;
> + case 3:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_3_LANE;
> + break;
> + case 4:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_4_LANE;
> + break;
Could you use struct v4l2_fwnode_endpoint directly? The mbus config is a
legacy struct from bygone times and I'd like to avoid using it in new
drivers.
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
> + .bound = subdev_notifier_bound,
> + .unbind = subdev_notifier_unbind,
> + .complete = subdev_notifier_complete,
> +};
> +
> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
> +{
> + struct v4l2_async_notifier *ntf = &isp_dev->notifier;
> + struct device *dev = isp_dev->dev;
> + int ret;
> +
> + v4l2_async_notifier_init(ntf);
> +
> + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> + dev, ntf, sizeof(struct sensor_async_subdev), 0,
> + rkisp1_fwnode_parse);
I know these functions aren't old but there's a better alternative. See
e.g. isp_parse_of_endpoints in drivers/media/platform/omap3isp/isp.c or
cio2_parse_firmware in drivers/media/pci/intel/ipu3/ipu3-cio2.c.
> + if (ret < 0)
> + return ret;
> +
> + if (list_empty(&ntf->asd_list))
> + return -ENODEV; /* no endpoint */
> +
> + ntf->ops = &subdev_notifier_ops;
> +
> + return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
> +}
--
Sakari Ailus
sakari.ailus@linux.intel.com
^ permalink raw reply
* Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support
From: Daniel Baluta @ 2019-08-07 15:29 UTC (permalink / raw)
To: Pierre-Louis Bossart
Cc: Daniel Baluta, Marco Felsch, Shawn Guo, Mark Rutland,
Aisheng Dong, Peng Fan, Anson Huang, Devicetree List, S.j. Wang,
Linux Kernel Mailing List, Paul Olaru, Rob Herring, dl-linux-imx,
Pengutronix Kernel Team, Leonard Crestez, Fabio Estevam,
linux-arm-kernel, sound-open-firmware
In-Reply-To: <d85909d6-c7cb-c64b-dfa9-6cee6c0da2cb@linux.intel.com>
On Tue, Jul 23, 2019 at 6:19 PM Pierre-Louis Bossart
<pierre-louis.bossart@linux.intel.com> wrote:
>
>
> > diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
> > index 61b97fc55bb2..2aa3a1cdf60c 100644
> > --- a/sound/soc/sof/Kconfig
> > +++ b/sound/soc/sof/Kconfig
> > @@ -36,6 +36,15 @@ config SND_SOC_SOF_ACPI
> > Say Y if you need this option
> > If unsure select "N".
> >
> > +config SND_SOC_SOF_DT
> > + tristate "SOF DT enumeration support"
> > + select SND_SOC_SOF
> > + select SND_SOC_SOF_OPTIONS
> > + help
> > + This adds support for Device Tree enumeration. This option is
> > + required to enable i.MX8 devices.
> > + Say Y if you need this option. If unsure select "N".
> > +
>
> [snip]
>
> > diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig
> > index fff64a9970f0..fa35994a79c4 100644
> > --- a/sound/soc/sof/imx/Kconfig
> > +++ b/sound/soc/sof/imx/Kconfig
> > @@ -12,6 +12,7 @@ if SND_SOC_SOF_IMX_TOPLEVEL
> >
> > config SND_SOC_SOF_IMX8
> > tristate "SOF support for i.MX8"
> > + select SND_SOC_SOF_DT
>
> This looks upside down. You should select SOF_DT first then include the
> NXP stuff.
One more thing: So this should be 'depends on SND_SOC_SOF_DT' right?
^ permalink raw reply
* Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support
From: Daniel Baluta @ 2019-08-07 15:28 UTC (permalink / raw)
To: Pierre-Louis Bossart
Cc: Daniel Baluta, Marco Felsch, Shawn Guo, Mark Rutland,
Aisheng Dong, Peng Fan, Anson Huang, Devicetree List, S.j. Wang,
Linux Kernel Mailing List, Paul Olaru, Rob Herring, dl-linux-imx,
Pengutronix Kernel Team, Leonard Crestez, Fabio Estevam,
linux-arm-kernel, sound-open-firmware
In-Reply-To: <85b4a2c4-761e-bdcf-f05e-2fb16c06f11e@linux.intel.com>
On Wed, Aug 7, 2019 at 6:22 PM Pierre-Louis Bossart
<pierre-louis.bossart@linux.intel.com> wrote:
>
>
> >>>> +static int sof_dt_probe(struct platform_device *pdev)
> >>>> +{
> >>>> + struct device *dev = &pdev->dev;
> >>>> + const struct sof_dev_desc *desc;
> >>>> + /*TODO: create a generic snd_soc_xxx_mach */
> >>>> + struct snd_soc_acpi_mach *mach;
> >>>
> >>> I wonder if you really need to use the same structures. For Intel we get
> >>> absolutely zero info from the firmware so rely on an ACPI codec ID as a
> >>> key to find information on which firmware and topology to use, and which
> >>> machine driver to load. You could have all this information in a DT blob?
> >>
> >> Yes. I see your point. I will still need to make a generic structure for
> >> snd_soc_acpi_mach so that everyone can use sof_nocodec_setup function.
> >>
> >> Maybe something like this:
> >>
> >> struct snd_soc_mach {
> >> union {
> >> struct snd_soc_acpi_mach acpi_mach;
> >> struct snd_soc_of_mach of_mach;
> >> }
> >> };
> >>
> >> and then change the prototype of sof_nocodec_setup.
> >
> > Hi Pierre,
> >
> > I fixed all the comments except the one above. Replacing snd_soc_acpi_mach
> > with a generic snd_soc_mach is not trivial task.
> >
> > I wonder if it is acceptable to get the initial patches as they are
> > now and later switch to
> > generic ACPI/OF abstraction.
> >
> > Asking this because for the moment on the i.MX side I have only
> > implemented no codec
> > version and we don't probe any of the machine drivers we have.
> >
> > So, there is this only one member of snd_soc_acpi_mach that imx
> > version is making use of:
> >
> > mach->drv_name = "sof-nocodec";
> >
> > That's all.
> >
> > I think the change as it is now is very clean and non-intrusive. Later
> > we will get options to
> > read firmware name and stuff from DT.
> >
> > Anyhow, I don't think we can get rid of snd_dev_desc structure on
> > i.MX. This will be used
> > to store the information read from DT:
> >
> > static struct sof_dev_desc sof_of_imx8qxp_desc = {
> > » .default_fw_path = "imx/sof",
> > » .default_tplg_path = "imx/sof-tplg",
> > » .nocodec_fw_filename = "sof-imx8.ri",
> > » .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
> > » .ops = &sof_imx8_ops,
> > };
> >
> > For the moment we will only use the default values.
>
> Yes, that's fine for now. If you don't have a real machine driver then
> there's nothing urgent to change.
>
> Is the new version on GitHub?
Not yet, will push it today and ping you.
^ permalink raw reply
* Re: [PATCH v8 09/14] media: rkisp1: add rockchip isp1 core driver
From: Sakari Ailus @ 2019-08-07 15:27 UTC (permalink / raw)
To: Helen Koike
Cc: linux-rockchip, devicetree, eddie.cai.linux, mchehab, heiko,
jacob2.chen, jeffy.chen, zyc, linux-kernel, tfiga, hans.verkuil,
laurent.pinchart, kernel, ezequiel, linux-media, linux-arm-kernel,
zhengsq, Jacob Chen, Allon Huang
In-Reply-To: <20190730184256.30338-10-helen.koike@collabora.com>
Hi Helen,
On Tue, Jul 30, 2019 at 03:42:51PM -0300, Helen Koike wrote:
> From: Jacob Chen <jacob2.chen@rock-chips.com>
>
> Add the core driver for rockchip isp1.
>
> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
> Signed-off-by: Jacob Chen <cc@rock-chips.com>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> [fixed compilation and run time errors regarding new v4l2 async API]
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> [Add missing module device table]
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> [update for upstream]
> Signed-off-by: Helen Koike <helen.koike@collabora.com>
>
> ---
>
> Changes in v8: None
> Changes in v7:
> - VIDEO_ROCKCHIP_ISP1 selects VIDEOBUF2_VMALLOC
> - add PHY_ROCKCHIP_DPHY as a dependency for VIDEO_ROCKCHIP_ISP1
> - Fix compilation and runtime errors due to bitrotting
> The code has bit-rotten since March 2018, fix compilation errors.
> The new V4L2 async notifier API requires notifiers to be initialized by
> a call to v4l2_async_notifier_init() before being used, do so.
> - Add missing module device table
> - use clk_bulk framework
> - add missing notifiers cleanups
> - s/strlcpy/strscpy
> - normalize bus_info name
> - fix s_stream error path, stream_cnt wans't being decremented properly
> - use devm_platform_ioremap_resource() helper
> - s/deice/device
> - redesign: remove mipi/csi subdevice, sensors connect directly to the
> isp subdevice in the media topology now.
> - remove "saved_state" member from rkisp1_stream struct
> - Reverse the order of MIs
> - Simplify MI interrupt handling
> Rather than adding unnecessary indirection, just use stream index to
> handle MI interrupt enable/disable/clear, since the stream index matches
> the order of bits now, thanks to previous patch. While at it, remove
> some dead code.
> - code styling and checkpatch fixes
>
> drivers/media/platform/Kconfig | 12 +
> drivers/media/platform/Makefile | 1 +
> drivers/media/platform/rockchip/isp1/Makefile | 7 +
> drivers/media/platform/rockchip/isp1/common.h | 101 +++
> drivers/media/platform/rockchip/isp1/dev.c | 675 ++++++++++++++++++
> drivers/media/platform/rockchip/isp1/dev.h | 97 +++
> 6 files changed, 893 insertions(+)
> create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
> create mode 100644 drivers/media/platform/rockchip/isp1/common.h
> create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
> create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
>
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index 89555f9a813f..e0e98937c565 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -106,6 +106,18 @@ config VIDEO_QCOM_CAMSS
> select VIDEOBUF2_DMA_SG
> select V4L2_FWNODE
>
> +config VIDEO_ROCKCHIP_ISP1
> + tristate "Rockchip Image Signal Processing v1 Unit driver"
> + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
> + depends on ARCH_ROCKCHIP || COMPILE_TEST
> + select VIDEOBUF2_DMA_CONTIG
> + select VIDEOBUF2_VMALLOC
> + select V4L2_FWNODE
> + select PHY_ROCKCHIP_DPHY
> + default n
> + ---help---
> + Support for ISP1 on the rockchip SoC.
> +
> config VIDEO_S3C_CAMIF
> tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
> depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 7cbbd925124c..f9fcf8e7c513 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1) += rcar_fdp1.o
> obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o
> obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
>
> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip/isp1/
> obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/
>
> obj-y += omap/
> diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile
> new file mode 100644
> index 000000000000..72706e80fc8b
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/Makefile
> @@ -0,0 +1,7 @@
> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += rockchip-isp1.o
> +rockchip-isp1-objs += rkisp1.o \
> + dev.o \
> + regs.o \
> + isp_stats.o \
> + isp_params.o \
> + capture.o
> diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
> new file mode 100644
> index 000000000000..606ce2793546
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/common.h
> @@ -0,0 +1,101 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef _RKISP1_COMMON_H
> +#define _RKISP1_COMMON_H
> +
> +#include <linux/mutex.h>
> +#include <media/media-device.h>
> +#include <media/media-entity.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/videobuf2-v4l2.h>
> +
> +#define RKISP1_DEFAULT_WIDTH 800
> +#define RKISP1_DEFAULT_HEIGHT 600
> +
> +#define RKISP1_MAX_STREAM 2
> +#define RKISP1_STREAM_MP 0
> +#define RKISP1_STREAM_SP 1
> +
> +#define RKISP1_PLANE_Y 0
> +#define RKISP1_PLANE_CB 1
> +#define RKISP1_PLANE_CR 2
> +
> +enum rkisp1_sd_type {
> + RKISP1_SD_SENSOR,
> + RKISP1_SD_PHY_CSI,
> + RKISP1_SD_VCM,
> + RKISP1_SD_FLASH,
> + RKISP1_SD_MAX,
> +};
I wonder if this is a leftover from the driver development time. Same goes
for the subdevs field in struct rkisp1_device.
> +
> +/* One structure per video node */
> +struct rkisp1_vdev_node {
> + struct vb2_queue buf_queue;
> + /* vfd lock */
> + struct mutex vlock;
> + struct video_device vdev;
> + struct media_pad pad;
> +};
> +
> +enum rkisp1_fmt_pix_type {
> + FMT_YUV,
> + FMT_RGB,
> + FMT_BAYER,
> + FMT_JPEG,
> + FMT_MAX
> +};
> +
> +enum rkisp1_fmt_raw_pat_type {
> + RAW_RGGB = 0,
> + RAW_GRBG,
> + RAW_GBRG,
> + RAW_BGGR,
> +};
> +
> +struct rkisp1_buffer {
> + struct vb2_v4l2_buffer vb;
> + struct list_head queue;
> + union {
> + u32 buff_addr[VIDEO_MAX_PLANES];
> + void *vaddr[VIDEO_MAX_PLANES];
> + };
> +};
> +
> +struct rkisp1_dummy_buffer {
> + void *vaddr;
> + dma_addr_t dma_addr;
> + u32 size;
> +};
> +
> +extern int rkisp1_debug;
> +
> +static inline
> +struct rkisp1_vdev_node *vdev_to_node(struct video_device *vdev)
> +{
> + return container_of(vdev, struct rkisp1_vdev_node, vdev);
> +}
> +
> +static inline struct rkisp1_vdev_node *queue_to_node(struct vb2_queue *q)
> +{
> + return container_of(q, struct rkisp1_vdev_node, buf_queue);
> +}
> +
> +static inline struct rkisp1_buffer *to_rkisp1_buffer(struct vb2_v4l2_buffer *vb)
> +{
> + return container_of(vb, struct rkisp1_buffer, vb);
> +}
> +
> +static inline struct vb2_queue *to_vb2_queue(struct file *file)
> +{
> + struct rkisp1_vdev_node *vnode = video_drvdata(file);
> +
> + return &vnode->buf_queue;
> +}
> +
> +#endif /* _RKISP1_COMMON_H */
> diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
> new file mode 100644
> index 000000000000..2b4a67e1a3b5
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/dev.c
> @@ -0,0 +1,675 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/phy/phy.h>
> +#include <linux/phy/phy-mipi-dphy.h>
> +
> +#include "common.h"
> +#include "regs.h"
> +
> +struct isp_match_data {
> + const char * const *clks;
> + int size;
unsigned int
> +};
> +
> +struct sensor_async_subdev {
> + struct v4l2_async_subdev asd;
> + struct v4l2_mbus_config mbus;
> + unsigned int lanes;
> +};
> +
> +int rkisp1_debug;
> +module_param_named(debug, rkisp1_debug, int, 0644);
> +MODULE_PARM_DESC(debug, "Debug level (0-1)");
Have you thought of using dynamic debug instead?
> +
> +/**************************** pipeline operations******************************/
> +
> +static int __isp_pipeline_prepare(struct rkisp1_pipeline *p,
> + struct media_entity *me)
> +{
> + struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> + struct v4l2_subdev *sd;
> + unsigned int i;
> +
> + p->num_subdevs = 0;
> + memset(p->subdevs, 0, sizeof(p->subdevs));
> +
> + while (1) {
> + struct media_pad *pad = NULL;
> +
> + /* Find remote source pad */
> + for (i = 0; i < me->num_pads; i++) {
> + struct media_pad *spad = &me->pads[i];
> +
> + if (!(spad->flags & MEDIA_PAD_FL_SINK))
> + continue;
> + pad = media_entity_remote_pad(spad);
> + if (pad)
> + break;
> + }
> +
> + if (!pad)
> + break;
> +
> + sd = media_entity_to_v4l2_subdev(pad->entity);
> + if (sd != &dev->isp_sdev.sd)
> + p->subdevs[p->num_subdevs++] = sd;
How do you make sure you don't overrun the array?
Instead, I'd avoid maintaining the array in the first place --- the same
information is available from the MC framework data structures --- see e.g.
the omap3isp driver.
> +
> + me = &sd->entity;
> + if (me->num_pads == 1)
> + break;
> + }
> + return 0;
> +}
> +
> +static int __subdev_set_power(struct v4l2_subdev *sd, int on)
> +{
> + int ret;
> +
> + if (!sd)
> + return -ENXIO;
> +
> + ret = v4l2_subdev_call(sd, core, s_power, on);
> +
> + return ret != -ENOIOCTLCMD ? ret : 0;
> +}
> +
> +static int __isp_pipeline_s_power(struct rkisp1_pipeline *p, bool on)
Could you instead use v4l2_pipeline_pm_use()?
> +{
> + struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> + int i, ret;
> +
> + if (on) {
> + __subdev_set_power(&dev->isp_sdev.sd, true);
> +
> + for (i = p->num_subdevs - 1; i >= 0; --i) {
> + ret = __subdev_set_power(p->subdevs[i], true);
> + if (ret < 0 && ret != -ENXIO)
> + goto err_power_off;
> + }
> + } else {
> + for (i = 0; i < p->num_subdevs; ++i)
> + __subdev_set_power(p->subdevs[i], false);
> +
> + __subdev_set_power(&dev->isp_sdev.sd, false);
> + }
> +
> + return 0;
> +
> +err_power_off:
> + for (++i; i < p->num_subdevs; ++i)
> + __subdev_set_power(p->subdevs[i], false);
> + __subdev_set_power(&dev->isp_sdev.sd, true);
> + return ret;
> +}
> +
> +static int rkisp1_pipeline_open(struct rkisp1_pipeline *p,
> + struct media_entity *me,
> + bool prepare)
> +{
> + int ret;
> +
> + if (WARN_ON(!p || !me))
> + return -EINVAL;
> + if (atomic_inc_return(&p->power_cnt) > 1)
> + return 0;
> +
> + /* go through media graphic and get subdevs */
> + if (prepare)
> + __isp_pipeline_prepare(p, me);
> +
> + if (!p->num_subdevs)
> + return -EINVAL;
> +
> + ret = __isp_pipeline_s_power(p, 1);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> +static int rkisp1_pipeline_close(struct rkisp1_pipeline *p)
> +{
> + int ret;
> +
> + if (atomic_dec_return(&p->power_cnt) > 0)
> + return 0;
> + ret = __isp_pipeline_s_power(p, 0);
> +
> + return ret == -ENXIO ? 0 : ret;
> +}
> +
> +/*
> + * stream-on order: isp_subdev, mipi dphy, sensor
> + * stream-off order: mipi dphy, sensor, isp_subdev
> + */
> +static int rkisp1_pipeline_set_stream(struct rkisp1_pipeline *p, bool on)
> +{
> + struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> + int i, ret;
> +
> + if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
> + (!on && atomic_dec_return(&p->stream_cnt) > 0))
> + return 0;
> +
> + if (on) {
> + ret = v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream,
> + true);
> + if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
> + v4l2_err(&dev->v4l2_dev,
> + "s_stream failed on subdevice %s (%d)\n",
> + dev->isp_sdev.sd.name,
> + ret);
> + atomic_dec(&p->stream_cnt);
> + return ret;
> + }
> + }
> +
> + /* phy -> sensor */
> + for (i = 0; i < p->num_subdevs; ++i) {
> + ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
> + if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> + goto err_stream_off;
You should stop after the first external sub-device.
It seems even the omap3isp driver doesn't do that. It's not easy to spot
such issues indeed.
> + }
> +
> + if (!on)
> + v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> +
> + return 0;
> +
> +err_stream_off:
> + for (--i; i >= 0; --i)
> + v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
> + v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> + atomic_dec(&p->stream_cnt);
> + return ret;
> +}
> +
> +/***************************** media controller *******************************/
> +/* See http://opensource.rock-chips.com/wiki_Rockchip-isp1 for Topology */
The host appears to be down, or there's a routing problem. Unless this is
fixed, having such a URL here doesn't do much good. :-I
> +
> +static int rkisp1_create_links(struct rkisp1_device *dev)
> +{
> + struct media_entity *source, *sink;
> + struct rkisp1_sensor *sensor;
> + unsigned int flags, pad;
> + int ret;
> +
> + /* sensor links(or mipi-phy) */
> + list_for_each_entry(sensor, &dev->sensors, list) {
> + for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
> + if (sensor->sd->entity.pads[pad].flags &
> + MEDIA_PAD_FL_SOURCE)
> + break;
Could you use media_entity_get_fwnode_pad() instead?
> +
> + if (pad == sensor->sd->entity.num_pads) {
> + dev_err(dev->dev,
> + "failed to find src pad for %s\n",
> + sensor->sd->name);
> +
> + return -ENXIO;
> + }
> +
> + ret = media_create_pad_link(
> + &sensor->sd->entity, pad,
> + &dev->isp_sdev.sd.entity,
> + RKISP1_ISP_PAD_SINK,
> + list_is_first(&sensor->list, &dev->sensors) ?
> + MEDIA_LNK_FL_ENABLED : 0);
> + if (ret) {
> + dev_err(dev->dev,
> + "failed to create link for %s\n",
> + sensor->sd->name);
> + return ret;
> + }
> + }
> +
> + /* params links */
> + source = &dev->params_vdev.vnode.vdev.entity;
> + sink = &dev->isp_sdev.sd.entity;
> + flags = MEDIA_LNK_FL_ENABLED;
> + ret = media_create_pad_link(source, 0, sink,
> + RKISP1_ISP_PAD_SINK_PARAMS, flags);
> + if (ret < 0)
> + return ret;
> +
> + /* create isp internal links */
> + /* SP links */
> + source = &dev->isp_sdev.sd.entity;
> + sink = &dev->stream[RKISP1_STREAM_SP].vnode.vdev.entity;
> + ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> + sink, 0, flags);
> + if (ret < 0)
> + return ret;
> +
> + /* MP links */
> + source = &dev->isp_sdev.sd.entity;
> + sink = &dev->stream[RKISP1_STREAM_MP].vnode.vdev.entity;
> + ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> + sink, 0, flags);
> + if (ret < 0)
> + return ret;
> +
> + /* 3A stats links */
> + source = &dev->isp_sdev.sd.entity;
> + sink = &dev->stats_vdev.vnode.vdev.entity;
> + return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
> + sink, 0, flags);
Indentation. Same for the calls to the same function above.
> +}
> +
> +static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> + struct v4l2_subdev *sd,
> + struct v4l2_async_subdev *asd)
> +{
> + struct rkisp1_device *isp_dev = container_of(notifier,
> + struct rkisp1_device,
> + notifier);
> + struct sensor_async_subdev *s_asd = container_of(asd,
> + struct sensor_async_subdev, asd);
> + struct rkisp1_sensor *sensor;
> +
> + sensor = devm_kzalloc(isp_dev->dev, sizeof(*sensor), GFP_KERNEL);
> + if (!sensor)
> + return -ENOMEM;
> +
> + sensor->lanes = s_asd->lanes;
> + sensor->mbus = s_asd->mbus;
> + sensor->sd = sd;
> + sensor->dphy = devm_phy_get(isp_dev->dev, "dphy");
> + if (IS_ERR(sensor->dphy)) {
> + if (PTR_ERR(sensor->dphy) != -EPROBE_DEFER)
> + dev_err(isp_dev->dev, "Couldn't get the MIPI D-PHY\n");
> + return PTR_ERR(sensor->dphy);
> + }
> + phy_init(sensor->dphy);
> +
> + list_add(&sensor->list, &isp_dev->sensors);
In general, maintaining the information on the external subdevs on your own
adds complexity to the driver. You can get the information when you need it
from the data structures maintained by MC (see e.g. the omap3isp driver for
examples).
> +
> + return 0;
> +}
> +
> +static struct rkisp1_sensor *sd_to_sensor(struct rkisp1_device *dev,
> + struct v4l2_subdev *sd)
> +{
> + struct rkisp1_sensor *sensor;
> +
> + list_for_each_entry(sensor, &dev->sensors, list)
> + if (sensor->sd == sd)
> + return sensor;
> +
> + return NULL;
> +}
> +
> +static void subdev_notifier_unbind(struct v4l2_async_notifier *notifier,
> + struct v4l2_subdev *sd,
> + struct v4l2_async_subdev *asd)
> +{
> + struct rkisp1_device *isp_dev = container_of(notifier,
> + struct rkisp1_device,
> + notifier);
> + struct rkisp1_sensor *sensor = sd_to_sensor(isp_dev, sd);
> +
> + /* TODO: check if a lock is required here */
> + list_del(&sensor->list);
> +
> + phy_exit(sensor->dphy);
> +}
> +
> +static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
> +{
> + struct rkisp1_device *dev = container_of(notifier, struct rkisp1_device,
> + notifier);
> + int ret;
> +
> + mutex_lock(&dev->media_dev.graph_mutex);
> + ret = rkisp1_create_links(dev);
> + if (ret < 0)
> + goto unlock;
> + ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
> + if (ret < 0)
> + goto unlock;
> +
> + v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n");
> +
> +unlock:
> + mutex_unlock(&dev->media_dev.graph_mutex);
> + return ret;
> +}
> +
> +static int rkisp1_fwnode_parse(struct device *dev,
> + struct v4l2_fwnode_endpoint *vep,
> + struct v4l2_async_subdev *asd)
> +{
> + struct sensor_async_subdev *s_asd =
> + container_of(asd, struct sensor_async_subdev, asd);
> +
> + if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
> + dev_err(dev, "Only CSI2 bus type is currently supported\n");
> + return -EINVAL;
> + }
> +
> + if (vep->base.port != 0) {
> + dev_err(dev, "The ISP has only port 0\n");
> + return -EINVAL;
> + }
> +
> + s_asd->mbus.type = vep->bus_type;
> + s_asd->mbus.flags = vep->bus.mipi_csi2.flags;
> + s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
> +
> + switch (vep->bus.mipi_csi2.num_data_lanes) {
> + case 1:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_1_LANE;
> + break;
> + case 2:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_2_LANE;
> + break;
> + case 3:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_3_LANE;
> + break;
> + case 4:
> + s_asd->mbus.flags |= V4L2_MBUS_CSI2_4_LANE;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
> + .bound = subdev_notifier_bound,
> + .unbind = subdev_notifier_unbind,
> + .complete = subdev_notifier_complete,
> +};
> +
> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
> +{
> + struct v4l2_async_notifier *ntf = &isp_dev->notifier;
> + struct device *dev = isp_dev->dev;
> + int ret;
> +
> + v4l2_async_notifier_init(ntf);
> +
> + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> + dev, ntf, sizeof(struct sensor_async_subdev), 0,
> + rkisp1_fwnode_parse);
> + if (ret < 0)
> + return ret;
> +
> + if (list_empty(&ntf->asd_list))
> + return -ENODEV; /* no endpoint */
> +
> + ntf->ops = &subdev_notifier_ops;
> +
> + return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
> +}
> +
> +/***************************** platform device *******************************/
> +
> +static int rkisp1_register_platform_subdevs(struct rkisp1_device *dev)
> +{
> + int ret;
> +
> + ret = rkisp1_register_isp_subdev(dev, &dev->v4l2_dev);
> + if (ret < 0)
> + return ret;
> +
> + ret = rkisp1_register_stream_vdevs(dev);
> + if (ret < 0)
> + goto err_unreg_isp_subdev;
> +
> + ret = rkisp1_register_stats_vdev(&dev->stats_vdev, &dev->v4l2_dev, dev);
> + if (ret < 0)
> + goto err_unreg_stream_vdev;
> +
> + ret = rkisp1_register_params_vdev(&dev->params_vdev, &dev->v4l2_dev,
> + dev);
> + if (ret < 0)
> + goto err_unreg_stats_vdev;
> +
> + ret = isp_subdev_notifier(dev);
> + if (ret < 0) {
> + v4l2_err(&dev->v4l2_dev,
> + "Failed to register subdev notifier(%d)\n", ret);
> + goto err_unreg_params_vdev;
> + }
> +
> + return 0;
> +err_unreg_params_vdev:
> + rkisp1_unregister_params_vdev(&dev->params_vdev);
> +err_unreg_stats_vdev:
> + rkisp1_unregister_stats_vdev(&dev->stats_vdev);
> +err_unreg_stream_vdev:
> + rkisp1_unregister_stream_vdevs(dev);
> +err_unreg_isp_subdev:
> + rkisp1_unregister_isp_subdev(dev);
> + return ret;
> +}
> +
> +static const char * const rk3399_isp_clks[] = {
> + "clk_isp",
> + "aclk_isp",
> + "hclk_isp",
> + "aclk_isp_wrap",
> + "hclk_isp_wrap",
> +};
> +
> +static const char * const rk3288_isp_clks[] = {
> + "clk_isp",
> + "aclk_isp",
> + "hclk_isp",
> + "pclk_isp_in",
> + "sclk_isp_jpe",
> +};
> +
> +static const struct isp_match_data rk3288_isp_clk_data = {
> + .clks = rk3288_isp_clks,
> + .size = ARRAY_SIZE(rk3288_isp_clks),
> +};
> +
> +static const struct isp_match_data rk3399_isp_clk_data = {
> + .clks = rk3399_isp_clks,
> + .size = ARRAY_SIZE(rk3399_isp_clks),
> +};
> +
> +static const struct of_device_id rkisp1_plat_of_match[] = {
> + {
> + .compatible = "rockchip,rk3288-cif-isp",
> + .data = &rk3288_isp_clk_data,
> + }, {
> + .compatible = "rockchip,rk3399-cif-isp",
> + .data = &rk3399_isp_clk_data,
> + },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, rkisp1_plat_of_match);
> +
> +static irqreturn_t rkisp1_irq_handler(int irq, void *ctx)
> +{
> + struct device *dev = ctx;
> + struct rkisp1_device *rkisp1_dev = dev_get_drvdata(dev);
> + unsigned int mis_val;
> +
> + mis_val = readl(rkisp1_dev->base_addr + CIF_ISP_MIS);
> + if (mis_val)
> + rkisp1_isp_isr(mis_val, rkisp1_dev);
> +
> + mis_val = readl(rkisp1_dev->base_addr + CIF_MIPI_MIS);
> + if (mis_val)
> + rkisp1_mipi_isr(mis_val, rkisp1_dev);
> +
> + mis_val = readl(rkisp1_dev->base_addr + CIF_MI_MIS);
> + if (mis_val)
> + rkisp1_mi_isr(mis_val, rkisp1_dev);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int rkisp1_plat_probe(struct platform_device *pdev)
> +{
> + struct device_node *node = pdev->dev.of_node;
> + const struct isp_match_data *clk_data;
> + const struct of_device_id *match;
> + struct device *dev = &pdev->dev;
> + struct rkisp1_device *isp_dev;
> + struct v4l2_device *v4l2_dev;
> + unsigned int i;
> + int ret, irq;
> +
> + match = of_match_node(rkisp1_plat_of_match, node);
> + isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
> + if (!isp_dev)
> + return -ENOMEM;
> +
> + INIT_LIST_HEAD(&isp_dev->sensors);
> +
> + dev_set_drvdata(dev, isp_dev);
> + isp_dev->dev = dev;
> +
> + isp_dev->base_addr = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(isp_dev->base_addr))
> + return PTR_ERR(isp_dev->base_addr);
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return irq;
> +
> + ret = devm_request_irq(dev, irq, rkisp1_irq_handler, IRQF_SHARED,
> + dev_driver_string(dev), dev);
> + if (ret < 0) {
> + dev_err(dev, "request irq failed: %d\n", ret);
> + return ret;
> + }
> +
> + isp_dev->irq = irq;
> + clk_data = match->data;
> +
> + for (i = 0; i < clk_data->size; i++)
> + isp_dev->clks[i].id = clk_data->clks[i];
> + ret = devm_clk_bulk_get(dev, clk_data->size, isp_dev->clks);
> + if (ret)
> + return ret;
> + isp_dev->clk_size = clk_data->size;
> +
> + atomic_set(&isp_dev->pipe.power_cnt, 0);
> + atomic_set(&isp_dev->pipe.stream_cnt, 0);
> + isp_dev->pipe.open = rkisp1_pipeline_open;
> + isp_dev->pipe.close = rkisp1_pipeline_close;
> + isp_dev->pipe.set_stream = rkisp1_pipeline_set_stream;
> +
> + rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
> + rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
> +
> + strscpy(isp_dev->media_dev.model, "rkisp1",
> + sizeof(isp_dev->media_dev.model));
> + isp_dev->media_dev.dev = &pdev->dev;
> + strscpy(isp_dev->media_dev.bus_info,
> + "platform: " DRIVER_NAME, sizeof(isp_dev->media_dev.bus_info));
> + media_device_init(&isp_dev->media_dev);
> +
> + v4l2_dev = &isp_dev->v4l2_dev;
> + v4l2_dev->mdev = &isp_dev->media_dev;
> + strscpy(v4l2_dev->name, "rkisp1", sizeof(v4l2_dev->name));
> + v4l2_ctrl_handler_init(&isp_dev->ctrl_handler, 5);
> + v4l2_dev->ctrl_handler = &isp_dev->ctrl_handler;
> +
> + ret = v4l2_device_register(isp_dev->dev, &isp_dev->v4l2_dev);
> + if (ret < 0)
Once you've initialised the control handler, you'll need to free it in case
of an error. I.e. add one more label for that purpose near the end.
> + return ret;
> +
> + ret = media_device_register(&isp_dev->media_dev);
> + if (ret < 0) {
> + v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
> + ret);
> + goto err_unreg_v4l2_dev;
> + }
> +
> + /* create & register platefom subdev (from of_node) */
> + ret = rkisp1_register_platform_subdevs(isp_dev);
> + if (ret < 0)
> + goto err_unreg_media_dev;
> +
> + pm_runtime_enable(&pdev->dev);
> +
> + return 0;
> +
> +err_unreg_media_dev:
> + media_device_unregister(&isp_dev->media_dev);
> +err_unreg_v4l2_dev:
> + v4l2_device_unregister(&isp_dev->v4l2_dev);
> + return ret;
> +}
> +
> +static int rkisp1_plat_remove(struct platform_device *pdev)
> +{
> + struct rkisp1_device *isp_dev = platform_get_drvdata(pdev);
> +
> + pm_runtime_disable(&pdev->dev);
> + media_device_unregister(&isp_dev->media_dev);
> + v4l2_async_notifier_unregister(&isp_dev->notifier);
> + v4l2_async_notifier_cleanup(&isp_dev->notifier);
> + v4l2_device_unregister(&isp_dev->v4l2_dev);
> + rkisp1_unregister_params_vdev(&isp_dev->params_vdev);
> + rkisp1_unregister_stats_vdev(&isp_dev->stats_vdev);
> + rkisp1_unregister_stream_vdevs(isp_dev);
> + rkisp1_unregister_isp_subdev(isp_dev);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
> +{
> + struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> +
> + clk_bulk_disable_unprepare(isp_dev->clk_size, isp_dev->clks);
> + return pinctrl_pm_select_sleep_state(dev);
> +}
> +
> +static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
> +{
> + struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> + int ret;
> +
> + ret = pinctrl_pm_select_default_state(dev);
> + if (ret < 0)
> + return ret;
> + ret = clk_bulk_prepare_enable(isp_dev->clk_size, isp_dev->clks);
> + if (ret < 0)
> + return ret;
> +
> + return 0;
> +}
> +
> +static const struct dev_pm_ops rkisp1_plat_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> + pm_runtime_force_resume)
> + SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rkisp1_plat_drv = {
> + .driver = {
> + .name = DRIVER_NAME,
> + .of_match_table = of_match_ptr(rkisp1_plat_of_match),
> + .pm = &rkisp1_plat_pm_ops,
> + },
> + .probe = rkisp1_plat_probe,
> + .remove = rkisp1_plat_remove,
> +};
> +
> +module_platform_driver(rkisp1_plat_drv);
> +MODULE_AUTHOR("Rockchip Camera/ISP team");
> +MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
> +MODULE_LICENSE("Dual BSD/GPL");
BSD or MIT?
> diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
> new file mode 100644
> index 000000000000..f7cbee316523
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/dev.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef _RKISP1_DEV_H
> +#define _RKISP1_DEV_H
> +
> +#include <linux/clk.h>
> +
> +#include "capture.h"
> +#include "rkisp1.h"
> +#include "isp_params.h"
> +#include "isp_stats.h"
> +
> +#define DRIVER_NAME "rkisp1"
> +#define ISP_VDEV_NAME DRIVER_NAME "_ispdev"
> +#define SP_VDEV_NAME DRIVER_NAME "_selfpath"
> +#define MP_VDEV_NAME DRIVER_NAME "_mainpath"
> +#define DMA_VDEV_NAME DRIVER_NAME "_dmapath"
> +
> +#define GRP_ID_SENSOR BIT(0)
> +#define GRP_ID_MIPIPHY BIT(1)
> +#define GRP_ID_ISP BIT(2)
> +#define GRP_ID_ISP_MP BIT(3)
> +#define GRP_ID_ISP_SP BIT(4)
> +
> +#define RKISP1_MAX_BUS_CLK 8
> +#define RKISP1_MAX_SENSOR 2
> +#define RKISP1_MAX_PIPELINE 4
> +
> +/*
> + * struct rkisp1_pipeline - An ISP hardware pipeline
> + *
> + * Capture device call other devices via pipeline
> + *
> + * @num_subdevs: number of linked subdevs
> + * @power_cnt: pipeline power count
> + * @stream_cnt: stream power count
> + */
> +struct rkisp1_pipeline {
> + struct media_pipeline pipe;
> + int num_subdevs;
> + atomic_t power_cnt;
> + atomic_t stream_cnt;
> + struct v4l2_subdev *subdevs[RKISP1_MAX_PIPELINE];
> + int (*open)(struct rkisp1_pipeline *p,
> + struct media_entity *me, bool prepare);
> + int (*close)(struct rkisp1_pipeline *p);
> + int (*set_stream)(struct rkisp1_pipeline *p, bool on);
> +};
> +
> +/*
> + * struct rkisp1_sensor - Sensor information
> + * @mbus: media bus configuration
> + */
> +struct rkisp1_sensor {
> + struct v4l2_subdev *sd;
> + struct v4l2_mbus_config mbus;
> + unsigned int lanes;
> + struct phy *dphy;
> + struct list_head list;
> +};
You seem to also have struct sensor_async_subdev that appears to contain
similar information. Would it be possible to unify the two?
This would appear to allow you getting rid of functions such as
sd_to_sensor, for instance.
> +
> +/*
> + * struct rkisp1_device - ISP platform device
> + * @base_addr: base register address
> + * @active_sensor: sensor in-use, set when streaming on
> + * @isp_sdev: ISP sub-device
> + * @rkisp1_stream: capture video device
> + * @stats_vdev: ISP statistics output device
> + * @params_vdev: ISP input parameters device
> + */
> +struct rkisp1_device {
> + void __iomem *base_addr;
> + int irq;
> + struct device *dev;
> + unsigned int clk_size;
> + struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK];
> + struct v4l2_device v4l2_dev;
> + struct v4l2_ctrl_handler ctrl_handler;
> + struct media_device media_dev;
> + struct v4l2_async_notifier notifier;
> + struct v4l2_subdev *subdevs[RKISP1_SD_MAX];
> + struct rkisp1_sensor *active_sensor;
> + struct list_head sensors;
> + struct rkisp1_isp_subdev isp_sdev;
> + struct rkisp1_stream stream[RKISP1_MAX_STREAM];
> + struct rkisp1_isp_stats_vdev stats_vdev;
> + struct rkisp1_isp_params_vdev params_vdev;
> + struct rkisp1_pipeline pipe;
> + struct vb2_alloc_ctx *alloc_ctx;
> +};
> +
> +#endif
--
Regards,
Sakari Ailus
sakari.ailus@linux.intel.com
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox