]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/video/s5p-fimc/fimc-mdevice.c
[media] s5p-fimc: Make sure an interrupt is properly requested
[mirror_ubuntu-artful-kernel.git] / drivers / media / video / s5p-fimc / fimc-mdevice.c
CommitLineData
d3953223
SN
1/*
2 * S5P/EXYNOS4 SoC series camera host interface media device driver
3 *
4 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5 * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 2 of the License,
10 * or (at your option) any later version.
11 */
12
13#include <linux/bug.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/i2c.h>
17#include <linux/kernel.h>
18#include <linux/list.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/pm_runtime.h>
22#include <linux/types.h>
23#include <linux/slab.h>
131b6c61 24#include <media/v4l2-ctrls.h>
d3953223
SN
25#include <media/media-device.h>
26
27#include "fimc-core.h"
0f735f52 28#include "fimc-lite.h"
d3953223
SN
29#include "fimc-mdevice.h"
30#include "mipi-csis.h"
31
32static int __fimc_md_set_camclk(struct fimc_md *fmd,
33 struct fimc_sensor_info *s_info,
34 bool on);
35/**
36 * fimc_pipeline_prepare - update pipeline information with subdevice pointers
37 * @fimc: fimc device terminating the pipeline
38 *
39 * Caller holds the graph mutex.
40 */
0f735f52 41void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me)
d3953223 42{
0f735f52 43 struct media_pad *pad = &me->pads[0];
d3953223 44 struct v4l2_subdev *sd;
0f735f52 45 int i;
d3953223 46
0f735f52
SN
47 for (i = 0; i < IDX_MAX; i++)
48 p->subdevs[i] = NULL;
d3953223 49
0f735f52
SN
50 while (1) {
51 if (!(pad->flags & MEDIA_PAD_FL_SINK))
52 break;
53
54 /* source pad */
55 pad = media_entity_remote_source(pad);
56 if (pad == NULL ||
57 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
58 break;
d3953223 59
0f735f52
SN
60 sd = media_entity_to_v4l2_subdev(pad->entity);
61
62 switch (sd->grp_id) {
63 case SENSOR_GROUP_ID:
64 p->subdevs[IDX_SENSOR] = sd;
65 break;
66 case CSIS_GROUP_ID:
67 p->subdevs[IDX_CSIS] = sd;
68 break;
69 case FIMC_GROUP_ID:
70 /* No need to control FIMC subdev through subdev ops */
71 break;
72 default:
73 pr_warn("%s: Unknown subdev grp_id: %#x\n",
74 __func__, sd->grp_id);
75 }
76 /* sink pad */
77 pad = &sd->entity.pads[0];
d3953223
SN
78 }
79}
80
81/**
82 * __subdev_set_power - change power state of a single subdev
83 * @sd: subdevice to change power state for
84 * @on: 1 to enable power or 0 to disable
85 *
86 * Return result of s_power subdev operation or -ENXIO if sd argument
87 * is NULL. Return 0 if the subdevice does not implement s_power.
88 */
89static int __subdev_set_power(struct v4l2_subdev *sd, int on)
90{
91 int *use_count;
92 int ret;
93
94 if (sd == NULL)
95 return -ENXIO;
96
97 use_count = &sd->entity.use_count;
98 if (on && (*use_count)++ > 0)
99 return 0;
100 else if (!on && (*use_count == 0 || --(*use_count) > 0))
101 return 0;
102 ret = v4l2_subdev_call(sd, core, s_power, on);
103
104 return ret != -ENOIOCTLCMD ? ret : 0;
105}
106
107/**
108 * fimc_pipeline_s_power - change power state of all pipeline subdevs
109 * @fimc: fimc device terminating the pipeline
0f735f52 110 * @state: true to power on, false to power off
d3953223 111 *
0f735f52 112 * Needs to be called with the graph mutex held.
d3953223 113 */
0f735f52 114int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
d3953223 115{
0f735f52
SN
116 unsigned int i;
117 int ret;
d3953223 118
0f735f52 119 if (p->subdevs[IDX_SENSOR] == NULL)
d3953223
SN
120 return -ENXIO;
121
0f735f52
SN
122 for (i = 0; i < IDX_MAX; i++) {
123 unsigned int idx = state ? (IDX_MAX - 1) - i : i;
124
125 ret = __subdev_set_power(p->subdevs[idx], state);
126 if (ret < 0 && ret != -ENXIO)
d3953223 127 return ret;
d3953223
SN
128 }
129
0f735f52 130 return 0;
d3953223
SN
131}
132
133/**
134 * __fimc_pipeline_initialize - update the pipeline information, enable power
135 * of all pipeline subdevs and the sensor clock
136 * @me: media entity to start graph walk with
137 * @prep: true to acquire sensor (and csis) subdevs
138 *
139 * This function must be called with the graph mutex held.
140 */
0f735f52 141static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
d3953223
SN
142 struct media_entity *me, bool prep)
143{
144 int ret;
145
146 if (prep)
0f735f52
SN
147 fimc_pipeline_prepare(p, me);
148
149 if (p->subdevs[IDX_SENSOR] == NULL)
d3953223 150 return -EINVAL;
0f735f52
SN
151
152 ret = fimc_md_set_camclk(p->subdevs[IDX_SENSOR], true);
d3953223
SN
153 if (ret)
154 return ret;
0f735f52
SN
155
156 return fimc_pipeline_s_power(p, 1);
d3953223
SN
157}
158
0f735f52 159int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
d3953223
SN
160 bool prep)
161{
162 int ret;
163
164 mutex_lock(&me->parent->graph_mutex);
0f735f52 165 ret = __fimc_pipeline_initialize(p, me, prep);
d3953223
SN
166 mutex_unlock(&me->parent->graph_mutex);
167
168 return ret;
169}
0f735f52 170EXPORT_SYMBOL_GPL(fimc_pipeline_initialize);
d3953223
SN
171
172/**
173 * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
174 * @fimc: fimc device terminating the pipeline
175 *
176 * Disable power of all subdevs in the pipeline and turn off the external
177 * sensor clock.
178 * Called with the graph mutex held.
179 */
0f735f52 180int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
d3953223
SN
181{
182 int ret = 0;
183
0f735f52
SN
184 if (p->subdevs[IDX_SENSOR]) {
185 ret = fimc_pipeline_s_power(p, 0);
186 fimc_md_set_camclk(p->subdevs[IDX_SENSOR], false);
d3953223
SN
187 }
188 return ret == -ENXIO ? 0 : ret;
189}
190
0f735f52 191int fimc_pipeline_shutdown(struct fimc_pipeline *p)
d3953223 192{
0f735f52 193 struct media_entity *me = &p->subdevs[IDX_SENSOR]->entity;
d3953223
SN
194 int ret;
195
196 mutex_lock(&me->parent->graph_mutex);
0f735f52 197 ret = __fimc_pipeline_shutdown(p);
d3953223
SN
198 mutex_unlock(&me->parent->graph_mutex);
199
200 return ret;
201}
0f735f52 202EXPORT_SYMBOL_GPL(fimc_pipeline_shutdown);
d3953223
SN
203
204/**
205 * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
0f735f52 206 * @pipeline: video pipeline structure
d3953223
SN
207 * @on: passed as the s_stream call argument
208 */
0f735f52 209int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
d3953223 210{
0f735f52 211 int i, ret;
d3953223 212
0f735f52 213 if (p->subdevs[IDX_SENSOR] == NULL)
d3953223
SN
214 return -ENODEV;
215
0f735f52
SN
216 for (i = 0; i < IDX_MAX; i++) {
217 unsigned int idx = on ? (IDX_MAX - 1) - i : i;
218
219 ret = v4l2_subdev_call(p->subdevs[idx], video, s_stream, on);
220
221 if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
222 return ret;
223 }
224
225 return 0;
226
d3953223 227}
0f735f52 228EXPORT_SYMBOL_GPL(fimc_pipeline_s_stream);
d3953223
SN
229
230/*
231 * Sensor subdevice helper functions
232 */
233static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
234 struct fimc_sensor_info *s_info)
235{
236 struct i2c_adapter *adapter;
237 struct v4l2_subdev *sd = NULL;
238
239 if (!s_info || !fmd)
240 return NULL;
241
242 adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num);
ecd9acbf
SN
243 if (!adapter) {
244 v4l2_warn(&fmd->v4l2_dev,
245 "Failed to get I2C adapter %d, deferring probe\n",
246 s_info->pdata->i2c_bus_num);
247 return ERR_PTR(-EPROBE_DEFER);
248 }
d3953223
SN
249 sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
250 s_info->pdata->board_info, NULL);
251 if (IS_ERR_OR_NULL(sd)) {
7acde02a 252 i2c_put_adapter(adapter);
ecd9acbf
SN
253 v4l2_warn(&fmd->v4l2_dev,
254 "Failed to acquire subdev %s, deferring probe\n",
255 s_info->pdata->board_info->type);
256 return ERR_PTR(-EPROBE_DEFER);
d3953223
SN
257 }
258 v4l2_set_subdev_hostdata(sd, s_info);
259 sd->grp_id = SENSOR_GROUP_ID;
260
261 v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
262 s_info->pdata->board_info->type);
263 return sd;
264}
265
266static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
267{
268 struct i2c_client *client = v4l2_get_subdevdata(sd);
7acde02a 269 struct i2c_adapter *adapter;
d3953223
SN
270
271 if (!client)
272 return;
273 v4l2_device_unregister_subdev(sd);
7acde02a 274 adapter = client->adapter;
d3953223 275 i2c_unregister_device(client);
7acde02a
SN
276 if (adapter)
277 i2c_put_adapter(adapter);
d3953223
SN
278}
279
280static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
281{
282 struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
283 struct fimc_dev *fd = NULL;
284 int num_clients, ret, i;
285
286 /*
287 * Runtime resume one of the FIMC entities to make sure
288 * the sclk_cam clocks are not globally disabled.
289 */
290 for (i = 0; !fd && i < ARRAY_SIZE(fmd->fimc); i++)
291 if (fmd->fimc[i])
292 fd = fmd->fimc[i];
293 if (!fd)
294 return -ENXIO;
295 ret = pm_runtime_get_sync(&fd->pdev->dev);
296 if (ret < 0)
297 return ret;
298
299 WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
300 num_clients = min_t(u32, pdata->num_clients, ARRAY_SIZE(fmd->sensor));
301
302 fmd->num_sensors = num_clients;
303 for (i = 0; i < num_clients; i++) {
ecd9acbf
SN
304 struct v4l2_subdev *sd;
305
d3953223
SN
306 fmd->sensor[i].pdata = &pdata->isp_info[i];
307 ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
308 if (ret)
309 break;
ecd9acbf 310 sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]);
d3953223 311 ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
ecd9acbf
SN
312
313 if (!IS_ERR(sd)) {
314 fmd->sensor[i].subdev = sd;
315 } else {
316 fmd->sensor[i].subdev = NULL;
317 ret = PTR_ERR(sd);
318 break;
319 }
d3953223
SN
320 if (ret)
321 break;
322 }
323 pm_runtime_put(&fd->pdev->dev);
324 return ret;
325}
326
327/*
328 * MIPI CSIS and FIMC platform devices registration.
329 */
330static int fimc_register_callback(struct device *dev, void *p)
331{
332 struct fimc_dev *fimc = dev_get_drvdata(dev);
693f5c40 333 struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
d3953223 334 struct fimc_md *fmd = p;
693f5c40 335 int ret = 0;
d3953223
SN
336
337 if (!fimc || !fimc->pdev)
338 return 0;
339 if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
340 return 0;
341
342 fmd->fimc[fimc->pdev->id] = fimc;
693f5c40
SN
343 sd->grp_id = FIMC_GROUP_ID;
344
345 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
346 if (ret) {
347 v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
348 fimc->id, ret);
349 }
350
d3953223
SN
351 return ret;
352}
353
354static int csis_register_callback(struct device *dev, void *p)
355{
356 struct v4l2_subdev *sd = dev_get_drvdata(dev);
357 struct platform_device *pdev;
358 struct fimc_md *fmd = p;
359 int id, ret;
360
361 if (!sd)
362 return 0;
363 pdev = v4l2_get_subdevdata(sd);
364 if (!pdev || pdev->id < 0 || pdev->id >= CSIS_MAX_ENTITIES)
365 return 0;
366 v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
367
368 id = pdev->id < 0 ? 0 : pdev->id;
369 fmd->csis[id].sd = sd;
370 sd->grp_id = CSIS_GROUP_ID;
371 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
372 if (ret)
373 v4l2_err(&fmd->v4l2_dev,
374 "Failed to register CSIS subdevice: %d\n", ret);
375 return ret;
376}
377
378/**
379 * fimc_md_register_platform_entities - register FIMC and CSIS media entities
380 */
381static int fimc_md_register_platform_entities(struct fimc_md *fmd)
382{
ecd9acbf 383 struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
d3953223 384 struct device_driver *driver;
ecd9acbf 385 int ret, i;
d3953223
SN
386
387 driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type);
ecd9acbf
SN
388 if (!driver) {
389 v4l2_warn(&fmd->v4l2_dev,
390 "%s driver not found, deffering probe\n",
391 FIMC_MODULE_NAME);
392 return -EPROBE_DEFER;
393 }
394
d3953223
SN
395 ret = driver_for_each_device(driver, NULL, fmd,
396 fimc_register_callback);
d3953223
SN
397 if (ret)
398 return ret;
ecd9acbf
SN
399 /*
400 * Check if there is any sensor on the MIPI-CSI2 bus and
401 * if not skip the s5p-csis module loading.
402 */
41df5bf0
SN
403 if (pdata == NULL)
404 return 0;
ecd9acbf
SN
405 for (i = 0; i < pdata->num_clients; i++) {
406 if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) {
407 ret = 1;
408 break;
409 }
410 }
411 if (!ret)
412 return 0;
d3953223
SN
413
414 driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type);
ecd9acbf
SN
415 if (!driver || !try_module_get(driver->owner)) {
416 v4l2_warn(&fmd->v4l2_dev,
417 "%s driver not found, deffering probe\n",
418 CSIS_DRIVER_NAME);
419 return -EPROBE_DEFER;
420 }
421
422 return driver_for_each_device(driver, NULL, fmd,
423 csis_register_callback);
d3953223
SN
424}
425
426static void fimc_md_unregister_entities(struct fimc_md *fmd)
427{
428 int i;
429
430 for (i = 0; i < FIMC_MAX_DEVS; i++) {
431 if (fmd->fimc[i] == NULL)
432 continue;
693f5c40 433 v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
d3953223
SN
434 fmd->fimc[i] = NULL;
435 }
436 for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
437 if (fmd->csis[i].sd == NULL)
438 continue;
439 v4l2_device_unregister_subdev(fmd->csis[i].sd);
ecd9acbf 440 module_put(fmd->csis[i].sd->owner);
d3953223
SN
441 fmd->csis[i].sd = NULL;
442 }
443 for (i = 0; i < fmd->num_sensors; i++) {
444 if (fmd->sensor[i].subdev == NULL)
445 continue;
446 fimc_md_unregister_sensor(fmd->sensor[i].subdev);
447 fmd->sensor[i].subdev = NULL;
448 }
449}
450
d3953223
SN
451/**
452 * __fimc_md_create_fimc_links - create links to all FIMC entities
453 * @fmd: fimc media device
454 * @source: the source entity to create links to all fimc entities from
455 * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null
456 * @pad: the source entity pad index
457 * @fimc_id: index of the fimc device for which link should be enabled
458 */
459static int __fimc_md_create_fimc_links(struct fimc_md *fmd,
460 struct media_entity *source,
461 struct v4l2_subdev *sensor,
462 int pad, int fimc_id)
463{
464 struct fimc_sensor_info *s_info;
465 struct media_entity *sink;
466 unsigned int flags;
237e0265 467 int ret, i;
d3953223
SN
468
469 for (i = 0; i < FIMC_MAX_DEVS; i++) {
470 if (!fmd->fimc[i])
471 break;
472 /*
473 * Some FIMC variants are not fitted with camera capture
474 * interface. Skip creating a link from sensor for those.
475 */
237e0265 476 if (sensor->grp_id == SENSOR_GROUP_ID &&
d3953223
SN
477 !fmd->fimc[i]->variant->has_cam_if)
478 continue;
479
480 flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0;
693f5c40 481 sink = &fmd->fimc[i]->vid_cap.subdev.entity;
237e0265
SN
482 ret = media_entity_create_link(source, pad, sink,
483 FIMC_SD_PAD_SINK, flags);
d3953223
SN
484 if (ret)
485 return ret;
486
237e0265
SN
487 /* Notify FIMC capture subdev entity */
488 ret = media_entity_call(sink, link_setup, &sink->pads[0],
489 &source->pads[pad], flags);
490 if (ret)
491 break;
492
d3953223
SN
493 v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]",
494 source->name, flags ? '=' : '-', sink->name);
495
237e0265 496 if (flags == 0)
d3953223
SN
497 continue;
498 s_info = v4l2_get_subdev_hostdata(sensor);
499 if (!WARN_ON(s_info == NULL)) {
500 unsigned long irq_flags;
501 spin_lock_irqsave(&fmd->slock, irq_flags);
502 s_info->host = fmd->fimc[i];
503 spin_unlock_irqrestore(&fmd->slock, irq_flags);
504 }
505 }
506 return 0;
507}
508
509/**
510 * fimc_md_create_links - create default links between registered entities
511 *
512 * Parallel interface sensor entities are connected directly to FIMC capture
513 * entities. The sensors using MIPI CSIS bus are connected through immutable
514 * link with CSI receiver entity specified by mux_id. Any registered CSIS
515 * entity has a link to each registered FIMC capture entity. Enabled links
516 * are created by default between each subsequent registered sensor and
517 * subsequent FIMC capture entity. The number of default active links is
518 * determined by the number of available sensors or FIMC entities,
519 * whichever is less.
520 */
521static int fimc_md_create_links(struct fimc_md *fmd)
522{
523 struct v4l2_subdev *sensor, *csis;
524 struct s5p_fimc_isp_info *pdata;
525 struct fimc_sensor_info *s_info;
237e0265
SN
526 struct media_entity *source, *sink;
527 int i, pad, fimc_id = 0;
d3953223 528 int ret = 0;
237e0265 529 u32 flags;
d3953223
SN
530
531 for (i = 0; i < fmd->num_sensors; i++) {
532 if (fmd->sensor[i].subdev == NULL)
533 continue;
534
535 sensor = fmd->sensor[i].subdev;
536 s_info = v4l2_get_subdev_hostdata(sensor);
537 if (!s_info || !s_info->pdata)
538 continue;
539
540 source = NULL;
541 pdata = s_info->pdata;
542
543 switch (pdata->bus_type) {
544 case FIMC_MIPI_CSI2:
545 if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
546 "Wrong CSI channel id: %d\n", pdata->mux_id))
547 return -EINVAL;
548
549 csis = fmd->csis[pdata->mux_id].sd;
550 if (WARN(csis == NULL,
551 "MIPI-CSI interface specified "
552 "but s5p-csis module is not loaded!\n"))
d12392ec 553 return -EINVAL;
d3953223
SN
554
555 ret = media_entity_create_link(&sensor->entity, 0,
556 &csis->entity, CSIS_PAD_SINK,
557 MEDIA_LNK_FL_IMMUTABLE |
558 MEDIA_LNK_FL_ENABLED);
559 if (ret)
560 return ret;
561
562 v4l2_info(&fmd->v4l2_dev, "created link [%s] => [%s]",
563 sensor->entity.name, csis->entity.name);
564
d3953223
SN
565 source = &csis->entity;
566 pad = CSIS_PAD_SOURCE;
567 break;
568
569 case FIMC_ITU_601...FIMC_ITU_656:
570 source = &sensor->entity;
571 pad = 0;
572 break;
573
574 default:
575 v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
576 pdata->bus_type);
577 return -EINVAL;
578 }
579 if (source == NULL)
580 continue;
581
582 ret = __fimc_md_create_fimc_links(fmd, source, sensor, pad,
237e0265 583 fimc_id++);
d3953223 584 }
237e0265
SN
585 /* Create immutable links between each FIMC's subdev and video node */
586 flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
587 for (i = 0; i < FIMC_MAX_DEVS; i++) {
588 if (!fmd->fimc[i])
589 continue;
693f5c40 590 source = &fmd->fimc[i]->vid_cap.subdev.entity;
237e0265
SN
591 sink = &fmd->fimc[i]->vid_cap.vfd->entity;
592 ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
593 sink, 0, flags);
594 if (ret)
595 break;
596 }
597
d3953223
SN
598 return ret;
599}
600
601/*
602 * The peripheral sensor clock management.
603 */
604static int fimc_md_get_clocks(struct fimc_md *fmd)
605{
606 char clk_name[32];
607 struct clk *clock;
608 int i;
609
610 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
611 snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i);
612 clock = clk_get(NULL, clk_name);
613 if (IS_ERR_OR_NULL(clock)) {
614 v4l2_err(&fmd->v4l2_dev, "Failed to get clock: %s",
615 clk_name);
616 return -ENXIO;
617 }
618 fmd->camclk[i].clock = clock;
619 }
620 return 0;
621}
622
623static void fimc_md_put_clocks(struct fimc_md *fmd)
624{
625 int i = FIMC_MAX_CAMCLKS;
626
627 while (--i >= 0) {
628 if (IS_ERR_OR_NULL(fmd->camclk[i].clock))
629 continue;
630 clk_put(fmd->camclk[i].clock);
631 fmd->camclk[i].clock = NULL;
632 }
633}
634
635static int __fimc_md_set_camclk(struct fimc_md *fmd,
636 struct fimc_sensor_info *s_info,
637 bool on)
638{
639 struct s5p_fimc_isp_info *pdata = s_info->pdata;
640 struct fimc_camclk_info *camclk;
641 int ret = 0;
642
643 if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL)
644 return -EINVAL;
645
646 if (s_info->clk_on == on)
647 return 0;
648 camclk = &fmd->camclk[pdata->clk_id];
649
650 dbg("camclk %d, f: %lu, clk: %p, on: %d",
651 pdata->clk_id, pdata->clk_frequency, camclk, on);
652
653 if (on) {
654 if (camclk->use_count > 0 &&
655 camclk->frequency != pdata->clk_frequency)
656 return -EINVAL;
657
658 if (camclk->use_count++ == 0) {
659 clk_set_rate(camclk->clock, pdata->clk_frequency);
660 camclk->frequency = pdata->clk_frequency;
661 ret = clk_enable(camclk->clock);
662 }
663 s_info->clk_on = 1;
664 dbg("Enabled camclk %d: f: %lu", pdata->clk_id,
665 clk_get_rate(camclk->clock));
666
667 return ret;
668 }
669
670 if (WARN_ON(camclk->use_count == 0))
671 return 0;
672
673 if (--camclk->use_count == 0) {
674 clk_disable(camclk->clock);
675 s_info->clk_on = 0;
676 dbg("Disabled camclk %d", pdata->clk_id);
677 }
678 return ret;
679}
680
681/**
682 * fimc_md_set_camclk - peripheral sensor clock setup
683 * @sd: sensor subdev to configure sclk_cam clock for
684 * @on: 1 to enable or 0 to disable the clock
685 *
686 * There are 2 separate clock outputs available in the SoC for external
687 * image processors. These clocks are shared between all registered FIMC
688 * devices to which sensors can be attached, either directly or through
689 * the MIPI CSI receiver. The clock is allowed here to be used by
690 * multiple sensors concurrently if they use same frequency.
691 * The per sensor subdev clk_on attribute helps to synchronize accesses
692 * to the sclk_cam clocks from the video and media device nodes.
693 * This function should only be called when the graph mutex is held.
694 */
695int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
696{
697 struct fimc_sensor_info *s_info = v4l2_get_subdev_hostdata(sd);
698 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
699
700 return __fimc_md_set_camclk(fmd, s_info, on);
701}
702
703static int fimc_md_link_notify(struct media_pad *source,
704 struct media_pad *sink, u32 flags)
705{
0f735f52 706 struct fimc_pipeline *pipeline;
237e0265 707 struct v4l2_subdev *sd;
d3953223
SN
708 struct fimc_dev *fimc;
709 int ret = 0;
710
237e0265 711 if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
d3953223
SN
712 return 0;
713
237e0265 714 sd = media_entity_to_v4l2_subdev(sink->entity);
d3953223 715
0f735f52
SN
716 switch (sd->grp_id) {
717 case FIMC_GROUP_ID:
718 fimc = v4l2_get_subdevdata(sd);
719 pipeline = &fimc->pipeline;
720 break;
721 default:
722 return 0;
723 }
131b6c61 724
0f735f52
SN
725 if (!(flags & MEDIA_LNK_FL_ENABLED)) {
726 ret = __fimc_pipeline_shutdown(pipeline);
727 pipeline->subdevs[IDX_SENSOR] = NULL;
728 pipeline->subdevs[IDX_CSIS] = NULL;
729
730 if (fimc) {
731 mutex_lock(&fimc->lock);
732 fimc_ctrls_delete(fimc->vid_cap.ctx);
733 mutex_unlock(&fimc->lock);
734 }
d3953223
SN
735 return ret;
736 }
737 /*
738 * Link activation. Enable power of pipeline elements only if the
739 * pipeline is already in use, i.e. its video node is opened.
131b6c61 740 * Recreate the controls destroyed during the link deactivation.
d3953223
SN
741 */
742 mutex_lock(&fimc->lock);
131b6c61 743 if (fimc->vid_cap.refcnt > 0) {
0f735f52
SN
744 ret = __fimc_pipeline_initialize(pipeline,
745 source->entity, true);
131b6c61
SN
746 if (!ret)
747 ret = fimc_capture_ctrls_create(fimc);
748 }
d3953223
SN
749 mutex_unlock(&fimc->lock);
750
751 return ret ? -EPIPE : ret;
752}
753
754static ssize_t fimc_md_sysfs_show(struct device *dev,
755 struct device_attribute *attr, char *buf)
756{
757 struct platform_device *pdev = to_platform_device(dev);
758 struct fimc_md *fmd = platform_get_drvdata(pdev);
759
760 if (fmd->user_subdev_api)
761 return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE);
762
763 return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
764}
765
766static ssize_t fimc_md_sysfs_store(struct device *dev,
767 struct device_attribute *attr,
768 const char *buf, size_t count)
769{
770 struct platform_device *pdev = to_platform_device(dev);
771 struct fimc_md *fmd = platform_get_drvdata(pdev);
772 bool subdev_api;
773 int i;
774
775 if (!strcmp(buf, "vid-dev\n"))
776 subdev_api = false;
777 else if (!strcmp(buf, "sub-dev\n"))
778 subdev_api = true;
779 else
780 return count;
781
782 fmd->user_subdev_api = subdev_api;
783 for (i = 0; i < FIMC_MAX_DEVS; i++)
784 if (fmd->fimc[i])
785 fmd->fimc[i]->vid_cap.user_subdev_api = subdev_api;
786 return count;
787}
788/*
789 * This device attribute is to select video pipeline configuration method.
790 * There are following valid values:
791 * vid-dev - for V4L2 video node API only, subdevice will be configured
792 * by the host driver.
793 * sub-dev - for media controller API, subdevs must be configured in user
794 * space before starting streaming.
795 */
796static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
797 fimc_md_sysfs_show, fimc_md_sysfs_store);
798
ecd9acbf 799static int fimc_md_probe(struct platform_device *pdev)
d3953223
SN
800{
801 struct v4l2_device *v4l2_dev;
802 struct fimc_md *fmd;
803 int ret;
804
6d91a51a 805 fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL);
d3953223
SN
806 if (!fmd)
807 return -ENOMEM;
808
809 spin_lock_init(&fmd->slock);
810 fmd->pdev = pdev;
811
812 strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
813 sizeof(fmd->media_dev.model));
814 fmd->media_dev.link_notify = fimc_md_link_notify;
815 fmd->media_dev.dev = &pdev->dev;
816
817 v4l2_dev = &fmd->v4l2_dev;
818 v4l2_dev->mdev = &fmd->media_dev;
e1d72f4d 819 v4l2_dev->notify = fimc_sensor_notify;
d3953223
SN
820 snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s",
821 dev_name(&pdev->dev));
822
823 ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
824 if (ret < 0) {
825 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
6d91a51a 826 return ret;
d3953223
SN
827 }
828 ret = media_device_register(&fmd->media_dev);
829 if (ret < 0) {
830 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
693f5c40 831 goto err_md;
d3953223
SN
832 }
833 ret = fimc_md_get_clocks(fmd);
834 if (ret)
693f5c40 835 goto err_clk;
d3953223
SN
836
837 fmd->user_subdev_api = false;
693f5c40
SN
838
839 /* Protect the media graph while we're registering entities */
840 mutex_lock(&fmd->media_dev.graph_mutex);
841
d3953223
SN
842 ret = fimc_md_register_platform_entities(fmd);
843 if (ret)
693f5c40 844 goto err_unlock;
d3953223 845
5cbf6f16
SN
846 if (pdev->dev.platform_data) {
847 ret = fimc_md_register_sensor_entities(fmd);
848 if (ret)
693f5c40 849 goto err_unlock;
5cbf6f16 850 }
d3953223
SN
851 ret = fimc_md_create_links(fmd);
852 if (ret)
693f5c40 853 goto err_unlock;
d3953223
SN
854 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
855 if (ret)
693f5c40 856 goto err_unlock;
d3953223
SN
857
858 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
693f5c40
SN
859 if (ret)
860 goto err_unlock;
861
862 platform_set_drvdata(pdev, fmd);
863 mutex_unlock(&fmd->media_dev.graph_mutex);
864 return 0;
865
866err_unlock:
867 mutex_unlock(&fmd->media_dev.graph_mutex);
868err_clk:
d3953223
SN
869 media_device_unregister(&fmd->media_dev);
870 fimc_md_put_clocks(fmd);
871 fimc_md_unregister_entities(fmd);
693f5c40 872err_md:
d3953223 873 v4l2_device_unregister(&fmd->v4l2_dev);
d3953223
SN
874 return ret;
875}
876
877static int __devexit fimc_md_remove(struct platform_device *pdev)
878{
879 struct fimc_md *fmd = platform_get_drvdata(pdev);
880
881 if (!fmd)
882 return 0;
883 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
884 fimc_md_unregister_entities(fmd);
885 media_device_unregister(&fmd->media_dev);
886 fimc_md_put_clocks(fmd);
d3953223
SN
887 return 0;
888}
889
890static struct platform_driver fimc_md_driver = {
891 .probe = fimc_md_probe,
892 .remove = __devexit_p(fimc_md_remove),
893 .driver = {
894 .name = "s5p-fimc-md",
895 .owner = THIS_MODULE,
896 }
897};
898
899int __init fimc_md_init(void)
900{
901 int ret;
ecd9acbf 902
d3953223
SN
903 request_module("s5p-csis");
904 ret = fimc_register_driver();
905 if (ret)
906 return ret;
ecd9acbf 907
d3953223
SN
908 return platform_driver_register(&fimc_md_driver);
909}
910void __exit fimc_md_exit(void)
911{
912 platform_driver_unregister(&fimc_md_driver);
913 fimc_unregister_driver();
914}
915
916module_init(fimc_md_init);
917module_exit(fimc_md_exit);
918
919MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
920MODULE_DESCRIPTION("S5P FIMC camera host interface/video postprocessor driver");
921MODULE_LICENSE("GPL");
922MODULE_VERSION("2.0.1");