summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/es2.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@google.com>2015-12-22 18:21:51 -0800
committerGreg Kroah-Hartman <gregkh@google.com>2016-01-12 11:11:49 -0800
commited4596e9b19104ccc1e87bde8fcadee3a473c101 (patch)
tree9d2467879c261da5e43c2b90da3d0620757ba60e /drivers/staging/greybus/es2.c
parentaccad1ba7d62543ab3bcf08813726ea87d237bb6 (diff)
greybus: host: provide "generic" apbridge output calls
Provide a new function, gb_hd_output() to send data to the apbridge. This is useful for the camera and audio drivers that need to do this type of messaging. The camera driver is converted to use this new function, the audio driver can use it when it gets merged later. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Tested-by: Mark Greer <mgreer@animalcreek.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Diffstat (limited to 'drivers/staging/greybus/es2.c')
-rw-r--r--drivers/staging/greybus/es2.c99
1 files changed, 70 insertions, 29 deletions
diff --git a/drivers/staging/greybus/es2.c b/drivers/staging/greybus/es2.c
index af5d7496c6be..1b5487fec903 100644
--- a/drivers/staging/greybus/es2.c
+++ b/drivers/staging/greybus/es2.c
@@ -13,7 +13,6 @@
#include <linux/debugfs.h>
#include <asm/unaligned.h>
-#include "es2.h"
#include "greybus.h"
#include "kernel_ver.h"
#include "connection.h"
@@ -134,14 +133,6 @@ struct cport_to_ep {
__u8 endpoint_out;
};
-struct es2_ap_csi_config_request {
- __u8 csi_id;
- __u8 clock_mode;
- __u8 num_lanes;
- __u8 padding;
- __le32 bus_freq;
-} __packed;
-
static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd)
{
return (struct es2_ap_dev *)&hd->hd_priv;
@@ -220,38 +211,87 @@ static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id)
}
#endif
-int es2_ap_csi_setup(struct gb_host_device *hd, bool start,
- struct es2_ap_csi_config *cfg)
+static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd)
{
- struct es2_ap_csi_config_request *cfg_req;
- struct es2_ap_dev *es2 = hd_to_es2(hd);
struct usb_device *udev = es2->usb_dev;
+ u8 *data;
int retval;
- cfg_req = kzalloc(sizeof(*cfg_req), GFP_KERNEL);
- if (!cfg_req)
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data)
return -ENOMEM;
-
- cfg_req->csi_id = cfg->csi_id;
-
- if (start) {
- cfg_req->clock_mode = cfg->clock_mode;
- cfg_req->num_lanes = cfg->num_lanes;
- cfg_req->bus_freq = cpu_to_le32(cfg->bus_freq);
- }
+ memcpy(data, req, size);
retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- REQUEST_CSI_TX_CONTROL,
+ cmd,
USB_DIR_OUT | USB_TYPE_VENDOR |
- USB_RECIP_INTERFACE, 0, 0, cfg_req,
- sizeof(*cfg_req), ES2_TIMEOUT);
+ USB_RECIP_INTERFACE,
+ 0, 0, data, size, ES2_TIMEOUT);
if (retval < 0)
- dev_err(&udev->dev, "failed to setup csi: %d\n", retval);
+ dev_err(&udev->dev, "%s: return error %d\n", __func__, retval);
+ else
+ retval = 0;
- kfree(cfg_req);
+ kfree(data);
return retval;
}
-EXPORT_SYMBOL_GPL(es2_ap_csi_setup);
+
+static void ap_urb_complete(struct urb *urb)
+{
+ struct usb_ctrlrequest *dr = urb->context;
+
+ kfree(dr);
+ usb_free_urb(urb);
+}
+
+static int output_async(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd)
+{
+ struct usb_device *udev = es2->usb_dev;
+ struct urb *urb;
+ struct usb_ctrlrequest *dr;
+ u8 *buf;
+ int retval;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ dr = kmalloc(sizeof(*dr) + size, GFP_ATOMIC);
+ if (!dr) {
+ usb_free_urb(urb);
+ return -ENOMEM;
+ }
+
+ buf = (u8 *)dr + sizeof(*dr);
+ memcpy(buf, req, size);
+
+ dr->bRequest = cmd;
+ dr->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
+ dr->wValue = 0;
+ dr->wIndex = 0;
+ dr->wLength = cpu_to_le16(size);
+
+ usb_fill_control_urb(urb, udev, usb_sndctrlpipe(udev, 0),
+ (unsigned char *)dr, buf, size,
+ ap_urb_complete, dr);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval) {
+ usb_free_urb(urb);
+ kfree(dr);
+ }
+ return retval;
+}
+
+static int output(struct gb_host_device *hd, void *req, u16 size, u8 cmd,
+ bool async)
+{
+ struct es2_ap_dev *es2 = hd_to_es2(hd);
+
+ if (async)
+ return output_async(es2, req, size, cmd);
+
+ return output_sync(es2, req, size, cmd);
+}
static int es2_cport_in_enable(struct es2_ap_dev *es2,
struct es2_cport_in *cport_in)
@@ -560,6 +600,7 @@ static struct gb_hd_driver es2_driver = {
.cport_enable = cport_enable,
.latency_tag_enable = latency_tag_enable,
.latency_tag_disable = latency_tag_disable,
+ .output = output,
};
/* Common function to report consistent warnings based on URB status */