]> git.karo-electronics.de Git - linux-beck.git/commitdiff
greybus: camera: Create and destroy data connection on demand
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Tue, 14 Jun 2016 12:59:25 +0000 (15:59 +0300)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 15 Jun 2016 12:05:47 +0000 (05:05 -0700)
Creating the data connection at probe time makes it impossible to
support multiple inserted camera modules as they would all try to
establish a data connection to the same CPort on the AP side. Create and
destroy the data connection when configuring the streams instead, as a
single module can be streaming at a time.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
Tested-by: Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/camera.c

index db7cdcee1c53f715cd40a5516931bb1fd74b41fc..0062f483fc2e89246b7a487e69b842be3531abdb 100644 (file)
@@ -42,6 +42,7 @@ enum gb_camera_state {
  * struct gb_camera - A Greybus Camera Device
  * @connection: the greybus connection for camera management
  * @data_connection: the greybus connection for camera data
+ * @data_cport_id: the data CPort ID on the module side
  * @mutex: protects the connection and state fields
  * @state: the current module state
  * @debugfs: debugfs entries for camera protocol operations testing
@@ -51,6 +52,7 @@ struct gb_camera {
        struct gb_bundle *bundle;
        struct gb_connection *connection;
        struct gb_connection *data_connection;
+       u16 data_cport_id;
 
        struct mutex mutex;
        enum gb_camera_state state;
@@ -196,12 +198,30 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam,
                struct gb_camera_csi_params *csi_params)
 {
        struct ap_csi_config_request csi_cfg;
+       struct gb_connection *conn;
        int ret;
 
+       /*
+        * Create the data connection between the camera module data CPort and
+        * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge.
+        */
+       conn = gb_connection_create_offloaded(gcam->bundle, gcam->data_cport_id,
+                                             GB_CONNECTION_FLAG_NO_FLOWCTRL |
+                                             GB_CONNECTION_FLAG_CDSI1);
+       if (IS_ERR(conn))
+               return PTR_ERR(conn);
+
+       gcam->data_connection = conn;
+       gb_connection_set_data(conn, gcam);
+
+       ret = gb_connection_enable(conn);
+       if (ret)
+               goto error_conn_destroy;
+
        /* Set the UniPro link to high speed mode. */
        ret = gb_camera_set_power_mode(gcam, true);
        if (ret < 0)
-               return ret;
+               goto error_conn_disable;
 
        /*
         * Configure the APB1 CSI transmitter using the lines count reported by
@@ -224,8 +244,7 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam,
 
        if (ret < 0) {
                gcam_err(gcam, "failed to start the CSI transmitter\n");
-               gb_camera_set_power_mode(gcam, false);
-               return ret;
+               goto error_power;
        }
 
        if (csi_params) {
@@ -236,6 +255,15 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam,
        }
 
        return 0;
+
+error_power:
+       gb_camera_set_power_mode(gcam, false);
+error_conn_disable:
+       gb_connection_disable(gcam->data_connection);
+error_conn_destroy:
+       gb_connection_destroy(gcam->data_connection);
+       gcam->data_connection = NULL;
+       return ret;
 }
 
 static void gb_camera_teardown_data_connection(struct gb_camera *gcam)
@@ -256,6 +284,11 @@ static void gb_camera_teardown_data_connection(struct gb_camera *gcam)
 
        /* Set the UniPro link to low speed mode. */
        gb_camera_set_power_mode(gcam, false);
+
+       /* Destroy the data connection. */
+       gb_connection_disable(gcam->data_connection);
+       gb_connection_destroy(gcam->data_connection);
+       gcam->data_connection = NULL;
 }
 
 /* -----------------------------------------------------------------------------
@@ -990,13 +1023,13 @@ static void gb_camera_cleanup(struct gb_camera *gcam)
 {
        gb_camera_debugfs_cleanup(gcam);
 
+       mutex_lock(&gcam->mutex);
        if (gcam->data_connection) {
                gb_connection_disable(gcam->data_connection);
                gb_connection_destroy(gcam->data_connection);
                gcam->data_connection = NULL;
        }
 
-       mutex_lock(&gcam->mutex);
        if (gcam->connection) {
                gb_connection_disable(gcam->connection);
                gb_connection_destroy(gcam->connection);
@@ -1055,6 +1088,7 @@ static int gb_camera_probe(struct gb_bundle *bundle,
 
        gcam->bundle = bundle;
        gcam->state = GB_CAMERA_STATE_UNCONFIGURED;
+       gcam->data_cport_id = data_cport_id;
 
        conn = gb_connection_create(bundle, mgmt_cport_id,
                                    gb_camera_request_handler);
@@ -1066,24 +1100,6 @@ static int gb_camera_probe(struct gb_bundle *bundle,
        gcam->connection = conn;
        gb_connection_set_data(conn, gcam);
 
-       ret = gb_connection_enable(conn);
-       if (ret)
-               goto error;
-
-       /*
-        * Create the data connection between the camera module data CPort and
-        * APB CDSI1. The CDSI1 CPort ID is hardcoded by the ES2 bridge.
-        */
-       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 = conn;
-       gb_connection_set_data(conn, gcam);
-
        ret = gb_connection_enable(conn);
        if (ret)
                goto error;