[PATCH 2/3] platform/chrome: cros_ec_lpc: Add power management ops

2016-12-16 Thread Thierry Escande
From: Archana Patni 

This patch adds suspend and resume pm ops to the LPC ChromeOS EC driver.
These LPC handlers call the croc_ec generic handlers.

Signed-off-by: Archana Patni 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/cros_ec_lpc.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 90703521..89afad7 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -333,10 +333,31 @@ static struct dmi_system_id cros_ec_lpc_dmi_table[] 
__initdata = {
 };
 MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_lpc_suspend(struct device *dev)
+{
+   struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
+
+   return cros_ec_suspend(ec_dev);
+}
+
+static int cros_ec_lpc_resume(struct device *dev)
+{
+   struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
+
+   return cros_ec_resume(ec_dev);
+}
+#endif
+
+const struct dev_pm_ops cros_ec_lpc_pm_ops = {
+   SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
+};
+
 static struct platform_driver cros_ec_lpc_driver = {
.driver = {
.name = DRV_NAME,
.acpi_match_table = cros_ec_lpc_acpi_device_ids,
+   .pm = _ec_lpc_pm_ops,
},
.probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove,
-- 
2.7.4



[PATCH 3/3] platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

2016-12-16 Thread Thierry Escande
From: Gwendal Grignou 

This patch installs a notify handler to process MKBP events for EC
firmware directing them over ACPI.

Signed-off-by: Gwendal Grignou 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/cros_ec_lpc.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 89afad7..eeb187e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -227,9 +227,20 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, 
unsigned int offset,
return cnt;
 }
 
+static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
+{
+   struct cros_ec_device *ec_dev = data;
+
+   if (ec_dev->mkbp_event_supported && cros_ec_get_next_event(ec_dev) > 0)
+   blocking_notifier_call_chain(_dev->event_notifier, 0,
+ec_dev);
+}
+
 static int cros_ec_lpc_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
+   struct acpi_device *adev;
+   acpi_status status;
struct cros_ec_device *ec_dev;
u8 buf[2];
int ret;
@@ -277,12 +288,33 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
return ret;
}
 
+   /*
+* Connect a notify handler to process MKBP messages if we have a
+* companion ACPI device.
+*/
+   adev = ACPI_COMPANION(dev);
+   if (adev) {
+   status = acpi_install_notify_handler(adev->handle,
+ACPI_ALL_NOTIFY,
+cros_ec_lpc_acpi_notify,
+ec_dev);
+   if (ACPI_FAILURE(status))
+   dev_warn(dev, "Failed to register notifier %08x\n",
+status);
+   }
+
return 0;
 }
 
 static int cros_ec_lpc_remove(struct platform_device *pdev)
 {
struct cros_ec_device *ec_dev;
+   struct acpi_device *adev;
+
+   adev = ACPI_COMPANION(>dev);
+   if (adev)
+   acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
+  cros_ec_lpc_acpi_notify);
 
ec_dev = platform_get_drvdata(pdev);
cros_ec_remove(ec_dev);
-- 
2.7.4



[PATCH 0/3] platform/chrome: cros_ec_lpc: MKBP events over ACPI

2016-12-16 Thread Thierry Escande
Hi,

This series adds support for MKBP events over ACPI. The ChromeOS EC LCP
driver is also now probed upon detection of the ACPI GOOG0004 device.
Last, a patch adds power management suspend and resume handlers.

This patchset depends on [1] to apply.
[1] https://lkml.org/lkml/2016/12/2/360

Regards,
 Thierry

Archana Patni (1):
  platform/chrome: cros_ec_lpc: Add power management ops

Gwendal Grignou (2):
  platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device
  platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

 drivers/platform/chrome/Kconfig   |  2 +-
 drivers/platform/chrome/cros_ec_lpc.c | 76 ---
 2 files changed, 63 insertions(+), 15 deletions(-)

-- 
2.7.4



[PATCH 0/3] platform/chrome: cros_ec_lpc: MKBP events over ACPI

2016-12-16 Thread Thierry Escande
Hi,

This series adds support for MKBP events over ACPI. The ChromeOS EC LCP
driver is also now probed upon detection of the ACPI GOOG0004 device.
Last, a patch adds power management suspend and resume handlers.

This patchset depends on [1] to apply.
[1] https://lkml.org/lkml/2016/12/2/360

Regards,
 Thierry

Archana Patni (1):
  platform/chrome: cros_ec_lpc: Add power management ops

Gwendal Grignou (2):
  platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device
  platform/chrome: cros_ec_lpc: Add MKBP events support over ACPI

 drivers/platform/chrome/Kconfig   |  2 +-
 drivers/platform/chrome/cros_ec_lpc.c | 76 ---
 2 files changed, 63 insertions(+), 15 deletions(-)

-- 
2.7.4



[PATCH 1/3] platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device

2016-12-16 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This patch removes platform_device_register() call and adds an ACPI
device id structure. The driver is now automatically probed for devices
with a GOOG0004 ACPI entry.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |  2 +-
 drivers/platform/chrome/cros_ec_lpc.c | 23 +--
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 6d80fb5..0ad6e29 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -49,7 +49,7 @@ config CROS_EC_CHARDEV
 
 config CROS_EC_LPC
 tristate "ChromeOS Embedded Controller (LPC)"
-depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
+depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
 help
   If you say Y here, you get support for talking to the ChromeOS EC
   over an LPC bus. This uses a simple byte-level protocol with a
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index bc2dc62..90703521 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -21,6 +21,7 @@
  * expensive.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -32,6 +33,7 @@
 #include 
 
 #define DRV_NAME "cros_ec_lpcs"
+#define ACPI_DRV_NAME "GOOG0004"
 
 static int ec_response_timed_out(void)
 {
@@ -288,6 +290,12 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
+   { ACPI_DRV_NAME, 0 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
+
 static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
{
/*
@@ -328,15 +336,12 @@ MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 static struct platform_driver cros_ec_lpc_driver = {
.driver = {
.name = DRV_NAME,
+   .acpi_match_table = cros_ec_lpc_acpi_device_ids,
},
.probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove,
 };
 
-static struct platform_device cros_ec_lpc_device = {
-   .name = DRV_NAME
-};
-
 static int __init cros_ec_lpc_init(void)
 {
int ret;
@@ -356,21 +361,11 @@ static int __init cros_ec_lpc_init(void)
return ret;
}
 
-   /* Register the device, and it'll get hooked up automatically */
-   ret = platform_device_register(_ec_lpc_device);
-   if (ret) {
-   pr_err(DRV_NAME ": can't register device: %d\n", ret);
-   platform_driver_unregister(_ec_lpc_driver);
-   cros_ec_lpc_reg_destroy();
-   return ret;
-   }
-
return 0;
 }
 
 static void __exit cros_ec_lpc_exit(void)
 {
-   platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
cros_ec_lpc_reg_destroy();
 }
-- 
2.7.4



[PATCH 1/3] platform/chrome: cros_ec_lpc: Add support for GOOG004 ACPI device

2016-12-16 Thread Thierry Escande
From: Gwendal Grignou 

This patch removes platform_device_register() call and adds an ACPI
device id structure. The driver is now automatically probed for devices
with a GOOG0004 ACPI entry.

Signed-off-by: Gwendal Grignou 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Kconfig   |  2 +-
 drivers/platform/chrome/cros_ec_lpc.c | 23 +--
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 6d80fb5..0ad6e29 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -49,7 +49,7 @@ config CROS_EC_CHARDEV
 
 config CROS_EC_LPC
 tristate "ChromeOS Embedded Controller (LPC)"
-depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
+depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
 help
   If you say Y here, you get support for talking to the ChromeOS EC
   over an LPC bus. This uses a simple byte-level protocol with a
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index bc2dc62..90703521 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -21,6 +21,7 @@
  * expensive.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -32,6 +33,7 @@
 #include 
 
 #define DRV_NAME "cros_ec_lpcs"
+#define ACPI_DRV_NAME "GOOG0004"
 
 static int ec_response_timed_out(void)
 {
@@ -288,6 +290,12 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)
return 0;
 }
 
+static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
+   { ACPI_DRV_NAME, 0 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
+
 static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
{
/*
@@ -328,15 +336,12 @@ MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
 static struct platform_driver cros_ec_lpc_driver = {
.driver = {
.name = DRV_NAME,
+   .acpi_match_table = cros_ec_lpc_acpi_device_ids,
},
.probe = cros_ec_lpc_probe,
.remove = cros_ec_lpc_remove,
 };
 
-static struct platform_device cros_ec_lpc_device = {
-   .name = DRV_NAME
-};
-
 static int __init cros_ec_lpc_init(void)
 {
int ret;
@@ -356,21 +361,11 @@ static int __init cros_ec_lpc_init(void)
return ret;
}
 
-   /* Register the device, and it'll get hooked up automatically */
-   ret = platform_device_register(_ec_lpc_device);
-   if (ret) {
-   pr_err(DRV_NAME ": can't register device: %d\n", ret);
-   platform_driver_unregister(_ec_lpc_driver);
-   cros_ec_lpc_reg_destroy();
-   return ret;
-   }
-
return 0;
 }
 
 static void __exit cros_ec_lpc_exit(void)
 {
-   platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
cros_ec_lpc_reg_destroy();
 }
-- 
2.7.4



[PATCH 3/3] iio: cros_ec_activity: add ChromeOS EC Activity Sensors

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This patch adds a driver for handling activity/gesture recognition
coming from the EC. Only significant motion is currently supported. It
is an incomplete driver: activity can be set, but ring buffer must be
used to receive interruption.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/iio/common/cros_ec_sensors/Kconfig |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile|   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 300 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  24 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   1 +
 5 files changed, 336 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig 
b/drivers/iio/common/cros_ec_sensors/Kconfig
index 3349c9d..0a64928 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -21,3 +21,13 @@ config IIO_CROS_EC_SENSORS
  Accelerometers, Gyroscope and Magnetometer that are
  presented by the ChromeOS EC Sensor hub.
  Creates an IIO device for each functions.
+
+config IIO_CROS_EC_ACTIVITY
+   tristate "ChromeOS EC Activity Sensors"
+   select IIO_CROS_EC_SENSORS_CORE
+   help
+ Module to handle activity events detections presented by the ChromeOS
+ EC Sensor hub.
+ Activities can be simple (low/no motion) or more complex (riding 
train).
+ They are being reported by physical devices or the EC itself.
+ Creates an IIO device to manage all activities.
diff --git a/drivers/iio/common/cros_ec_sensors/Makefile 
b/drivers/iio/common/cros_ec_sensors/Makefile
index ec716ff..a4a2d6c 100644
--- a/drivers/iio/common/cros_ec_sensors/Makefile
+++ b/drivers/iio/common/cros_ec_sensors/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
 obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
+obj-$(CONFIG_IIO_CROS_EC_ACTIVITY) += cros_ec_activity.o
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
new file mode 100644
index 000..f14c3d3
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
@@ -0,0 +1,300 @@
+/*
+ * cros_ec_sensors_activity - Driver for activities/gesture recognition.
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the cros-ec interface to communicate with the Chrome OS
+ * EC about accelerometer data. Accelerometer access is presented through
+ * iio sysfs.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cros_ec_sensors_core.h"
+
+#define DRV_NAME "cros-ec-activity"
+
+/* st data for ec_sensors iio driver. */
+struct cros_ec_sensors_state {
+   /* Shared by all sensors */
+   struct cros_ec_sensors_core_state core;
+
+   struct iio_chan_spec *channels;
+   unsigned int nb_activities;
+};
+
+static const struct iio_event_spec cros_ec_activity_single_shot[] = {
+   {
+   .type = IIO_EV_TYPE_CHANGE,
+   /* significant motion trigger when we get out of still. */
+   .dir = IIO_EV_DIR_FALLING,
+   .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+},
+};
+
+static int ec_sensors_read(struct iio_dev *indio_dev,
+  struct iio_chan_spec const *chan,
+  int *val, int *val2, long mask)
+{
+   dev_warn(_dev->dev, "%s: Not Expected: %d\n", __func__,
+chan->channel2);
+
+   return -EPERM;
+}
+
+static int ec_sensors_write(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   int val, int val2, long mask)
+{
+   dev_warn(_dev->dev, "%s: Not Expected: %d\n", __func__,
+chan->channel2);
+
+   return -EPERM;
+}
+
+static int cros_ec_read_event_config(struct iio_dev *indio_dev,
+const struct iio_chan_spec *chan,
+enum iio_event_type type,
+enum iio_event_direction dir)
+{
+   struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (chan->type !

[PATCH 3/3] iio: cros_ec_activity: add ChromeOS EC Activity Sensors

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou 

This patch adds a driver for handling activity/gesture recognition
coming from the EC. Only significant motion is currently supported. It
is an incomplete driver: activity can be set, but ring buffer must be
used to receive interruption.

Signed-off-by: Gwendal Grignou 
Signed-off-by: Thierry Escande 
---
 drivers/iio/common/cros_ec_sensors/Kconfig |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile|   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 300 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  24 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   1 +
 5 files changed, 336 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig 
b/drivers/iio/common/cros_ec_sensors/Kconfig
index 3349c9d..0a64928 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -21,3 +21,13 @@ config IIO_CROS_EC_SENSORS
  Accelerometers, Gyroscope and Magnetometer that are
  presented by the ChromeOS EC Sensor hub.
  Creates an IIO device for each functions.
+
+config IIO_CROS_EC_ACTIVITY
+   tristate "ChromeOS EC Activity Sensors"
+   select IIO_CROS_EC_SENSORS_CORE
+   help
+ Module to handle activity events detections presented by the ChromeOS
+ EC Sensor hub.
+ Activities can be simple (low/no motion) or more complex (riding 
train).
+ They are being reported by physical devices or the EC itself.
+ Creates an IIO device to manage all activities.
diff --git a/drivers/iio/common/cros_ec_sensors/Makefile 
b/drivers/iio/common/cros_ec_sensors/Makefile
index ec716ff..a4a2d6c 100644
--- a/drivers/iio/common/cros_ec_sensors/Makefile
+++ b/drivers/iio/common/cros_ec_sensors/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
 obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
+obj-$(CONFIG_IIO_CROS_EC_ACTIVITY) += cros_ec_activity.o
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
new file mode 100644
index 000..f14c3d3
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_activity.c
@@ -0,0 +1,300 @@
+/*
+ * cros_ec_sensors_activity - Driver for activities/gesture recognition.
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the cros-ec interface to communicate with the Chrome OS
+ * EC about accelerometer data. Accelerometer access is presented through
+ * iio sysfs.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cros_ec_sensors_core.h"
+
+#define DRV_NAME "cros-ec-activity"
+
+/* st data for ec_sensors iio driver. */
+struct cros_ec_sensors_state {
+   /* Shared by all sensors */
+   struct cros_ec_sensors_core_state core;
+
+   struct iio_chan_spec *channels;
+   unsigned int nb_activities;
+};
+
+static const struct iio_event_spec cros_ec_activity_single_shot[] = {
+   {
+   .type = IIO_EV_TYPE_CHANGE,
+   /* significant motion trigger when we get out of still. */
+   .dir = IIO_EV_DIR_FALLING,
+   .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+},
+};
+
+static int ec_sensors_read(struct iio_dev *indio_dev,
+  struct iio_chan_spec const *chan,
+  int *val, int *val2, long mask)
+{
+   dev_warn(_dev->dev, "%s: Not Expected: %d\n", __func__,
+chan->channel2);
+
+   return -EPERM;
+}
+
+static int ec_sensors_write(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   int val, int val2, long mask)
+{
+   dev_warn(_dev->dev, "%s: Not Expected: %d\n", __func__,
+chan->channel2);
+
+   return -EPERM;
+}
+
+static int cros_ec_read_event_config(struct iio_dev *indio_dev,
+const struct iio_chan_spec *chan,
+enum iio_event_type type,
+enum iio_event_direction dir)
+{
+   struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (chan->type != IIO_ACTIVITY)
+   return -EINVAL;
+
+   mutex_lock(>core.cmd_l

[PATCH 0/3] Add ChromeOS EC Activity Sensors driver

2016-12-05 Thread Thierry Escande
Hi,

This patchset adds support for an activity sensors driver handling
activity/gesture recognition coming from the EC. Only significant motion
is currently supported. Moreover it is an incomplete driver: activity can
be set and ring buffer must be used to receive interruption.

This patchset depends on [1] to apply (which is merged into linux-next).

[1] https://lkml.org/lkml/2016/8/1/141

Regards,
 Thierry

Gwendal Grignou (3):
  mfd: cros_ec: update MOTIONSENSE definitions and commands
  iio: core: Add double tap as possible gesture
  iio: cros_ec_activity: add ChromeOS EC Activity Sensors

 drivers/iio/common/cros_ec_sensors/Kconfig |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile|   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 300 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  24 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   1 +
 drivers/iio/industrialio-core.c|   1 +
 include/linux/mfd/cros_ec_commands.h   |  35 +++
 include/uapi/linux/iio/types.h |   1 +
 8 files changed, 373 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

-- 
2.7.4



[PATCH 0/3] Add ChromeOS EC Activity Sensors driver

2016-12-05 Thread Thierry Escande
Hi,

This patchset adds support for an activity sensors driver handling
activity/gesture recognition coming from the EC. Only significant motion
is currently supported. Moreover it is an incomplete driver: activity can
be set and ring buffer must be used to receive interruption.

This patchset depends on [1] to apply (which is merged into linux-next).

[1] https://lkml.org/lkml/2016/8/1/141

Regards,
 Thierry

Gwendal Grignou (3):
  mfd: cros_ec: update MOTIONSENSE definitions and commands
  iio: core: Add double tap as possible gesture
  iio: cros_ec_activity: add ChromeOS EC Activity Sensors

 drivers/iio/common/cros_ec_sensors/Kconfig |  10 +
 drivers/iio/common/cros_ec_sensors/Makefile|   1 +
 .../iio/common/cros_ec_sensors/cros_ec_activity.c  | 300 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  |  24 ++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  |   1 +
 drivers/iio/industrialio-core.c|   1 +
 include/linux/mfd/cros_ec_commands.h   |  35 +++
 include/uapi/linux/iio/types.h |   1 +
 8 files changed, 373 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_activity.c

-- 
2.7.4



[PATCH 2/3] iio: core: Add double tap as possible gesture

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This adds the IIO_MOD_DOUBLE_TAP entry to the iio_modifier enum and the
corresponding "double_tap" string to the iio_modifier_names array.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/iio/industrialio-core.c | 1 +
 include/uapi/linux/iio/types.h  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index fc340ed..82ce05f 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -120,6 +120,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
+   [IIO_MOD_DOUBLE_TAP] = "double_tap",
 };
 
 /* relies on pairs of these shared then separate */
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 22e5e58..47d2768 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -80,6 +80,7 @@ enum iio_modifier {
IIO_MOD_CO2,
IIO_MOD_VOC,
IIO_MOD_LIGHT_UV,
+   IIO_MOD_DOUBLE_TAP,
 };
 
 enum iio_event_type {
-- 
2.7.4



[PATCH 2/3] iio: core: Add double tap as possible gesture

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou 

This adds the IIO_MOD_DOUBLE_TAP entry to the iio_modifier enum and the
corresponding "double_tap" string to the iio_modifier_names array.

Signed-off-by: Gwendal Grignou 
Signed-off-by: Thierry Escande 
---
 drivers/iio/industrialio-core.c | 1 +
 include/uapi/linux/iio/types.h  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index fc340ed..82ce05f 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -120,6 +120,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_Q] = "q",
[IIO_MOD_CO2] = "co2",
[IIO_MOD_VOC] = "voc",
+   [IIO_MOD_DOUBLE_TAP] = "double_tap",
 };
 
 /* relies on pairs of these shared then separate */
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 22e5e58..47d2768 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -80,6 +80,7 @@ enum iio_modifier {
IIO_MOD_CO2,
IIO_MOD_VOC,
IIO_MOD_LIGHT_UV,
+   IIO_MOD_DOUBLE_TAP,
 };
 
 enum iio_event_type {
-- 
2.7.4



[PATCH 1/3] mfd: cros_ec: Add activity motion sense definitions

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou <gwen...@chromium.org>

This adds motion sense definitions to the commands header related to the
activity sensors attached behind the ChromeOS Embedded Controller.
Supported activities are MOTION and DOUBLE_TAP.

Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 include/linux/mfd/cros_ec_commands.h | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index 1683003..80e6060 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -1417,6 +1417,18 @@ enum motionsense_command {
 */
MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
 
+   /*
+* List available activities for a MOTION sensor.
+* Indicates if they are enabled or disabled.
+*/
+   MOTIONSENSE_CMD_LIST_ACTIVITIES = 12,
+
+   /*
+* Activity management
+* Enable/Disable activity recognition.
+*/
+   MOTIONSENSE_CMD_SET_ACTIVITY = 13,
+
/* Number of motionsense sub-commands. */
MOTIONSENSE_NUM_CMDS
 };
@@ -1494,6 +1506,21 @@ struct ec_response_motion_sensor_data {
};
 } __packed;
 
+/* List supported activity recognition */
+enum motionsensor_activity {
+   MOTIONSENSE_ACTIVITY_RESERVED = 0,
+   MOTIONSENSE_ACTIVITY_SIG_MOTION = 1,
+   MOTIONSENSE_ACTIVITY_DOUBLE_TAP = 2,
+};
+
+struct ec_motion_sense_activity {
+   uint8_t sensor_num;
+   uint8_t activity;   /* one of enum motionsensor_activity */
+   uint8_t enable; /* 1: enable, 0: disable */
+   uint8_t reserved;
+   uint16_t parameters[3]; /* activity dependent parameters */
+};
+
 struct ec_params_motion_sense {
uint8_t cmd;
union {
@@ -1561,6 +1588,8 @@ struct ec_params_motion_sense {
/* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
int32_t data;
} sensor_odr, sensor_range;
+
+   struct ec_motion_sense_activity set_activity;
};
 } __packed;
 
@@ -1611,6 +1640,12 @@ struct ec_response_motion_sense {
int16_t temp;
int16_t offset[3];
} sensor_offset, perform_calib;
+
+   struct {
+   uint16_t reserved;
+   uint32_t enabled;
+   uint32_t disabled;
+   } __packed list_activities;
};
 } __packed;
 
-- 
2.7.4



[PATCH 1/3] mfd: cros_ec: Add activity motion sense definitions

2016-12-05 Thread Thierry Escande
From: Gwendal Grignou 

This adds motion sense definitions to the commands header related to the
activity sensors attached behind the ChromeOS Embedded Controller.
Supported activities are MOTION and DOUBLE_TAP.

Signed-off-by: Gwendal Grignou 
Signed-off-by: Thierry Escande 
---
 include/linux/mfd/cros_ec_commands.h | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index 1683003..80e6060 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -1417,6 +1417,18 @@ enum motionsense_command {
 */
MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
 
+   /*
+* List available activities for a MOTION sensor.
+* Indicates if they are enabled or disabled.
+*/
+   MOTIONSENSE_CMD_LIST_ACTIVITIES = 12,
+
+   /*
+* Activity management
+* Enable/Disable activity recognition.
+*/
+   MOTIONSENSE_CMD_SET_ACTIVITY = 13,
+
/* Number of motionsense sub-commands. */
MOTIONSENSE_NUM_CMDS
 };
@@ -1494,6 +1506,21 @@ struct ec_response_motion_sensor_data {
};
 } __packed;
 
+/* List supported activity recognition */
+enum motionsensor_activity {
+   MOTIONSENSE_ACTIVITY_RESERVED = 0,
+   MOTIONSENSE_ACTIVITY_SIG_MOTION = 1,
+   MOTIONSENSE_ACTIVITY_DOUBLE_TAP = 2,
+};
+
+struct ec_motion_sense_activity {
+   uint8_t sensor_num;
+   uint8_t activity;   /* one of enum motionsensor_activity */
+   uint8_t enable; /* 1: enable, 0: disable */
+   uint8_t reserved;
+   uint16_t parameters[3]; /* activity dependent parameters */
+};
+
 struct ec_params_motion_sense {
uint8_t cmd;
union {
@@ -1561,6 +1588,8 @@ struct ec_params_motion_sense {
/* Data to set or EC_MOTION_SENSE_NO_VALUE to read. */
int32_t data;
} sensor_odr, sensor_range;
+
+   struct ec_motion_sense_activity set_activity;
};
 } __packed;
 
@@ -1611,6 +1640,12 @@ struct ec_response_motion_sense {
int16_t temp;
int16_t offset[3];
} sensor_offset, perform_calib;
+
+   struct {
+   uint16_t reserved;
+   uint32_t enabled;
+   uint32_t disabled;
+   } __packed list_activities;
};
 } __packed;
 
-- 
2.7.4



[PATCH v2 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-12-02 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |  12 +++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 140 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  90 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 331 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..6d80fb5 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,18 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
+ If you have a ChromeOS Embedded Controller Microchip EC variant
+ choose Y here.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 6a782a6..bc2dc62 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -346,10 +346,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -358,6 +361,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -368,6 +372,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..2eda2c2
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,140 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include 
+#inc

[PATCH v2 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-12-02 Thread Thierry Escande
From: Shawn Nematbakhsh 

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Kconfig   |  12 +++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 140 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  90 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 331 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..6d80fb5 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,18 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
+ If you have a ChromeOS Embedded Controller Microchip EC variant
+ choose Y here.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 6a782a6..bc2dc62 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -346,10 +346,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -358,6 +361,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -368,6 +372,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..2eda2c2
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,140 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This mutex must be held while accessi

[PATCH v2 0/2] platform/chrome: Add support for mec1322 EC

2016-12-02 Thread Thierry Escande
Hi Benson,

This series adds support for the LPC Microchip Embedded Controller 1322.

v2:
-Add a few lines in Kconfig description
-Fixed coding style issues
-Updated copyright to year 2016

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig   |  12 +++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  93 +---
 drivers/platform/chrome/cros_ec_lpc_mec.c | 140 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 
 include/linux/mfd/cros_ec_lpc_mec.h   |  90 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 482 insertions(+), 51 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.7.4



[PATCH v2 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-12-02 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 88 +--
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 ++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 151 insertions(+), 51 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpc.o
+cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..6a782a6 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
unsigned long one_second = jiffies + HZ;
+   u8 data;
 
usleep_range(200, 300);
do {
-   if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+   if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, ) &
+   EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
struct ec_host_request *request;
struct ec_host_response response;
-   u8 sum = 0;
-   int i;
+   u8 sum;
int ret = 0;
u8 *dout;
 
ret = cros_ec_prepare_tx(ec, msg);
 
/* Write buffer */
-   for (i = 0; i < ret; i++)
-   outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
request = (struct ec_host_request *)ec->dout;
 
/* Here we go */
-   outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+   sum = EC_COMMAND_PROTOCOL_3;
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, );
 
if (ec_response_timed_out()) {
dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Check result */
-   msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+   msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   for (i = 0; i < sizeof(response); i++) {
-   dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-   sum += dout[i];
-   }
+   sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
+dout);
 
msg->result = response.result;
 
@@ -97,11 +97,9 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Read response and process checksum */
-   for (i = 0; i < response.data_len; i++) {
-   msg->data[i] =
-   inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-   sum += msg->data[i];
-   }
+   sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET +
+ sizeof(response), response.data_len,
+ msg->data);
 
if (sum) {
dev_err(ec->dev,
@@ -121,8 +119,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
struct cros_ec_command *msg)
 {
struct ec_lpc_host_args args;
-   int csum;
-   int i;
+   u8 sum;
int ret = 0;
 
if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
@@ -139,24 +136,20 @@ static int cros_ec_cmd_xfe

[PATCH v2 0/2] platform/chrome: Add support for mec1322 EC

2016-12-02 Thread Thierry Escande
Hi Benson,

This series adds support for the LPC Microchip Embedded Controller 1322.

v2:
-Add a few lines in Kconfig description
-Fixed coding style issues
-Updated copyright to year 2016

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig   |  12 +++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  93 +---
 drivers/platform/chrome/cros_ec_lpc_mec.c | 140 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 
 include/linux/mfd/cros_ec_lpc_mec.h   |  90 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 482 insertions(+), 51 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.7.4



[PATCH v2 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-12-02 Thread Thierry Escande
From: Shawn Nematbakhsh 

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 88 +--
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 ++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 151 insertions(+), 51 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpc.o
+cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..6a782a6 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
unsigned long one_second = jiffies + HZ;
+   u8 data;
 
usleep_range(200, 300);
do {
-   if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+   if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, ) &
+   EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
struct ec_host_request *request;
struct ec_host_response response;
-   u8 sum = 0;
-   int i;
+   u8 sum;
int ret = 0;
u8 *dout;
 
ret = cros_ec_prepare_tx(ec, msg);
 
/* Write buffer */
-   for (i = 0; i < ret; i++)
-   outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
request = (struct ec_host_request *)ec->dout;
 
/* Here we go */
-   outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+   sum = EC_COMMAND_PROTOCOL_3;
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, );
 
if (ec_response_timed_out()) {
dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Check result */
-   msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+   msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   for (i = 0; i < sizeof(response); i++) {
-   dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-   sum += dout[i];
-   }
+   sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
+dout);
 
msg->result = response.result;
 
@@ -97,11 +97,9 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Read response and process checksum */
-   for (i = 0; i < response.data_len; i++) {
-   msg->data[i] =
-   inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-   sum += msg->data[i];
-   }
+   sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET +
+ sizeof(response), response.data_len,
+ msg->data);
 
if (sum) {
dev_err(ec->dev,
@@ -121,8 +119,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
struct cros_ec_command *msg)
 {
struct ec_lpc_host_args args;
-   int csum;
-   int i;
+   u8 sum;
int ret = 0;
 
if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
@@ -139,24 +136,20 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
args.data_size = msg->outsize;
 
/* Initialize ch

Re: [PATCH RESEND 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-12-01 Thread Thierry Escande

Hi Enric,

Thanks for the review.

On 30/11/2016 16:48, Enric Balletbo Serra wrote:

Hi Thierry,

I reviewed your patches and looks good to me, I only found a few style
things that is up to maintainer decide if are needed or not, most of
them are feedback I received on other subsystems. Ah, and I've a
question about runtime detection of the EC (see below), but guess the
answer is no.

Reviewed-by: Enric Balletbo i Serra <enric.balle...@collabora.com>

2016-11-08 13:27 GMT+01:00 Thierry Escande <thierry.esca...@collabora.com>:

From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.

+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+


As reported by checkpatch, write a paragraph that describes the config
symbol fully. Maybe adding something like this

  If you have a ChromeOS Embedded Controller Microchip EC variant
  choose Y here.

According to the help if you have a non-Microchip EC you should leave
this as N. Would be possible some kind of runtime detection of the EC
? Just thinking in out loud.
Well, we can use the EC_CMD_GET_CHIP_INFO command and check for the chip 
name as it is "mec1322" (at least on the cyan that I have).


Regards,
 Thierry




 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}

+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}

@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}

@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }

 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/ch

Re: [PATCH RESEND 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-12-01 Thread Thierry Escande

Hi Enric,

Thanks for the review.

On 30/11/2016 16:48, Enric Balletbo Serra wrote:

Hi Thierry,

I reviewed your patches and looks good to me, I only found a few style
things that is up to maintainer decide if are needed or not, most of
them are feedback I received on other subsystems. Ah, and I've a
question about runtime detection of the EC (see below), but guess the
answer is no.

Reviewed-by: Enric Balletbo i Serra 

2016-11-08 13:27 GMT+01:00 Thierry Escande :

From: Shawn Nematbakhsh 

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Gwendal Grignou 
Signed-off-by: Guenter Roeck 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.

+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+


As reported by checkpatch, write a paragraph that describes the config
symbol fully. Maybe adding something like this

  If you have a ChromeOS Embedded Controller Microchip EC variant
  choose Y here.

According to the help if you have a non-Microchip EC you should leave
this as N. Would be possible some kind of runtime detection of the EC
? Just thinking in out loud.
Well, we can use the EC_CMD_GET_CHIP_INFO command and check for the chip 
name as it is "mec1322" (at least on the cyan that I have).


Regards,
 Thierry




 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}

+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}

@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}

@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }

 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 Google, Inc
+ *


Update the copyright to 2016


+ * This software is licensed under the ter

Re: [PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-11-22 Thread Thierry Escande

Hi Mauro,

On 18/11/2016 19:59, Mauro Carvalho Chehab wrote:

Em Tue, 25 Oct 2016 10:22:29 +0200
Thierry Escande <thierry.esca...@collabora.com> escreveu:


From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.


Why to add it? There's no other patch on this series with would
justify its needs...


It is used by a Rockchip vpu driver which is only in the chromeos public 
tree for now and will be upstreamed soon.


Regards,
 Thierry



Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes in v2:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes in v3:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes in v4:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro

Changes in v5:
- Use is_output queue field in VB2_DMA_DIR() macro

 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 23 +++
 5 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;

memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;

memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;

offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, bu

Re: [PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-11-22 Thread Thierry Escande

Hi Mauro,

On 18/11/2016 19:59, Mauro Carvalho Chehab wrote:

Em Tue, 25 Oct 2016 10:22:29 +0200
Thierry Escande  escreveu:


From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.


Why to add it? There's no other patch on this series with would
justify its needs...


It is used by a Rockchip vpu driver which is only in the chromeos public 
tree for now and will be upstreamed soon.


Regards,
 Thierry



Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Signed-off-by: Thierry Escande 
---

Changes in v2:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes in v3:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes in v4:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro

Changes in v5:
- Use is_output queue field in VB2_DMA_DIR() macro

 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 23 +++
 5 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;

memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;

memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;

offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_

[PATCH RESEND 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-11-08 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#in

[PATCH RESEND 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-11-08 Thread Thierry Escande
From: Shawn Nematbakhsh 

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Gwendal Grignou 
Signed-off-by: Guenter Roeck 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This mutex must be held while accessing the EMI unit. We can't rely on the
+ * EC

[PATCH RESEND 0/2] platform/chrome: Add support for mec1322 EC

2016-11-08 Thread Thierry Escande
Hi,

This serie adds support for the LPC Microchip Embedded Controller 1322.

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  92 +--
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 487 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.7.4



[PATCH RESEND 0/2] platform/chrome: Add support for mec1322 EC

2016-11-08 Thread Thierry Escande
Hi,

This serie adds support for the LPC Microchip Embedded Controller 1322.

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  92 +--
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 487 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.7.4



[PATCH RESEND 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-11-08 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 87 ++-
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 +++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 152 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpc.o
+cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..617074e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
unsigned long one_second = jiffies + HZ;
+   u8 data;
 
usleep_range(200, 300);
do {
-   if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+   if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, ) &
+   EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
struct ec_host_request *request;
struct ec_host_response response;
-   u8 sum = 0;
-   int i;
+   u8 sum;
int ret = 0;
u8 *dout;
 
ret = cros_ec_prepare_tx(ec, msg);
 
/* Write buffer */
-   for (i = 0; i < ret; i++)
-   outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
request = (struct ec_host_request *)ec->dout;
 
/* Here we go */
-   outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+   sum = EC_COMMAND_PROTOCOL_3;
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, );
 
if (ec_response_timed_out()) {
dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Check result */
-   msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+   msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   for (i = 0; i < sizeof(response); i++) {
-   dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-   sum += dout[i];
-   }
+   sum = cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET, sizeof(response), dout);
 
msg->result = response.result;
 
@@ -97,11 +97,10 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Read response and process checksum */
-   for (i = 0; i < response.data_len; i++) {
-   msg->data[i] =
-   inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-   sum += msg->data[i];
-   }
+   sum += cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET + sizeof(response),
+   response.data_len,
+   msg->data);
 
if (sum) {
dev_err(ec->dev,
@@ -121,8 +120,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
struct cros_ec_command *msg)
 {
struct ec_lpc_host_args args;
-   int csum;
-   int i;
+   u8 sum;
int ret = 0;
 
if (msg->outs

[PATCH RESEND 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-11-08 Thread Thierry Escande
From: Shawn Nematbakhsh 

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Gwendal Grignou 
Signed-off-by: Guenter Roeck 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 87 ++-
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 +++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 152 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpc.o
+cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..617074e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
unsigned long one_second = jiffies + HZ;
+   u8 data;
 
usleep_range(200, 300);
do {
-   if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+   if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, ) &
+   EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
struct ec_host_request *request;
struct ec_host_response response;
-   u8 sum = 0;
-   int i;
+   u8 sum;
int ret = 0;
u8 *dout;
 
ret = cros_ec_prepare_tx(ec, msg);
 
/* Write buffer */
-   for (i = 0; i < ret; i++)
-   outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
request = (struct ec_host_request *)ec->dout;
 
/* Here we go */
-   outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+   sum = EC_COMMAND_PROTOCOL_3;
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, );
 
if (ec_response_timed_out()) {
dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Check result */
-   msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+   msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   for (i = 0; i < sizeof(response); i++) {
-   dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-   sum += dout[i];
-   }
+   sum = cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET, sizeof(response), dout);
 
msg->result = response.result;
 
@@ -97,11 +97,10 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Read response and process checksum */
-   for (i = 0; i < response.data_len; i++) {
-   msg->data[i] =
-   inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-   sum += msg->data[i];
-   }
+   sum += cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET + sizeof(response),
+   response.data_len,
+   msg->data);
 
if (sum) {
dev_err(ec->dev,
@@ -121,8 +120,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
struct cros_ec_command *msg)
 {
struct ec_lpc_host_args args;
-   int csum;
-   int i;
+   u8 sum;
int ret = 0;
 
if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
@@ -139,24 +137,21 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
args.dat

[PATCH v3 2/2] [media] videobuf2-dc: Support cacheable MMAP

2016-10-26 Thread Thierry Escande
From: Heng-Ruey Hsu <henry...@chromium.org>

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

This patch enables cacheable memory for DMA coherent allocator in mmap
buffer allocation if non-consistent DMA attribute is set and kernel
mapping is present. Even if userspace doesn't mmap the buffer, sync
still should be happening if kernel mapping is present.
If not done in allocation, it is enabled when memory is mapped from
userspace (if non-consistent DMA attribute is set).

Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org>
Tested-by: Heng-ruey Hsu <henry...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 0d9665d..89b534a 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   /*
+* Enable cache maintenance. Even if userspace doesn't mmap the buffer,
+* sync still should be happening if kernel mapping is present.
+*/
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -227,6 +239,10 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   /* Enable cache maintenance if not enabled in allocation. */
+   if (!buf->dma_sgt && buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v3 2/2] [media] videobuf2-dc: Support cacheable MMAP

2016-10-26 Thread Thierry Escande
From: Heng-Ruey Hsu 

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

This patch enables cacheable memory for DMA coherent allocator in mmap
buffer allocation if non-consistent DMA attribute is set and kernel
mapping is present. Even if userspace doesn't mmap the buffer, sync
still should be happening if kernel mapping is present.
If not done in allocation, it is enabled when memory is mapped from
userspace (if non-consistent DMA attribute is set).

Signed-off-by: Heng-Ruey Hsu 
Tested-by: Heng-ruey Hsu 
Reviewed-by: Tomasz Figa 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 0d9665d..89b534a 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   /*
+* Enable cache maintenance. Even if userspace doesn't mmap the buffer,
+* sync still should be happening if kernel mapping is present.
+*/
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -227,6 +239,10 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   /* Enable cache maintenance if not enabled in allocation. */
+   if (!buf->dma_sgt && buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v3 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

2016-10-26 Thread Thierry Escande
This patch moves vb2_dc_get_base_sgt() function above mmap buffers
callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it
will be called for cacheable MMAP support introduced in the next patch.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +-
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index a44e383..0d9665d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
return size;
 }
 
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+   int ret;
+   struct sg_table *sgt;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (!sgt) {
+   dev_err(buf->dev, "failed to alloc sg table\n");
+   return NULL;
+   }
+
+   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+   buf->size, buf->attrs);
+   if (ret < 0) {
+   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+   kfree(sgt);
+   return NULL;
+   }
+
+   return sgt;
+}
+
 /*/
 /* callbacks for all buffers */
 /*/
@@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
.release = vb2_dc_dmabuf_ops_release,
 };
 
-static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
-{
-   int ret;
-   struct sg_table *sgt;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (!sgt) {
-   dev_err(buf->dev, "failed to alloc sg table\n");
-   return NULL;
-   }
-
-   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
-   buf->size, buf->attrs);
-   if (ret < 0) {
-   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
-   kfree(sgt);
-   return NULL;
-   }
-
-   return sgt;
-}
-
 static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
struct vb2_dc_buf *buf = buf_priv;
-- 
2.7.4



[PATCH v3 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

2016-10-26 Thread Thierry Escande
This patch moves vb2_dc_get_base_sgt() function above mmap buffers
callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it
will be called for cacheable MMAP support introduced in the next patch.

Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +-
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index a44e383..0d9665d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
return size;
 }
 
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+   int ret;
+   struct sg_table *sgt;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (!sgt) {
+   dev_err(buf->dev, "failed to alloc sg table\n");
+   return NULL;
+   }
+
+   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+   buf->size, buf->attrs);
+   if (ret < 0) {
+   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+   kfree(sgt);
+   return NULL;
+   }
+
+   return sgt;
+}
+
 /*/
 /* callbacks for all buffers */
 /*/
@@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
.release = vb2_dc_dmabuf_ops_release,
 };
 
-static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
-{
-   int ret;
-   struct sg_table *sgt;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (!sgt) {
-   dev_err(buf->dev, "failed to alloc sg table\n");
-   return NULL;
-   }
-
-   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
-   buf->size, buf->attrs);
-   if (ret < 0) {
-   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
-   kfree(sgt);
-   return NULL;
-   }
-
-   return sgt;
-}
-
 static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
struct vb2_dc_buf *buf = buf_priv;
-- 
2.7.4



[PATCH v3 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2016-10-26 Thread Thierry Escande
Hi,

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.

Changes in v2:
- Put function move in a separate patch
- Added comments

Changes in v3:
- Remove redundant test on NO_KERNEL_MAPPING DMA attribute in mmap()

Heng-Ruey Hsu (1):
  [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
  [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

 drivers/media/v4l2-core/videobuf2-dma-contig.c | 60 --
 1 file changed, 38 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH v3 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2016-10-26 Thread Thierry Escande
Hi,

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.

Changes in v2:
- Put function move in a separate patch
- Added comments

Changes in v3:
- Remove redundant test on NO_KERNEL_MAPPING DMA attribute in mmap()

Heng-Ruey Hsu (1):
  [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
  [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

 drivers/media/v4l2-core/videobuf2-dma-contig.c | 60 --
 1 file changed, 38 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-25 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes in v2:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes in v3:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes in v4:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro

Changes in v5:
- Use is_output queue field in VB2_DMA_DIR() macro

 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 23 +++
 5 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;
 
offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_fail_pfnvec;
buf->vec = vec;
@@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->

[PATCH v5] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-25 Thread Thierry Escande
From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Signed-off-by: Thierry Escande 
---

Changes in v2:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes in v3:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes in v4:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro

Changes in v5:
- Use is_output queue field in VB2_DMA_DIR() macro

 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 23 +++
 5 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;
 
offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_fail_pfnvec;
buf->vec = vec;
@@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
while (--i >= 0) {
-   if (buf->dma_dir == DMA_FROM_DEVICE)
+   if (VB2_DMA_DIR_CAPTURE(

[PATCH v2 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2016-10-24 Thread Thierry Escande
Hi,

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.

Changes in v2:
- Put function move in a separate patch
- Added comments

Heng-Ruey Hsu (1):
  [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
  [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

 drivers/media/v4l2-core/videobuf2-dma-contig.c | 62 +-
 1 file changed, 40 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH v2 0/2] [media] videobuf2-dc: Add support for cacheable MMAP

2016-10-24 Thread Thierry Escande
Hi,

This series adds support for cacheable MMAP in DMA coherent allocator.

The first patch moves the vb2_dc_get_base_sgt() function above mmap
callbacks for calls introduced by the second patch. This avoids a
forward declaration.

Changes in v2:
- Put function move in a separate patch
- Added comments

Heng-Ruey Hsu (1):
  [media] videobuf2-dc: Support cacheable MMAP

Thierry Escande (1):
  [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

 drivers/media/v4l2-core/videobuf2-dma-contig.c | 62 +-
 1 file changed, 40 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH v2 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

2016-10-24 Thread Thierry Escande
This patch moves vb2_dc_get_base_sgt() function above mmap buffers
callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it
will be called for cacheable MMAP support introduced in the next patch.

Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +-
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index a44e383..0d9665d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
return size;
 }
 
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+   int ret;
+   struct sg_table *sgt;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (!sgt) {
+   dev_err(buf->dev, "failed to alloc sg table\n");
+   return NULL;
+   }
+
+   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+   buf->size, buf->attrs);
+   if (ret < 0) {
+   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+   kfree(sgt);
+   return NULL;
+   }
+
+   return sgt;
+}
+
 /*/
 /* callbacks for all buffers */
 /*/
@@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
.release = vb2_dc_dmabuf_ops_release,
 };
 
-static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
-{
-   int ret;
-   struct sg_table *sgt;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (!sgt) {
-   dev_err(buf->dev, "failed to alloc sg table\n");
-   return NULL;
-   }
-
-   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
-   buf->size, buf->attrs);
-   if (ret < 0) {
-   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
-   kfree(sgt);
-   return NULL;
-   }
-
-   return sgt;
-}
-
 static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
struct vb2_dc_buf *buf = buf_priv;
-- 
2.7.4



[PATCH v2 1/2] [media] videobuf2-dc: Move vb2_dc_get_base_sgt() above mmap callbacks

2016-10-24 Thread Thierry Escande
This patch moves vb2_dc_get_base_sgt() function above mmap buffers
callbacks, particularly vb2_dc_alloc() and vb2_dc_mmap() from where it
will be called for cacheable MMAP support introduced in the next patch.

Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 44 +-
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index a44e383..0d9665d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -61,6 +61,28 @@ static unsigned long vb2_dc_get_contiguous_size(struct 
sg_table *sgt)
return size;
 }
 
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
+{
+   int ret;
+   struct sg_table *sgt;
+
+   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+   if (!sgt) {
+   dev_err(buf->dev, "failed to alloc sg table\n");
+   return NULL;
+   }
+
+   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
+   buf->size, buf->attrs);
+   if (ret < 0) {
+   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
+   kfree(sgt);
+   return NULL;
+   }
+
+   return sgt;
+}
+
 /*/
 /* callbacks for all buffers */
 /*/
@@ -363,28 +385,6 @@ static struct dma_buf_ops vb2_dc_dmabuf_ops = {
.release = vb2_dc_dmabuf_ops_release,
 };
 
-static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
-{
-   int ret;
-   struct sg_table *sgt;
-
-   sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
-   if (!sgt) {
-   dev_err(buf->dev, "failed to alloc sg table\n");
-   return NULL;
-   }
-
-   ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
-   buf->size, buf->attrs);
-   if (ret < 0) {
-   dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
-   kfree(sgt);
-   return NULL;
-   }
-
-   return sgt;
-}
-
 static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
struct vb2_dc_buf *buf = buf_priv;
-- 
2.7.4



[PATCH v2 2/2] [media] videobuf2-dc: Support cacheable MMAP

2016-10-24 Thread Thierry Escande
From: Heng-Ruey Hsu <henry...@chromium.org>

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

This patch enables cacheable memory for DMA coherent allocator in mmap
buffer allocation if non-consistent DMA attribute is set and kernel
mapping is present. Even if userspace doesn't mmap the buffer, sync
still should be happening if kernel mapping is present.
If not done in allocation, it is enabled when memory is mapped from
userspace when no kernel mapping is present and non-consistent DMA
attribute set.

Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org>
Tested-by: Heng-ruey Hsu <henry...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 0d9665d..1f7649d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   /*
+* Enable cacheable memory. Even if userspace doesn't mmap the buffer,
+* sync still should be happening if kernel mapping is present.
+*/
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -227,6 +239,12 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   /* Enable cacheable memory if not enabled in allocation. */
+   if (!buf->dma_sgt &&
+   buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v2 2/2] [media] videobuf2-dc: Support cacheable MMAP

2016-10-24 Thread Thierry Escande
From: Heng-Ruey Hsu 

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

This patch enables cacheable memory for DMA coherent allocator in mmap
buffer allocation if non-consistent DMA attribute is set and kernel
mapping is present. Even if userspace doesn't mmap the buffer, sync
still should be happening if kernel mapping is present.
If not done in allocation, it is enabled when memory is mapped from
userspace when no kernel mapping is present and non-consistent DMA
attribute set.

Signed-off-by: Heng-Ruey Hsu 
Tested-by: Heng-ruey Hsu 
Reviewed-by: Tomasz Figa 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 0d9665d..1f7649d 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -151,6 +151,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -192,6 +196,14 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   /*
+* Enable cacheable memory. Even if userspace doesn't mmap the buffer,
+* sync still should be happening if kernel mapping is present.
+*/
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -227,6 +239,12 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   /* Enable cacheable memory if not enabled in allocation. */
+   if (!buf->dma_sgt &&
+   buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING &&
+   buf->attrs & DMA_ATTR_NON_CONSISTENT)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH v4] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-24 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes since v3:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro


 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 24 
 5 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;
 
offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_fail_pfnvec;
buf->vec = vec;
@@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
while (--i >= 0) {
-

[PATCH v4] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-24 Thread Thierry Escande
From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

This patch introduces 2 macros:
VB2_DMA_DIR(q) returns the corresponding dma_dir for the passed queue
type, tanking care of the capture_dma_birectional flag.

VB2_DMA_DIR_CAPTURE(d) is a test macro returning true if the passed DMA
direction refers to a capture buffer. This test is used to map virtual
addresses for writing and to mark pages as dirty.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Signed-off-by: Thierry Escande 
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes since v3:
- Fixed typos in include/media/videobuf2-core.h
- Added VB2_DMA_DIR_CAPTURE() test macro


 drivers/media/v4l2-core/videobuf2-core.c   |  9 +++--
 drivers/media/v4l2-core/videobuf2-dma-contig.c |  2 +-
 drivers/media/v4l2-core/videobuf2-dma-sg.c |  5 +++--
 drivers/media/v4l2-core/videobuf2-vmalloc.c|  4 ++--
 include/media/videobuf2-core.h | 24 
 5 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..a44e383 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->dma_dir = dma_dir;
 
offset = vaddr & ~PAGE_MASK;
-   vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size, VB2_DMA_DIR_CAPTURE(dma_dir));
if (IS_ERR(vec)) {
ret = PTR_ERR(vec);
goto fail_buf;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c 
b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index ecff8f49..51c98f6 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -238,7 +238,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, 
unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
buf->dma_sgt = >sg_table;
-   vec = vb2_create_framevec(vaddr, size, buf->dma_dir == DMA_FROM_DEVICE);
+   vec = vb2_create_framevec(vaddr, size,
+ VB2_DMA_DIR_CAPTURE(buf->dma_dir));
if (IS_ERR(vec))
goto userptr_fail_pfnvec;
buf->vec = vec;
@@ -291,7 +292,7 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
while (--i >= 0) {
-   if (buf->dma_dir == DMA_FROM_DEVICE)
+   if (VB2_DMA_DIR_CAPTURE(buf->dma_dir))
set_page_dirty_lock(bu

Re: [PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-21 Thread Thierry Escande

Hi Sakari,

On 21/10/2016 09:48, Sakari Ailus wrote:

Hi Thierry,

On Fri, Oct 21, 2016 at 09:25:05AM +0200, Thierry Escande wrote:

From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>



Please also check where dma_dir is being used especially in memory type
implementation. There are several comparisons to DMA_FROM_DEVICE which will
have a different result if DMA_BIDIRECTIONAL is used instead.

Nice catch, thanks.

How about a macro like this:

#define VB2_DMA_DIR_CAPTURE(d) \
((d) == DMA_FROM_DEVICE || (d) == DMA_BIDIRECTIONAL)

Regards,
 Thierry



Re: [PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-21 Thread Thierry Escande

Hi Sakari,

On 21/10/2016 09:48, Sakari Ailus wrote:

Hi Thierry,

On Fri, Oct 21, 2016 at 09:25:05AM +0200, Thierry Escande wrote:

From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Signed-off-by: Thierry Escande 



Please also check where dma_dir is being used especially in memory type
implementation. There are several comparisons to DMA_FROM_DEVICE which will
have a different result if DMA_BIDIRECTIONAL is used instead.

Nice catch, thanks.

How about a macro like this:

#define VB2_DMA_DIR_CAPTURE(d) \
((d) == DMA_FROM_DEVICE || (d) == DMA_BIDIRECTIONAL)

Regards,
 Thierry



[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-21 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes since v3:
- Fixed typos in include/media/videobuf2-core.h

 drivers/media/v4l2-core/videobuf2-core.c |  9 +++--
 include/media/videobuf2-core.h   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..a6cfdfb 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -499,6 +502,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -554,6 +558,17 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Returns the corresponding DMA direction given the vb2_queue type (capture or
+ * output). Returns DMA_BIDIRECTIONAL for capture buffers if the vb2_queue 
field
+ * capture_dma_bidirectional is set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-21 Thread Thierry Escande
From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Signed-off-by: Thierry Escande 
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

Changes since v3:
- Fixed typos in include/media/videobuf2-core.h

 drivers/media/v4l2-core/videobuf2-core.c |  9 +++--
 include/media/videobuf2-core.h   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..a6cfdfb 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -499,6 +502,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -554,6 +558,17 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Returns the corresponding DMA direction given the vb2_queue type (capture or
+ * output). Returns DMA_BIDIRECTIONAL for capture buffers if the vb2_queue 
field
+ * capture_dma_bidirectional is set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-20 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

 drivers/media/v4l2-core/videobuf2-core.c |  9 +++--
 include/media/videobuf2-core.h   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..631f08b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -499,6 +502,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -554,6 +558,17 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Return the corresponding DMA direction given the vb2_queue type (capture or
+ * output). returns DMA_BIRECTIONAL for capture buffers if the vb2_queue field
+ * capture_dma_bidirectional is set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH v3] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-20 Thread Thierry Escande
From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Signed-off-by: Thierry Escande 
---

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Changes since v2:
- Get rid of dma_dir field and therefore squashed the previous patch

 drivers/media/v4l2-core/videobuf2-core.c |  9 +++--
 include/media/videobuf2-core.h   | 15 +++
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..22d6105 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -978,8 +977,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1096,8 +1094,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   enum dma_data_direction dma_dir = VB2_DMA_DIR(q);
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..631f08b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -499,6 +502,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -554,6 +558,17 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Return the corresponding DMA direction given the vb2_queue type (capture or
+ * output). returns DMA_BIRECTIONAL for capture buffers if the vb2_queue field
+ * capture_dma_bidirectional is set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



Re: [PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-20 Thread Thierry Escande

Hi Sakari,

On 19/10/2016 23:29, Sakari Ailus wrote:

Hi Thierry,

On Wed, Oct 19, 2016 at 10:24:16AM +0200, Thierry Escande wrote:

From: Pawel Osciak <posc...@chromium.org>

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Owen Lin <owen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)

mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);


My bad, I guess I expressed myself unclearly.

Could you introduce the macro in this patch? You can then remove q->dma_dir
altogether.

My bad. Sorry for the confusion...

The v3 is on its way.

Regards,
 Thierry



Re: [PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-20 Thread Thierry Escande

Hi Sakari,

On 19/10/2016 23:29, Sakari Ailus wrote:

Hi Thierry,

On Wed, Oct 19, 2016 at 10:24:16AM +0200, Thierry Escande wrote:

From: Pawel Osciak 

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Reviewed-by: Tomasz Figa 
Reviewed-by: Owen Lin 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)

mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);


My bad, I guess I expressed myself unclearly.

Could you introduce the macro in this patch? You can then remove q->dma_dir
altogether.

My bad. Sorry for the confusion...

The v3 is on its way.

Regards,
 Thierry



[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-19 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Owen Lin <owen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef883..fde1e2d 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
+   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
+  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..38410dd 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -489,6 +489,7 @@ struct vb2_buf_ops {
  * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
  * @fileio:file io emulator internal data, used only if emulator is active
  * @threadio:  thread io internal data, used only if thread is active
+ * @dma_dir:   DMA direction to use for buffers on this queue
  */
 struct vb2_queue {
unsigned inttype;
@@ -540,6 +541,7 @@ struct vb2_queue {
 
struct vb2_fileio_data  *fileio;
struct vb2_threadio_data*threadio;
+   enum dma_data_direction dma_dir;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
/*
-- 
2.7.4



[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-19 Thread Thierry Escande
From: Pawel Osciak 

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Reviewed-by: Tomasz Figa 
Reviewed-by: Owen Lin 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef883..fde1e2d 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
+   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
+  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..38410dd 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -489,6 +489,7 @@ struct vb2_buf_ops {
  * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
  * @fileio:file io emulator internal data, used only if emulator is active
  * @threadio:  thread io internal data, used only if thread is active
+ * @dma_dir:   DMA direction to use for buffers on this queue
  */
 struct vb2_queue {
unsigned inttype;
@@ -540,6 +541,7 @@ struct vb2_queue {
 
struct vb2_fileio_data  *fileio;
struct vb2_threadio_data*threadio;
+   enum dma_data_direction dma_dir;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
/*
-- 
2.7.4



[PATCH 2/2] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-19 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-v4l2.c |  3 +--
 include/media/videobuf2-core.h   | 14 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..c92197c 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,7 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   q->dma_dir = VB2_DMA_DIR(q);
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..cd55917 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -556,6 +560,16 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Return the corresponding DMA direction given the vb2_queue type (capture or
+ * output). returns DMA_BIRECTIONAL for capture buffers if set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH 2/2] [media] vb2: Add support for capture_dma_bidirectional queue flag

2016-10-19 Thread Thierry Escande
From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Reviewed-by: Tomasz Figa 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-v4l2.c |  3 +--
 include/media/videobuf2-core.h   | 14 ++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..c92197c 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,7 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+   q->dma_dir = VB2_DMA_DIR(q);
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..cd55917 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @capture_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues.
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsignedcapture_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
@@ -556,6 +560,16 @@ struct vb2_queue {
 #endif
 };
 
+/*
+ * Return the corresponding DMA direction given the vb2_queue type (capture or
+ * output). returns DMA_BIRECTIONAL for capture buffers if set by the driver.
+ */
+#define VB2_DMA_DIR(q) (V4L2_TYPE_IS_OUTPUT((q)->type)   \
+   ? DMA_TO_DEVICE  \
+   : (q)->capture_dma_bidirectional \
+ ? DMA_BIDIRECTIONAL\
+ : DMA_FROM_DEVICE)
+
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
  * @vb:vb2_buffer to which the plane in question belongs to
-- 
2.7.4



[PATCH 0/2] [media] DMA direction support in vb2_queue

2016-10-19 Thread Thierry Escande
Hi,

This series adds a dma_dir field to the vb2_queue structure in order to
store the DMA direction once for all in vb2_queue_init();

It also adds a new capture_dma_bidirectional flag to the vb2_queue
structure allowing the hardware to read from the CAPTURE buffer. This
flag is ignored for OUTPUT queues. This is used on ChromeOS by the
rockchip-vpu driver.

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Pawel Osciak (2):
  [media] vb2: Store dma_dir in vb2_queue
  [media] vb2: Add support for capture_dma_bidirectional queue flag

 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h   |  6 ++
 3 files changed, 15 insertions(+), 9 deletions(-)

-- 
2.7.4



[PATCH 0/2] [media] DMA direction support in vb2_queue

2016-10-19 Thread Thierry Escande
Hi,

This series adds a dma_dir field to the vb2_queue structure in order to
store the DMA direction once for all in vb2_queue_init();

It also adds a new capture_dma_bidirectional flag to the vb2_queue
structure allowing the hardware to read from the CAPTURE buffer. This
flag is ignored for OUTPUT queues. This is used on ChromeOS by the
rockchip-vpu driver.

Changes since v1:
- Renamed use_dma_bidirectional field as capture_dma_bidirectional
- Added a VB2_DMA_DIR() macro

Pawel Osciak (2):
  [media] vb2: Store dma_dir in vb2_queue
  [media] vb2: Add support for capture_dma_bidirectional queue flag

 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h   |  6 ++
 3 files changed, 15 insertions(+), 9 deletions(-)

-- 
2.7.4



Re: [PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag

2016-10-18 Thread Thierry Escande

Hi Sakari,

On 17/10/2016 12:06, Sakari Ailus wrote:

Hi Thierry,

Thanks for the set. A few comments below.

On Fri, Oct 14, 2016 at 02:08:14PM +0200, Thierry Escande wrote:

From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.


Just out of curiosity --- when do you return these buffers back to the user?
Once they're no longer needed as reference frames?
Tbh, I don't now. This is used by a rockchip vpu driver not yet 
upstreamed in the chromeos v4.4 kernel tree. Pawel might answer this 
question I guess.






This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++--
 include/media/videobuf2-core.h   | 4 
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..9255291 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+   if (V4L2_TYPE_IS_OUTPUT(q->type))
+   q->dma_dir = DMA_TO_DEVICE;
+   else
+   q->dma_dir = q->use_dma_bidirectional
+  ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;

return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..e613c74 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduse_dma_bidirectional:1;


This field is in the same struct as dma_dir which it directly affects.

How about adding a macro instead to give you the queue DMA direction
instead?

E.g.

#define vb2_dma_dir(q) \
(V4L2_TYPE_IS_OUTPUT((q)->type) ? DMA_TO_DEVICE : \
 (q)->use_dma_bidirectional ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE)

I would call this capture_dma_bidirectional as it only affects capture. Or
simply choose DMA_BIDIRECTIONAL whenever the flag is set.

Sure. Will do.

Regards,
 Thierry


Re: [PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag

2016-10-18 Thread Thierry Escande

Hi Sakari,

On 17/10/2016 12:06, Sakari Ailus wrote:

Hi Thierry,

Thanks for the set. A few comments below.

On Fri, Oct 14, 2016 at 02:08:14PM +0200, Thierry Escande wrote:

From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.


Just out of curiosity --- when do you return these buffers back to the user?
Once they're no longer needed as reference frames?
Tbh, I don't now. This is used by a rockchip vpu driver not yet 
upstreamed in the chromeos v4.4 kernel tree. Pawel might answer this 
question I guess.






This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Reviewed-by: Tomasz Figa 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++--
 include/media/videobuf2-core.h   | 4 
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..9255291 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+   if (V4L2_TYPE_IS_OUTPUT(q->type))
+   q->dma_dir = DMA_TO_DEVICE;
+   else
+   q->dma_dir = q->use_dma_bidirectional
+  ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;

return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..e613c74 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduse_dma_bidirectional:1;


This field is in the same struct as dma_dir which it directly affects.

How about adding a macro instead to give you the queue DMA direction
instead?

E.g.

#define vb2_dma_dir(q) \
(V4L2_TYPE_IS_OUTPUT((q)->type) ? DMA_TO_DEVICE : \
 (q)->use_dma_bidirectional ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE)

I would call this capture_dma_bidirectional as it only affects capture. Or
simply choose DMA_BIDIRECTIONAL whenever the flag is set.

Sure. Will do.

Regards,
 Thierry


[PATCH] [media] videobuf2-dma-contig: Support cacheable MMAP

2016-10-14 Thread Thierry Escande
From: Heng-Ruey Hsu <henry...@chromium.org>

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

Signed-off-by: Heng-Ruey Hsu <henry...@chromium.org>
Tested-by: Heng-ruey Hsu <henry...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..c953c24 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -42,6 +42,12 @@ struct vb2_dc_buf {
 };
 
 /*/
+/*   Forward declarations*/
+/*/
+
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf);
+
+/*/
 /*scatterlist table functions*/
 /*/
 
@@ -129,6 +135,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -170,6 +180,10 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+(buf->attrs & DMA_ATTR_NON_CONSISTENT))
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -205,6 +219,11 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   (buf->attrs & DMA_ATTR_NON_CONSISTENT) &&
+   !buf->dma_sgt)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH] [media] videobuf2-dma-contig: Support cacheable MMAP

2016-10-14 Thread Thierry Escande
From: Heng-Ruey Hsu 

DMA allocations for MMAP type are uncached by default. But for
some cases, CPU has to access the buffers. ie: memcpy for format
converter. Supporting cacheable MMAP improves huge performance.

Signed-off-by: Heng-Ruey Hsu 
Tested-by: Heng-ruey Hsu 
Reviewed-by: Tomasz Figa 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-dma-contig.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c 
b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fb6a177..c953c24 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -42,6 +42,12 @@ struct vb2_dc_buf {
 };
 
 /*/
+/*   Forward declarations*/
+/*/
+
+static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf);
+
+/*/
 /*scatterlist table functions*/
 /*/
 
@@ -129,6 +135,10 @@ static void vb2_dc_put(void *buf_priv)
sg_free_table(buf->sgt_base);
kfree(buf->sgt_base);
}
+   if (buf->dma_sgt) {
+   sg_free_table(buf->dma_sgt);
+   kfree(buf->dma_sgt);
+   }
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
   buf->attrs);
put_device(buf->dev);
@@ -170,6 +180,10 @@ static void *vb2_dc_alloc(struct device *dev, unsigned 
long attrs,
buf->handler.put = vb2_dc_put;
buf->handler.arg = buf;
 
+   if (!(buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+(buf->attrs & DMA_ATTR_NON_CONSISTENT))
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
atomic_inc(>refcount);
 
return buf;
@@ -205,6 +219,11 @@ static int vb2_dc_mmap(void *buf_priv, struct 
vm_area_struct *vma)
 
vma->vm_ops->open(vma);
 
+   if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) &&
+   (buf->attrs & DMA_ATTR_NON_CONSISTENT) &&
+   !buf->dma_sgt)
+   buf->dma_sgt = vb2_dc_get_base_sgt(buf);
+
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
-- 
2.7.4



[PATCH 0/2] [media] DMA direction support in vb2_queue

2016-10-14 Thread Thierry Escande
Hi,

This series adds a dma_dir field to the vb2_queue structure in order to
store the DMA direction once for all in vb2_queue_init();

It also adds a new use_dma_bidirectional flag to the vb2_queue structure
allowing the hardware to read from the CAPTURE buffer. This flag is
ignored for OUTPUT queues. This is used on ChromeOS by the rockchip-vpu
driver.

Pawel Osciak (2):
  [media] vb2: Store dma_dir in vb2_queue
  [media] vb2: Add support for use_dma_bidirectional queue flag

 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h   |  6 ++
 3 files changed, 15 insertions(+), 9 deletions(-)

-- 
2.7.4



[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-14 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Reviewed-by: Owen Lin <owen...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef883..fde1e2d 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
+   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
+  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..38410dd 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -489,6 +489,7 @@ struct vb2_buf_ops {
  * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
  * @fileio:file io emulator internal data, used only if emulator is active
  * @threadio:  thread io internal data, used only if thread is active
+ * @dma_dir:   DMA direction to use for buffers on this queue
  */
 struct vb2_queue {
unsigned inttype;
@@ -540,6 +541,7 @@ struct vb2_queue {
 
struct vb2_fileio_data  *fileio;
struct vb2_threadio_data*threadio;
+   enum dma_data_direction dma_dir;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
/*
-- 
2.7.4



[PATCH 0/2] [media] DMA direction support in vb2_queue

2016-10-14 Thread Thierry Escande
Hi,

This series adds a dma_dir field to the vb2_queue structure in order to
store the DMA direction once for all in vb2_queue_init();

It also adds a new use_dma_bidirectional flag to the vb2_queue structure
allowing the hardware to read from the CAPTURE buffer. This flag is
ignored for OUTPUT queues. This is used on ChromeOS by the rockchip-vpu
driver.

Pawel Osciak (2):
  [media] vb2: Store dma_dir in vb2_queue
  [media] vb2: Add support for use_dma_bidirectional queue flag

 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  6 ++
 include/media/videobuf2-core.h   |  6 ++
 3 files changed, 15 insertions(+), 9 deletions(-)

-- 
2.7.4



[PATCH 1/2] [media] vb2: Store dma_dir in vb2_queue

2016-10-14 Thread Thierry Escande
From: Pawel Osciak 

Store dma_dir in struct vb2_queue and reuse it, instead of recalculating
it each time.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Reviewed-by: Tomasz Figa 
Reviewed-by: Owen Lin 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-core.c | 12 +++-
 drivers/media/v4l2-core/videobuf2-v4l2.c |  2 ++
 include/media/videobuf2-core.h   |  2 ++
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c 
b/drivers/media/v4l2-core/videobuf2-core.c
index 21900202..f12103c 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -194,8 +194,6 @@ static void __enqueue_in_driver(struct vb2_buffer *vb);
 static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
int ret = -ENOMEM;
@@ -209,7 +207,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 
mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev,
-   q->dma_attrs, size, dma_dir, q->gfp_flags);
+   q->dma_attrs, size, q->dma_dir, q->gfp_flags);
if (IS_ERR(mem_priv)) {
if (mem_priv)
ret = PTR_ERR(mem_priv);
@@ -978,8 +976,6 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const void 
*pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1030,7 +1026,7 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const 
void *pb)
mem_priv = call_ptr_memop(vb, get_userptr,
q->alloc_devs[plane] ? : q->dev,
planes[plane].m.userptr,
-   planes[plane].length, dma_dir);
+   planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1096,8 +1092,6 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
void *mem_priv;
unsigned int plane;
int ret = 0;
-   enum dma_data_direction dma_dir =
-   q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
bool reacquired = vb->planes[0].mem_priv == NULL;
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1156,7 +1150,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const 
void *pb)
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf,
q->alloc_devs[plane] ? : q->dev,
-   dbuf, planes[plane].length, dma_dir);
+   dbuf, planes[plane].length, q->dma_dir);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef883..fde1e2d 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,6 +659,8 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
+   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
+  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index ac5898a..38410dd 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -489,6 +489,7 @@ struct vb2_buf_ops {
  * when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
  * @fileio:file io emulator internal data, used only if emulator is active
  * @threadio:  thread io internal data, used only if thread is active
+ * @dma_dir:   DMA direction to use for buffers on this queue
  */
 struct vb2_queue {
unsigned inttype;
@@ -540,6 +541,7 @@ struct vb2_queue {
 
struct vb2_fileio_data  *fileio;
struct vb2_threadio_data*threadio;
+   enum dma_data_direction dma_dir;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
/*
-- 
2.7.4



[PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag

2016-10-14 Thread Thierry Escande
From: Pawel Osciak <posc...@chromium.org>

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak <posc...@chromium.org>
Tested-by: Pawel Osciak <posc...@chromium.org>
Reviewed-by: Tomasz Figa <tf...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++--
 include/media/videobuf2-core.h   | 4 
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..9255291 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+   if (V4L2_TYPE_IS_OUTPUT(q->type))
+   q->dma_dir = DMA_TO_DEVICE;
+   else
+   q->dma_dir = q->use_dma_bidirectional
+  ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..e613c74 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduse_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
-- 
2.7.4



[PATCH 2/2] [media] vb2: Add support for use_dma_bidirectional queue flag

2016-10-14 Thread Thierry Escande
From: Pawel Osciak 

When this flag is set for CAPTURE queues by the driver on calling
vb2_queue_init(), it forces the buffers on the queue to be
allocated/mapped with DMA_BIDIRECTIONAL direction flag, instead of
DMA_FROM_DEVICE. This allows the device not only to write to the
buffers, but also read out from them. This may be useful e.g. for codec
hardware, which may be using CAPTURE buffers as reference to decode
other buffers.

This flag is ignored for OUTPUT queues, as we don't want to allow HW to
be able to write to OUTPUT buffers.

Signed-off-by: Pawel Osciak 
Tested-by: Pawel Osciak 
Reviewed-by: Tomasz Figa 
Signed-off-by: Thierry Escande 
---
 drivers/media/v4l2-core/videobuf2-v4l2.c | 8 ++--
 include/media/videobuf2-core.h   | 4 
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c 
b/drivers/media/v4l2-core/videobuf2-v4l2.c
index fde1e2d..9255291 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -659,8 +659,12 @@ int vb2_queue_init(struct vb2_queue *q)
 * queues will always initialize waiting_for_buffers to false.
 */
q->quirk_poll_must_check_waiting_for_buffers = true;
-   q->dma_dir = V4L2_TYPE_IS_OUTPUT(q->type)
-  ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+   if (V4L2_TYPE_IS_OUTPUT(q->type))
+   q->dma_dir = DMA_TO_DEVICE;
+   else
+   q->dma_dir = q->use_dma_bidirectional
+  ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
 
return vb2_core_queue_init(q);
 }
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 38410dd..e613c74 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -433,6 +433,9 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return POLLERR at poll when QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @use_dma_bidirectional: use DMA_BIDIRECTIONAL for CAPTURE buffers; this
+ * allows HW to read from the CAPTURE buffers in
+ * addition to writing; ignored for OUTPUT queues
  * @lock:  pointer to a mutex that protects the vb2_queue struct. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -500,6 +503,7 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduse_dma_bidirectional:1;
 
struct mutex*lock;
void*owner;
-- 
2.7.4



[PATCH] driver-core: add test module for asynchronous probing

2016-09-29 Thread Thierry Escande
From: Dmitry Torokhov <d...@chromium.org>

This test module tries to test asynchronous driver probing by having a
driver that sleeps for an extended period of time (5 secs) in its
probe() method. It measures the time needed to register this driver
(with device already registered) and a new device (with driver already
registered). The module will fail to load if the time spent in register
call is more than half the probing sleep time.

As a sanity check the driver will then try to synchronously register
driver and device and fail if registration takes less than half of the
probing sleep time.

Signed-off-by: Dmitry Torokhov <d...@chromium.org>
Reviewed-by: Olof Johansson <ol...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/base/Kconfig|   2 +
 drivers/base/Makefile   |   2 +
 drivers/base/test/Kconfig   |   9 ++
 drivers/base/test/Makefile  |   1 +
 drivers/base/test/test_async_driver_probe.c | 171 
 5 files changed, 185 insertions(+)
 create mode 100644 drivers/base/test/Kconfig
 create mode 100644 drivers/base/test/Makefile
 create mode 100644 drivers/base/test/test_async_driver_probe.c

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 98504ec..b31fba2 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -212,6 +212,8 @@ config DEBUG_DEVRES
 
  If you are unsure about this, Say N here.
 
+source "drivers/base/test/Kconfig"
+
 config SYS_HYPERVISOR
bool
default n
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 2609ba2..f2816f6 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -24,5 +24,7 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o
 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
 obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
 
+obj-y  += test/
+
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff --git a/drivers/base/test/Kconfig b/drivers/base/test/Kconfig
new file mode 100644
index 000..9aa0d45
--- /dev/null
+++ b/drivers/base/test/Kconfig
@@ -0,0 +1,9 @@
+config TEST_ASYNC_DRIVER_PROBE
+   tristate "Build kernel module to test asynchronous driver probing"
+   depends on m
+   help
+ Enabling this option produces a kernel module that allows
+ testing asynchronous driver probing by the device core.
+ The module name will be test_async_driver_probe.ko
+
+ If unsure say N.
diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile
new file mode 100644
index 000..90477c5
--- /dev/null
+++ b/drivers/base/test/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE)  += test_async_driver_probe.o
diff --git a/drivers/base/test/test_async_driver_probe.c 
b/drivers/base/test/test_async_driver_probe.c
new file mode 100644
index 000..3a71e83
--- /dev/null
+++ b/drivers/base/test/test_async_driver_probe.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TEST_PROBE_DELAY   (5 * 1000)  /* 5 sec */
+#define TEST_PROBE_THRESHOLD   (TEST_PROBE_DELAY / 2)
+
+static int test_probe(struct platform_device *pdev)
+{
+   dev_info(>dev, "sleeping for %d msecs in probe\n",
+TEST_PROBE_DELAY);
+   msleep(TEST_PROBE_DELAY);
+   dev_info(>dev, "done sleeping\n");
+
+   return 0;
+}
+
+static struct platform_driver async_driver = {
+   .driver = {
+   .name = "test_async_driver",
+   .owner = THIS_MODULE,
+   .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+   },
+   .probe = test_probe,
+};
+
+static struct platform_driver sync_driver = {
+   .driver = {
+   .name = "test_sync_driver",
+   .owner = THIS_MODULE,
+   .probe_type = PROBE_FORCE_SYNCHRONOUS,
+   },
+   .probe = test_probe,
+};
+
+static struct platform_device *async_dev_1, *async_dev_2;
+static struct platform_device *sync_dev_1;
+
+static int __init test_async_probe_init(void)
+{
+   ktime_t calltime, delta;
+   unsigned long long duration;
+   int error;
+
+   pr_info("registering first asynchronous device...\n");
+
+   async_dev_1 = platform_device_register_simple(&q

[PATCH] driver-core: add test module for asynchronous probing

2016-09-29 Thread Thierry Escande
From: Dmitry Torokhov 

This test module tries to test asynchronous driver probing by having a
driver that sleeps for an extended period of time (5 secs) in its
probe() method. It measures the time needed to register this driver
(with device already registered) and a new device (with driver already
registered). The module will fail to load if the time spent in register
call is more than half the probing sleep time.

As a sanity check the driver will then try to synchronously register
driver and device and fail if registration takes less than half of the
probing sleep time.

Signed-off-by: Dmitry Torokhov 
Reviewed-by: Olof Johansson 
Signed-off-by: Guenter Roeck 
Signed-off-by: Thierry Escande 
---
 drivers/base/Kconfig|   2 +
 drivers/base/Makefile   |   2 +
 drivers/base/test/Kconfig   |   9 ++
 drivers/base/test/Makefile  |   1 +
 drivers/base/test/test_async_driver_probe.c | 171 
 5 files changed, 185 insertions(+)
 create mode 100644 drivers/base/test/Kconfig
 create mode 100644 drivers/base/test/Makefile
 create mode 100644 drivers/base/test/test_async_driver_probe.c

diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 98504ec..b31fba2 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -212,6 +212,8 @@ config DEBUG_DEVRES
 
  If you are unsure about this, Say N here.
 
+source "drivers/base/test/Kconfig"
+
 config SYS_HYPERVISOR
bool
default n
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 2609ba2..f2816f6 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -24,5 +24,7 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o
 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
 obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
 
+obj-y  += test/
+
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff --git a/drivers/base/test/Kconfig b/drivers/base/test/Kconfig
new file mode 100644
index 000..9aa0d45
--- /dev/null
+++ b/drivers/base/test/Kconfig
@@ -0,0 +1,9 @@
+config TEST_ASYNC_DRIVER_PROBE
+   tristate "Build kernel module to test asynchronous driver probing"
+   depends on m
+   help
+ Enabling this option produces a kernel module that allows
+ testing asynchronous driver probing by the device core.
+ The module name will be test_async_driver_probe.ko
+
+ If unsure say N.
diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile
new file mode 100644
index 000..90477c5
--- /dev/null
+++ b/drivers/base/test/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE)  += test_async_driver_probe.o
diff --git a/drivers/base/test/test_async_driver_probe.c 
b/drivers/base/test/test_async_driver_probe.c
new file mode 100644
index 000..3a71e83
--- /dev/null
+++ b/drivers/base/test/test_async_driver_probe.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TEST_PROBE_DELAY   (5 * 1000)  /* 5 sec */
+#define TEST_PROBE_THRESHOLD   (TEST_PROBE_DELAY / 2)
+
+static int test_probe(struct platform_device *pdev)
+{
+   dev_info(>dev, "sleeping for %d msecs in probe\n",
+TEST_PROBE_DELAY);
+   msleep(TEST_PROBE_DELAY);
+   dev_info(>dev, "done sleeping\n");
+
+   return 0;
+}
+
+static struct platform_driver async_driver = {
+   .driver = {
+   .name = "test_async_driver",
+   .owner = THIS_MODULE,
+   .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+   },
+   .probe = test_probe,
+};
+
+static struct platform_driver sync_driver = {
+   .driver = {
+   .name = "test_sync_driver",
+   .owner = THIS_MODULE,
+   .probe_type = PROBE_FORCE_SYNCHRONOUS,
+   },
+   .probe = test_probe,
+};
+
+static struct platform_device *async_dev_1, *async_dev_2;
+static struct platform_device *sync_dev_1;
+
+static int __init test_async_probe_init(void)
+{
+   ktime_t calltime, delta;
+   unsigned long long duration;
+   int error;
+
+   pr_info("registering first asynchronous device...\n");
+
+   async_dev_1 = platform_device_register_simple("test_async_driver", 1,
+ NULL, 0);
+   if (IS_ERR(async_dev_1)) {
+ 

[PATCH 0/2] platform/chrome: Add support for mec1322 EC

2016-09-07 Thread Thierry Escande
Hi,

This serie adds support for the LPC Microchip Embedded Controller 1322.

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  92 +--
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 487 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.7.4



[PATCH 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-09-07 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <gro...@chromium.org>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#in

[PATCH 0/2] platform/chrome: Add support for mec1322 EC

2016-09-07 Thread Thierry Escande
Hi,

This serie adds support for the LPC Microchip Embedded Controller 1322.

Shawn Nematbakhsh (2):
  platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants
  platform/chrome: cros_ec_lpc: Add support for mec1322 EC

 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   4 +-
 drivers/platform/chrome/cros_ec_lpc.c |  92 +--
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c | 133 +++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  61 +
 7 files changed, 487 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

-- 
2.7.4



[PATCH 2/2] platform/chrome: cros_ec_lpc: Add support for mec1322 EC

2016-09-07 Thread Thierry Escande
From: Shawn Nematbakhsh 

This adds support for the ChromeOS LPC Microchip Embedded Controller
(mec1322) variant.

mec1322 accesses I/O region [800h, 9ffh] through embedded memory
interface (EMI) rather than LPC.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Gwendal Grignou 
Signed-off-by: Guenter Roeck 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Kconfig   |   9 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_lpc.c |   5 ++
 drivers/platform/chrome/cros_ec_lpc_mec.c | 144 ++
 drivers/platform/chrome/cros_ec_lpc_reg.c |  69 ++
 include/linux/mfd/cros_ec_lpc_mec.h   |  93 +++
 include/linux/mfd/cros_ec_lpc_reg.h   |  14 +++
 7 files changed, 335 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_mec.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_mec.h

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 76bdae1..55149f2 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_LPC
   To compile this driver as a module, choose M here: the
   module will be called cros_ec_lpc.
 
+config CROS_EC_LPC_MEC
+   bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
+   depends on CROS_EC_LPC
+   default n
+   help
+ If you say Y here, a variant LPC protocol for the Microchip EC
+ will be used. Note that this variant is not backward compatible
+ with non-Microchip ECs.
+
 config CROS_EC_PROTO
 bool
 help
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 127fbe8..b8f7a3b 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -5,6 +5,7 @@ cros_ec_devs-objs   := cros_ec_dev.o 
cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 617074e..264234b 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -349,10 +349,13 @@ static int __init cros_ec_lpc_init(void)
return -ENODEV;
}
 
+   cros_ec_lpc_reg_init();
+
/* Register the driver */
ret = platform_driver_register(_ec_lpc_driver);
if (ret) {
pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -361,6 +364,7 @@ static int __init cros_ec_lpc_init(void)
if (ret) {
pr_err(DRV_NAME ": can't register device: %d\n", ret);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
return ret;
}
 
@@ -371,6 +375,7 @@ static void __exit cros_ec_lpc_exit(void)
 {
platform_device_unregister(_ec_lpc_device);
platform_driver_unregister(_ec_lpc_driver);
+   cros_ec_lpc_reg_destroy();
 }
 
 module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c 
b/drivers/platform/chrome/cros_ec_lpc_mec.c
new file mode 100644
index 000..09e2e21
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_lpc_mec.c
@@ -0,0 +1,144 @@
+/*
+ * cros_ec_lpc_mec - LPC variant I/O for Microchip EC
+ *
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This mutex must be held while accessing the EMI unit. We can't rely on the
+ * EC

[PATCH 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-09-07 Thread Thierry Escande
From: Shawn Nematbakhsh <sha...@chromium.org>

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh <sha...@chromium.org>
Signed-off-by: Gwendal Grignou <gwen...@chromium.org>
Signed-off-by: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Thierry Escande <thierry.esca...@collabora.com>
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 87 ++-
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 +++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 152 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpc.o
+cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..617074e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
unsigned long one_second = jiffies + HZ;
+   u8 data;
 
usleep_range(200, 300);
do {
-   if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+   if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, ) &
+   EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
struct ec_host_request *request;
struct ec_host_response response;
-   u8 sum = 0;
-   int i;
+   u8 sum;
int ret = 0;
u8 *dout;
 
ret = cros_ec_prepare_tx(ec, msg);
 
/* Write buffer */
-   for (i = 0; i < ret; i++)
-   outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
request = (struct ec_host_request *)ec->dout;
 
/* Here we go */
-   outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+   sum = EC_COMMAND_PROTOCOL_3;
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, );
 
if (ec_response_timed_out()) {
dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Check result */
-   msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+   msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   for (i = 0; i < sizeof(response); i++) {
-   dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-   sum += dout[i];
-   }
+   sum = cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET, sizeof(response), dout);
 
msg->result = response.result;
 
@@ -97,11 +97,10 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Read response and process checksum */
-   for (i = 0; i < response.data_len; i++) {
-   msg->data[i] =
-   inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-   sum += msg->data[i];
-   }
+   sum += cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET + sizeof(response),
+   response.data_len,
+   msg->data);
 
if (sum) {
dev_err(ec->dev,
@@ -121,8 +120,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
struct cros_ec_command *msg)
 {
struct ec_lpc_host_args args;
-   int csum;
-   int i;
+   u8 sum;
int ret = 0;
 
if (msg->outs

[PATCH 1/2] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants

2016-09-07 Thread Thierry Escande
From: Shawn Nematbakhsh 

Call common functions for read / write to prepare support for future
LPC protocol variants which use different I/O ops than inb / outb.

Signed-off-by: Shawn Nematbakhsh 
Signed-off-by: Gwendal Grignou 
Signed-off-by: Guenter Roeck 
Signed-off-by: Thierry Escande 
---
 drivers/platform/chrome/Makefile  |  3 +-
 drivers/platform/chrome/cros_ec_lpc.c | 87 ++-
 drivers/platform/chrome/cros_ec_lpc_reg.c | 64 +++
 include/linux/mfd/cros_ec_lpc_reg.h   | 47 +
 4 files changed, 152 insertions(+), 49 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c
 create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 4f34627..127fbe8 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_PSTORE)   += chromeos_pstore.o
 cros_ec_devs-objs  := cros_ec_dev.o cros_ec_sysfs.o \
   cros_ec_lightbar.o cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_devs.o
-obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpc.o
+cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
+obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
 obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index f9a2454..617074e 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -26,19 +26,22 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
-#define DRV_NAME "cros_ec_lpc"
+#define DRV_NAME "cros_ec_lpcs"
 
 static int ec_response_timed_out(void)
 {
unsigned long one_second = jiffies + HZ;
+   u8 data;
 
usleep_range(200, 300);
do {
-   if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+   if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, ) &
+   EC_LPC_STATUS_BUSY_MASK))
return 0;
usleep_range(100, 200);
} while (time_before(jiffies, one_second));
@@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
 {
struct ec_host_request *request;
struct ec_host_response response;
-   u8 sum = 0;
-   int i;
+   u8 sum;
int ret = 0;
u8 *dout;
 
ret = cros_ec_prepare_tx(ec, msg);
 
/* Write buffer */
-   for (i = 0; i < ret; i++)
-   outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i);
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
 
request = (struct ec_host_request *)ec->dout;
 
/* Here we go */
-   outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
+   sum = EC_COMMAND_PROTOCOL_3;
+   cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, );
 
if (ec_response_timed_out()) {
dev_warn(ec->dev, "EC responsed timed out\n");
@@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Check result */
-   msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+   msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, );
ret = cros_ec_check_result(ec, msg);
if (ret)
goto done;
 
/* Read back response */
dout = (u8 *)
-   for (i = 0; i < sizeof(response); i++) {
-   dout[i] = inb(EC_LPC_ADDR_HOST_PACKET + i);
-   sum += dout[i];
-   }
+   sum = cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET, sizeof(response), dout);
 
msg->result = response.result;
 
@@ -97,11 +97,10 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
}
 
/* Read response and process checksum */
-   for (i = 0; i < response.data_len; i++) {
-   msg->data[i] =
-   inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i);
-   sum += msg->data[i];
-   }
+   sum += cros_ec_lpc_read_bytes(
+   EC_LPC_ADDR_HOST_PACKET + sizeof(response),
+   response.data_len,
+   msg->data);
 
if (sum) {
dev_err(ec->dev,
@@ -121,8 +120,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
struct cros_ec_command *msg)
 {
struct ec_lpc_host_args args;
-   int csum;
-   int i;
+   u8 sum;
int ret = 0;
 
if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
@@ -139,24 +137,21 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
args.dat

<    3   4   5   6   7   8