@@ -185,6 +185,37 @@ static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool on)
185
185
return ret ;
186
186
}
187
187
188
+ /**
189
+ * __fimc_pipeline_enable - enable power of all pipeline subdevs
190
+ * and the sensor clock
191
+ * @ep: video pipeline structure
192
+ * @fmd: fimc media device
193
+ *
194
+ * Called with the graph mutex held.
195
+ */
196
+ static int __fimc_pipeline_enable (struct exynos_media_pipeline * ep ,
197
+ struct fimc_md * fmd )
198
+ {
199
+ struct fimc_pipeline * p = to_fimc_pipeline (ep );
200
+ int ret ;
201
+
202
+ /* Enable PXLASYNC clock if this pipeline includes FIMC-IS */
203
+ if (!IS_ERR (fmd -> wbclk [CLK_IDX_WB_B ]) && p -> subdevs [IDX_IS_ISP ]) {
204
+ ret = clk_prepare_enable (fmd -> wbclk [CLK_IDX_WB_B ]);
205
+ if (ret < 0 )
206
+ return ret ;
207
+ }
208
+
209
+ ret = fimc_pipeline_s_power (p , 1 );
210
+ if (!ret )
211
+ return 0 ;
212
+
213
+ if (!IS_ERR (fmd -> wbclk [CLK_IDX_WB_B ]) && p -> subdevs [IDX_IS_ISP ])
214
+ clk_disable_unprepare (fmd -> wbclk [CLK_IDX_WB_B ]);
215
+
216
+ return ret ;
217
+ }
218
+
188
219
/**
189
220
* __fimc_pipeline_open - update the pipeline information, enable power
190
221
* of all pipeline subdevs and the sensor clock
@@ -199,7 +230,6 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
199
230
struct fimc_md * fmd = entity_to_fimc_mdev (me );
200
231
struct fimc_pipeline * p = to_fimc_pipeline (ep );
201
232
struct v4l2_subdev * sd ;
202
- int ret ;
203
233
204
234
if (WARN_ON (p == NULL || me == NULL ))
205
235
return - EINVAL ;
@@ -208,24 +238,16 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
208
238
fimc_pipeline_prepare (p , me );
209
239
210
240
sd = p -> subdevs [IDX_SENSOR ];
211
- if (sd == NULL )
212
- return - EINVAL ;
213
-
214
- /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */
215
- if (!IS_ERR (fmd -> wbclk [CLK_IDX_WB_B ]) && p -> subdevs [IDX_IS_ISP ]) {
216
- ret = clk_prepare_enable (fmd -> wbclk [CLK_IDX_WB_B ]);
217
- if (ret < 0 )
218
- return ret ;
219
- }
220
-
221
- ret = fimc_pipeline_s_power (p , 1 );
222
- if (!ret )
241
+ if (sd == NULL ) {
242
+ pr_warn ("%s(): No sensor subdev\n" , __func__ );
243
+ /*
244
+ * Pipeline open cannot fail so as to make it possible
245
+ * for the user space to configure the pipeline.
246
+ */
223
247
return 0 ;
248
+ }
224
249
225
- if (!IS_ERR (fmd -> wbclk [CLK_IDX_WB_B ]) && p -> subdevs [IDX_IS_ISP ])
226
- clk_disable_unprepare (fmd -> wbclk [CLK_IDX_WB_B ]);
227
-
228
- return ret ;
250
+ return __fimc_pipeline_enable (ep , fmd );
229
251
}
230
252
231
253
/**
@@ -269,10 +291,43 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
269
291
{ IDX_CSIS , IDX_FLITE , IDX_FIMC , IDX_SENSOR , IDX_IS_ISP },
270
292
};
271
293
struct fimc_pipeline * p = to_fimc_pipeline (ep );
294
+ struct fimc_md * fmd = entity_to_fimc_mdev (& p -> subdevs [IDX_CSIS ]-> entity );
295
+ enum fimc_subdev_index sd_id ;
272
296
int i , ret = 0 ;
273
297
274
- if (p -> subdevs [IDX_SENSOR ] == NULL )
275
- return - ENODEV ;
298
+ if (p -> subdevs [IDX_SENSOR ] == NULL ) {
299
+ if (!fmd -> user_subdev_api ) {
300
+ /*
301
+ * Sensor must be already discovered if we
302
+ * aren't in the user_subdev_api mode
303
+ */
304
+ return - ENODEV ;
305
+ }
306
+
307
+ /* Get pipeline sink entity */
308
+ if (p -> subdevs [IDX_FIMC ])
309
+ sd_id = IDX_FIMC ;
310
+ else if (p -> subdevs [IDX_IS_ISP ])
311
+ sd_id = IDX_IS_ISP ;
312
+ else if (p -> subdevs [IDX_FLITE ])
313
+ sd_id = IDX_FLITE ;
314
+ else
315
+ return - ENODEV ;
316
+
317
+ /*
318
+ * Sensor could have been linked between open and STREAMON -
319
+ * check if this is the case.
320
+ */
321
+ fimc_pipeline_prepare (p , & p -> subdevs [sd_id ]-> entity );
322
+
323
+ if (p -> subdevs [IDX_SENSOR ] == NULL )
324
+ return - ENODEV ;
325
+
326
+ ret = __fimc_pipeline_enable (ep , fmd );
327
+ if (ret < 0 )
328
+ return ret ;
329
+
330
+ }
276
331
277
332
for (i = 0 ; i < IDX_MAX ; i ++ ) {
278
333
unsigned int idx = seq [on ][i ];
@@ -282,8 +337,10 @@ static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on)
282
337
if (ret < 0 && ret != - ENOIOCTLCMD && ret != - ENODEV )
283
338
goto error ;
284
339
}
340
+
285
341
return 0 ;
286
342
error :
343
+ fimc_pipeline_s_power (p , !on );
287
344
for (; i >= 0 ; i -- ) {
288
345
unsigned int idx = seq [on ][i ];
289
346
v4l2_subdev_call (p -> subdevs [idx ], video , s_stream , !on );
0 commit comments