aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/camera.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2016-05-20 14:33:35 +0300
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-20 16:47:30 -0700
commit68b66c28010ebc2ebe21d6bad2de2eda1bed01fc (patch)
treec087327a6b97e0ef8080906546be9e2dfd897aaf /drivers/staging/greybus/camera.c
parentgreybus: fw-management: Fix error message's text (diff)
downloadlinux-dev-68b66c28010ebc2ebe21d6bad2de2eda1bed01fc.tar.xz
linux-dev-68b66c28010ebc2ebe21d6bad2de2eda1bed01fc.zip
greybus: camera: Convert to bundle driver
Convert the legacy camera protocol driver to a bundle driver. Modules now can (and must) declare the camera data cport in their manifest as the data connection isn't hardcoded anymore. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/camera.c')
-rw-r--r--drivers/staging/greybus/camera.c123
1 files changed, 84 insertions, 39 deletions
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c
index 4831ad652c04..dd482bd94637 100644
--- a/drivers/staging/greybus/camera.c
+++ b/drivers/staging/greybus/camera.c
@@ -36,11 +36,11 @@ struct gb_camera_debugfs_buffer {
/**
* struct gb_camera - A Greybus Camera Device
* @connection: the greybus connection for camera control
- * @data_connected: whether the data connection has been established
* @debugfs: debugfs entries for camera protocol operations testing
* @module: Greybus camera module registered to HOST processor.
*/
struct gb_camera {
+ struct gb_bundle *bundle;
struct gb_connection *connection;
struct gb_connection *data_connection;
@@ -103,12 +103,9 @@ static const struct gb_camera_fmt_map mbus_to_gbus_format[] = {
#define GB_CAMERA_MAX_SETTINGS_SIZE 8192
-#define gcam_dbg(gcam, format...) \
- dev_dbg(&gcam->connection->bundle->dev, format)
-#define gcam_info(gcam, format...) \
- dev_info(&gcam->connection->bundle->dev, format)
-#define gcam_err(gcam, format...) \
- dev_err(&gcam->connection->bundle->dev, format)
+#define gcam_dbg(gcam, format...) dev_dbg(&gcam->bundle->dev, format)
+#define gcam_info(gcam, format...) dev_info(&gcam->bundle->dev, format)
+#define gcam_err(gcam, format...) dev_err(&gcam->bundle->dev, format)
/* -----------------------------------------------------------------------------
* Camera Protocol Operations
@@ -383,14 +380,14 @@ static int gb_camera_flush(struct gb_camera *gcam, u32 *request_id)
return 0;
}
-static int gb_camera_event_recv(u8 type, struct gb_operation *op)
+static int gb_camera_request_handler(struct gb_operation *op)
{
struct gb_camera *gcam = gb_connection_get_data(op->connection);
struct gb_camera_metadata_request *payload;
struct gb_message *request;
- if (type != GB_CAMERA_TYPE_METADATA) {
- gcam_err(gcam, "Unsupported unsolicited event: %u\n", type);
+ if (op->type != GB_CAMERA_TYPE_METADATA) {
+ gcam_err(gcam, "Unsupported unsolicited event: %u\n", op->type);
return -EINVAL;
}
@@ -849,7 +846,7 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam)
* Create root debugfs entry and a file entry for each camera operation.
*/
snprintf(dirname, 27, "camera-%u.%u", connection->intf->interface_id,
- connection->bundle->id);
+ gcam->bundle->id);
gcam->debugfs.root = debugfs_create_dir(dirname, gb_debugfs_get());
if (IS_ERR(gcam->debugfs.root)) {
@@ -905,39 +902,84 @@ static void gb_camera_cleanup(struct gb_camera *gcam)
gb_connection_destroy(gcam->data_connection);
}
+ if (gcam->connection) {
+ gb_connection_disable(gcam->connection);
+ gb_connection_destroy(gcam->connection);
+ }
+
kfree(gcam);
}
-static int gb_camera_connection_init(struct gb_connection *connection)
+static int gb_camera_probe(struct gb_bundle *bundle,
+ const struct greybus_bundle_id *id)
{
- struct gb_connection *data;
+ struct gb_connection *conn;
struct gb_camera *gcam;
- unsigned long data_flags;
+ u16 mgmt_cport_id = 0;
+ u16 data_cport_id = 0;
+ unsigned int i;
int ret;
+ /*
+ * The camera bundle must contain exactly two CPorts, one for the
+ * camera management protocol and one for the camera data protocol.
+ */
+ if (bundle->num_cports != 2)
+ return -ENODEV;
+
+ for (i = 0; i < bundle->num_cports; ++i) {
+ struct greybus_descriptor_cport *desc = &bundle->cport_desc[i];
+
+ switch (desc->protocol_id) {
+ case GREYBUS_PROTOCOL_CAMERA_MGMT:
+ mgmt_cport_id = le16_to_cpu(desc->id);
+ break;
+ case GREYBUS_PROTOCOL_CAMERA_DATA:
+ data_cport_id = le16_to_cpu(desc->id);
+ break;
+ default:
+ return -ENODEV;
+ }
+ }
+
+ if (!mgmt_cport_id || !data_cport_id)
+ return -ENODEV;
+
gcam = kzalloc(sizeof(*gcam), GFP_KERNEL);
if (!gcam)
return -ENOMEM;
- gcam->connection = connection;
- gb_connection_set_data(connection, gcam);
+ gcam->bundle = bundle;
+
+ conn = gb_connection_create(bundle, mgmt_cport_id,
+ gb_camera_request_handler);
+ if (IS_ERR(conn)) {
+ ret = PTR_ERR(conn);
+ goto error;
+ }
+
+ gcam->connection = conn;
+ gb_connection_set_data(conn, gcam);
+
+ ret = gb_connection_enable(conn);
+ if (ret)
+ goto error;
/*
- * Create the data connection between camera module CDSI0 and APB CDS1.
- * The CPort IDs are hardcoded by the ES2 bridges.
+ * Create the data connection between the camera module data CPort and
+ * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge.
*/
- data_flags = GB_CONNECTION_FLAG_NO_FLOWCTRL | GB_CONNECTION_FLAG_CDSI1;
-
- data = gb_connection_create_offloaded(connection->bundle,
- ES2_APB_CDSI0_CPORT,
- data_flags);
- if (IS_ERR(data)) {
- ret = PTR_ERR(data);
+ conn = gb_connection_create_offloaded(bundle, data_cport_id,
+ GB_CONNECTION_FLAG_NO_FLOWCTRL |
+ GB_CONNECTION_FLAG_CDSI1);
+ if (IS_ERR(conn)) {
+ ret = PTR_ERR(conn);
goto error;
}
- gcam->data_connection = data;
+ gcam->data_connection = conn;
+ gb_connection_set_data(conn, gcam);
- ret = gb_connection_enable(data);
+ ret = gb_connection_enable(conn);
if (ret)
goto error;
@@ -949,6 +991,8 @@ static int gb_camera_connection_init(struct gb_connection *connection)
if (ret < 0)
goto error;
+ greybus_set_drvdata(bundle, gcam);
+
return 0;
error:
@@ -956,25 +1000,26 @@ error:
return ret;
}
-static void gb_camera_connection_exit(struct gb_connection *connection)
+static void gb_camera_disconnect(struct gb_bundle *bundle)
{
- struct gb_camera *gcam = gb_connection_get_data(connection);
+ struct gb_camera *gcam = greybus_get_drvdata(bundle);
gb_camera_unregister_intf_ops(gcam);
-
gb_camera_cleanup(gcam);
}
-static struct gb_protocol camera_protocol = {
- .name = "camera",
- .id = GREYBUS_PROTOCOL_CAMERA_MGMT,
- .major = GB_CAMERA_VERSION_MAJOR,
- .minor = GB_CAMERA_VERSION_MINOR,
- .connection_init = gb_camera_connection_init,
- .connection_exit = gb_camera_connection_exit,
- .request_recv = gb_camera_event_recv,
+static const struct greybus_bundle_id gb_camera_id_table[] = {
+ { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
+ { },
+};
+
+static struct greybus_driver gb_camera_driver = {
+ .name = "camera",
+ .probe = gb_camera_probe,
+ .disconnect = gb_camera_disconnect,
+ .id_table = gb_camera_id_table,
};
-gb_protocol_driver(&camera_protocol);
+module_greybus_driver(gb_camera_driver);
MODULE_LICENSE("GPL v2");