aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/video4linux/fimc.txt30
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/media/platform/exynos4-is/Kconfig3
-rw-r--r--drivers/media/platform/exynos4-is/common.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-core.h2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp-video.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp.h2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite-reg.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-lite.h2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-reg.c2
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c329
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.h6
-rw-r--r--drivers/media/platform/exynos4-is/mipi-csis.c43
-rw-r--r--include/linux/platform_data/mipi-csis.h28
-rw-r--r--include/media/exynos-fimc.h (renamed from include/media/s5p_fimc.h)21
16 files changed, 50 insertions, 427 deletions
diff --git a/Documentation/video4linux/fimc.txt b/Documentation/video4linux/fimc.txt
index 7d6e160724bd..e0c6b8bc4743 100644
--- a/Documentation/video4linux/fimc.txt
+++ b/Documentation/video4linux/fimc.txt
@@ -140,39 +140,9 @@ You can either grep through the kernel log to find relevant information, i.e.
140or retrieve the information from /dev/media? with help of the media-ctl tool: 140or retrieve the information from /dev/media? with help of the media-ctl tool:
141# media-ctl -p 141# media-ctl -p
142 142
1436. Platform support
144===================
145
146The machine code (arch/arm/plat-samsung and arch/arm/mach-*) must select
147following options:
148
149CONFIG_S5P_DEV_FIMC0 mandatory
150CONFIG_S5P_DEV_FIMC1 \
151CONFIG_S5P_DEV_FIMC2 | optional
152CONFIG_S5P_DEV_FIMC3 |
153CONFIG_S5P_SETUP_FIMC /
154CONFIG_S5P_DEV_CSIS0 \ optional for MIPI-CSI interface
155CONFIG_S5P_DEV_CSIS1 /
156
157Except that, relevant s5p_device_fimc? should be registered in the machine code
158in addition to a "s5p-fimc-md" platform device to which the media device driver
159is bound. The "s5p-fimc-md" device instance is required even if only mem-to-mem
160operation is used.
161
162The description of sensor(s) attached to FIMC/MIPI-CSIS camera inputs should be
163passed as the "s5p-fimc-md" device platform_data. The platform data structure
164is defined in file include/media/s5p_fimc.h.
165
1667. Build 1437. Build
167======== 144========
168 145
169This driver depends on following config options:
170PLAT_S5P,
171PM_RUNTIME,
172I2C,
173REGULATOR,
174VIDEO_V4L2_SUBDEV_API,
175
176If the driver is built as a loadable kernel module (CONFIG_VIDEO_SAMSUNG_S5P_FIMC=m) 146If the driver is built as a loadable kernel module (CONFIG_VIDEO_SAMSUNG_S5P_FIMC=m)
177two modules are created (in addition to the core v4l2 modules): s5p-fimc.ko and 147two modules are created (in addition to the core v4l2 modules): s5p-fimc.ko and
178optional s5p-csis.ko (MIPI-CSI receiver subdev). 148optional s5p-csis.ko (MIPI-CSI receiver subdev).
diff --git a/MAINTAINERS b/MAINTAINERS
index 129621ed165f..6b7c633a2e98 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7654,7 +7654,6 @@ L: linux-media@vger.kernel.org
7654Q: https://patchwork.linuxtv.org/project/linux-media/list/ 7654Q: https://patchwork.linuxtv.org/project/linux-media/list/
7655S: Supported 7655S: Supported
7656F: drivers/media/platform/exynos4-is/ 7656F: drivers/media/platform/exynos4-is/
7657F: include/media/s5p_fimc.h
7658 7657
7659SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER 7658SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER
7660M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com> 7659M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
index e1b2ceba00c1..5dcaa0a80540 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -3,6 +3,7 @@ config VIDEO_SAMSUNG_EXYNOS4_IS
3 bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver" 3 bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver"
4 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 4 depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
5 depends on (PLAT_S5P || ARCH_EXYNOS) 5 depends on (PLAT_S5P || ARCH_EXYNOS)
6 depends on OF && COMMON_CLK
6 help 7 help
7 Say Y here to enable camera host interface devices for 8 Say Y here to enable camera host interface devices for
8 Samsung S5P and EXYNOS SoC series. 9 Samsung S5P and EXYNOS SoC series.
@@ -17,7 +18,7 @@ config VIDEO_S5P_FIMC
17 depends on I2C 18 depends on I2C
18 select VIDEOBUF2_DMA_CONTIG 19 select VIDEOBUF2_DMA_CONTIG
19 select V4L2_MEM2MEM_DEV 20 select V4L2_MEM2MEM_DEV
20 select MFD_SYSCON if OF 21 select MFD_SYSCON
21 select VIDEO_EXYNOS4_IS_COMMON 22 select VIDEO_EXYNOS4_IS_COMMON
22 help 23 help
23 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host 24 This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host
diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c
index 0ec210b4da1d..0eb34ecb8ee4 100644
--- a/drivers/media/platform/exynos4-is/common.c
+++ b/drivers/media/platform/exynos4-is/common.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <media/s5p_fimc.h> 13#include <media/exynos-fimc.h>
14#include "common.h" 14#include "common.h"
15 15
16/* Called with the media graph mutex held or entity->stream_count > 0. */ 16/* Called with the media graph mutex held or entity->stream_count > 0. */
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index 1790fb4e32ea..6c75c6ced1f7 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -27,7 +27,7 @@
27#include <media/v4l2-device.h> 27#include <media/v4l2-device.h>
28#include <media/v4l2-mem2mem.h> 28#include <media/v4l2-mem2mem.h>
29#include <media/v4l2-mediabus.h> 29#include <media/v4l2-mediabus.h>
30#include <media/s5p_fimc.h> 30#include <media/exynos-fimc.h>
31 31
32#define dbg(fmt, args...) \ 32#define dbg(fmt, args...) \
33 pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args) 33 pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args)
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
index ced46600e343..93f9cf2ebcd6 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -30,7 +30,7 @@
30#include <media/v4l2-ioctl.h> 30#include <media/v4l2-ioctl.h>
31#include <media/videobuf2-core.h> 31#include <media/videobuf2-core.h>
32#include <media/videobuf2-dma-contig.h> 32#include <media/videobuf2-dma-contig.h>
33#include <media/s5p_fimc.h> 33#include <media/exynos-fimc.h>
34 34
35#include "common.h" 35#include "common.h"
36#include "media-dev.h" 36#include "media-dev.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
index 4dc55a18d978..b99be09b49fc 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp.h
@@ -24,7 +24,7 @@
24#include <media/videobuf2-core.h> 24#include <media/videobuf2-core.h>
25#include <media/v4l2-device.h> 25#include <media/v4l2-device.h>
26#include <media/v4l2-mediabus.h> 26#include <media/v4l2-mediabus.h>
27#include <media/s5p_fimc.h> 27#include <media/exynos-fimc.h>
28 28
29extern int fimc_isp_debug; 29extern int fimc_isp_debug;
30 30
diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
index d0dc7ee04452..bc3ec7d25a32 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
@@ -12,7 +12,7 @@
12#include <linux/bitops.h> 12#include <linux/bitops.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/io.h> 14#include <linux/io.h>
15#include <media/s5p_fimc.h> 15#include <media/exynos-fimc.h>
16 16
17#include "fimc-lite-reg.h" 17#include "fimc-lite-reg.h"
18#include "fimc-lite.h" 18#include "fimc-lite.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 630aef52dbb8..a97d2352f1d7 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -30,7 +30,7 @@
30#include <media/v4l2-mem2mem.h> 30#include <media/v4l2-mem2mem.h>
31#include <media/videobuf2-core.h> 31#include <media/videobuf2-core.h>
32#include <media/videobuf2-dma-contig.h> 32#include <media/videobuf2-dma-contig.h>
33#include <media/s5p_fimc.h> 33#include <media/exynos-fimc.h>
34 34
35#include "common.h" 35#include "common.h"
36#include "fimc-core.h" 36#include "fimc-core.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
index 7428b2d22b52..ea19dc7be63e 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.h
+++ b/drivers/media/platform/exynos4-is/fimc-lite.h
@@ -23,7 +23,7 @@
23#include <media/v4l2-ctrls.h> 23#include <media/v4l2-ctrls.h>
24#include <media/v4l2-device.h> 24#include <media/v4l2-device.h>
25#include <media/v4l2-mediabus.h> 25#include <media/v4l2-mediabus.h>
26#include <media/s5p_fimc.h> 26#include <media/exynos-fimc.h>
27 27
28#define FIMC_LITE_DRV_NAME "exynos-fimc-lite" 28#define FIMC_LITE_DRV_NAME "exynos-fimc-lite"
29#define FLITE_CLK_NAME "flite" 29#define FLITE_CLK_NAME "flite"
diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c
index 1db8cb4c46ef..2d77fd8f440a 100644
--- a/drivers/media/platform/exynos4-is/fimc-reg.c
+++ b/drivers/media/platform/exynos4-is/fimc-reg.c
@@ -13,7 +13,7 @@
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/regmap.h> 14#include <linux/regmap.h>
15 15
16#include <media/s5p_fimc.h> 16#include <media/exynos-fimc.h>
17#include "media-dev.h" 17#include "media-dev.h"
18 18
19#include "fimc-reg.h" 19#include "fimc-reg.h"
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 6e2d6042ade6..344718df5c62 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -31,7 +31,7 @@
31#include <media/v4l2-ctrls.h> 31#include <media/v4l2-ctrls.h>
32#include <media/v4l2-of.h> 32#include <media/v4l2-of.h>
33#include <media/media-device.h> 33#include <media/media-device.h>
34#include <media/s5p_fimc.h> 34#include <media/exynos-fimc.h>
35 35
36#include "media-dev.h" 36#include "media-dev.h"
37#include "fimc-core.h" 37#include "fimc-core.h"
@@ -39,10 +39,6 @@
39#include "fimc-lite.h" 39#include "fimc-lite.h"
40#include "mipi-csis.h" 40#include "mipi-csis.h"
41 41
42static int __fimc_md_set_camclk(struct fimc_md *fmd,
43 struct fimc_source_info *si,
44 bool on);
45
46/* Set up image sensor subdev -> FIMC capture node notifications. */ 42/* Set up image sensor subdev -> FIMC capture node notifications. */
47static void __setup_sensor_notification(struct fimc_md *fmd, 43static void __setup_sensor_notification(struct fimc_md *fmd,
48 struct v4l2_subdev *sensor, 44 struct v4l2_subdev *sensor,
@@ -223,17 +219,10 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
223 return ret; 219 return ret;
224 } 220 }
225 221
226 ret = fimc_md_set_camclk(sd, true);
227 if (ret < 0)
228 goto err_wbclk;
229
230 ret = fimc_pipeline_s_power(p, 1); 222 ret = fimc_pipeline_s_power(p, 1);
231 if (!ret) 223 if (!ret)
232 return 0; 224 return 0;
233 225
234 fimc_md_set_camclk(sd, false);
235
236err_wbclk:
237 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP]) 226 if (!IS_ERR(fmd->wbclk[CLK_IDX_WB_B]) && p->subdevs[IDX_IS_ISP])
238 clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]); 227 clk_disable_unprepare(fmd->wbclk[CLK_IDX_WB_B]);
239 228
@@ -259,7 +248,6 @@ static int __fimc_pipeline_close(struct exynos_media_pipeline *ep)
259 } 248 }
260 249
261 ret = fimc_pipeline_s_power(p, 0); 250 ret = fimc_pipeline_s_power(p, 0);
262 fimc_md_set_camclk(sd, false);
263 251
264 fmd = entity_to_fimc_mdev(&sd->entity); 252 fmd = entity_to_fimc_mdev(&sd->entity);
265 253
@@ -337,75 +325,14 @@ static void fimc_md_pipelines_free(struct fimc_md *fmd)
337 } 325 }
338} 326}
339 327
340/*
341 * Sensor subdevice helper functions
342 */
343static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
344 struct fimc_source_info *si)
345{
346 struct i2c_adapter *adapter;
347 struct v4l2_subdev *sd = NULL;
348
349 if (!si || !fmd)
350 return NULL;
351 /*
352 * If FIMC bus type is not Writeback FIFO assume it is same
353 * as sensor_bus_type.
354 */
355 si->fimc_bus_type = si->sensor_bus_type;
356
357 adapter = i2c_get_adapter(si->i2c_bus_num);
358 if (!adapter) {
359 v4l2_warn(&fmd->v4l2_dev,
360 "Failed to get I2C adapter %d, deferring probe\n",
361 si->i2c_bus_num);
362 return ERR_PTR(-EPROBE_DEFER);
363 }
364 sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
365 si->board_info, NULL);
366 if (IS_ERR_OR_NULL(sd)) {
367 i2c_put_adapter(adapter);
368 v4l2_warn(&fmd->v4l2_dev,
369 "Failed to acquire subdev %s, deferring probe\n",
370 si->board_info->type);
371 return ERR_PTR(-EPROBE_DEFER);
372 }
373 v4l2_set_subdev_hostdata(sd, si);
374 sd->grp_id = GRP_ID_SENSOR;
375
376 v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
377 sd->name);
378 return sd;
379}
380
381static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
382{
383 struct i2c_client *client = v4l2_get_subdevdata(sd);
384 struct i2c_adapter *adapter;
385
386 if (!client || client->dev.of_node)
387 return;
388
389 v4l2_device_unregister_subdev(sd);
390
391 adapter = client->adapter;
392 i2c_unregister_device(client);
393 if (adapter)
394 i2c_put_adapter(adapter);
395}
396
397#ifdef CONFIG_OF
398/* Parse port node and register as a sub-device any sensor specified there. */ 328/* Parse port node and register as a sub-device any sensor specified there. */
399static int fimc_md_parse_port_node(struct fimc_md *fmd, 329static int fimc_md_parse_port_node(struct fimc_md *fmd,
400 struct device_node *port, 330 struct device_node *port,
401 unsigned int index) 331 unsigned int index)
402{ 332{
333 struct fimc_source_info *pd = &fmd->sensor[index].pdata;
403 struct device_node *rem, *ep, *np; 334 struct device_node *rem, *ep, *np;
404 struct fimc_source_info *pd;
405 struct v4l2_of_endpoint endpoint; 335 struct v4l2_of_endpoint endpoint;
406 u32 val;
407
408 pd = &fmd->sensor[index].pdata;
409 336
410 /* Assume here a port node can have only one endpoint node. */ 337 /* Assume here a port node can have only one endpoint node. */
411 ep = of_get_next_child(port, NULL); 338 ep = of_get_next_child(port, NULL);
@@ -425,20 +352,6 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
425 ep->full_name); 352 ep->full_name);
426 return 0; 353 return 0;
427 } 354 }
428 if (!of_property_read_u32(rem, "samsung,camclk-out", &val))
429 pd->clk_id = val;
430
431 if (!of_property_read_u32(rem, "clock-frequency", &val))
432 pd->clk_frequency = val;
433 else
434 pd->clk_frequency = DEFAULT_SENSOR_CLK_FREQ;
435
436 if (pd->clk_frequency == 0) {
437 v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n",
438 rem->full_name);
439 of_node_put(rem);
440 return -EINVAL;
441 }
442 355
443 if (fimc_input_is_parallel(endpoint.base.port)) { 356 if (fimc_input_is_parallel(endpoint.base.port)) {
444 if (endpoint.bus_type == V4L2_MBUS_PARALLEL) 357 if (endpoint.bus_type == V4L2_MBUS_PARALLEL)
@@ -485,14 +398,26 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
485} 398}
486 399
487/* Register all SoC external sub-devices */ 400/* Register all SoC external sub-devices */
488static int fimc_md_of_sensors_register(struct fimc_md *fmd, 401static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
489 struct device_node *np)
490{ 402{
491 struct device_node *parent = fmd->pdev->dev.of_node; 403 struct device_node *parent = fmd->pdev->dev.of_node;
492 struct device_node *node, *ports; 404 struct device_node *node, *ports;
493 int index = 0; 405 int index = 0;
494 int ret; 406 int ret;
495 407
408 /*
409 * Runtime resume one of the FIMC entities to make sure
410 * the sclk_cam clocks are not globally disabled.
411 */
412 if (!fmd->pmf)
413 return -ENXIO;
414
415 ret = pm_runtime_get_sync(fmd->pmf);
416 if (ret < 0)
417 return ret;
418
419 fmd->num_sensors = 0;
420
496 /* Attach sensors linked to MIPI CSI-2 receivers */ 421 /* Attach sensors linked to MIPI CSI-2 receivers */
497 for_each_available_child_of_node(parent, node) { 422 for_each_available_child_of_node(parent, node) {
498 struct device_node *port; 423 struct device_node *port;
@@ -506,14 +431,14 @@ static int fimc_md_of_sensors_register(struct fimc_md *fmd,
506 431
507 ret = fimc_md_parse_port_node(fmd, port, index); 432 ret = fimc_md_parse_port_node(fmd, port, index);
508 if (ret < 0) 433 if (ret < 0)
509 return ret; 434 goto rpm_put;
510 index++; 435 index++;
511 } 436 }
512 437
513 /* Attach sensors listed in the parallel-ports node */ 438 /* Attach sensors listed in the parallel-ports node */
514 ports = of_get_child_by_name(parent, "parallel-ports"); 439 ports = of_get_child_by_name(parent, "parallel-ports");
515 if (!ports) 440 if (!ports)
516 return 0; 441 goto rpm_put;
517 442
518 for_each_child_of_node(ports, node) { 443 for_each_child_of_node(ports, node) {
519 ret = fimc_md_parse_port_node(fmd, node, index); 444 ret = fimc_md_parse_port_node(fmd, node, index);
@@ -521,8 +446,9 @@ static int fimc_md_of_sensors_register(struct fimc_md *fmd,
521 break; 446 break;
522 index++; 447 index++;
523 } 448 }
524 449rpm_put:
525 return 0; 450 pm_runtime_put(fmd->pmf);
451 return ret;
526} 452}
527 453
528static int __of_get_csis_id(struct device_node *np) 454static int __of_get_csis_id(struct device_node *np)
@@ -535,68 +461,10 @@ static int __of_get_csis_id(struct device_node *np)
535 of_property_read_u32(np, "reg", &reg); 461 of_property_read_u32(np, "reg", &reg);
536 return reg - FIMC_INPUT_MIPI_CSI2_0; 462 return reg - FIMC_INPUT_MIPI_CSI2_0;
537} 463}
538#else
539#define fimc_md_of_sensors_register(fmd, np) (-ENOSYS)
540#define __of_get_csis_id(np) (-ENOSYS)
541#endif
542
543static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
544{
545 struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
546 struct device_node *of_node = fmd->pdev->dev.of_node;
547 int num_clients = 0;
548 int ret, i;
549
550 /*
551 * Runtime resume one of the FIMC entities to make sure
552 * the sclk_cam clocks are not globally disabled.
553 */
554 if (!fmd->pmf)
555 return -ENXIO;
556
557 ret = pm_runtime_get_sync(fmd->pmf);
558 if (ret < 0)
559 return ret;
560
561 if (of_node) {
562 fmd->num_sensors = 0;
563 ret = fimc_md_of_sensors_register(fmd, of_node);
564 } else if (pdata) {
565 WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
566 num_clients = min_t(u32, pdata->num_clients,
567 ARRAY_SIZE(fmd->sensor));
568 fmd->num_sensors = num_clients;
569
570 for (i = 0; i < num_clients; i++) {
571 struct fimc_sensor_info *si = &fmd->sensor[i];
572 struct v4l2_subdev *sd;
573
574 si->pdata = pdata->source_info[i];
575 ret = __fimc_md_set_camclk(fmd, &si->pdata, true);
576 if (ret)
577 break;
578 sd = fimc_md_register_sensor(fmd, &si->pdata);
579 ret = __fimc_md_set_camclk(fmd, &si->pdata, false);
580
581 if (IS_ERR(sd)) {
582 si->subdev = NULL;
583 ret = PTR_ERR(sd);
584 break;
585 }
586 si->subdev = sd;
587 if (ret)
588 break;
589 }
590 }
591
592 pm_runtime_put(fmd->pmf);
593 return ret;
594}
595 464
596/* 465/*
597 * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration. 466 * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration.
598 */ 467 */
599
600static int register_fimc_lite_entity(struct fimc_md *fmd, 468static int register_fimc_lite_entity(struct fimc_md *fmd,
601 struct fimc_lite *fimc_lite) 469 struct fimc_lite *fimc_lite)
602{ 470{
@@ -753,35 +621,9 @@ dev_unlock:
753 return ret; 621 return ret;
754} 622}
755 623
756static int fimc_md_pdev_match(struct device *dev, void *data)
757{
758 struct platform_device *pdev = to_platform_device(dev);
759 int plat_entity = -1;
760 int ret;
761 char *p;
762
763 if (!get_device(dev))
764 return -ENODEV;
765
766 if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) {
767 plat_entity = IDX_CSIS;
768 } else {
769 p = strstr(pdev->name, "fimc");
770 if (p && *(p + 4) == 0)
771 plat_entity = IDX_FIMC;
772 }
773
774 if (plat_entity >= 0)
775 ret = fimc_md_register_platform_entity(data, pdev,
776 plat_entity);
777 put_device(dev);
778 return 0;
779}
780
781/* Register FIMC, FIMC-LITE and CSIS media entities */ 624/* Register FIMC, FIMC-LITE and CSIS media entities */
782#ifdef CONFIG_OF 625static int fimc_md_register_platform_entities(struct fimc_md *fmd,
783static int fimc_md_register_of_platform_entities(struct fimc_md *fmd, 626 struct device_node *parent)
784 struct device_node *parent)
785{ 627{
786 struct device_node *node; 628 struct device_node *node;
787 int ret = 0; 629 int ret = 0;
@@ -815,9 +657,6 @@ static int fimc_md_register_of_platform_entities(struct fimc_md *fmd,
815 657
816 return ret; 658 return ret;
817} 659}
818#else
819#define fimc_md_register_of_platform_entities(fmd, node) (-ENOSYS)
820#endif
821 660
822static void fimc_md_unregister_entities(struct fimc_md *fmd) 661static void fimc_md_unregister_entities(struct fimc_md *fmd)
823{ 662{
@@ -845,14 +684,6 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
845 v4l2_device_unregister_subdev(fmd->csis[i].sd); 684 v4l2_device_unregister_subdev(fmd->csis[i].sd);
846 fmd->csis[i].sd = NULL; 685 fmd->csis[i].sd = NULL;
847 } 686 }
848 if (fmd->pdev->dev.of_node == NULL) {
849 for (i = 0; i < fmd->num_sensors; i++) {
850 if (fmd->sensor[i].subdev == NULL)
851 continue;
852 fimc_md_unregister_sensor(fmd->sensor[i].subdev);
853 fmd->sensor[i].subdev = NULL;
854 }
855 }
856 687
857 if (fmd->fimc_is) 688 if (fmd->fimc_is)
858 v4l2_device_unregister_subdev(&fmd->fimc_is->isp.subdev); 689 v4l2_device_unregister_subdev(&fmd->fimc_is->isp.subdev);
@@ -1137,7 +968,7 @@ static void fimc_md_put_clocks(struct fimc_md *fmd)
1137 968
1138static int fimc_md_get_clocks(struct fimc_md *fmd) 969static int fimc_md_get_clocks(struct fimc_md *fmd)
1139{ 970{
1140 struct device *dev = NULL; 971 struct device *dev = &fmd->pdev->dev;
1141 char clk_name[32]; 972 char clk_name[32];
1142 struct clk *clock; 973 struct clk *clock;
1143 int i, ret = 0; 974 int i, ret = 0;
@@ -1145,16 +976,12 @@ static int fimc_md_get_clocks(struct fimc_md *fmd)
1145 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) 976 for (i = 0; i < FIMC_MAX_CAMCLKS; i++)
1146 fmd->camclk[i].clock = ERR_PTR(-EINVAL); 977 fmd->camclk[i].clock = ERR_PTR(-EINVAL);
1147 978
1148 if (fmd->pdev->dev.of_node)
1149 dev = &fmd->pdev->dev;
1150
1151 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) { 979 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
1152 snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i); 980 snprintf(clk_name, sizeof(clk_name), "sclk_cam%u", i);
1153 clock = clk_get(dev, clk_name); 981 clock = clk_get(dev, clk_name);
1154 982
1155 if (IS_ERR(clock)) { 983 if (IS_ERR(clock)) {
1156 dev_err(&fmd->pdev->dev, "Failed to get clock: %s\n", 984 dev_err(dev, "Failed to get clock: %s\n", clk_name);
1157 clk_name);
1158 ret = PTR_ERR(clock); 985 ret = PTR_ERR(clock);
1159 break; 986 break;
1160 } 987 }
@@ -1188,86 +1015,6 @@ static int fimc_md_get_clocks(struct fimc_md *fmd)
1188 return ret; 1015 return ret;
1189} 1016}
1190 1017
1191static int __fimc_md_set_camclk(struct fimc_md *fmd,
1192 struct fimc_source_info *si,
1193 bool on)
1194{
1195 struct fimc_camclk_info *camclk;
1196 int ret = 0;
1197
1198 /*
1199 * When device tree is used the sensor drivers are supposed to
1200 * control the clock themselves. This whole function will be
1201 * removed once S5PV210 platform is converted to the device tree.
1202 */
1203 if (fmd->pdev->dev.of_node)
1204 return 0;
1205
1206 if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf)
1207 return -EINVAL;
1208
1209 camclk = &fmd->camclk[si->clk_id];
1210
1211 dbg("camclk %d, f: %lu, use_count: %d, on: %d",
1212 si->clk_id, si->clk_frequency, camclk->use_count, on);
1213
1214 if (on) {
1215 if (camclk->use_count > 0 &&
1216 camclk->frequency != si->clk_frequency)
1217 return -EINVAL;
1218
1219 if (camclk->use_count++ == 0) {
1220 clk_set_rate(camclk->clock, si->clk_frequency);
1221 camclk->frequency = si->clk_frequency;
1222 ret = pm_runtime_get_sync(fmd->pmf);
1223 if (ret < 0)
1224 return ret;
1225 ret = clk_prepare_enable(camclk->clock);
1226 dbg("Enabled camclk %d: f: %lu", si->clk_id,
1227 clk_get_rate(camclk->clock));
1228 }
1229 return ret;
1230 }
1231
1232 if (WARN_ON(camclk->use_count == 0))
1233 return 0;
1234
1235 if (--camclk->use_count == 0) {
1236 clk_disable_unprepare(camclk->clock);
1237 pm_runtime_put(fmd->pmf);
1238 dbg("Disabled camclk %d", si->clk_id);
1239 }
1240 return ret;
1241}
1242
1243/**
1244 * fimc_md_set_camclk - peripheral sensor clock setup
1245 * @sd: sensor subdev to configure sclk_cam clock for
1246 * @on: 1 to enable or 0 to disable the clock
1247 *
1248 * There are 2 separate clock outputs available in the SoC for external
1249 * image processors. These clocks are shared between all registered FIMC
1250 * devices to which sensors can be attached, either directly or through
1251 * the MIPI CSI receiver. The clock is allowed here to be used by
1252 * multiple sensors concurrently if they use same frequency.
1253 * This function should only be called when the graph mutex is held.
1254 */
1255int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
1256{
1257 struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd);
1258 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
1259
1260 /*
1261 * If there is a clock provider registered the sensors will
1262 * handle their clock themselves, no need to control it on
1263 * the host interface side.
1264 */
1265 if (fmd->clk_provider.num_clocks > 0)
1266 return 0;
1267
1268 return __fimc_md_set_camclk(fmd, si, on);
1269}
1270
1271static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable) 1018static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable)
1272{ 1019{
1273 struct exynos_video_entity *ve; 1020 struct exynos_video_entity *ve;
@@ -1426,7 +1173,6 @@ static int fimc_md_get_pinctrl(struct fimc_md *fmd)
1426 return 0; 1173 return 0;
1427} 1174}
1428 1175
1429#ifdef CONFIG_OF
1430static int cam_clk_prepare(struct clk_hw *hw) 1176static int cam_clk_prepare(struct clk_hw *hw)
1431{ 1177{
1432 struct cam_clk *camclk = to_cam_clk(hw); 1178 struct cam_clk *camclk = to_cam_clk(hw);
@@ -1518,10 +1264,6 @@ err:
1518 fimc_md_unregister_clk_provider(fmd); 1264 fimc_md_unregister_clk_provider(fmd);
1519 return ret; 1265 return ret;
1520} 1266}
1521#else
1522#define fimc_md_register_clk_provider(fmd) (0)
1523#define fimc_md_unregister_clk_provider(fmd)
1524#endif
1525 1267
1526static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, 1268static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
1527 struct v4l2_subdev *subdev, 1269 struct v4l2_subdev *subdev,
@@ -1585,8 +1327,8 @@ static int fimc_md_probe(struct platform_device *pdev)
1585 return -ENOMEM; 1327 return -ENOMEM;
1586 1328
1587 spin_lock_init(&fmd->slock); 1329 spin_lock_init(&fmd->slock);
1588 fmd->pdev = pdev;
1589 INIT_LIST_HEAD(&fmd->pipelines); 1330 INIT_LIST_HEAD(&fmd->pipelines);
1331 fmd->pdev = pdev;
1590 1332
1591 strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", 1333 strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
1592 sizeof(fmd->media_dev.model)); 1334 sizeof(fmd->media_dev.model));
@@ -1599,6 +1341,7 @@ static int fimc_md_probe(struct platform_device *pdev)
1599 strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name)); 1341 strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
1600 1342
1601 fmd->use_isp = fimc_md_is_isp_available(dev->of_node); 1343 fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
1344 fmd->user_subdev_api = true;
1602 1345
1603 ret = v4l2_device_register(dev, &fmd->v4l2_dev); 1346 ret = v4l2_device_register(dev, &fmd->v4l2_dev);
1604 if (ret < 0) { 1347 if (ret < 0) {
@@ -1616,8 +1359,6 @@ static int fimc_md_probe(struct platform_device *pdev)
1616 if (ret) 1359 if (ret)
1617 goto err_md; 1360 goto err_md;
1618 1361
1619 fmd->user_subdev_api = (dev->of_node != NULL);
1620
1621 ret = fimc_md_get_pinctrl(fmd); 1362 ret = fimc_md_get_pinctrl(fmd);
1622 if (ret < 0) { 1363 if (ret < 0) {
1623 if (ret != EPROBE_DEFER) 1364 if (ret != EPROBE_DEFER)
@@ -1630,22 +1371,16 @@ static int fimc_md_probe(struct platform_device *pdev)
1630 /* Protect the media graph while we're registering entities */ 1371 /* Protect the media graph while we're registering entities */
1631 mutex_lock(&fmd->media_dev.graph_mutex); 1372 mutex_lock(&fmd->media_dev.graph_mutex);
1632 1373
1633 if (dev->of_node) 1374 ret = fimc_md_register_platform_entities(fmd, dev->of_node);
1634 ret = fimc_md_register_of_platform_entities(fmd, dev->of_node);
1635 else
1636 ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
1637 fimc_md_pdev_match);
1638 if (ret) { 1375 if (ret) {
1639 mutex_unlock(&fmd->media_dev.graph_mutex); 1376 mutex_unlock(&fmd->media_dev.graph_mutex);
1640 goto err_clk; 1377 goto err_clk;
1641 } 1378 }
1642 1379
1643 if (dev->platform_data || dev->of_node) { 1380 ret = fimc_md_register_sensor_entities(fmd);
1644 ret = fimc_md_register_sensor_entities(fmd); 1381 if (ret) {
1645 if (ret) { 1382 mutex_unlock(&fmd->media_dev.graph_mutex);
1646 mutex_unlock(&fmd->media_dev.graph_mutex); 1383 goto err_m_ent;
1647 goto err_m_ent;
1648 }
1649 } 1384 }
1650 1385
1651 mutex_unlock(&fmd->media_dev.graph_mutex); 1386 mutex_unlock(&fmd->media_dev.graph_mutex);
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 58c49456b13f..03214541f149 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -19,7 +19,7 @@
19#include <media/media-entity.h> 19#include <media/media-entity.h>
20#include <media/v4l2-device.h> 20#include <media/v4l2-device.h>
21#include <media/v4l2-subdev.h> 21#include <media/v4l2-subdev.h>
22#include <media/s5p_fimc.h> 22#include <media/exynos-fimc.h>
23 23
24#include "fimc-core.h" 24#include "fimc-core.h"
25#include "fimc-lite.h" 25#include "fimc-lite.h"
@@ -94,9 +94,7 @@ struct fimc_sensor_info {
94}; 94};
95 95
96struct cam_clk { 96struct cam_clk {
97#ifdef CONFIG_COMMON_CLK
98 struct clk_hw hw; 97 struct clk_hw hw;
99#endif
100 struct fimc_md *fmd; 98 struct fimc_md *fmd;
101}; 99};
102#define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw) 100#define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw)
@@ -144,9 +142,7 @@ struct fimc_md {
144 142
145 struct cam_clk_provider { 143 struct cam_clk_provider {
146 struct clk *clks[FIMC_MAX_CAMCLKS]; 144 struct clk *clks[FIMC_MAX_CAMCLKS];
147#ifdef CONFIG_COMMON_CLK
148 struct clk_onecell_data clk_data; 145 struct clk_onecell_data clk_data;
149#endif
150 struct device_node *of_node; 146 struct device_node *of_node;
151 struct cam_clk camclk[FIMC_MAX_CAMCLKS]; 147 struct cam_clk camclk[FIMC_MAX_CAMCLKS];
152 int num_clocks; 148 int num_clocks;
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index 3678ba59725c..ae54ef5f535d 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -22,14 +22,13 @@
22#include <linux/of.h> 22#include <linux/of.h>
23#include <linux/of_graph.h> 23#include <linux/of_graph.h>
24#include <linux/phy/phy.h> 24#include <linux/phy/phy.h>
25#include <linux/platform_data/mipi-csis.h>
26#include <linux/platform_device.h> 25#include <linux/platform_device.h>
27#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
28#include <linux/regulator/consumer.h> 27#include <linux/regulator/consumer.h>
29#include <linux/slab.h> 28#include <linux/slab.h>
30#include <linux/spinlock.h> 29#include <linux/spinlock.h>
31#include <linux/videodev2.h> 30#include <linux/videodev2.h>
32#include <media/s5p_fimc.h> 31#include <media/exynos-fimc.h>
33#include <media/v4l2-of.h> 32#include <media/v4l2-of.h>
34#include <media/v4l2-subdev.h> 33#include <media/v4l2-subdev.h>
35 34
@@ -730,26 +729,6 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
730 return IRQ_HANDLED; 729 return IRQ_HANDLED;
731} 730}
732 731
733static int s5pcsis_get_platform_data(struct platform_device *pdev,
734 struct csis_state *state)
735{
736 struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data;
737
738 if (pdata == NULL) {
739 dev_err(&pdev->dev, "Platform data not specified\n");
740 return -EINVAL;
741 }
742
743 state->clk_frequency = pdata->clk_rate;
744 state->num_lanes = pdata->lanes;
745 state->hs_settle = pdata->hs_settle;
746 state->index = max(0, pdev->id);
747 state->max_num_lanes = state->index ? CSIS1_MAX_LANES :
748 CSIS0_MAX_LANES;
749 return 0;
750}
751
752#ifdef CONFIG_OF
753static int s5pcsis_parse_dt(struct platform_device *pdev, 732static int s5pcsis_parse_dt(struct platform_device *pdev,
754 struct csis_state *state) 733 struct csis_state *state)
755{ 734{
@@ -787,9 +766,6 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,
787 766
788 return 0; 767 return 0;
789} 768}
790#else
791#define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
792#endif
793 769
794static int s5pcsis_pm_resume(struct device *dev, bool runtime); 770static int s5pcsis_pm_resume(struct device *dev, bool runtime);
795static const struct of_device_id s5pcsis_of_match[]; 771static const struct of_device_id s5pcsis_of_match[];
@@ -812,19 +788,14 @@ static int s5pcsis_probe(struct platform_device *pdev)
812 spin_lock_init(&state->slock); 788 spin_lock_init(&state->slock);
813 state->pdev = pdev; 789 state->pdev = pdev;
814 790
815 if (dev->of_node) { 791 of_id = of_match_node(s5pcsis_of_match, dev->of_node);
816 of_id = of_match_node(s5pcsis_of_match, dev->of_node); 792 if (WARN_ON(of_id == NULL))
817 if (WARN_ON(of_id == NULL)) 793 return -EINVAL;
818 return -EINVAL;
819
820 drv_data = of_id->data;
821 state->interrupt_mask = drv_data->interrupt_mask;
822 794
823 ret = s5pcsis_parse_dt(pdev, state); 795 drv_data = of_id->data;
824 } else { 796 state->interrupt_mask = drv_data->interrupt_mask;
825 ret = s5pcsis_get_platform_data(pdev, state);
826 }
827 797
798 ret = s5pcsis_parse_dt(pdev, state);
828 if (ret < 0) 799 if (ret < 0)
829 return ret; 800 return ret;
830 801
diff --git a/include/linux/platform_data/mipi-csis.h b/include/linux/platform_data/mipi-csis.h
deleted file mode 100644
index c2fd9024717c..000000000000
--- a/include/linux/platform_data/mipi-csis.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Copyright (C) 2010 - 2012 Samsung Electronics Co., Ltd.
3 *
4 * Samsung S5P/Exynos SoC series MIPI CSIS device support
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __PLAT_SAMSUNG_MIPI_CSIS_H_
12#define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
13
14/**
15 * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
16 * @clk_rate: bus clock frequency
17 * @wclk_source: CSI wrapper clock selection: 0 - bus clock, 1 - ext. SCLK_CAM
18 * @lanes: number of data lanes used
19 * @hs_settle: HS-RX settle time
20 */
21struct s5p_platform_mipi_csis {
22 unsigned long clk_rate;
23 u8 wclk_source;
24 u8 lanes;
25 u8 hs_settle;
26};
27
28#endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff --git a/include/media/s5p_fimc.h b/include/media/exynos-fimc.h
index b975c285c8a9..aa44660e2041 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/exynos-fimc.h
@@ -61,41 +61,20 @@ enum fimc_bus_type {
61#define GRP_ID_FLITE (1 << 13) 61#define GRP_ID_FLITE (1 << 13)
62#define GRP_ID_FIMC_IS (1 << 14) 62#define GRP_ID_FIMC_IS (1 << 14)
63 63
64struct i2c_board_info;
65
66/** 64/**
67 * struct fimc_source_info - video source description required for the host 65 * struct fimc_source_info - video source description required for the host
68 * interface configuration 66 * interface configuration
69 * 67 *
70 * @board_info: pointer to I2C subdevice's board info
71 * @clk_frequency: frequency of the clock the host interface provides to sensor
72 * @fimc_bus_type: FIMC camera input type 68 * @fimc_bus_type: FIMC camera input type
73 * @sensor_bus_type: image sensor bus type, MIPI, ITU-R BT.601 etc. 69 * @sensor_bus_type: image sensor bus type, MIPI, ITU-R BT.601 etc.
74 * @flags: the parallel sensor bus flags defining signals polarity (V4L2_MBUS_*) 70 * @flags: the parallel sensor bus flags defining signals polarity (V4L2_MBUS_*)
75 * @i2c_bus_num: i2c control bus id the sensor is attached to
76 * @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU) 71 * @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU)
77 * @clk_id: index of the SoC peripheral clock for sensors
78 */ 72 */
79struct fimc_source_info { 73struct fimc_source_info {
80 struct i2c_board_info *board_info;
81 unsigned long clk_frequency;
82 enum fimc_bus_type fimc_bus_type; 74 enum fimc_bus_type fimc_bus_type;
83 enum fimc_bus_type sensor_bus_type; 75 enum fimc_bus_type sensor_bus_type;
84 u16 flags; 76 u16 flags;
85 u16 i2c_bus_num;
86 u16 mux_id; 77 u16 mux_id;
87 u8 clk_id;
88};
89
90/**
91 * struct s5p_platform_fimc - camera host interface platform data
92 *
93 * @source_info: properties of an image source for the host interface setup
94 * @num_clients: the number of attached image sources
95 */
96struct s5p_platform_fimc {
97 struct fimc_source_info *source_info;
98 int num_clients;
99}; 78};
100 79
101/* 80/*