Commit 9120b906 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Greg Kroah-Hartman

greybus: camera: Create and destroy data connection on demand

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: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: default avatarGjorgji Rosikopulos <grosikopulos@mm-sol.com>
Tested-by: default avatarGjorgji Rosikopulos <grosikopulos@mm-sol.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 3b8ebfeb
...@@ -42,6 +42,7 @@ enum gb_camera_state { ...@@ -42,6 +42,7 @@ enum gb_camera_state {
* struct gb_camera - A Greybus Camera Device * struct gb_camera - A Greybus Camera Device
* @connection: the greybus connection for camera management * @connection: the greybus connection for camera management
* @data_connection: the greybus connection for camera data * @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 * @mutex: protects the connection and state fields
* @state: the current module state * @state: the current module state
* @debugfs: debugfs entries for camera protocol operations testing * @debugfs: debugfs entries for camera protocol operations testing
...@@ -51,6 +52,7 @@ struct gb_camera { ...@@ -51,6 +52,7 @@ struct gb_camera {
struct gb_bundle *bundle; struct gb_bundle *bundle;
struct gb_connection *connection; struct gb_connection *connection;
struct gb_connection *data_connection; struct gb_connection *data_connection;
u16 data_cport_id;
struct mutex mutex; struct mutex mutex;
enum gb_camera_state state; enum gb_camera_state state;
...@@ -196,12 +198,30 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, ...@@ -196,12 +198,30 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam,
struct gb_camera_csi_params *csi_params) struct gb_camera_csi_params *csi_params)
{ {
struct ap_csi_config_request csi_cfg; struct ap_csi_config_request csi_cfg;
struct gb_connection *conn;
int ret; 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. */ /* Set the UniPro link to high speed mode. */
ret = gb_camera_set_power_mode(gcam, true); ret = gb_camera_set_power_mode(gcam, true);
if (ret < 0) if (ret < 0)
return ret; goto error_conn_disable;
/* /*
* Configure the APB1 CSI transmitter using the lines count reported by * 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, ...@@ -224,8 +244,7 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam,
if (ret < 0) { if (ret < 0) {
gcam_err(gcam, "failed to start the CSI transmitter\n"); gcam_err(gcam, "failed to start the CSI transmitter\n");
gb_camera_set_power_mode(gcam, false); goto error_power;
return ret;
} }
if (csi_params) { if (csi_params) {
...@@ -236,6 +255,15 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam, ...@@ -236,6 +255,15 @@ static int gb_camera_setup_data_connection(struct gb_camera *gcam,
} }
return 0; 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) 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) ...@@ -256,6 +284,11 @@ static void gb_camera_teardown_data_connection(struct gb_camera *gcam)
/* Set the UniPro link to low speed mode. */ /* Set the UniPro link to low speed mode. */
gb_camera_set_power_mode(gcam, false); 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) ...@@ -990,13 +1023,13 @@ static void gb_camera_cleanup(struct gb_camera *gcam)
{ {
gb_camera_debugfs_cleanup(gcam); gb_camera_debugfs_cleanup(gcam);
mutex_lock(&gcam->mutex);
if (gcam->data_connection) { if (gcam->data_connection) {
gb_connection_disable(gcam->data_connection); gb_connection_disable(gcam->data_connection);
gb_connection_destroy(gcam->data_connection); gb_connection_destroy(gcam->data_connection);
gcam->data_connection = NULL; gcam->data_connection = NULL;
} }
mutex_lock(&gcam->mutex);
if (gcam->connection) { if (gcam->connection) {
gb_connection_disable(gcam->connection); gb_connection_disable(gcam->connection);
gb_connection_destroy(gcam->connection); gb_connection_destroy(gcam->connection);
...@@ -1055,6 +1088,7 @@ static int gb_camera_probe(struct gb_bundle *bundle, ...@@ -1055,6 +1088,7 @@ static int gb_camera_probe(struct gb_bundle *bundle,
gcam->bundle = bundle; gcam->bundle = bundle;
gcam->state = GB_CAMERA_STATE_UNCONFIGURED; gcam->state = GB_CAMERA_STATE_UNCONFIGURED;
gcam->data_cport_id = data_cport_id;
conn = gb_connection_create(bundle, mgmt_cport_id, conn = gb_connection_create(bundle, mgmt_cport_id,
gb_camera_request_handler); gb_camera_request_handler);
...@@ -1066,24 +1100,6 @@ static int gb_camera_probe(struct gb_bundle *bundle, ...@@ -1066,24 +1100,6 @@ static int gb_camera_probe(struct gb_bundle *bundle,
gcam->connection = conn; gcam->connection = conn;
gb_connection_set_data(conn, gcam); 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); ret = gb_connection_enable(conn);
if (ret) if (ret)
goto error; goto error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment