greybus: es2: Add support for CSI transmitter configuration
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Fri, 18 Dec 2015 19:23:24 +0000 (21:23 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Tue, 22 Dec 2015 00:35:27 +0000 (16:35 -0800)
Export a function from the es2 driver to configure the CSI transmitter
through the corresponding USB vendor control request.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/es2.c
drivers/staging/greybus/es2.h [new file with mode: 0644]

index 1be4a7c511852cc2ae6fa4f29482cfe07be58ba1..334ed06b8900a1c5868f517d5ddb83f36b64ed71 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/debugfs.h>
 #include <asm/unaligned.h>
 
+#include "es2.h"
 #include "greybus.h"
 #include "kernel_ver.h"
 #include "connection.h"
@@ -60,6 +61,9 @@ MODULE_DEVICE_TABLE(usb, id_table);
 #define REQUEST_LATENCY_TAG_EN 0x06
 #define REQUEST_LATENCY_TAG_DIS        0x07
 
+/* vendor request to control the CSI transmitter */
+#define REQUEST_CSI_TX_CONTROL 0x08
+
 /*
  * @endpoint: bulk in endpoint for CPort data
  * @urb: array of urbs for the CPort in messages
@@ -130,6 +134,14 @@ 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;
+} __attribute__((__packed__));
+
 static inline struct es2_ap_dev *hd_to_es2(struct gb_host_device *hd)
 {
        return (struct es2_ap_dev *)&hd->hd_priv;
@@ -208,6 +220,42 @@ 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)
+{
+       struct es2_ap_csi_config_request cfg_req;
+       struct es2_ap_dev *es2 = hd_to_es2(hd);
+       struct usb_device *udev = es2->usb_dev;
+       int retval;
+
+       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.padding = 0;
+               cfg_req.bus_freq = cfg->bus_freq;
+       } else {
+               cfg_req.clock_mode = 0;
+               cfg_req.num_lanes = 0;
+               cfg_req.padding = 0;
+               cfg_req.bus_freq = 0;
+       }
+
+       retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                REQUEST_CSI_TX_CONTROL,
+                                USB_DIR_OUT | USB_TYPE_VENDOR |
+                                USB_RECIP_INTERFACE, 0, 0, &cfg_req,
+                                sizeof(cfg_req), ES2_TIMEOUT);
+       if (retval < 0) {
+               dev_err(&udev->dev, "failed to setup csi: %d\n", retval);
+               return retval;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(es2_ap_csi_setup);
+
 static int es2_cport_in_enable(struct es2_ap_dev *es2,
                                struct es2_cport_in *cport_in)
 {
diff --git a/drivers/staging/greybus/es2.h b/drivers/staging/greybus/es2.h
new file mode 100644 (file)
index 0000000..ea29770
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Greybus "AP" USB driver for "ES2" controller chips
+ *
+ * Copyright 2015 Google Inc.
+ * Copyright 2015 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#ifndef __ES2_H
+#define __ES2_H
+
+#include <linux/types.h>
+
+struct gb_host_device;
+
+struct es2_ap_csi_config {
+       u8 csi_id;
+       u8 clock_mode;
+       u8 num_lanes;
+       u32 bus_freq;
+};
+
+int es2_ap_csi_setup(struct gb_host_device *hd, bool start,
+                    struct es2_ap_csi_config *cfg);
+
+#endif /* __ES2_H */