aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/media/samsung-fimc.txt44
-rw-r--r--Documentation/devicetree/bindings/media/samsung-s5c73m3.txt97
-rw-r--r--Documentation/devicetree/bindings/media/samsung-s5k6a3.txt33
-rw-r--r--Documentation/video4linux/fimc.txt5
-rw-r--r--drivers/media/i2c/Kconfig8
-rw-r--r--drivers/media/i2c/Makefile1
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c207
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-spi.c6
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3.h4
-rw-r--r--drivers/media/i2c/s5k6a3.c389
-rw-r--r--drivers/media/platform/exynos4-is/Kconfig9
-rw-r--r--drivers/media/platform/exynos4-is/Makefile4
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-param.c2
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-param.h5
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-regs.c16
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-regs.h1
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-sensor.c285
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is-sensor.h49
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is.c98
-rw-r--r--drivers/media/platform/exynos4-is/fimc-is.h9
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp-video.c660
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp-video.h44
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp.c29
-rw-r--r--drivers/media/platform/exynos4-is/fimc-isp.h27
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c363
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.h32
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-regs.h24
27 files changed, 1886 insertions, 565 deletions
diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt
index 96312f6c4c26..922d6f8e74be 100644
--- a/Documentation/devicetree/bindings/media/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt
@@ -15,11 +15,21 @@ Common 'camera' node
15 15
16Required properties: 16Required properties:
17 17
18- compatible : must be "samsung,fimc", "simple-bus" 18- compatible: must be "samsung,fimc", "simple-bus"
19- clocks : list of clock specifiers, corresponding to entries in 19- clocks: list of clock specifiers, corresponding to entries in
20 the clock-names property; 20 the clock-names property;
21- clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0", 21- clock-names : must contain "sclk_cam0", "sclk_cam1", "pxl_async0",
22 "pxl_async1" entries, matching entries in the clocks property. 22 "pxl_async1" entries, matching entries in the clocks property.
23
24- #clock-cells: from the common clock bindings (../clock/clock-bindings.txt),
25 must be 1. A clock provider is associated with the 'camera' node and it should
26 be referenced by external sensors that use clocks provided by the SoC on
27 CAM_*_CLKOUT pins. The clock specifier cell stores an index of a clock.
28 The indices are 0, 1 for CAM_A_CLKOUT, CAM_B_CLKOUT clocks respectively.
29
30- clock-output-names: from the common clock bindings, should contain names of
31 clocks registered by the camera subsystem corresponding to CAM_A_CLKOUT,
32 CAM_B_CLKOUT output clocks respectively.
23 33
24The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used 34The pinctrl bindings defined in ../pinctrl/pinctrl-bindings.txt must be used
25to define a required pinctrl state named "default" and optional pinctrl states: 35to define a required pinctrl state named "default" and optional pinctrl states:
@@ -32,6 +42,7 @@ way around.
32 42
33The 'camera' node must include at least one 'fimc' child node. 43The 'camera' node must include at least one 'fimc' child node.
34 44
45
35'fimc' device nodes 46'fimc' device nodes
36------------------- 47-------------------
37 48
@@ -88,8 +99,8 @@ port nodes specifies data input - 0, 1 indicates input A, B respectively.
88 99
89Optional properties 100Optional properties
90 101
91- samsung,camclk-out : specifies clock output for remote sensor, 102- samsung,camclk-out (deprecated) : specifies clock output for remote sensor,
92 0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT; 103 0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
93 104
94Image sensor nodes 105Image sensor nodes
95------------------ 106------------------
@@ -97,8 +108,6 @@ Image sensor nodes
97The sensor device nodes should be added to their control bus controller (e.g. 108The sensor device nodes should be added to their control bus controller (e.g.
98I2C0) nodes and linked to a port node in the csis or the parallel-ports node, 109I2C0) nodes and linked to a port node in the csis or the parallel-ports node,
99using the common video interfaces bindings, defined in video-interfaces.txt. 110using the common video interfaces bindings, defined in video-interfaces.txt.
100The implementation of this bindings requires clock-frequency property to be
101present in the sensor device nodes.
102 111
103Example: 112Example:
104 113
@@ -114,7 +123,7 @@ Example:
114 vddio-supply = <...>; 123 vddio-supply = <...>;
115 124
116 clock-frequency = <24000000>; 125 clock-frequency = <24000000>;
117 clocks = <...>; 126 clocks = <&camera 1>;
118 clock-names = "mclk"; 127 clock-names = "mclk";
119 128
120 port { 129 port {
@@ -135,7 +144,7 @@ Example:
135 vddio-supply = <...>; 144 vddio-supply = <...>;
136 145
137 clock-frequency = <24000000>; 146 clock-frequency = <24000000>;
138 clocks = <...>; 147 clocks = <&camera 0>;
139 clock-names = "mclk"; 148 clock-names = "mclk";
140 149
141 port { 150 port {
@@ -149,12 +158,17 @@ Example:
149 158
150 camera { 159 camera {
151 compatible = "samsung,fimc", "simple-bus"; 160 compatible = "samsung,fimc", "simple-bus";
152 #address-cells = <1>; 161 clocks = <&clock 132>, <&clock 133>, <&clock 351>,
153 #size-cells = <1>; 162 <&clock 352>;
154 status = "okay"; 163 clock-names = "sclk_cam0", "sclk_cam1", "pxl_async0",
155 164 "pxl_async1";
165 #clock-cells = <1>;
166 clock-output-names = "cam_a_clkout", "cam_b_clkout";
156 pinctrl-names = "default"; 167 pinctrl-names = "default";
157 pinctrl-0 = <&cam_port_a_clk_active>; 168 pinctrl-0 = <&cam_port_a_clk_active>;
169 status = "okay";
170 #address-cells = <1>;
171 #size-cells = <1>;
158 172
159 /* parallel camera ports */ 173 /* parallel camera ports */
160 parallel-ports { 174 parallel-ports {
diff --git a/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
new file mode 100644
index 000000000000..2c85c4538a6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
@@ -0,0 +1,97 @@
1Samsung S5C73M3 8Mp camera ISP
2------------------------------
3
4The S5C73M3 camera ISP supports MIPI CSI-2 and parallel (ITU-R BT.656) video
5data busses. The I2C bus is the main control bus and additionally the SPI bus
6is used, mostly for transferring the firmware to and from the device. Two
7slave device nodes corresponding to these control bus interfaces are required
8and should be placed under respective bus controller nodes.
9
10I2C slave device node
11---------------------
12
13Required properties:
14
15- compatible : "samsung,s5c73m3";
16- reg : I2C slave address of the sensor;
17- vdd-int-supply : digital power supply (1.2V);
18- vdda-supply : analog power supply (1.2V);
19- vdd-reg-supply : regulator input power supply (2.8V);
20- vddio-host-supply : host I/O power supply (1.8V to 2.8V);
21- vddio-cis-supply : CIS I/O power supply (1.2V to 1.8V);
22- vdd-af-supply : lens power supply (2.8V);
23- xshutdown-gpios : specifier of GPIO connected to the XSHUTDOWN pin;
24- standby-gpios : specifier of GPIO connected to the STANDBY pin;
25- clocks : should contain list of phandle and clock specifier pairs
26 according to common clock bindings for the clocks described
27 in the clock-names property;
28- clock-names : should contain "cis_extclk" entry for the CIS_EXTCLK clock;
29
30Optional properties:
31
32- clock-frequency : the frequency at which the "cis_extclk" clock should be
33 configured to operate, in Hz; if this property is not
34 specified default 24 MHz value will be used.
35
36The common video interfaces bindings (see video-interfaces.txt) should be used
37to specify link from the S5C73M3 to an external image data receiver. The S5C73M3
38device node should contain one 'port' child node with an 'endpoint' subnode for
39this purpose. The data link from a raw image sensor to the S5C73M3 can be
40similarly specified, but it is optional since the S5C73M3 ISP and a raw image
41sensor are usually inseparable and form a hybrid module.
42
43Following properties are valid for the endpoint node(s):
44
45endpoint subnode
46----------------
47
48- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
49 video-interfaces.txt. This sensor doesn't support data lane remapping
50 and physical lane indexes in subsequent elements of the array should
51 be only consecutive ascending values.
52
53SPI device node
54---------------
55
56Required properties:
57
58- compatible : "samsung,s5c73m3";
59
60For more details see description of the SPI busses bindings
61(../spi/spi-bus.txt) and bindings of a specific bus controller.
62
63Example:
64
65i2c@138A000000 {
66 ...
67 s5c73m3@3c {
68 compatible = "samsung,s5c73m3";
69 reg = <0x3c>;
70 vdd-int-supply = <&buck9_reg>;
71 vdda-supply = <&ldo17_reg>;
72 vdd-reg-supply = <&cam_io_reg>;
73 vddio-host-supply = <&ldo18_reg>;
74 vddio-cis-supply = <&ldo9_reg>;
75 vdd-af-supply = <&cam_af_reg>;
76 clock-frequency = <24000000>;
77 clocks = <&clk 0>;
78 clock-names = "cis_extclk";
79 reset-gpios = <&gpf1 3 1>;
80 standby-gpios = <&gpm0 1 1>;
81 port {
82 s5c73m3_ep: endpoint {
83 remote-endpoint = <&csis0_ep>;
84 data-lanes = <1 2 3 4>;
85 };
86 };
87 };
88};
89
90spi@1392000 {
91 ...
92 s5c73m3_spi: s5c73m3@0 {
93 compatible = "samsung,s5c73m3";
94 reg = <0>;
95 ...
96 };
97};
diff --git a/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt b/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
new file mode 100644
index 000000000000..cce01e82f3e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/samsung-s5k6a3.txt
@@ -0,0 +1,33 @@
1Samsung S5K6A3(YX) raw image sensor
2---------------------------------
3
4S5K6A3(YX) is a raw image sensor with MIPI CSI-2 and CCP2 image data interfaces
5and CCI (I2C compatible) control bus.
6
7Required properties:
8
9- compatible : "samsung,s5k6a3";
10- reg : I2C slave address of the sensor;
11- svdda-supply : core voltage supply;
12- svddio-supply : I/O voltage supply;
13- afvdd-supply : AF (actuator) voltage supply;
14- gpios : specifier of a GPIO connected to the RESET pin;
15- clocks : should contain list of phandle and clock specifier pairs
16 according to common clock bindings for the clocks described
17 in the clock-names property;
18- clock-names : should contain "extclk" entry for the sensor's EXTCLK clock;
19
20Optional properties:
21
22- clock-frequency : the frequency at which the "extclk" clock should be
23 configured to operate, in Hz; if this property is not
24 specified default 24 MHz value will be used.
25
26The common video interfaces bindings (see video-interfaces.txt) should be
27used to specify link to the image data receiver. The S5K6A3(YX) device
28node should contain one 'port' child node with an 'endpoint' subnode.
29
30Following properties are valid for the endpoint node:
31
32- data-lanes : (optional) specifies MIPI CSI-2 data lanes as covered in
33 video-interfaces.txt. The sensor supports only one data lane.
diff --git a/Documentation/video4linux/fimc.txt b/Documentation/video4linux/fimc.txt
index e51f1b5b7324..7d6e160724bd 100644
--- a/Documentation/video4linux/fimc.txt
+++ b/Documentation/video4linux/fimc.txt
@@ -151,9 +151,8 @@ CONFIG_S5P_DEV_FIMC1 \
151CONFIG_S5P_DEV_FIMC2 | optional 151CONFIG_S5P_DEV_FIMC2 | optional
152CONFIG_S5P_DEV_FIMC3 | 152CONFIG_S5P_DEV_FIMC3 |
153CONFIG_S5P_SETUP_FIMC / 153CONFIG_S5P_SETUP_FIMC /
154CONFIG_S5P_SETUP_MIPIPHY \ 154CONFIG_S5P_DEV_CSIS0 \ optional for MIPI-CSI interface
155CONFIG_S5P_DEV_CSIS0 | optional for MIPI-CSI interface 155CONFIG_S5P_DEV_CSIS1 /
156CONFIG_S5P_DEV_CSIS1 /
157 156
158Except that, relevant s5p_device_fimc? should be registered in the machine code 157Except that, relevant s5p_device_fimc? should be registered in the machine code
159in addition to a "s5p-fimc-md" platform device to which the media device driver 158in addition to a "s5p-fimc-md" platform device to which the media device driver
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index c930be30eb7e..441053be7f55 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -579,6 +579,14 @@ config VIDEO_S5K6AA
579 This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M 579 This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
580 camera sensor with an embedded SoC image signal processor. 580 camera sensor with an embedded SoC image signal processor.
581 581
582config VIDEO_S5K6A3
583 tristate "Samsung S5K6A3 sensor support"
584 depends on MEDIA_CAMERA_SUPPORT
585 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
586 ---help---
587 This is a V4L2 sensor-level driver for Samsung S5K6A3 raw
588 camera sensor.
589
582config VIDEO_S5K4ECGX 590config VIDEO_S5K4ECGX
583 tristate "Samsung S5K4ECGX sensor support" 591 tristate "Samsung S5K4ECGX sensor support"
584 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 592 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 01b6bfc0db5b..01ae9328e582 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
66obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o 66obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
67obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o 67obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
68obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o 68obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
69obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o
69obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o 70obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
70obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o 71obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o
71obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/ 72obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index e7f555cc827a..a4459301b5f8 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -15,7 +15,7 @@
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 */ 16 */
17 17
18#include <linux/sizes.h> 18#include <linux/clk.h>
19#include <linux/delay.h> 19#include <linux/delay.h>
20#include <linux/firmware.h> 20#include <linux/firmware.h>
21#include <linux/gpio.h> 21#include <linux/gpio.h>
@@ -23,7 +23,9 @@
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/media.h> 24#include <linux/media.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/of_gpio.h>
26#include <linux/regulator/consumer.h> 27#include <linux/regulator/consumer.h>
28#include <linux/sizes.h>
27#include <linux/slab.h> 29#include <linux/slab.h>
28#include <linux/spi/spi.h> 30#include <linux/spi/spi.h>
29#include <linux/videodev2.h> 31#include <linux/videodev2.h>
@@ -33,6 +35,7 @@
33#include <media/v4l2-subdev.h> 35#include <media/v4l2-subdev.h>
34#include <media/v4l2-mediabus.h> 36#include <media/v4l2-mediabus.h>
35#include <media/s5c73m3.h> 37#include <media/s5c73m3.h>
38#include <media/v4l2-of.h>
36 39
37#include "s5c73m3.h" 40#include "s5c73m3.h"
38 41
@@ -46,6 +49,8 @@ static int update_fw;
46module_param(update_fw, int, 0644); 49module_param(update_fw, int, 0644);
47 50
48#define S5C73M3_EMBEDDED_DATA_MAXLEN SZ_4K 51#define S5C73M3_EMBEDDED_DATA_MAXLEN SZ_4K
52#define S5C73M3_MIPI_DATA_LANES 4
53#define S5C73M3_CLK_NAME "cis_extclk"
49 54
50static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = { 55static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = {
51 "vdd-int", /* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */ 56 "vdd-int", /* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */
@@ -1355,9 +1360,20 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
1355 for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) { 1360 for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) {
1356 ret = regulator_enable(state->supplies[i].consumer); 1361 ret = regulator_enable(state->supplies[i].consumer);
1357 if (ret) 1362 if (ret)
1358 goto err; 1363 goto err_reg_dis;
1359 } 1364 }
1360 1365
1366 ret = clk_set_rate(state->clock, state->mclk_frequency);
1367 if (ret < 0)
1368 goto err_reg_dis;
1369
1370 ret = clk_prepare_enable(state->clock);
1371 if (ret < 0)
1372 goto err_reg_dis;
1373
1374 v4l2_dbg(1, s5c73m3_dbg, &state->oif_sd, "clock frequency: %ld\n",
1375 clk_get_rate(state->clock));
1376
1361 s5c73m3_gpio_deassert(state, STBY); 1377 s5c73m3_gpio_deassert(state, STBY);
1362 usleep_range(100, 200); 1378 usleep_range(100, 200);
1363 1379
@@ -1365,7 +1381,8 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
1365 usleep_range(50, 100); 1381 usleep_range(50, 100);
1366 1382
1367 return 0; 1383 return 0;
1368err: 1384
1385err_reg_dis:
1369 for (--i; i >= 0; i--) 1386 for (--i; i >= 0; i--)
1370 regulator_disable(state->supplies[i].consumer); 1387 regulator_disable(state->supplies[i].consumer);
1371 return ret; 1388 return ret;
@@ -1380,6 +1397,9 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
1380 1397
1381 if (s5c73m3_gpio_assert(state, STBY)) 1398 if (s5c73m3_gpio_assert(state, STBY))
1382 usleep_range(100, 200); 1399 usleep_range(100, 200);
1400
1401 clk_disable_unprepare(state->clock);
1402
1383 state->streaming = 0; 1403 state->streaming = 0;
1384 state->isp_ready = 0; 1404 state->isp_ready = 0;
1385 1405
@@ -1388,6 +1408,7 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
1388 if (ret) 1408 if (ret)
1389 goto err; 1409 goto err;
1390 } 1410 }
1411
1391 return 0; 1412 return 0;
1392err: 1413err:
1393 for (++i; i < S5C73M3_MAX_SUPPLIES; i++) { 1414 for (++i; i < S5C73M3_MAX_SUPPLIES; i++) {
@@ -1396,6 +1417,8 @@ err:
1396 v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n", 1417 v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n",
1397 state->supplies[i].supply, r); 1418 state->supplies[i].supply, r);
1398 } 1419 }
1420
1421 clk_prepare_enable(state->clock);
1399 return ret; 1422 return ret;
1400} 1423}
1401 1424
@@ -1451,17 +1474,6 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
1451 S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD, 1474 S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
1452 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); 1475 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1453 1476
1454 mutex_lock(&state->lock);
1455 ret = __s5c73m3_power_on(state);
1456 if (ret == 0)
1457 s5c73m3_get_fw_version(state);
1458
1459 __s5c73m3_power_off(state);
1460 mutex_unlock(&state->lock);
1461
1462 v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n",
1463 __func__, ret ? "failed" : "succeeded", ret);
1464
1465 return ret; 1477 return ret;
1466} 1478}
1467 1479
@@ -1519,41 +1531,112 @@ static const struct v4l2_subdev_ops oif_subdev_ops = {
1519 .video = &s5c73m3_oif_video_ops, 1531 .video = &s5c73m3_oif_video_ops,
1520}; 1532};
1521 1533
1522static int s5c73m3_configure_gpios(struct s5c73m3 *state, 1534static int s5c73m3_configure_gpios(struct s5c73m3 *state)
1523 const struct s5c73m3_platform_data *pdata) 1535{
1536 static const char * const gpio_names[] = {
1537 "S5C73M3_STBY", "S5C73M3_RST"
1538 };
1539 struct i2c_client *c = state->i2c_client;
1540 struct s5c73m3_gpio *g = state->gpio;
1541 int ret, i;
1542
1543 for (i = 0; i < GPIO_NUM; ++i) {
1544 unsigned int flags = GPIOF_DIR_OUT;
1545 if (g[i].level)
1546 flags |= GPIOF_INIT_HIGH;
1547 ret = devm_gpio_request_one(&c->dev, g[i].gpio, flags,
1548 gpio_names[i]);
1549 if (ret) {
1550 v4l2_err(c, "failed to request gpio %s\n",
1551 gpio_names[i]);
1552 return ret;
1553 }
1554 }
1555 return 0;
1556}
1557
1558static int s5c73m3_parse_gpios(struct s5c73m3 *state)
1559{
1560 static const char * const prop_names[] = {
1561 "standby-gpios", "xshutdown-gpios",
1562 };
1563 struct device *dev = &state->i2c_client->dev;
1564 struct device_node *node = dev->of_node;
1565 int ret, i;
1566
1567 for (i = 0; i < GPIO_NUM; ++i) {
1568 enum of_gpio_flags of_flags;
1569
1570 ret = of_get_named_gpio_flags(node, prop_names[i],
1571 0, &of_flags);
1572 if (ret < 0) {
1573 dev_err(dev, "failed to parse %s DT property\n",
1574 prop_names[i]);
1575 return -EINVAL;
1576 }
1577 state->gpio[i].gpio = ret;
1578 state->gpio[i].level = !(of_flags & OF_GPIO_ACTIVE_LOW);
1579 }
1580 return 0;
1581}
1582
1583static int s5c73m3_get_platform_data(struct s5c73m3 *state)
1524{ 1584{
1525 struct device *dev = &state->i2c_client->dev; 1585 struct device *dev = &state->i2c_client->dev;
1526 const struct s5c73m3_gpio *gpio; 1586 const struct s5c73m3_platform_data *pdata = dev->platform_data;
1527 unsigned long flags; 1587 struct device_node *node = dev->of_node;
1588 struct device_node *node_ep;
1589 struct v4l2_of_endpoint ep;
1528 int ret; 1590 int ret;
1529 1591
1530 state->gpio[STBY].gpio = -EINVAL; 1592 if (!node) {
1531 state->gpio[RST].gpio = -EINVAL; 1593 if (!pdata) {
1594 dev_err(dev, "Platform data not specified\n");
1595 return -EINVAL;
1596 }
1532 1597
1533 gpio = &pdata->gpio_stby; 1598 state->mclk_frequency = pdata->mclk_frequency;
1534 if (gpio_is_valid(gpio->gpio)) { 1599 state->gpio[STBY] = pdata->gpio_stby;
1535 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) 1600 state->gpio[RST] = pdata->gpio_reset;
1536 | GPIOF_EXPORT; 1601 return 0;
1537 ret = devm_gpio_request_one(dev, gpio->gpio, flags, 1602 }
1538 "S5C73M3_STBY"); 1603
1539 if (ret < 0) 1604 state->clock = devm_clk_get(dev, S5C73M3_CLK_NAME);
1540 return ret; 1605 if (IS_ERR(state->clock))
1606 return PTR_ERR(state->clock);
1541 1607
1542 state->gpio[STBY] = *gpio; 1608 if (of_property_read_u32(node, "clock-frequency",
1609 &state->mclk_frequency)) {
1610 state->mclk_frequency = S5C73M3_DEFAULT_MCLK_FREQ;
1611 dev_info(dev, "using default %u Hz clock frequency\n",
1612 state->mclk_frequency);
1543 } 1613 }
1544 1614
1545 gpio = &pdata->gpio_reset; 1615 ret = s5c73m3_parse_gpios(state);
1546 if (gpio_is_valid(gpio->gpio)) { 1616 if (ret < 0)
1547 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) 1617 return -EINVAL;
1548 | GPIOF_EXPORT;
1549 ret = devm_gpio_request_one(dev, gpio->gpio, flags,
1550 "S5C73M3_RST");
1551 if (ret < 0)
1552 return ret;
1553 1618
1554 state->gpio[RST] = *gpio; 1619 node_ep = v4l2_of_get_next_endpoint(node, NULL);
1620 if (!node_ep) {
1621 dev_warn(dev, "no endpoint defined for node: %s\n",
1622 node->full_name);
1623 return 0;
1555 } 1624 }
1556 1625
1626 v4l2_of_parse_endpoint(node_ep, &ep);
1627 of_node_put(node_ep);
1628
1629 if (ep.bus_type != V4L2_MBUS_CSI2) {
1630 dev_err(dev, "unsupported bus type\n");
1631 return -EINVAL;
1632 }
1633 /*
1634 * Number of MIPI CSI-2 data lanes is currently not configurable,
1635 * always a default value of 4 lanes is used.
1636 */
1637 if (ep.bus.mipi_csi2.num_data_lanes != S5C73M3_MIPI_DATA_LANES)
1638 dev_info(dev, "falling back to 4 MIPI CSI-2 data lanes\n");
1639
1557 return 0; 1640 return 0;
1558} 1641}
1559 1642
@@ -1561,21 +1644,20 @@ static int s5c73m3_probe(struct i2c_client *client,
1561 const struct i2c_device_id *id) 1644 const struct i2c_device_id *id)
1562{ 1645{
1563 struct device *dev = &client->dev; 1646 struct device *dev = &client->dev;
1564 const struct s5c73m3_platform_data *pdata = client->dev.platform_data;
1565 struct v4l2_subdev *sd; 1647 struct v4l2_subdev *sd;
1566 struct v4l2_subdev *oif_sd; 1648 struct v4l2_subdev *oif_sd;
1567 struct s5c73m3 *state; 1649 struct s5c73m3 *state;
1568 int ret, i; 1650 int ret, i;
1569 1651
1570 if (pdata == NULL) {
1571 dev_err(&client->dev, "Platform data not specified\n");
1572 return -EINVAL;
1573 }
1574
1575 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); 1652 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
1576 if (!state) 1653 if (!state)
1577 return -ENOMEM; 1654 return -ENOMEM;
1578 1655
1656 state->i2c_client = client;
1657 ret = s5c73m3_get_platform_data(state);
1658 if (ret < 0)
1659 return ret;
1660
1579 mutex_init(&state->lock); 1661 mutex_init(&state->lock);
1580 sd = &state->sensor_sd; 1662 sd = &state->sensor_sd;
1581 oif_sd = &state->oif_sd; 1663 oif_sd = &state->oif_sd;
@@ -1613,11 +1695,7 @@ static int s5c73m3_probe(struct i2c_client *client,
1613 if (ret < 0) 1695 if (ret < 0)
1614 return ret; 1696 return ret;
1615 1697
1616 state->mclk_frequency = pdata->mclk_frequency; 1698 ret = s5c73m3_configure_gpios(state);
1617 state->bus_type = pdata->bus_type;
1618 state->i2c_client = client;
1619
1620 ret = s5c73m3_configure_gpios(state, pdata);
1621 if (ret) 1699 if (ret)
1622 goto out_err; 1700 goto out_err;
1623 1701
@@ -1651,9 +1729,29 @@ static int s5c73m3_probe(struct i2c_client *client,
1651 if (ret < 0) 1729 if (ret < 0)
1652 goto out_err; 1730 goto out_err;
1653 1731
1732 oif_sd->dev = dev;
1733
1734 ret = __s5c73m3_power_on(state);
1735 if (ret < 0)
1736 goto out_err1;
1737
1738 ret = s5c73m3_get_fw_version(state);
1739 __s5c73m3_power_off(state);
1740
1741 if (ret < 0) {
1742 dev_err(dev, "Device detection failed: %d\n", ret);
1743 goto out_err1;
1744 }
1745
1746 ret = v4l2_async_register_subdev(oif_sd);
1747 if (ret < 0)
1748 goto out_err1;
1749
1654 v4l2_info(sd, "%s: completed successfully\n", __func__); 1750 v4l2_info(sd, "%s: completed successfully\n", __func__);
1655 return 0; 1751 return 0;
1656 1752
1753out_err1:
1754 s5c73m3_unregister_spi_driver(state);
1657out_err: 1755out_err:
1658 media_entity_cleanup(&sd->entity); 1756 media_entity_cleanup(&sd->entity);
1659 return ret; 1757 return ret;
@@ -1665,7 +1763,7 @@ static int s5c73m3_remove(struct i2c_client *client)
1665 struct s5c73m3 *state = oif_sd_to_s5c73m3(oif_sd); 1763 struct s5c73m3 *state = oif_sd_to_s5c73m3(oif_sd);
1666 struct v4l2_subdev *sensor_sd = &state->sensor_sd; 1764 struct v4l2_subdev *sensor_sd = &state->sensor_sd;
1667 1765
1668 v4l2_device_unregister_subdev(oif_sd); 1766 v4l2_async_unregister_subdev(oif_sd);
1669 1767
1670 v4l2_ctrl_handler_free(oif_sd->ctrl_handler); 1768 v4l2_ctrl_handler_free(oif_sd->ctrl_handler);
1671 media_entity_cleanup(&oif_sd->entity); 1769 media_entity_cleanup(&oif_sd->entity);
@@ -1684,8 +1782,17 @@ static const struct i2c_device_id s5c73m3_id[] = {
1684}; 1782};
1685MODULE_DEVICE_TABLE(i2c, s5c73m3_id); 1783MODULE_DEVICE_TABLE(i2c, s5c73m3_id);
1686 1784
1785#ifdef CONFIG_OF
1786static const struct of_device_id s5c73m3_of_match[] = {
1787 { .compatible = "samsung,s5c73m3" },
1788 { }
1789};
1790MODULE_DEVICE_TABLE(of, s5c73m3_of_match);
1791#endif
1792
1687static struct i2c_driver s5c73m3_i2c_driver = { 1793static struct i2c_driver s5c73m3_i2c_driver = {
1688 .driver = { 1794 .driver = {
1795 .of_match_table = of_match_ptr(s5c73m3_of_match),
1689 .name = DRIVER_NAME, 1796 .name = DRIVER_NAME,
1690 }, 1797 },
1691 .probe = s5c73m3_probe, 1798 .probe = s5c73m3_probe,
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
index 8079e26eb5e2..f60b265b4da1 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
@@ -27,6 +27,11 @@
27 27
28#define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI" 28#define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI"
29 29
30static const struct of_device_id s5c73m3_spi_ids[] = {
31 { .compatible = "samsung,s5c73m3" },
32 { }
33};
34
30enum spi_direction { 35enum spi_direction {
31 SPI_DIR_RX, 36 SPI_DIR_RX,
32 SPI_DIR_TX 37 SPI_DIR_TX
@@ -146,6 +151,7 @@ int s5c73m3_register_spi_driver(struct s5c73m3 *state)
146 spidrv->driver.name = S5C73M3_SPI_DRV_NAME; 151 spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
147 spidrv->driver.bus = &spi_bus_type; 152 spidrv->driver.bus = &spi_bus_type;
148 spidrv->driver.owner = THIS_MODULE; 153 spidrv->driver.owner = THIS_MODULE;
154 spidrv->driver.of_match_table = s5c73m3_spi_ids;
149 155
150 return spi_register_driver(spidrv); 156 return spi_register_driver(spidrv);
151} 157}
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h
index 9dfa516f6944..9656b6723dc6 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3.h
+++ b/drivers/media/i2c/s5c73m3/s5c73m3.h
@@ -17,6 +17,7 @@
17#ifndef S5C73M3_H_ 17#ifndef S5C73M3_H_
18#define S5C73M3_H_ 18#define S5C73M3_H_
19 19
20#include <linux/clk.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
21#include <linux/regulator/consumer.h> 22#include <linux/regulator/consumer.h>
22#include <media/v4l2-common.h> 23#include <media/v4l2-common.h>
@@ -321,6 +322,7 @@ enum s5c73m3_oif_pads {
321 322
322 323
323#define S5C73M3_MAX_SUPPLIES 6 324#define S5C73M3_MAX_SUPPLIES 6
325#define S5C73M3_DEFAULT_MCLK_FREQ 24000000U
324 326
325struct s5c73m3_ctrls { 327struct s5c73m3_ctrls {
326 struct v4l2_ctrl_handler handler; 328 struct v4l2_ctrl_handler handler;
@@ -391,6 +393,8 @@ struct s5c73m3 {
391 struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES]; 393 struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES];
392 struct s5c73m3_gpio gpio[GPIO_NUM]; 394 struct s5c73m3_gpio gpio[GPIO_NUM];
393 395
396 struct clk *clock;
397
394 /* External master clock frequency */ 398 /* External master clock frequency */
395 u32 mclk_frequency; 399 u32 mclk_frequency;
396 /* Video bus type - MIPI-CSI2/parallel */ 400 /* Video bus type - MIPI-CSI2/parallel */
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
new file mode 100644
index 000000000000..7bc2271ca009
--- /dev/null
+++ b/drivers/media/i2c/s5k6a3.c
@@ -0,0 +1,389 @@
1/*
2 * Samsung S5K6A3 image sensor driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Author: 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 version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/gpio.h>
17#include <linux/i2c.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/of_gpio.h>
21#include <linux/pm_runtime.h>
22#include <linux/regulator/consumer.h>
23#include <linux/slab.h>
24#include <linux/videodev2.h>
25#include <media/v4l2-async.h>
26#include <media/v4l2-subdev.h>
27
28#define S5K6A3_SENSOR_MAX_WIDTH 1412
29#define S5K6A3_SENSOR_MAX_HEIGHT 1412
30#define S5K6A3_SENSOR_MIN_WIDTH 32
31#define S5K6A3_SENSOR_MIN_HEIGHT 32
32
33#define S5K6A3_DEFAULT_WIDTH 1296
34#define S5K6A3_DEFAULT_HEIGHT 732
35
36#define S5K6A3_DRV_NAME "S5K6A3"
37#define S5K6A3_CLK_NAME "extclk"
38#define S5K6A3_DEFAULT_CLK_FREQ 24000000U
39
40enum {
41 S5K6A3_SUPP_VDDA,
42 S5K6A3_SUPP_VDDIO,
43 S5K6A3_SUPP_AFVDD,
44 S5K6A3_NUM_SUPPLIES,
45};
46
47/**
48 * struct s5k6a3 - fimc-is sensor data structure
49 * @dev: pointer to this I2C client device structure
50 * @subdev: the image sensor's v4l2 subdev
51 * @pad: subdev media source pad
52 * @supplies: image sensor's voltage regulator supplies
53 * @gpio_reset: GPIO connected to the sensor's reset pin
54 * @lock: mutex protecting the structure's members below
55 * @format: media bus format at the sensor's source pad
56 */
57struct s5k6a3 {
58 struct device *dev;
59 struct v4l2_subdev subdev;
60 struct media_pad pad;
61 struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES];
62 int gpio_reset;
63 struct mutex lock;
64 struct v4l2_mbus_framefmt format;
65 struct clk *clock;
66 u32 clock_frequency;
67 int power_count;
68};
69
70static const char * const s5k6a3_supply_names[] = {
71 [S5K6A3_SUPP_VDDA] = "svdda",
72 [S5K6A3_SUPP_VDDIO] = "svddio",
73 [S5K6A3_SUPP_AFVDD] = "afvdd",
74};
75
76static inline struct s5k6a3 *sd_to_s5k6a3(struct v4l2_subdev *sd)
77{
78 return container_of(sd, struct s5k6a3, subdev);
79}
80
81static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
82 {
83 .code = V4L2_MBUS_FMT_SGRBG10_1X10,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .field = V4L2_FIELD_NONE,
86 }
87};
88
89static const struct v4l2_mbus_framefmt *find_sensor_format(
90 struct v4l2_mbus_framefmt *mf)
91{
92 int i;
93
94 for (i = 0; i < ARRAY_SIZE(s5k6a3_formats); i++)
95 if (mf->code == s5k6a3_formats[i].code)
96 return &s5k6a3_formats[i];
97
98 return &s5k6a3_formats[0];
99}
100
101static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
102 struct v4l2_subdev_fh *fh,
103 struct v4l2_subdev_mbus_code_enum *code)
104{
105 if (code->index >= ARRAY_SIZE(s5k6a3_formats))
106 return -EINVAL;
107
108 code->code = s5k6a3_formats[code->index].code;
109 return 0;
110}
111
112static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
113{
114 const struct v4l2_mbus_framefmt *fmt;
115
116 fmt = find_sensor_format(mf);
117 mf->code = fmt->code;
118 v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
119 S5K6A3_SENSOR_MAX_WIDTH, 0,
120 &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
121 S5K6A3_SENSOR_MAX_HEIGHT, 0, 0);
122}
123
124static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
125 struct s5k6a3 *sensor, struct v4l2_subdev_fh *fh,
126 u32 pad, enum v4l2_subdev_format_whence which)
127{
128 if (which == V4L2_SUBDEV_FORMAT_TRY)
129 return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
130
131 return &sensor->format;
132}
133
134static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
135 struct v4l2_subdev_fh *fh,
136 struct v4l2_subdev_format *fmt)
137{
138 struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
139 struct v4l2_mbus_framefmt *mf;
140
141 s5k6a3_try_format(&fmt->format);
142
143 mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
144 if (mf) {
145 mutex_lock(&sensor->lock);
146 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
147 *mf = fmt->format;
148 mutex_unlock(&sensor->lock);
149 }
150 return 0;
151}
152
153static int s5k6a3_get_fmt(struct v4l2_subdev *sd,
154 struct v4l2_subdev_fh *fh,
155 struct v4l2_subdev_format *fmt)
156{
157 struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
158 struct v4l2_mbus_framefmt *mf;
159
160 mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
161
162 mutex_lock(&sensor->lock);
163 fmt->format = *mf;
164 mutex_unlock(&sensor->lock);
165 return 0;
166}
167
168static struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
169 .enum_mbus_code = s5k6a3_enum_mbus_code,
170 .get_fmt = s5k6a3_get_fmt,
171 .set_fmt = s5k6a3_set_fmt,
172};
173
174static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
175{
176 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
177
178 *format = s5k6a3_formats[0];
179 format->width = S5K6A3_DEFAULT_WIDTH;
180 format->height = S5K6A3_DEFAULT_HEIGHT;
181
182 return 0;
183}
184
185static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops = {
186 .open = s5k6a3_open,
187};
188
189static int __s5k6a3_power_on(struct s5k6a3 *sensor)
190{
191 int i = S5K6A3_SUPP_VDDA;
192 int ret;
193
194 ret = clk_set_rate(sensor->clock, sensor->clock_frequency);
195 if (ret < 0)
196 return ret;
197
198 ret = pm_runtime_get(sensor->dev);
199 if (ret < 0)
200 return ret;
201
202 ret = regulator_enable(sensor->supplies[i].consumer);
203 if (ret < 0)
204 goto error_rpm_put;
205
206 ret = clk_prepare_enable(sensor->clock);
207 if (ret < 0)
208 goto error_reg_dis;
209
210 for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
211 ret = regulator_enable(sensor->supplies[i].consumer);
212 if (ret < 0)
213 goto error_reg_dis;
214 }
215
216 gpio_set_value(sensor->gpio_reset, 1);
217 usleep_range(600, 800);
218 gpio_set_value(sensor->gpio_reset, 0);
219 usleep_range(600, 800);
220 gpio_set_value(sensor->gpio_reset, 1);
221
222 /* Delay needed for the sensor initialization */
223 msleep(20);
224 return 0;
225
226error_reg_dis:
227 for (--i; i >= 0; --i)
228 regulator_disable(sensor->supplies[i].consumer);
229error_rpm_put:
230 pm_runtime_put(sensor->dev);
231 return ret;
232}
233
234static int __s5k6a3_power_off(struct s5k6a3 *sensor)
235{
236 int i;
237
238 gpio_set_value(sensor->gpio_reset, 0);
239
240 for (i = S5K6A3_NUM_SUPPLIES - 1; i >= 0; i--)
241 regulator_disable(sensor->supplies[i].consumer);
242
243 clk_disable_unprepare(sensor->clock);
244 pm_runtime_put(sensor->dev);
245 return 0;
246}
247
248static int s5k6a3_s_power(struct v4l2_subdev *sd, int on)
249{
250 struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
251 int ret = 0;
252
253 mutex_lock(&sensor->lock);
254
255 if (sensor->power_count == !on) {
256 if (on)
257 ret = __s5k6a3_power_on(sensor);
258 else
259 ret = __s5k6a3_power_off(sensor);
260
261 if (ret == 0)
262 sensor->power_count += on ? 1 : -1;
263 }
264
265 mutex_unlock(&sensor->lock);
266 return ret;
267}
268
269static struct v4l2_subdev_core_ops s5k6a3_core_ops = {
270 .s_power = s5k6a3_s_power,
271};
272
273static struct v4l2_subdev_ops s5k6a3_subdev_ops = {
274 .core = &s5k6a3_core_ops,
275 .pad = &s5k6a3_pad_ops,
276};
277
278static int s5k6a3_probe(struct i2c_client *client,
279 const struct i2c_device_id *id)
280{
281 struct device *dev = &client->dev;
282 struct s5k6a3 *sensor;
283 struct v4l2_subdev *sd;
284 int gpio, i, ret;
285
286 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
287 if (!sensor)
288 return -ENOMEM;
289
290 mutex_init(&sensor->lock);
291 sensor->gpio_reset = -EINVAL;
292 sensor->clock = ERR_PTR(-EINVAL);
293 sensor->dev = dev;
294
295 sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME);
296 if (IS_ERR(sensor->clock))
297 return PTR_ERR(sensor->clock);
298
299 gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
300 if (!gpio_is_valid(gpio))
301 return gpio;
302
303 ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
304 S5K6A3_DRV_NAME);
305 if (ret < 0)
306 return ret;
307
308 sensor->gpio_reset = gpio;
309
310 if (of_property_read_u32(dev->of_node, "clock-frequency",
311 &sensor->clock_frequency)) {
312 sensor->clock_frequency = S5K6A3_DEFAULT_CLK_FREQ;
313 dev_info(dev, "using default %u Hz clock frequency\n",
314 sensor->clock_frequency);
315 }
316
317 for (i = 0; i < S5K6A3_NUM_SUPPLIES; i++)
318 sensor->supplies[i].supply = s5k6a3_supply_names[i];
319
320 ret = devm_regulator_bulk_get(&client->dev, S5K6A3_NUM_SUPPLIES,
321 sensor->supplies);
322 if (ret < 0)
323 return ret;
324
325 sd = &sensor->subdev;
326 v4l2_i2c_subdev_init(sd, client, &s5k6a3_subdev_ops);
327 sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
328 sd->internal_ops = &s5k6a3_sd_internal_ops;
329
330 sensor->format.code = s5k6a3_formats[0].code;
331 sensor->format.width = S5K6A3_DEFAULT_WIDTH;
332 sensor->format.height = S5K6A3_DEFAULT_HEIGHT;
333
334 sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
335 ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
336 if (ret < 0)
337 return ret;
338
339 pm_runtime_no_callbacks(dev);
340 pm_runtime_enable(dev);
341
342 ret = v4l2_async_register_subdev(sd);
343
344 if (ret < 0) {
345 pm_runtime_disable(&client->dev);
346 media_entity_cleanup(&sd->entity);
347 }
348
349 return ret;
350}
351
352static int s5k6a3_remove(struct i2c_client *client)
353{
354 struct v4l2_subdev *sd = i2c_get_clientdata(client);
355
356 pm_runtime_disable(&client->dev);
357 v4l2_async_unregister_subdev(sd);
358 media_entity_cleanup(&sd->entity);
359 return 0;
360}
361
362static const struct i2c_device_id s5k6a3_ids[] = {
363 { }
364};
365
366#ifdef CONFIG_OF
367static const struct of_device_id s5k6a3_of_match[] = {
368 { .compatible = "samsung,s5k6a3" },
369 { /* sentinel */ }
370};
371MODULE_DEVICE_TABLE(of, s5k6a3_of_match);
372#endif
373
374static struct i2c_driver s5k6a3_driver = {
375 .driver = {
376 .of_match_table = of_match_ptr(s5k6a3_of_match),
377 .name = S5K6A3_DRV_NAME,
378 .owner = THIS_MODULE,
379 },
380 .probe = s5k6a3_probe,
381 .remove = s5k6a3_remove,
382 .id_table = s5k6a3_ids,
383};
384
385module_i2c_driver(s5k6a3_driver);
386
387MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
388MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
389MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
index 01ed1ecdff7e..e1b2ceba00c1 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -64,4 +64,13 @@ config VIDEO_EXYNOS4_FIMC_IS
64 To compile this driver as a module, choose M here: the 64 To compile this driver as a module, choose M here: the
65 module will be called exynos4-fimc-is. 65 module will be called exynos4-fimc-is.
66 66
67config VIDEO_EXYNOS4_ISP_DMA_CAPTURE
68 bool "EXYNOS4x12 FIMC-IS ISP Direct DMA capture support"
69 depends on VIDEO_EXYNOS4_FIMC_IS
70 select VIDEO_EXYNOS4_IS_COMMON
71 default y
72 help
73 This option enables an additional video device node exposing a V4L2
74 video capture interface for the FIMC-IS ISP raw (Bayer) capture DMA.
75
67endif # VIDEO_SAMSUNG_EXYNOS4_IS 76endif # VIDEO_SAMSUNG_EXYNOS4_IS
diff --git a/drivers/media/platform/exynos4-is/Makefile b/drivers/media/platform/exynos4-is/Makefile
index c2ff29ba6856..eed1b185d813 100644
--- a/drivers/media/platform/exynos4-is/Makefile
+++ b/drivers/media/platform/exynos4-is/Makefile
@@ -6,6 +6,10 @@ exynos4-is-common-objs := common.o
6exynos-fimc-is-objs := fimc-is.o fimc-isp.o fimc-is-sensor.o fimc-is-regs.o 6exynos-fimc-is-objs := fimc-is.o fimc-isp.o fimc-is-sensor.o fimc-is-regs.o
7exynos-fimc-is-objs += fimc-is-param.o fimc-is-errno.o fimc-is-i2c.o 7exynos-fimc-is-objs += fimc-is-param.o fimc-is-errno.o fimc-is-i2c.o
8 8
9ifeq ($(CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE),y)
10exynos-fimc-is-objs += fimc-isp-video.o
11endif
12
9obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o 13obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o
10obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o 14obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o
11obj-$(CONFIG_VIDEO_EXYNOS4_FIMC_IS) += exynos-fimc-is.o 15obj-$(CONFIG_VIDEO_EXYNOS4_FIMC_IS) += exynos-fimc-is.o
diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c
index 9bf3ddd9e028..bf1465d1bf6d 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-param.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-param.c
@@ -56,7 +56,7 @@ static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is)
56 __hw_param_copy(dst, src); 56 __hw_param_copy(dst, src);
57} 57}
58 58
59static int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset) 59int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset)
60{ 60{
61 struct is_param_region *par = &is->is_p_region->parameter; 61 struct is_param_region *par = &is->is_p_region->parameter;
62 struct chain_config *cfg = &is->config[is->config_index]; 62 struct chain_config *cfg = &is->config[is->config_index];
diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.h b/drivers/media/platform/exynos4-is/fimc-is-param.h
index f9358c27ae2d..8e31f7642776 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-param.h
+++ b/drivers/media/platform/exynos4-is/fimc-is-param.h
@@ -911,6 +911,10 @@ struct is_region {
911 u32 shared[MAX_SHARED_COUNT]; 911 u32 shared[MAX_SHARED_COUNT];
912} __packed; 912} __packed;
913 913
914/* Offset to the ISP DMA2 output buffer address array. */
915#define DMA2_OUTPUT_ADDR_ARRAY_OFFS \
916 (offsetof(struct is_region, shared) + 32 * sizeof(u32))
917
914struct is_debug_frame_descriptor { 918struct is_debug_frame_descriptor {
915 u32 sensor_frame_time; 919 u32 sensor_frame_time;
916 u32 sensor_exposure_time; 920 u32 sensor_exposure_time;
@@ -988,6 +992,7 @@ struct sensor_open_extended {
988struct fimc_is; 992struct fimc_is;
989 993
990int fimc_is_hw_get_sensor_max_framerate(struct fimc_is *is); 994int fimc_is_hw_get_sensor_max_framerate(struct fimc_is *is);
995int __fimc_is_hw_update_param(struct fimc_is *is, u32 offset);
991void fimc_is_set_initial_params(struct fimc_is *is); 996void fimc_is_set_initial_params(struct fimc_is *is);
992unsigned int __get_pending_param_count(struct fimc_is *is); 997unsigned int __get_pending_param_count(struct fimc_is *is);
993 998
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c
index 2628733c4e10..cfe4406a83ff 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-regs.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c
@@ -105,6 +105,20 @@ int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num_args)
105 return 0; 105 return 0;
106} 106}
107 107
108void fimc_is_hw_set_isp_buf_mask(struct fimc_is *is, unsigned int mask)
109{
110 if (hweight32(mask) == 1) {
111 dev_err(&is->pdev->dev, "%s(): not enough buffers (mask %#x)\n",
112 __func__, mask);
113 return;
114 }
115
116 if (mcuctl_read(is, MCUCTL_REG_ISSR(23)) != 0)
117 dev_dbg(&is->pdev->dev, "non-zero DMA buffer mask\n");
118
119 mcuctl_write(mask, is, MCUCTL_REG_ISSR(23));
120}
121
108void fimc_is_hw_set_sensor_num(struct fimc_is *is) 122void fimc_is_hw_set_sensor_num(struct fimc_is *is)
109{ 123{
110 pr_debug("setting sensor index to: %d\n", is->sensor_index); 124 pr_debug("setting sensor index to: %d\n", is->sensor_index);
@@ -112,7 +126,7 @@ void fimc_is_hw_set_sensor_num(struct fimc_is *is)
112 mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0)); 126 mcuctl_write(IH_REPLY_DONE, is, MCUCTL_REG_ISSR(0));
113 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); 127 mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1));
114 mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2)); 128 mcuctl_write(IHC_GET_SENSOR_NUM, is, MCUCTL_REG_ISSR(2));
115 mcuctl_write(FIMC_IS_SENSOR_NUM, is, MCUCTL_REG_ISSR(3)); 129 mcuctl_write(FIMC_IS_SENSORS_NUM, is, MCUCTL_REG_ISSR(3));
116} 130}
117 131
118void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index) 132void fimc_is_hw_close_sensor(struct fimc_is *is, unsigned int index)
diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.h b/drivers/media/platform/exynos4-is/fimc-is-regs.h
index 1d9d4ffc6ad5..141e5ddadbeb 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-regs.h
+++ b/drivers/media/platform/exynos4-is/fimc-is-regs.h
@@ -147,6 +147,7 @@ int fimc_is_hw_get_params(struct fimc_is *is, unsigned int num);
147void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is); 147void fimc_is_hw_set_intgr0_gd0(struct fimc_is *is);
148int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is); 148int fimc_is_hw_wait_intmsr0_intmsd0(struct fimc_is *is);
149void fimc_is_hw_set_sensor_num(struct fimc_is *is); 149void fimc_is_hw_set_sensor_num(struct fimc_is *is);
150void fimc_is_hw_set_isp_buf_mask(struct fimc_is *is, unsigned int mask);
150void fimc_is_hw_stream_on(struct fimc_is *is); 151void fimc_is_hw_stream_on(struct fimc_is *is);
151void fimc_is_hw_stream_off(struct fimc_is *is); 152void fimc_is_hw_stream_off(struct fimc_is *is);
152int fimc_is_hw_set_param(struct fimc_is *is); 153int fimc_is_hw_set_param(struct fimc_is *is);
diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.c b/drivers/media/platform/exynos4-is/fimc-is-sensor.c
index 6647421e5d3a..10e82e21b5d1 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-sensor.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-sensor.c
@@ -2,276 +2,21 @@
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver 2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 * 3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd. 4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 *
6 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> 5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
7 * 6 *
8 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
11 */ 10 */
12#include <linux/delay.h>
13#include <linux/device.h>
14#include <linux/errno.h>
15#include <linux/gpio.h>
16#include <linux/i2c.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/of_gpio.h>
20#include <linux/pm_runtime.h>
21#include <linux/regulator/consumer.h>
22#include <linux/slab.h>
23#include <media/v4l2-subdev.h>
24 11
25#include "fimc-is.h"
26#include "fimc-is-sensor.h" 12#include "fimc-is-sensor.h"
27 13
28#define DRIVER_NAME "FIMC-IS-SENSOR"
29
30static const char * const sensor_supply_names[] = {
31 "svdda",
32 "svddio",
33};
34
35static const struct v4l2_mbus_framefmt fimc_is_sensor_formats[] = {
36 {
37 .code = V4L2_MBUS_FMT_SGRBG10_1X10,
38 .colorspace = V4L2_COLORSPACE_SRGB,
39 .field = V4L2_FIELD_NONE,
40 }
41};
42
43static const struct v4l2_mbus_framefmt *find_sensor_format(
44 struct v4l2_mbus_framefmt *mf)
45{
46 int i;
47
48 for (i = 0; i < ARRAY_SIZE(fimc_is_sensor_formats); i++)
49 if (mf->code == fimc_is_sensor_formats[i].code)
50 return &fimc_is_sensor_formats[i];
51
52 return &fimc_is_sensor_formats[0];
53}
54
55static int fimc_is_sensor_enum_mbus_code(struct v4l2_subdev *sd,
56 struct v4l2_subdev_fh *fh,
57 struct v4l2_subdev_mbus_code_enum *code)
58{
59 if (code->index >= ARRAY_SIZE(fimc_is_sensor_formats))
60 return -EINVAL;
61
62 code->code = fimc_is_sensor_formats[code->index].code;
63 return 0;
64}
65
66static void fimc_is_sensor_try_format(struct fimc_is_sensor *sensor,
67 struct v4l2_mbus_framefmt *mf)
68{
69 const struct sensor_drv_data *dd = sensor->drvdata;
70 const struct v4l2_mbus_framefmt *fmt;
71
72 fmt = find_sensor_format(mf);
73 mf->code = fmt->code;
74 v4l_bound_align_image(&mf->width, 16 + 8, dd->width, 0,
75 &mf->height, 12 + 8, dd->height, 0, 0);
76}
77
78static struct v4l2_mbus_framefmt *__fimc_is_sensor_get_format(
79 struct fimc_is_sensor *sensor, struct v4l2_subdev_fh *fh,
80 u32 pad, enum v4l2_subdev_format_whence which)
81{
82 if (which == V4L2_SUBDEV_FORMAT_TRY)
83 return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
84
85 return &sensor->format;
86}
87
88static int fimc_is_sensor_set_fmt(struct v4l2_subdev *sd,
89 struct v4l2_subdev_fh *fh,
90 struct v4l2_subdev_format *fmt)
91{
92 struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
93 struct v4l2_mbus_framefmt *mf;
94
95 fimc_is_sensor_try_format(sensor, &fmt->format);
96
97 mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
98 if (mf) {
99 mutex_lock(&sensor->lock);
100 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
101 *mf = fmt->format;
102 mutex_unlock(&sensor->lock);
103 }
104 return 0;
105}
106
107static int fimc_is_sensor_get_fmt(struct v4l2_subdev *sd,
108 struct v4l2_subdev_fh *fh,
109 struct v4l2_subdev_format *fmt)
110{
111 struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
112 struct v4l2_mbus_framefmt *mf;
113
114 mf = __fimc_is_sensor_get_format(sensor, fh, fmt->pad, fmt->which);
115
116 mutex_lock(&sensor->lock);
117 fmt->format = *mf;
118 mutex_unlock(&sensor->lock);
119 return 0;
120}
121
122static struct v4l2_subdev_pad_ops fimc_is_sensor_pad_ops = {
123 .enum_mbus_code = fimc_is_sensor_enum_mbus_code,
124 .get_fmt = fimc_is_sensor_get_fmt,
125 .set_fmt = fimc_is_sensor_set_fmt,
126};
127
128static int fimc_is_sensor_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
129{
130 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
131
132 *format = fimc_is_sensor_formats[0];
133 format->width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
134 format->height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
135
136 return 0;
137}
138
139static const struct v4l2_subdev_internal_ops fimc_is_sensor_sd_internal_ops = {
140 .open = fimc_is_sensor_open,
141};
142
143static int fimc_is_sensor_s_power(struct v4l2_subdev *sd, int on)
144{
145 struct fimc_is_sensor *sensor = sd_to_fimc_is_sensor(sd);
146 int gpio = sensor->gpio_reset;
147 int ret;
148
149 if (on) {
150 ret = pm_runtime_get(sensor->dev);
151 if (ret < 0)
152 return ret;
153
154 ret = regulator_bulk_enable(SENSOR_NUM_SUPPLIES,
155 sensor->supplies);
156 if (ret < 0) {
157 pm_runtime_put(sensor->dev);
158 return ret;
159 }
160 if (gpio_is_valid(gpio)) {
161 gpio_set_value(gpio, 1);
162 usleep_range(600, 800);
163 gpio_set_value(gpio, 0);
164 usleep_range(10000, 11000);
165 gpio_set_value(gpio, 1);
166 }
167
168 /* A delay needed for the sensor initialization. */
169 msleep(20);
170 } else {
171 if (gpio_is_valid(gpio))
172 gpio_set_value(gpio, 0);
173
174 ret = regulator_bulk_disable(SENSOR_NUM_SUPPLIES,
175 sensor->supplies);
176 if (!ret)
177 pm_runtime_put(sensor->dev);
178 }
179
180 pr_info("%s:%d: on: %d, ret: %d\n", __func__, __LINE__, on, ret);
181
182 return ret;
183}
184
185static struct v4l2_subdev_core_ops fimc_is_sensor_core_ops = {
186 .s_power = fimc_is_sensor_s_power,
187};
188
189static struct v4l2_subdev_ops fimc_is_sensor_subdev_ops = {
190 .core = &fimc_is_sensor_core_ops,
191 .pad = &fimc_is_sensor_pad_ops,
192};
193
194static const struct of_device_id fimc_is_sensor_of_match[];
195
196static int fimc_is_sensor_probe(struct i2c_client *client,
197 const struct i2c_device_id *id)
198{
199 struct device *dev = &client->dev;
200 struct fimc_is_sensor *sensor;
201 const struct of_device_id *of_id;
202 struct v4l2_subdev *sd;
203 int gpio, i, ret;
204
205 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
206 if (!sensor)
207 return -ENOMEM;
208
209 mutex_init(&sensor->lock);
210 sensor->gpio_reset = -EINVAL;
211
212 gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
213 if (gpio_is_valid(gpio)) {
214 ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
215 DRIVER_NAME);
216 if (ret < 0)
217 return ret;
218 }
219 sensor->gpio_reset = gpio;
220
221 for (i = 0; i < SENSOR_NUM_SUPPLIES; i++)
222 sensor->supplies[i].supply = sensor_supply_names[i];
223
224 ret = devm_regulator_bulk_get(&client->dev, SENSOR_NUM_SUPPLIES,
225 sensor->supplies);
226 if (ret < 0)
227 return ret;
228
229 of_id = of_match_node(fimc_is_sensor_of_match, dev->of_node);
230 if (!of_id)
231 return -ENODEV;
232
233 sensor->drvdata = of_id->data;
234 sensor->dev = dev;
235
236 sd = &sensor->subdev;
237 v4l2_i2c_subdev_init(sd, client, &fimc_is_sensor_subdev_ops);
238 snprintf(sd->name, sizeof(sd->name), sensor->drvdata->subdev_name);
239 sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
240
241 sensor->format.code = fimc_is_sensor_formats[0].code;
242 sensor->format.width = FIMC_IS_SENSOR_DEF_PIX_WIDTH;
243 sensor->format.height = FIMC_IS_SENSOR_DEF_PIX_HEIGHT;
244
245 sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
246 ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
247 if (ret < 0)
248 return ret;
249
250 pm_runtime_no_callbacks(dev);
251 pm_runtime_enable(dev);
252
253 return ret;
254}
255
256static int fimc_is_sensor_remove(struct i2c_client *client)
257{
258 struct v4l2_subdev *sd = i2c_get_clientdata(client);
259 media_entity_cleanup(&sd->entity);
260 return 0;
261}
262
263static const struct i2c_device_id fimc_is_sensor_ids[] = {
264 { }
265};
266
267static const struct sensor_drv_data s5k6a3_drvdata = { 14static const struct sensor_drv_data s5k6a3_drvdata = {
268 .id = FIMC_IS_SENSOR_ID_S5K6A3, 15 .id = FIMC_IS_SENSOR_ID_S5K6A3,
269 .subdev_name = "S5K6A3", 16 .open_timeout = S5K6A3_OPEN_TIMEOUT,
270 .width = S5K6A3_SENSOR_WIDTH,
271 .height = S5K6A3_SENSOR_HEIGHT,
272}; 17};
273 18
274static const struct of_device_id fimc_is_sensor_of_match[] = { 19static const struct of_device_id fimc_is_sensor_of_ids[] = {
275 { 20 {
276 .compatible = "samsung,s5k6a3", 21 .compatible = "samsung,s5k6a3",
277 .data = &s5k6a3_drvdata, 22 .data = &s5k6a3_drvdata,
@@ -279,27 +24,11 @@ static const struct of_device_id fimc_is_sensor_of_match[] = {
279 { } 24 { }
280}; 25};
281 26
282static struct i2c_driver fimc_is_sensor_driver = { 27const struct sensor_drv_data *fimc_is_sensor_get_drvdata(
283 .driver = { 28 struct device_node *node)
284 .of_match_table = fimc_is_sensor_of_match,
285 .name = DRIVER_NAME,
286 .owner = THIS_MODULE,
287 },
288 .probe = fimc_is_sensor_probe,
289 .remove = fimc_is_sensor_remove,
290 .id_table = fimc_is_sensor_ids,
291};
292
293int fimc_is_register_sensor_driver(void)
294{ 29{
295 return i2c_add_driver(&fimc_is_sensor_driver); 30 const struct of_device_id *of_id;
296}
297 31
298void fimc_is_unregister_sensor_driver(void) 32 of_id = of_match_node(fimc_is_sensor_of_ids, node);
299{ 33 return of_id ? of_id->data : NULL;
300 i2c_del_driver(&fimc_is_sensor_driver);
301} 34}
302
303MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
304MODULE_DESCRIPTION("Exynos4x12 FIMC-IS image sensor subdev driver");
305MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos4-is/fimc-is-sensor.h b/drivers/media/platform/exynos4-is/fimc-is-sensor.h
index 6036d49a6c68..173ccffa4bcd 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-sensor.h
+++ b/drivers/media/platform/exynos4-is/fimc-is-sensor.h
@@ -13,24 +13,13 @@
13#ifndef FIMC_IS_SENSOR_H_ 13#ifndef FIMC_IS_SENSOR_H_
14#define FIMC_IS_SENSOR_H_ 14#define FIMC_IS_SENSOR_H_
15 15
16#include <linux/clk.h> 16#include <linux/of.h>
17#include <linux/device.h> 17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/consumer.h>
21#include <linux/videodev2.h>
22#include <media/v4l2-subdev.h>
23
24#define FIMC_IS_SENSOR_OPEN_TIMEOUT 2000 /* ms */
25
26#define FIMC_IS_SENSOR_DEF_PIX_WIDTH 1296
27#define FIMC_IS_SENSOR_DEF_PIX_HEIGHT 732
28 18
19#define S5K6A3_OPEN_TIMEOUT 2000 /* ms */
29#define S5K6A3_SENSOR_WIDTH 1392 20#define S5K6A3_SENSOR_WIDTH 1392
30#define S5K6A3_SENSOR_HEIGHT 1392 21#define S5K6A3_SENSOR_HEIGHT 1392
31 22
32#define SENSOR_NUM_SUPPLIES 2
33
34enum fimc_is_sensor_id { 23enum fimc_is_sensor_id {
35 FIMC_IS_SENSOR_ID_S5K3H2 = 1, 24 FIMC_IS_SENSOR_ID_S5K3H2 = 1,
36 FIMC_IS_SENSOR_ID_S5K6A3, 25 FIMC_IS_SENSOR_ID_S5K6A3,
@@ -45,45 +34,23 @@ enum fimc_is_sensor_id {
45 34
46struct sensor_drv_data { 35struct sensor_drv_data {
47 enum fimc_is_sensor_id id; 36 enum fimc_is_sensor_id id;
48 const char * const subdev_name; 37 /* sensor open timeout in ms */
49 unsigned int width; 38 unsigned short open_timeout;
50 unsigned int height;
51}; 39};
52 40
53/** 41/**
54 * struct fimc_is_sensor - fimc-is sensor data structure 42 * struct fimc_is_sensor - fimc-is sensor data structure
55 * @dev: pointer to this I2C client device structure
56 * @subdev: the image sensor's v4l2 subdev
57 * @pad: subdev media source pad
58 * @supplies: image sensor's voltage regulator supplies
59 * @gpio_reset: GPIO connected to the sensor's reset pin
60 * @drvdata: a pointer to the sensor's parameters data structure 43 * @drvdata: a pointer to the sensor's parameters data structure
61 * @i2c_bus: ISP I2C bus index (0...1) 44 * @i2c_bus: ISP I2C bus index (0...1)
62 * @test_pattern: true to enable video test pattern 45 * @test_pattern: true to enable video test pattern
63 * @lock: mutex protecting the structure's members below
64 * @format: media bus format at the sensor's source pad
65 */ 46 */
66struct fimc_is_sensor { 47struct fimc_is_sensor {
67 struct device *dev;
68 struct v4l2_subdev subdev;
69 struct media_pad pad;
70 struct regulator_bulk_data supplies[SENSOR_NUM_SUPPLIES];
71 int gpio_reset;
72 const struct sensor_drv_data *drvdata; 48 const struct sensor_drv_data *drvdata;
73 unsigned int i2c_bus; 49 unsigned int i2c_bus;
74 bool test_pattern; 50 u8 test_pattern;
75
76 struct mutex lock;
77 struct v4l2_mbus_framefmt format;
78}; 51};
79 52
80static inline 53const struct sensor_drv_data *fimc_is_sensor_get_drvdata(
81struct fimc_is_sensor *sd_to_fimc_is_sensor(struct v4l2_subdev *sd) 54 struct device_node *node);
82{
83 return container_of(sd, struct fimc_is_sensor, subdev);
84}
85
86int fimc_is_register_sensor_driver(void);
87void fimc_is_unregister_sensor_driver(void);
88 55
89#endif /* FIMC_IS_SENSOR_H_ */ 56#endif /* FIMC_IS_SENSOR_H_ */
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
index 9bdfa4599bc3..128b73b6cce2 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.c
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
@@ -161,78 +161,69 @@ static void fimc_is_disable_clocks(struct fimc_is *is)
161 } 161 }
162} 162}
163 163
164static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor, 164static int fimc_is_parse_sensor_config(struct fimc_is *is, unsigned int index,
165 struct device_node *np) 165 struct device_node *node)
166{ 166{
167 struct fimc_is_sensor *sensor = &is->sensor[index];
167 u32 tmp = 0; 168 u32 tmp = 0;
168 int ret; 169 int ret;
169 170
170 np = of_graph_get_next_endpoint(np, NULL); 171 sensor->drvdata = fimc_is_sensor_get_drvdata(node);
171 if (!np) 172 if (!sensor->drvdata) {
173 dev_err(&is->pdev->dev, "no driver data found for: %s\n",
174 node->full_name);
175 return -EINVAL;
176 }
177
178 node = of_graph_get_next_endpoint(node, NULL);
179 if (!node)
172 return -ENXIO; 180 return -ENXIO;
173 np = of_graph_get_remote_port(np); 181
174 if (!np) 182 node = of_graph_get_remote_port(node);
183 if (!node)
175 return -ENXIO; 184 return -ENXIO;
176 185
177 /* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */ 186 /* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */
178 ret = of_property_read_u32(np, "reg", &tmp); 187 ret = of_property_read_u32(node, "reg", &tmp);
179 sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0; 188 if (ret < 0) {
189 dev_err(&is->pdev->dev, "reg property not found at: %s\n",
190 node->full_name);
191 return ret;
192 }
180 193
181 return ret; 194 sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
195 return 0;
182} 196}
183 197
184static int fimc_is_register_subdevs(struct fimc_is *is) 198static int fimc_is_register_subdevs(struct fimc_is *is)
185{ 199{
186 struct device_node *adapter, *child; 200 struct device_node *i2c_bus, *child;
187 int ret; 201 int ret, index = 0;
188 202
189 ret = fimc_isp_subdev_create(&is->isp); 203 ret = fimc_isp_subdev_create(&is->isp);
190 if (ret < 0) 204 if (ret < 0)
191 return ret; 205 return ret;
192 206
193 for_each_compatible_node(adapter, NULL, FIMC_IS_I2C_COMPATIBLE) { 207 /* Initialize memory allocator context for the ISP DMA. */
194 if (!of_find_device_by_node(adapter)) { 208 is->isp.alloc_ctx = is->alloc_ctx;
195 of_node_put(adapter);
196 return -EPROBE_DEFER;
197 }
198
199 for_each_available_child_of_node(adapter, child) {
200 struct i2c_client *client;
201 struct v4l2_subdev *sd;
202
203 client = of_find_i2c_device_by_node(child);
204 if (!client)
205 goto e_retry;
206
207 sd = i2c_get_clientdata(client);
208 if (!sd)
209 goto e_retry;
210 209
211 /* FIXME: Add support for multiple sensors. */ 210 for_each_compatible_node(i2c_bus, NULL, FIMC_IS_I2C_COMPATIBLE) {
212 if (WARN_ON(is->sensor)) 211 for_each_available_child_of_node(i2c_bus, child) {
213 continue; 212 ret = fimc_is_parse_sensor_config(is, index, child);
214 213
215 is->sensor = sd_to_fimc_is_sensor(sd); 214 if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) {
216 215 of_node_put(child);
217 if (fimc_is_parse_sensor_config(is->sensor, child)) { 216 return ret;
218 dev_warn(&is->pdev->dev, "DT parse error: %s\n",
219 child->full_name);
220 } 217 }
221 pr_debug("%s(): registered subdev: %p\n", 218 index++;
222 __func__, sd->name);
223 } 219 }
224 } 220 }
225 return 0; 221 return 0;
226
227e_retry:
228 of_node_put(child);
229 return -EPROBE_DEFER;
230} 222}
231 223
232static int fimc_is_unregister_subdevs(struct fimc_is *is) 224static int fimc_is_unregister_subdevs(struct fimc_is *is)
233{ 225{
234 fimc_isp_subdev_destroy(&is->isp); 226 fimc_isp_subdev_destroy(&is->isp);
235 is->sensor = NULL;
236 return 0; 227 return 0;
237} 228}
238 229
@@ -647,7 +638,7 @@ static int fimc_is_hw_open_sensor(struct fimc_is *is,
647 fimc_is_hw_set_intgr0_gd0(is); 638 fimc_is_hw_set_intgr0_gd0(is);
648 639
649 return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1, 640 return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1,
650 FIMC_IS_SENSOR_OPEN_TIMEOUT); 641 sensor->drvdata->open_timeout);
651} 642}
652 643
653 644
@@ -661,8 +652,8 @@ int fimc_is_hw_initialize(struct fimc_is *is)
661 u32 prev_id; 652 u32 prev_id;
662 int i, ret; 653 int i, ret;
663 654
664 /* Sensor initialization. */ 655 /* Sensor initialization. Only one sensor is currently supported. */
665 ret = fimc_is_hw_open_sensor(is, is->sensor); 656 ret = fimc_is_hw_open_sensor(is, &is->sensor[0]);
666 if (ret < 0) 657 if (ret < 0)
667 return ret; 658 return ret;
668 659
@@ -977,27 +968,20 @@ static int fimc_is_module_init(void)
977{ 968{
978 int ret; 969 int ret;
979 970
980 ret = fimc_is_register_sensor_driver();
981 if (ret < 0)
982 return ret;
983
984 ret = fimc_is_register_i2c_driver(); 971 ret = fimc_is_register_i2c_driver();
985 if (ret < 0) 972 if (ret < 0)
986 goto err_sens; 973 return ret;
987 974
988 ret = platform_driver_register(&fimc_is_driver); 975 ret = platform_driver_register(&fimc_is_driver);
989 if (!ret)
990 return ret;
991 976
992 fimc_is_unregister_i2c_driver(); 977 if (ret < 0)
993err_sens: 978 fimc_is_unregister_i2c_driver();
994 fimc_is_unregister_sensor_driver(); 979
995 return ret; 980 return ret;
996} 981}
997 982
998static void fimc_is_module_exit(void) 983static void fimc_is_module_exit(void)
999{ 984{
1000 fimc_is_unregister_sensor_driver();
1001 fimc_is_unregister_i2c_driver(); 985 fimc_is_unregister_i2c_driver();
1002 platform_driver_unregister(&fimc_is_driver); 986 platform_driver_unregister(&fimc_is_driver);
1003} 987}
diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h
index 61bb0127e19d..e0be691af2d3 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.h
+++ b/drivers/media/platform/exynos4-is/fimc-is.h
@@ -39,7 +39,7 @@
39#define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ 39#define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */
40#define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ 40#define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */
41 41
42#define FIMC_IS_SENSOR_NUM 2 42#define FIMC_IS_SENSORS_NUM 2
43 43
44/* Memory definitions */ 44/* Memory definitions */
45#define FIMC_IS_CPU_MEM_SIZE (0xa00000) 45#define FIMC_IS_CPU_MEM_SIZE (0xa00000)
@@ -253,7 +253,7 @@ struct fimc_is {
253 struct firmware *f_w; 253 struct firmware *f_w;
254 254
255 struct fimc_isp isp; 255 struct fimc_isp isp;
256 struct fimc_is_sensor *sensor; 256 struct fimc_is_sensor sensor[FIMC_IS_SENSORS_NUM];
257 struct fimc_is_setfile setfile; 257 struct fimc_is_setfile setfile;
258 258
259 struct vb2_alloc_ctx *alloc_ctx; 259 struct vb2_alloc_ctx *alloc_ctx;
@@ -292,6 +292,11 @@ static inline struct fimc_is *fimc_isp_to_is(struct fimc_isp *isp)
292 return container_of(isp, struct fimc_is, isp); 292 return container_of(isp, struct fimc_is, isp);
293} 293}
294 294
295static inline struct chain_config *__get_curr_is_config(struct fimc_is *is)
296{
297 return &is->config[is->config_index];
298}
299
295static inline void fimc_is_mem_barrier(void) 300static inline void fimc_is_mem_barrier(void)
296{ 301{
297 mb(); 302 mb();
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
new file mode 100644
index 000000000000..e92b4e115adb
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -0,0 +1,660 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * FIMC-IS ISP video input and video output DMA interface driver
5 *
6 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
7 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
8 *
9 * The hardware handling code derived from a driver written by
10 * Younghwan Joo <yhwan.joo@samsung.com>.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/bitops.h>
18#include <linux/device.h>
19#include <linux/delay.h>
20#include <linux/errno.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/types.h>
24#include <linux/printk.h>
25#include <linux/pm_runtime.h>
26#include <linux/slab.h>
27#include <linux/videodev2.h>
28
29#include <media/v4l2-device.h>
30#include <media/v4l2-ioctl.h>
31#include <media/videobuf2-core.h>
32#include <media/videobuf2-dma-contig.h>
33#include <media/s5p_fimc.h>
34
35#include "common.h"
36#include "media-dev.h"
37#include "fimc-is.h"
38#include "fimc-isp-video.h"
39#include "fimc-is-param.h"
40
41static int isp_video_capture_queue_setup(struct vb2_queue *vq,
42 const struct v4l2_format *pfmt,
43 unsigned int *num_buffers, unsigned int *num_planes,
44 unsigned int sizes[], void *allocators[])
45{
46 struct fimc_isp *isp = vb2_get_drv_priv(vq);
47 struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt;
48 const struct v4l2_pix_format_mplane *pixm = NULL;
49 const struct fimc_fmt *fmt;
50 unsigned int wh, i;
51
52 if (pfmt) {
53 pixm = &pfmt->fmt.pix_mp;
54 fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, -1);
55 wh = pixm->width * pixm->height;
56 } else {
57 fmt = isp->video_capture.format;
58 wh = vid_fmt->width * vid_fmt->height;
59 }
60
61 if (fmt == NULL)
62 return -EINVAL;
63
64 *num_buffers = clamp_t(u32, *num_buffers, FIMC_ISP_REQ_BUFS_MIN,
65 FIMC_ISP_REQ_BUFS_MAX);
66 *num_planes = fmt->memplanes;
67
68 for (i = 0; i < fmt->memplanes; i++) {
69 unsigned int size = (wh * fmt->depth[i]) / 8;
70 if (pixm)
71 sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
72 else
73 sizes[i] = size;
74 allocators[i] = isp->alloc_ctx;
75 }
76
77 return 0;
78}
79
80static inline struct param_dma_output *__get_isp_dma2(struct fimc_is *is)
81{
82 return &__get_curr_is_config(is)->isp.dma2_output;
83}
84
85static int isp_video_capture_start_streaming(struct vb2_queue *q,
86 unsigned int count)
87{
88 struct fimc_isp *isp = vb2_get_drv_priv(q);
89 struct fimc_is *is = fimc_isp_to_is(isp);
90 struct param_dma_output *dma = __get_isp_dma2(is);
91 struct fimc_is_video *video = &isp->video_capture;
92 int ret;
93
94 if (!test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state) ||
95 test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state))
96 return 0;
97
98
99 dma->cmd = DMA_OUTPUT_COMMAND_ENABLE;
100 dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE;
101 dma->buffer_address = is->is_dma_p_region +
102 DMA2_OUTPUT_ADDR_ARRAY_OFFS;
103 dma->buffer_number = video->reqbufs_count;
104 dma->dma_out_mask = video->buf_mask;
105
106 isp_dbg(2, &video->ve.vdev,
107 "buf_count: %d, planes: %d, dma addr table: %#x\n",
108 video->buf_count, video->format->memplanes,
109 dma->buffer_address);
110
111 fimc_is_mem_barrier();
112
113 fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
114 __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT);
115
116 ret = fimc_is_itf_s_param(is, false);
117 if (ret < 0)
118 return ret;
119
120 ret = fimc_pipeline_call(&video->ve, set_stream, 1);
121 if (ret < 0)
122 return ret;
123
124 set_bit(ST_ISP_VID_CAP_STREAMING, &isp->state);
125 return ret;
126}
127
128static int isp_video_capture_stop_streaming(struct vb2_queue *q)
129{
130 struct fimc_isp *isp = vb2_get_drv_priv(q);
131 struct fimc_is *is = fimc_isp_to_is(isp);
132 struct param_dma_output *dma = __get_isp_dma2(is);
133 int ret;
134
135 ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0);
136 if (ret < 0)
137 return ret;
138
139 dma->cmd = DMA_OUTPUT_COMMAND_DISABLE;
140 dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE;
141 dma->buffer_number = 0;
142 dma->buffer_address = 0;
143 dma->dma_out_mask = 0;
144
145 fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT);
146 __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT);
147
148 ret = fimc_is_itf_s_param(is, false);
149 if (ret < 0)
150 dev_warn(&is->pdev->dev, "%s: DMA stop failed\n", __func__);
151
152 fimc_is_hw_set_isp_buf_mask(is, 0);
153
154 clear_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state);
155 clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state);
156
157 isp->video_capture.buf_count = 0;
158 return 0;
159}
160
161static int isp_video_capture_buffer_prepare(struct vb2_buffer *vb)
162{
163 struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue);
164 struct fimc_is_video *video = &isp->video_capture;
165 int i;
166
167 if (video->format == NULL)
168 return -EINVAL;
169
170 for (i = 0; i < video->format->memplanes; i++) {
171 unsigned long size = video->pixfmt.plane_fmt[i].sizeimage;
172
173 if (vb2_plane_size(vb, i) < size) {
174 v4l2_err(&video->ve.vdev,
175 "User buffer too small (%ld < %ld)\n",
176 vb2_plane_size(vb, i), size);
177 return -EINVAL;
178 }
179 vb2_set_plane_payload(vb, i, size);
180 }
181
182 /* Check if we get one of the already known buffers. */
183 if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) {
184 dma_addr_t dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
185 int i;
186
187 for (i = 0; i < video->buf_count; i++)
188 if (video->buffers[i]->dma_addr[0] == dma_addr)
189 return 0;
190 return -ENXIO;
191 }
192
193 return 0;
194}
195
196static void isp_video_capture_buffer_queue(struct vb2_buffer *vb)
197{
198 struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue);
199 struct fimc_is_video *video = &isp->video_capture;
200 struct fimc_is *is = fimc_isp_to_is(isp);
201 struct isp_video_buf *ivb = to_isp_video_buf(vb);
202 unsigned long flags;
203 unsigned int i;
204
205 if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) {
206 spin_lock_irqsave(&is->slock, flags);
207 video->buf_mask |= BIT(ivb->index);
208 spin_unlock_irqrestore(&is->slock, flags);
209 } else {
210 unsigned int num_planes = video->format->memplanes;
211
212 ivb->index = video->buf_count;
213 video->buffers[ivb->index] = ivb;
214
215 for (i = 0; i < num_planes; i++) {
216 int buf_index = ivb->index * num_planes + i;
217
218 ivb->dma_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
219 is->is_p_region->shared[32 + buf_index] =
220 ivb->dma_addr[i];
221
222 isp_dbg(2, &video->ve.vdev,
223 "dma_buf %d (%d/%d/%d) addr: %#x\n",
224 buf_index, ivb->index, i, vb->v4l2_buf.index,
225 ivb->dma_addr[i]);
226 }
227
228 if (++video->buf_count < video->reqbufs_count)
229 return;
230
231 video->buf_mask = (1UL << video->buf_count) - 1;
232 set_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state);
233 }
234
235 if (!test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state))
236 isp_video_capture_start_streaming(vb->vb2_queue, 0);
237}
238
239/*
240 * FIMC-IS ISP input and output DMA interface interrupt handler.
241 * Locking: called with is->slock spinlock held.
242 */
243void fimc_isp_video_irq_handler(struct fimc_is *is)
244{
245 struct fimc_is_video *video = &is->isp.video_capture;
246 struct vb2_buffer *vb;
247 int buf_index;
248
249 /* TODO: Ensure the DMA is really stopped in stop_streaming callback */
250 if (!test_bit(ST_ISP_VID_CAP_STREAMING, &is->isp.state))
251 return;
252
253 buf_index = (is->i2h_cmd.args[1] - 1) % video->buf_count;
254 vb = &video->buffers[buf_index]->vb;
255
256 v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
257 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
258
259 video->buf_mask &= ~BIT(buf_index);
260 fimc_is_hw_set_isp_buf_mask(is, video->buf_mask);
261}
262
263static const struct vb2_ops isp_video_capture_qops = {
264 .queue_setup = isp_video_capture_queue_setup,
265 .buf_prepare = isp_video_capture_buffer_prepare,
266 .buf_queue = isp_video_capture_buffer_queue,
267 .wait_prepare = vb2_ops_wait_prepare,
268 .wait_finish = vb2_ops_wait_finish,
269 .start_streaming = isp_video_capture_start_streaming,
270 .stop_streaming = isp_video_capture_stop_streaming,
271};
272
273static int isp_video_open(struct file *file)
274{
275 struct fimc_isp *isp = video_drvdata(file);
276 struct exynos_video_entity *ve = &isp->video_capture.ve;
277 struct media_entity *me = &ve->vdev.entity;
278 int ret;
279
280 if (mutex_lock_interruptible(&isp->video_lock))
281 return -ERESTARTSYS;
282
283 ret = v4l2_fh_open(file);
284 if (ret < 0)
285 goto unlock;
286
287 ret = pm_runtime_get_sync(&isp->pdev->dev);
288 if (ret < 0)
289 goto rel_fh;
290
291 if (v4l2_fh_is_singular_file(file)) {
292 mutex_lock(&me->parent->graph_mutex);
293
294 ret = fimc_pipeline_call(ve, open, me, true);
295
296 /* Mark the video pipeline as in use. */
297 if (ret == 0)
298 me->use_count++;
299
300 mutex_unlock(&me->parent->graph_mutex);
301 }
302 if (!ret)
303 goto unlock;
304rel_fh:
305 v4l2_fh_release(file);
306unlock:
307 mutex_unlock(&isp->video_lock);
308 return ret;
309}
310
311static int isp_video_release(struct file *file)
312{
313 struct fimc_isp *isp = video_drvdata(file);
314 struct fimc_is_video *ivc = &isp->video_capture;
315 struct media_entity *entity = &ivc->ve.vdev.entity;
316 struct media_device *mdev = entity->parent;
317 int ret = 0;
318
319 mutex_lock(&isp->video_lock);
320
321 if (v4l2_fh_is_singular_file(file) && ivc->streaming) {
322 media_entity_pipeline_stop(entity);
323 ivc->streaming = 0;
324 }
325
326 vb2_fop_release(file);
327
328 if (v4l2_fh_is_singular_file(file)) {
329 fimc_pipeline_call(&ivc->ve, close);
330
331 mutex_lock(&mdev->graph_mutex);
332 entity->use_count--;
333 mutex_unlock(&mdev->graph_mutex);
334 }
335
336 pm_runtime_put(&isp->pdev->dev);
337 mutex_unlock(&isp->video_lock);
338
339 return ret;
340}
341
342static const struct v4l2_file_operations isp_video_fops = {
343 .owner = THIS_MODULE,
344 .open = isp_video_open,
345 .release = isp_video_release,
346 .poll = vb2_fop_poll,
347 .unlocked_ioctl = video_ioctl2,
348 .mmap = vb2_fop_mmap,
349};
350
351/*
352 * Video node ioctl operations
353 */
354static int isp_video_querycap(struct file *file, void *priv,
355 struct v4l2_capability *cap)
356{
357 struct fimc_isp *isp = video_drvdata(file);
358
359 __fimc_vidioc_querycap(&isp->pdev->dev, cap, V4L2_CAP_STREAMING);
360 return 0;
361}
362
363static int isp_video_enum_fmt_mplane(struct file *file, void *priv,
364 struct v4l2_fmtdesc *f)
365{
366 const struct fimc_fmt *fmt;
367
368 if (f->index >= FIMC_ISP_NUM_FORMATS)
369 return -EINVAL;
370
371 fmt = fimc_isp_find_format(NULL, NULL, f->index);
372 if (WARN_ON(fmt == NULL))
373 return -EINVAL;
374
375 strlcpy(f->description, fmt->name, sizeof(f->description));
376 f->pixelformat = fmt->fourcc;
377
378 return 0;
379}
380
381static int isp_video_g_fmt_mplane(struct file *file, void *fh,
382 struct v4l2_format *f)
383{
384 struct fimc_isp *isp = video_drvdata(file);
385
386 f->fmt.pix_mp = isp->video_capture.pixfmt;
387 return 0;
388}
389
390static void __isp_video_try_fmt(struct fimc_isp *isp,
391 struct v4l2_pix_format_mplane *pixm,
392 const struct fimc_fmt **fmt)
393{
394 *fmt = fimc_isp_find_format(&pixm->pixelformat, NULL, 2);
395
396 pixm->colorspace = V4L2_COLORSPACE_SRGB;
397 pixm->field = V4L2_FIELD_NONE;
398 pixm->num_planes = (*fmt)->memplanes;
399 pixm->pixelformat = (*fmt)->fourcc;
400 /*
401 * TODO: double check with the docmentation these width/height
402 * constraints are correct.
403 */
404 v4l_bound_align_image(&pixm->width, FIMC_ISP_SOURCE_WIDTH_MIN,
405 FIMC_ISP_SOURCE_WIDTH_MAX, 3,
406 &pixm->height, FIMC_ISP_SOURCE_HEIGHT_MIN,
407 FIMC_ISP_SOURCE_HEIGHT_MAX, 0, 0);
408}
409
410static int isp_video_try_fmt_mplane(struct file *file, void *fh,
411 struct v4l2_format *f)
412{
413 struct fimc_isp *isp = video_drvdata(file);
414
415 __isp_video_try_fmt(isp, &f->fmt.pix_mp, NULL);
416 return 0;
417}
418
419static int isp_video_s_fmt_mplane(struct file *file, void *priv,
420 struct v4l2_format *f)
421{
422 struct fimc_isp *isp = video_drvdata(file);
423 struct fimc_is *is = fimc_isp_to_is(isp);
424 struct v4l2_pix_format_mplane *pixm = &f->fmt.pix_mp;
425 const struct fimc_fmt *ifmt = NULL;
426 struct param_dma_output *dma = __get_isp_dma2(is);
427
428 __isp_video_try_fmt(isp, pixm, &ifmt);
429
430 if (WARN_ON(ifmt == NULL))
431 return -EINVAL;
432
433 dma->format = DMA_OUTPUT_FORMAT_BAYER;
434 dma->order = DMA_OUTPUT_ORDER_GB_BG;
435 dma->plane = ifmt->memplanes;
436 dma->bitwidth = ifmt->depth[0];
437 dma->width = pixm->width;
438 dma->height = pixm->height;
439
440 fimc_is_mem_barrier();
441
442 isp->video_capture.format = ifmt;
443 isp->video_capture.pixfmt = *pixm;
444
445 return 0;
446}
447
448/*
449 * Check for source/sink format differences at each link.
450 * Return 0 if the formats match or -EPIPE otherwise.
451 */
452static int isp_video_pipeline_validate(struct fimc_isp *isp)
453{
454 struct v4l2_subdev *sd = &isp->subdev;
455 struct v4l2_subdev_format sink_fmt, src_fmt;
456 struct media_pad *pad;
457 int ret;
458
459 while (1) {
460 /* Retrieve format at the sink pad */
461 pad = &sd->entity.pads[0];
462 if (!(pad->flags & MEDIA_PAD_FL_SINK))
463 break;
464 sink_fmt.pad = pad->index;
465 sink_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
466 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sink_fmt);
467 if (ret < 0 && ret != -ENOIOCTLCMD)
468 return -EPIPE;
469
470 /* Retrieve format at the source pad */
471 pad = media_entity_remote_pad(pad);
472 if (pad == NULL ||
473 media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
474 break;
475
476 sd = media_entity_to_v4l2_subdev(pad->entity);
477 src_fmt.pad = pad->index;
478 src_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
479 ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &src_fmt);
480 if (ret < 0 && ret != -ENOIOCTLCMD)
481 return -EPIPE;
482
483 if (src_fmt.format.width != sink_fmt.format.width ||
484 src_fmt.format.height != sink_fmt.format.height ||
485 src_fmt.format.code != sink_fmt.format.code)
486 return -EPIPE;
487 }
488
489 return 0;
490}
491
492static int isp_video_streamon(struct file *file, void *priv,
493 enum v4l2_buf_type type)
494{
495 struct fimc_isp *isp = video_drvdata(file);
496 struct exynos_video_entity *ve = &isp->video_capture.ve;
497 struct media_entity *me = &ve->vdev.entity;
498 int ret;
499
500 ret = media_entity_pipeline_start(me, &ve->pipe->mp);
501 if (ret < 0)
502 return ret;
503
504 ret = isp_video_pipeline_validate(isp);
505 if (ret < 0)
506 goto p_stop;
507
508 ret = vb2_ioctl_streamon(file, priv, type);
509 if (ret < 0)
510 goto p_stop;
511
512 isp->video_capture.streaming = 1;
513 return 0;
514p_stop:
515 media_entity_pipeline_stop(me);
516 return ret;
517}
518
519static int isp_video_streamoff(struct file *file, void *priv,
520 enum v4l2_buf_type type)
521{
522 struct fimc_isp *isp = video_drvdata(file);
523 struct fimc_is_video *video = &isp->video_capture;
524 int ret;
525
526 ret = vb2_ioctl_streamoff(file, priv, type);
527 if (ret < 0)
528 return ret;
529
530 media_entity_pipeline_stop(&video->ve.vdev.entity);
531 video->streaming = 0;
532 return 0;
533}
534
535static int isp_video_reqbufs(struct file *file, void *priv,
536 struct v4l2_requestbuffers *rb)
537{
538 struct fimc_isp *isp = video_drvdata(file);
539 int ret;
540
541 ret = vb2_ioctl_reqbufs(file, priv, rb);
542 if (ret < 0)
543 return ret;
544
545 if (rb->count && rb->count < FIMC_ISP_REQ_BUFS_MIN) {
546 rb->count = 0;
547 vb2_ioctl_reqbufs(file, priv, rb);
548 ret = -ENOMEM;
549 }
550
551 isp->video_capture.reqbufs_count = rb->count;
552 return ret;
553}
554
555static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
556 .vidioc_querycap = isp_video_querycap,
557 .vidioc_enum_fmt_vid_cap_mplane = isp_video_enum_fmt_mplane,
558 .vidioc_try_fmt_vid_cap_mplane = isp_video_try_fmt_mplane,
559 .vidioc_s_fmt_vid_cap_mplane = isp_video_s_fmt_mplane,
560 .vidioc_g_fmt_vid_cap_mplane = isp_video_g_fmt_mplane,
561 .vidioc_reqbufs = isp_video_reqbufs,
562 .vidioc_querybuf = vb2_ioctl_querybuf,
563 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
564 .vidioc_create_bufs = vb2_ioctl_create_bufs,
565 .vidioc_qbuf = vb2_ioctl_qbuf,
566 .vidioc_dqbuf = vb2_ioctl_dqbuf,
567 .vidioc_streamon = isp_video_streamon,
568 .vidioc_streamoff = isp_video_streamoff,
569};
570
571int fimc_isp_video_device_register(struct fimc_isp *isp,
572 struct v4l2_device *v4l2_dev,
573 enum v4l2_buf_type type)
574{
575 struct vb2_queue *q = &isp->video_capture.vb_queue;
576 struct fimc_is_video *iv;
577 struct video_device *vdev;
578 int ret;
579
580 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
581 iv = &isp->video_capture;
582 else
583 return -ENOSYS;
584
585 mutex_init(&isp->video_lock);
586 INIT_LIST_HEAD(&iv->pending_buf_q);
587 INIT_LIST_HEAD(&iv->active_buf_q);
588 iv->format = fimc_isp_find_format(NULL, NULL, 0);
589 iv->pixfmt.width = IS_DEFAULT_WIDTH;
590 iv->pixfmt.height = IS_DEFAULT_HEIGHT;
591 iv->pixfmt.pixelformat = iv->format->fourcc;
592 iv->pixfmt.colorspace = V4L2_COLORSPACE_SRGB;
593 iv->reqbufs_count = 0;
594
595 memset(q, 0, sizeof(*q));
596 q->type = type;
597 q->io_modes = VB2_MMAP | VB2_USERPTR;
598 q->ops = &isp_video_capture_qops;
599 q->mem_ops = &vb2_dma_contig_memops;
600 q->buf_struct_size = sizeof(struct isp_video_buf);
601 q->drv_priv = isp;
602 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
603 q->lock = &isp->video_lock;
604
605 ret = vb2_queue_init(q);
606 if (ret < 0)
607 return ret;
608
609 vdev = &iv->ve.vdev;
610 memset(vdev, 0, sizeof(*vdev));
611 snprintf(vdev->name, sizeof(vdev->name), "fimc-is-isp.%s",
612 type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ?
613 "capture" : "output");
614 vdev->queue = q;
615 vdev->fops = &isp_video_fops;
616 vdev->ioctl_ops = &isp_video_ioctl_ops;
617 vdev->v4l2_dev = v4l2_dev;
618 vdev->minor = -1;
619 vdev->release = video_device_release_empty;
620 vdev->lock = &isp->video_lock;
621
622 iv->pad.flags = MEDIA_PAD_FL_SINK;
623 ret = media_entity_init(&vdev->entity, 1, &iv->pad, 0);
624 if (ret < 0)
625 return ret;
626
627 video_set_drvdata(vdev, isp);
628
629 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
630 if (ret < 0) {
631 media_entity_cleanup(&vdev->entity);
632 return ret;
633 }
634
635 v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
636 vdev->name, video_device_node_name(vdev));
637
638 return 0;
639}
640
641void fimc_isp_video_device_unregister(struct fimc_isp *isp,
642 enum v4l2_buf_type type)
643{
644 struct exynos_video_entity *ve;
645
646 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
647 ve = &isp->video_capture.ve;
648 else
649 return;
650
651 mutex_lock(&isp->video_lock);
652
653 if (video_is_registered(&ve->vdev)) {
654 video_unregister_device(&ve->vdev);
655 media_entity_cleanup(&ve->vdev.entity);
656 ve->pipe = NULL;
657 }
658
659 mutex_unlock(&isp->video_lock);
660}
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.h b/drivers/media/platform/exynos4-is/fimc-isp-video.h
new file mode 100644
index 000000000000..98c662654bb6
--- /dev/null
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.h
@@ -0,0 +1,44 @@
1/*
2 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * 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 version 2 as
9 * published by the Free Software Foundation.
10 */
11#ifndef FIMC_ISP_VIDEO__
12#define FIMC_ISP_VIDEO__
13
14#include <media/videobuf2-core.h>
15#include "fimc-isp.h"
16
17#ifdef CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE
18int fimc_isp_video_device_register(struct fimc_isp *isp,
19 struct v4l2_device *v4l2_dev,
20 enum v4l2_buf_type type);
21
22void fimc_isp_video_device_unregister(struct fimc_isp *isp,
23 enum v4l2_buf_type type);
24
25void fimc_isp_video_irq_handler(struct fimc_is *is);
26#else
27static inline void fimc_isp_video_irq_handler(struct fimc_is *is)
28{
29}
30
31static inline int fimc_isp_video_device_register(struct fimc_isp *isp,
32 struct v4l2_device *v4l2_dev,
33 enum v4l2_buf_type type)
34{
35 return 0;
36}
37
38void fimc_isp_video_device_unregister(struct fimc_isp *isp,
39 enum v4l2_buf_type type)
40{
41}
42#endif /* !CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE */
43
44#endif /* FIMC_ISP_VIDEO__ */
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c
index f3c6136aa5b4..be62d6b9ac48 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp.c
@@ -25,6 +25,7 @@
25#include <media/v4l2-device.h> 25#include <media/v4l2-device.h>
26 26
27#include "media-dev.h" 27#include "media-dev.h"
28#include "fimc-isp-video.h"
28#include "fimc-is-command.h" 29#include "fimc-is-command.h"
29#include "fimc-is-param.h" 30#include "fimc-is-param.h"
30#include "fimc-is-regs.h" 31#include "fimc-is-regs.h"
@@ -93,8 +94,8 @@ void fimc_isp_irq_handler(struct fimc_is *is)
93 is->i2h_cmd.args[1] = mcuctl_read(is, MCUCTL_REG_ISSR(21)); 94 is->i2h_cmd.args[1] = mcuctl_read(is, MCUCTL_REG_ISSR(21));
94 95
95 fimc_is_fw_clear_irq1(is, FIMC_IS_INT_FRAME_DONE_ISP); 96 fimc_is_fw_clear_irq1(is, FIMC_IS_INT_FRAME_DONE_ISP);
97 fimc_isp_video_irq_handler(is);
96 98
97 /* TODO: Complete ISP DMA interrupt handler */
98 wake_up(&is->irq_queue); 99 wake_up(&is->irq_queue);
99} 100}
100 101
@@ -388,7 +389,33 @@ static int fimc_isp_subdev_open(struct v4l2_subdev *sd,
388 return 0; 389 return 0;
389} 390}
390 391
392static int fimc_isp_subdev_registered(struct v4l2_subdev *sd)
393{
394 struct fimc_isp *isp = v4l2_get_subdevdata(sd);
395 int ret;
396
397 /* Use pipeline object allocated by the media device. */
398 isp->video_capture.ve.pipe = v4l2_get_subdev_hostdata(sd);
399
400 ret = fimc_isp_video_device_register(isp, sd->v4l2_dev,
401 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
402 if (ret < 0)
403 isp->video_capture.ve.pipe = NULL;
404
405 return ret;
406}
407
408static void fimc_isp_subdev_unregistered(struct v4l2_subdev *sd)
409{
410 struct fimc_isp *isp = v4l2_get_subdevdata(sd);
411
412 fimc_isp_video_device_unregister(isp,
413 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
414}
415
391static const struct v4l2_subdev_internal_ops fimc_is_subdev_internal_ops = { 416static const struct v4l2_subdev_internal_ops fimc_is_subdev_internal_ops = {
417 .registered = fimc_isp_subdev_registered,
418 .unregistered = fimc_isp_subdev_unregistered,
392 .open = fimc_isp_subdev_open, 419 .open = fimc_isp_subdev_open,
393}; 420};
394 421
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
index 03bf95ab017b..4dc55a18d978 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp.h
@@ -35,17 +35,18 @@ extern int fimc_isp_debug;
35#define FIMC_ISP_SINK_WIDTH_MIN (16 + 8) 35#define FIMC_ISP_SINK_WIDTH_MIN (16 + 8)
36#define FIMC_ISP_SINK_HEIGHT_MIN (12 + 8) 36#define FIMC_ISP_SINK_HEIGHT_MIN (12 + 8)
37#define FIMC_ISP_SOURCE_WIDTH_MIN 8 37#define FIMC_ISP_SOURCE_WIDTH_MIN 8
38#define FIMC_ISP_SOURC_HEIGHT_MIN 8 38#define FIMC_ISP_SOURCE_HEIGHT_MIN 8
39#define FIMC_ISP_CAC_MARGIN_WIDTH 16 39#define FIMC_ISP_CAC_MARGIN_WIDTH 16
40#define FIMC_ISP_CAC_MARGIN_HEIGHT 12 40#define FIMC_ISP_CAC_MARGIN_HEIGHT 12
41 41
42#define FIMC_ISP_SINK_WIDTH_MAX (4000 - 16) 42#define FIMC_ISP_SINK_WIDTH_MAX (4000 - 16)
43#define FIMC_ISP_SINK_HEIGHT_MAX (4000 + 12) 43#define FIMC_ISP_SINK_HEIGHT_MAX (4000 + 12)
44#define FIMC_ISP_SOURCE_WIDTH_MAX 4000 44#define FIMC_ISP_SOURCE_WIDTH_MAX 4000
45#define FIMC_ISP_SOURC_HEIGHT_MAX 4000 45#define FIMC_ISP_SOURCE_HEIGHT_MAX 4000
46 46
47#define FIMC_ISP_NUM_FORMATS 3 47#define FIMC_ISP_NUM_FORMATS 3
48#define FIMC_ISP_REQ_BUFS_MIN 2 48#define FIMC_ISP_REQ_BUFS_MIN 2
49#define FIMC_ISP_REQ_BUFS_MAX 32
49 50
50#define FIMC_ISP_SD_PAD_SINK 0 51#define FIMC_ISP_SD_PAD_SINK 0
51#define FIMC_ISP_SD_PAD_SRC_FIFO 1 52#define FIMC_ISP_SD_PAD_SRC_FIFO 1
@@ -100,6 +101,16 @@ struct fimc_isp_ctrls {
100 struct v4l2_ctrl *colorfx; 101 struct v4l2_ctrl *colorfx;
101}; 102};
102 103
104struct isp_video_buf {
105 struct vb2_buffer vb;
106 dma_addr_t dma_addr[FIMC_ISP_MAX_PLANES];
107 unsigned int index;
108};
109
110#define to_isp_video_buf(_b) container_of(_b, struct isp_video_buf, vb)
111
112#define FIMC_ISP_MAX_BUFS 4
113
103/** 114/**
104 * struct fimc_is_video - fimc-is video device structure 115 * struct fimc_is_video - fimc-is video device structure
105 * @vdev: video_device structure 116 * @vdev: video_device structure
@@ -114,18 +125,26 @@ struct fimc_isp_ctrls {
114 * @format: current pixel format 125 * @format: current pixel format
115 */ 126 */
116struct fimc_is_video { 127struct fimc_is_video {
117 struct video_device vdev; 128 struct exynos_video_entity ve;
118 enum v4l2_buf_type type; 129 enum v4l2_buf_type type;
119 struct media_pad pad; 130 struct media_pad pad;
120 struct list_head pending_buf_q; 131 struct list_head pending_buf_q;
121 struct list_head active_buf_q; 132 struct list_head active_buf_q;
122 struct vb2_queue vb_queue; 133 struct vb2_queue vb_queue;
123 unsigned int frame_count;
124 unsigned int reqbufs_count; 134 unsigned int reqbufs_count;
135 unsigned int buf_count;
136 unsigned int buf_mask;
137 unsigned int frame_count;
125 int streaming; 138 int streaming;
139 struct isp_video_buf *buffers[FIMC_ISP_MAX_BUFS];
126 const struct fimc_fmt *format; 140 const struct fimc_fmt *format;
141 struct v4l2_pix_format_mplane pixfmt;
127}; 142};
128 143
144/* struct fimc_isp:state bit definitions */
145#define ST_ISP_VID_CAP_BUF_PREP 0
146#define ST_ISP_VID_CAP_STREAMING 1
147
129/** 148/**
130 * struct fimc_isp - FIMC-IS ISP data structure 149 * struct fimc_isp - FIMC-IS ISP data structure
131 * @pdev: pointer to FIMC-IS platform device 150 * @pdev: pointer to FIMC-IS platform device
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 04d6ecdd314c..e62211a80f0e 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -11,6 +11,8 @@
11 */ 11 */
12 12
13#include <linux/bug.h> 13#include <linux/bug.h>
14#include <linux/clk.h>
15#include <linux/clk-provider.h>
14#include <linux/device.h> 16#include <linux/device.h>
15#include <linux/errno.h> 17#include <linux/errno.h>
16#include <linux/i2c.h> 18#include <linux/i2c.h>
@@ -25,6 +27,7 @@
25#include <linux/pm_runtime.h> 27#include <linux/pm_runtime.h>
26#include <linux/types.h> 28#include <linux/types.h>
27#include <linux/slab.h> 29#include <linux/slab.h>
30#include <media/v4l2-async.h>
28#include <media/v4l2-ctrls.h> 31#include <media/v4l2-ctrls.h>
29#include <media/v4l2-of.h> 32#include <media/v4l2-of.h>
30#include <media/media-device.h> 33#include <media/media-device.h>
@@ -219,6 +222,7 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep,
219 if (ret < 0) 222 if (ret < 0)
220 return ret; 223 return ret;
221 } 224 }
225
222 ret = fimc_md_set_camclk(sd, true); 226 ret = fimc_md_set_camclk(sd, true);
223 if (ret < 0) 227 if (ret < 0)
224 goto err_wbclk; 228 goto err_wbclk;
@@ -379,77 +383,18 @@ static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
379 struct i2c_client *client = v4l2_get_subdevdata(sd); 383 struct i2c_client *client = v4l2_get_subdevdata(sd);
380 struct i2c_adapter *adapter; 384 struct i2c_adapter *adapter;
381 385
382 if (!client) 386 if (!client || client->dev.of_node)
383 return; 387 return;
384 388
385 v4l2_device_unregister_subdev(sd); 389 v4l2_device_unregister_subdev(sd);
386 390
387 if (!client->dev.of_node) { 391 adapter = client->adapter;
388 adapter = client->adapter; 392 i2c_unregister_device(client);
389 i2c_unregister_device(client); 393 if (adapter)
390 if (adapter) 394 i2c_put_adapter(adapter);
391 i2c_put_adapter(adapter);
392 }
393} 395}
394 396
395#ifdef CONFIG_OF 397#ifdef CONFIG_OF
396/* Register I2C client subdev associated with @node. */
397static int fimc_md_of_add_sensor(struct fimc_md *fmd,
398 struct device_node *node, int index)
399{
400 struct fimc_sensor_info *si;
401 struct i2c_client *client;
402 struct v4l2_subdev *sd;
403 int ret;
404
405 if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
406 return -EINVAL;
407 si = &fmd->sensor[index];
408
409 client = of_find_i2c_device_by_node(node);
410 if (!client)
411 return -EPROBE_DEFER;
412
413 device_lock(&client->dev);
414
415 if (!client->dev.driver ||
416 !try_module_get(client->dev.driver->owner)) {
417 ret = -EPROBE_DEFER;
418 v4l2_info(&fmd->v4l2_dev, "No driver found for %s\n",
419 node->full_name);
420 goto dev_put;
421 }
422
423 /* Enable sensor's master clock */
424 ret = __fimc_md_set_camclk(fmd, &si->pdata, true);
425 if (ret < 0)
426 goto mod_put;
427 sd = i2c_get_clientdata(client);
428
429 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
430 __fimc_md_set_camclk(fmd, &si->pdata, false);
431 if (ret < 0)
432 goto mod_put;
433
434 v4l2_set_subdev_hostdata(sd, &si->pdata);
435 if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
436 sd->grp_id = GRP_ID_FIMC_IS_SENSOR;
437 else
438 sd->grp_id = GRP_ID_SENSOR;
439
440 si->subdev = sd;
441 v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
442 sd->name, fmd->num_sensors);
443 fmd->num_sensors++;
444
445mod_put:
446 module_put(client->dev.driver->owner);
447dev_put:
448 device_unlock(&client->dev);
449 put_device(&client->dev);
450 return ret;
451}
452
453/* Parse port node and register as a sub-device any sensor specified there. */ 398/* Parse port node and register as a sub-device any sensor specified there. */
454static int fimc_md_parse_port_node(struct fimc_md *fmd, 399static int fimc_md_parse_port_node(struct fimc_md *fmd,
455 struct device_node *port, 400 struct device_node *port,
@@ -458,7 +403,6 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
458 struct device_node *rem, *ep, *np; 403 struct device_node *rem, *ep, *np;
459 struct fimc_source_info *pd; 404 struct fimc_source_info *pd;
460 struct v4l2_of_endpoint endpoint; 405 struct v4l2_of_endpoint endpoint;
461 int ret;
462 u32 val; 406 u32 val;
463 407
464 pd = &fmd->sensor[index].pdata; 408 pd = &fmd->sensor[index].pdata;
@@ -486,6 +430,8 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
486 430
487 if (!of_property_read_u32(rem, "clock-frequency", &val)) 431 if (!of_property_read_u32(rem, "clock-frequency", &val))
488 pd->clk_frequency = val; 432 pd->clk_frequency = val;
433 else
434 pd->clk_frequency = DEFAULT_SENSOR_CLK_FREQ;
489 435
490 if (pd->clk_frequency == 0) { 436 if (pd->clk_frequency == 0) {
491 v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n", 437 v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n",
@@ -525,10 +471,17 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd,
525 else 471 else
526 pd->fimc_bus_type = pd->sensor_bus_type; 472 pd->fimc_bus_type = pd->sensor_bus_type;
527 473
528 ret = fimc_md_of_add_sensor(fmd, rem, index); 474 if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
529 of_node_put(rem); 475 return -EINVAL;
530 476
531 return ret; 477 fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF;
478 fmd->sensor[index].asd.match.of.node = rem;
479 fmd->async_subdevs[index] = &fmd->sensor[index].asd;
480
481 fmd->num_sensors++;
482
483 of_node_put(rem);
484 return 0;
532} 485}
533 486
534/* Register all SoC external sub-devices */ 487/* Register all SoC external sub-devices */
@@ -732,8 +685,16 @@ static int register_csis_entity(struct fimc_md *fmd,
732static int register_fimc_is_entity(struct fimc_md *fmd, struct fimc_is *is) 685static int register_fimc_is_entity(struct fimc_md *fmd, struct fimc_is *is)
733{ 686{
734 struct v4l2_subdev *sd = &is->isp.subdev; 687 struct v4l2_subdev *sd = &is->isp.subdev;
688 struct exynos_media_pipeline *ep;
735 int ret; 689 int ret;
736 690
691 /* Allocate pipeline object for the ISP capture video node. */
692 ep = fimc_md_pipeline_create(fmd);
693 if (!ep)
694 return -ENOMEM;
695
696 v4l2_set_subdev_hostdata(sd, ep);
697
737 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); 698 ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
738 if (ret) { 699 if (ret) {
739 v4l2_err(&fmd->v4l2_dev, 700 v4l2_err(&fmd->v4l2_dev,
@@ -884,11 +845,13 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
884 v4l2_device_unregister_subdev(fmd->csis[i].sd); 845 v4l2_device_unregister_subdev(fmd->csis[i].sd);
885 fmd->csis[i].sd = NULL; 846 fmd->csis[i].sd = NULL;
886 } 847 }
887 for (i = 0; i < fmd->num_sensors; i++) { 848 if (fmd->pdev->dev.of_node == NULL) {
888 if (fmd->sensor[i].subdev == NULL) 849 for (i = 0; i < fmd->num_sensors; i++) {
889 continue; 850 if (fmd->sensor[i].subdev == NULL)
890 fimc_md_unregister_sensor(fmd->sensor[i].subdev); 851 continue;
891 fmd->sensor[i].subdev = NULL; 852 fimc_md_unregister_sensor(fmd->sensor[i].subdev);
853 fmd->sensor[i].subdev = NULL;
854 }
892 } 855 }
893 856
894 if (fmd->fimc_is) 857 if (fmd->fimc_is)
@@ -1005,16 +968,17 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
1005/* Create FIMC-IS links */ 968/* Create FIMC-IS links */
1006static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd) 969static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
1007{ 970{
971 struct fimc_isp *isp = &fmd->fimc_is->isp;
1008 struct media_entity *source, *sink; 972 struct media_entity *source, *sink;
1009 int i, ret; 973 int i, ret;
1010 974
1011 source = &fmd->fimc_is->isp.subdev.entity; 975 source = &isp->subdev.entity;
1012 976
1013 for (i = 0; i < FIMC_MAX_DEVS; i++) { 977 for (i = 0; i < FIMC_MAX_DEVS; i++) {
1014 if (fmd->fimc[i] == NULL) 978 if (fmd->fimc[i] == NULL)
1015 continue; 979 continue;
1016 980
1017 /* Link from IS-ISP subdev to FIMC */ 981 /* Link from FIMC-IS-ISP subdev to FIMC */
1018 sink = &fmd->fimc[i]->vid_cap.subdev.entity; 982 sink = &fmd->fimc[i]->vid_cap.subdev.entity;
1019 ret = media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_FIFO, 983 ret = media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_FIFO,
1020 sink, FIMC_SD_PAD_SINK_FIFO, 0); 984 sink, FIMC_SD_PAD_SINK_FIFO, 0);
@@ -1022,7 +986,15 @@ static int __fimc_md_create_fimc_is_links(struct fimc_md *fmd)
1022 return ret; 986 return ret;
1023 } 987 }
1024 988
1025 return ret; 989 /* Link from FIMC-IS-ISP subdev to fimc-is-isp.capture video node */
990 sink = &isp->video_capture.ve.vdev.entity;
991
992 /* Skip this link if the fimc-is-isp video node driver isn't built-in */
993 if (sink->num_pads == 0)
994 return 0;
995
996 return media_entity_create_link(source, FIMC_ISP_SD_PAD_SRC_DMA,
997 sink, 0, 0);
1026} 998}
1027 999
1028/** 1000/**
@@ -1223,6 +1195,14 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
1223 struct fimc_camclk_info *camclk; 1195 struct fimc_camclk_info *camclk;
1224 int ret = 0; 1196 int ret = 0;
1225 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
1226 if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf) 1206 if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf)
1227 return -EINVAL; 1207 return -EINVAL;
1228 1208
@@ -1277,6 +1257,14 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
1277 struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd); 1257 struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd);
1278 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity); 1258 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
1279 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
1280 return __fimc_md_set_camclk(fmd, si, on); 1268 return __fimc_md_set_camclk(fmd, si, on);
1281} 1269}
1282 1270
@@ -1438,6 +1426,153 @@ static int fimc_md_get_pinctrl(struct fimc_md *fmd)
1438 return 0; 1426 return 0;
1439} 1427}
1440 1428
1429#ifdef CONFIG_OF
1430static int cam_clk_prepare(struct clk_hw *hw)
1431{
1432 struct cam_clk *camclk = to_cam_clk(hw);
1433 int ret;
1434
1435 if (camclk->fmd->pmf == NULL)
1436 return -ENODEV;
1437
1438 ret = pm_runtime_get_sync(camclk->fmd->pmf);
1439 return ret < 0 ? ret : 0;
1440}
1441
1442static void cam_clk_unprepare(struct clk_hw *hw)
1443{
1444 struct cam_clk *camclk = to_cam_clk(hw);
1445
1446 if (camclk->fmd->pmf == NULL)
1447 return;
1448
1449 pm_runtime_put_sync(camclk->fmd->pmf);
1450}
1451
1452static const struct clk_ops cam_clk_ops = {
1453 .prepare = cam_clk_prepare,
1454 .unprepare = cam_clk_unprepare,
1455};
1456
1457static void fimc_md_unregister_clk_provider(struct fimc_md *fmd)
1458{
1459 struct cam_clk_provider *cp = &fmd->clk_provider;
1460 unsigned int i;
1461
1462 if (cp->of_node)
1463 of_clk_del_provider(cp->of_node);
1464
1465 for (i = 0; i < cp->num_clocks; i++)
1466 clk_unregister(cp->clks[i]);
1467}
1468
1469static int fimc_md_register_clk_provider(struct fimc_md *fmd)
1470{
1471 struct cam_clk_provider *cp = &fmd->clk_provider;
1472 struct device *dev = &fmd->pdev->dev;
1473 int i, ret;
1474
1475 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
1476 struct cam_clk *camclk = &cp->camclk[i];
1477 struct clk_init_data init;
1478 const char *p_name;
1479
1480 ret = of_property_read_string_index(dev->of_node,
1481 "clock-output-names", i, &init.name);
1482 if (ret < 0)
1483 break;
1484
1485 p_name = __clk_get_name(fmd->camclk[i].clock);
1486
1487 /* It's safe since clk_register() will duplicate the string. */
1488 init.parent_names = &p_name;
1489 init.num_parents = 1;
1490 init.ops = &cam_clk_ops;
1491 init.flags = CLK_SET_RATE_PARENT;
1492 camclk->hw.init = &init;
1493 camclk->fmd = fmd;
1494
1495 cp->clks[i] = clk_register(NULL, &camclk->hw);
1496 if (IS_ERR(cp->clks[i])) {
1497 dev_err(dev, "failed to register clock: %s (%ld)\n",
1498 init.name, PTR_ERR(cp->clks[i]));
1499 ret = PTR_ERR(cp->clks[i]);
1500 goto err;
1501 }
1502 cp->num_clocks++;
1503 }
1504
1505 if (cp->num_clocks == 0) {
1506 dev_warn(dev, "clk provider not registered\n");
1507 return 0;
1508 }
1509
1510 cp->clk_data.clks = cp->clks;
1511 cp->clk_data.clk_num = cp->num_clocks;
1512 cp->of_node = dev->of_node;
1513 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
1514 &cp->clk_data);
1515 if (ret == 0)
1516 return 0;
1517err:
1518 fimc_md_unregister_clk_provider(fmd);
1519 return ret;
1520}
1521#else
1522#define fimc_md_register_clk_provider(fmd) (0)
1523#define fimc_md_unregister_clk_provider(fmd) (0)
1524#endif
1525
1526static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
1527 struct v4l2_subdev *subdev,
1528 struct v4l2_async_subdev *asd)
1529{
1530 struct fimc_md *fmd = notifier_to_fimc_md(notifier);
1531 struct fimc_sensor_info *si = NULL;
1532 int i;
1533
1534 /* Find platform data for this sensor subdev */
1535 for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++)
1536 if (fmd->sensor[i].asd.match.of.node == subdev->dev->of_node)
1537 si = &fmd->sensor[i];
1538
1539 if (si == NULL)
1540 return -EINVAL;
1541
1542 v4l2_set_subdev_hostdata(subdev, &si->pdata);
1543
1544 if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK)
1545 subdev->grp_id = GRP_ID_FIMC_IS_SENSOR;
1546 else
1547 subdev->grp_id = GRP_ID_SENSOR;
1548
1549 si->subdev = subdev;
1550
1551 v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
1552 subdev->name, fmd->num_sensors);
1553
1554 fmd->num_sensors++;
1555
1556 return 0;
1557}
1558
1559static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
1560{
1561 struct fimc_md *fmd = notifier_to_fimc_md(notifier);
1562 int ret;
1563
1564 mutex_lock(&fmd->media_dev.graph_mutex);
1565
1566 ret = fimc_md_create_links(fmd);
1567 if (ret < 0)
1568 goto unlock;
1569
1570 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
1571unlock:
1572 mutex_unlock(&fmd->media_dev.graph_mutex);
1573 return ret;
1574}
1575
1441static int fimc_md_probe(struct platform_device *pdev) 1576static int fimc_md_probe(struct platform_device *pdev)
1442{ 1577{
1443 struct device *dev = &pdev->dev; 1578 struct device *dev = &pdev->dev;
@@ -1470,63 +1605,91 @@ static int fimc_md_probe(struct platform_device *pdev)
1470 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); 1605 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
1471 return ret; 1606 return ret;
1472 } 1607 }
1608
1473 ret = media_device_register(&fmd->media_dev); 1609 ret = media_device_register(&fmd->media_dev);
1474 if (ret < 0) { 1610 if (ret < 0) {
1475 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); 1611 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
1476 goto err_md; 1612 goto err_v4l2_dev;
1477 } 1613 }
1614
1478 ret = fimc_md_get_clocks(fmd); 1615 ret = fimc_md_get_clocks(fmd);
1479 if (ret) 1616 if (ret)
1480 goto err_clk; 1617 goto err_md;
1481 1618
1482 fmd->user_subdev_api = (dev->of_node != NULL); 1619 fmd->user_subdev_api = (dev->of_node != NULL);
1483 1620
1484 /* Protect the media graph while we're registering entities */
1485 mutex_lock(&fmd->media_dev.graph_mutex);
1486
1487 ret = fimc_md_get_pinctrl(fmd); 1621 ret = fimc_md_get_pinctrl(fmd);
1488 if (ret < 0) { 1622 if (ret < 0) {
1489 if (ret != EPROBE_DEFER) 1623 if (ret != EPROBE_DEFER)
1490 dev_err(dev, "Failed to get pinctrl: %d\n", ret); 1624 dev_err(dev, "Failed to get pinctrl: %d\n", ret);
1491 goto err_unlock; 1625 goto err_clk;
1492 } 1626 }
1493 1627
1628 platform_set_drvdata(pdev, fmd);
1629
1630 /* Protect the media graph while we're registering entities */
1631 mutex_lock(&fmd->media_dev.graph_mutex);
1632
1494 if (dev->of_node) 1633 if (dev->of_node)
1495 ret = fimc_md_register_of_platform_entities(fmd, dev->of_node); 1634 ret = fimc_md_register_of_platform_entities(fmd, dev->of_node);
1496 else 1635 else
1497 ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, 1636 ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
1498 fimc_md_pdev_match); 1637 fimc_md_pdev_match);
1499 if (ret) 1638 if (ret) {
1500 goto err_unlock; 1639 mutex_unlock(&fmd->media_dev.graph_mutex);
1640 goto err_clk;
1641 }
1501 1642
1502 if (dev->platform_data || dev->of_node) { 1643 if (dev->platform_data || dev->of_node) {
1503 ret = fimc_md_register_sensor_entities(fmd); 1644 ret = fimc_md_register_sensor_entities(fmd);
1504 if (ret) 1645 if (ret) {
1505 goto err_unlock; 1646 mutex_unlock(&fmd->media_dev.graph_mutex);
1647 goto err_m_ent;
1648 }
1506 } 1649 }
1507 1650
1508 ret = fimc_md_create_links(fmd); 1651 mutex_unlock(&fmd->media_dev.graph_mutex);
1509 if (ret)
1510 goto err_unlock;
1511 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
1512 if (ret)
1513 goto err_unlock;
1514 1652
1515 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); 1653 ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1516 if (ret) 1654 if (ret)
1517 goto err_unlock; 1655 goto err_m_ent;
1656 /*
1657 * FIMC platform devices need to be registered before the sclk_cam
1658 * clocks provider, as one of these devices needs to be activated
1659 * to enable the clock.
1660 */
1661 ret = fimc_md_register_clk_provider(fmd);
1662 if (ret < 0) {
1663 v4l2_err(v4l2_dev, "clock provider registration failed\n");
1664 goto err_attr;
1665 }
1666
1667 if (fmd->num_sensors > 0) {
1668 fmd->subdev_notifier.subdevs = fmd->async_subdevs;
1669 fmd->subdev_notifier.num_subdevs = fmd->num_sensors;
1670 fmd->subdev_notifier.bound = subdev_notifier_bound;
1671 fmd->subdev_notifier.complete = subdev_notifier_complete;
1672 fmd->num_sensors = 0;
1673
1674 ret = v4l2_async_notifier_register(&fmd->v4l2_dev,
1675 &fmd->subdev_notifier);
1676 if (ret)
1677 goto err_clk_p;
1678 }
1518 1679
1519 platform_set_drvdata(pdev, fmd);
1520 mutex_unlock(&fmd->media_dev.graph_mutex);
1521 return 0; 1680 return 0;
1522 1681
1523err_unlock: 1682err_clk_p:
1524 mutex_unlock(&fmd->media_dev.graph_mutex); 1683 fimc_md_unregister_clk_provider(fmd);
1684err_attr:
1685 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1525err_clk: 1686err_clk:
1526 fimc_md_put_clocks(fmd); 1687 fimc_md_put_clocks(fmd);
1688err_m_ent:
1527 fimc_md_unregister_entities(fmd); 1689 fimc_md_unregister_entities(fmd);
1528 media_device_unregister(&fmd->media_dev);
1529err_md: 1690err_md:
1691 media_device_unregister(&fmd->media_dev);
1692err_v4l2_dev:
1530 v4l2_device_unregister(&fmd->v4l2_dev); 1693 v4l2_device_unregister(&fmd->v4l2_dev);
1531 return ret; 1694 return ret;
1532} 1695}
@@ -1538,12 +1701,16 @@ static int fimc_md_remove(struct platform_device *pdev)
1538 if (!fmd) 1701 if (!fmd)
1539 return 0; 1702 return 0;
1540 1703
1704 fimc_md_unregister_clk_provider(fmd);
1705 v4l2_async_notifier_unregister(&fmd->subdev_notifier);
1706
1541 v4l2_device_unregister(&fmd->v4l2_dev); 1707 v4l2_device_unregister(&fmd->v4l2_dev);
1542 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); 1708 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1543 fimc_md_unregister_entities(fmd); 1709 fimc_md_unregister_entities(fmd);
1544 fimc_md_pipelines_free(fmd); 1710 fimc_md_pipelines_free(fmd);
1545 media_device_unregister(&fmd->media_dev); 1711 media_device_unregister(&fmd->media_dev);
1546 fimc_md_put_clocks(fmd); 1712 fimc_md_put_clocks(fmd);
1713
1547 return 0; 1714 return 0;
1548} 1715}
1549 1716
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 62599fd7756f..ee1e2519f728 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -10,6 +10,7 @@
10#define FIMC_MDEVICE_H_ 10#define FIMC_MDEVICE_H_
11 11
12#include <linux/clk.h> 12#include <linux/clk.h>
13#include <linux/clk-provider.h>
13#include <linux/platform_device.h> 14#include <linux/platform_device.h>
14#include <linux/mutex.h> 15#include <linux/mutex.h>
15#include <linux/of.h> 16#include <linux/of.h>
@@ -31,8 +32,9 @@
31 32
32#define PINCTRL_STATE_IDLE "idle" 33#define PINCTRL_STATE_IDLE "idle"
33 34
34#define FIMC_MAX_SENSORS 8 35#define FIMC_MAX_SENSORS 4
35#define FIMC_MAX_CAMCLKS 2 36#define FIMC_MAX_CAMCLKS 2
37#define DEFAULT_SENSOR_CLK_FREQ 24000000U
36 38
37/* LCD/ISP Writeback clocks (PIXELASYNCMx) */ 39/* LCD/ISP Writeback clocks (PIXELASYNCMx) */
38enum { 40enum {
@@ -78,6 +80,7 @@ struct fimc_camclk_info {
78/** 80/**
79 * struct fimc_sensor_info - image data source subdev information 81 * struct fimc_sensor_info - image data source subdev information
80 * @pdata: sensor's atrributes passed as media device's platform data 82 * @pdata: sensor's atrributes passed as media device's platform data
83 * @asd: asynchronous subdev registration data structure
81 * @subdev: image sensor v4l2 subdev 84 * @subdev: image sensor v4l2 subdev
82 * @host: fimc device the sensor is currently linked to 85 * @host: fimc device the sensor is currently linked to
83 * 86 *
@@ -85,10 +88,17 @@ struct fimc_camclk_info {
85 */ 88 */
86struct fimc_sensor_info { 89struct fimc_sensor_info {
87 struct fimc_source_info pdata; 90 struct fimc_source_info pdata;
91 struct v4l2_async_subdev asd;
88 struct v4l2_subdev *subdev; 92 struct v4l2_subdev *subdev;
89 struct fimc_dev *host; 93 struct fimc_dev *host;
90}; 94};
91 95
96struct cam_clk {
97 struct clk_hw hw;
98 struct fimc_md *fmd;
99};
100#define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw)
101
92/** 102/**
93 * struct fimc_md - fimc media device information 103 * struct fimc_md - fimc media device information
94 * @csis: MIPI CSIS subdevs data 104 * @csis: MIPI CSIS subdevs data
@@ -105,6 +115,7 @@ struct fimc_sensor_info {
105 * @pinctrl: camera port pinctrl handle 115 * @pinctrl: camera port pinctrl handle
106 * @state_default: pinctrl default state handle 116 * @state_default: pinctrl default state handle
107 * @state_idle: pinctrl idle state handle 117 * @state_idle: pinctrl idle state handle
118 * @cam_clk_provider: CAMCLK clock provider structure
108 * @user_subdev_api: true if subdevs are not configured by the host driver 119 * @user_subdev_api: true if subdevs are not configured by the host driver
109 * @slock: spinlock protecting @sensor array 120 * @slock: spinlock protecting @sensor array
110 */ 121 */
@@ -122,13 +133,25 @@ struct fimc_md {
122 struct media_device media_dev; 133 struct media_device media_dev;
123 struct v4l2_device v4l2_dev; 134 struct v4l2_device v4l2_dev;
124 struct platform_device *pdev; 135 struct platform_device *pdev;
136
125 struct fimc_pinctrl { 137 struct fimc_pinctrl {
126 struct pinctrl *pinctrl; 138 struct pinctrl *pinctrl;
127 struct pinctrl_state *state_default; 139 struct pinctrl_state *state_default;
128 struct pinctrl_state *state_idle; 140 struct pinctrl_state *state_idle;
129 } pinctl; 141 } pinctl;
130 bool user_subdev_api;
131 142
143 struct cam_clk_provider {
144 struct clk *clks[FIMC_MAX_CAMCLKS];
145 struct clk_onecell_data clk_data;
146 struct device_node *of_node;
147 struct cam_clk camclk[FIMC_MAX_CAMCLKS];
148 int num_clocks;
149 } clk_provider;
150
151 struct v4l2_async_notifier subdev_notifier;
152 struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS];
153
154 bool user_subdev_api;
132 spinlock_t slock; 155 spinlock_t slock;
133 struct list_head pipelines; 156 struct list_head pipelines;
134}; 157};
@@ -145,6 +168,11 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
145 container_of(me->parent, struct fimc_md, media_dev); 168 container_of(me->parent, struct fimc_md, media_dev);
146} 169}
147 170
171static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n)
172{
173 return container_of(n, struct fimc_md, subdev_notifier);
174}
175
148static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) 176static inline void fimc_md_graph_lock(struct exynos_video_entity *ve)
149{ 177{
150 mutex_lock(&ve->vdev.entity.parent->graph_mutex); 178 mutex_lock(&ve->vdev.entity.parent->graph_mutex);
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
index 33f2c7374cfd..57fb05bb8c77 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-regs.h
+++ b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
@@ -210,19 +210,19 @@
210 210
211/* JPEG CNTL Register bit */ 211/* JPEG CNTL Register bit */
212#define EXYNOS4_ENC_DEC_MODE_MASK (0xfffffffc << 0) 212#define EXYNOS4_ENC_DEC_MODE_MASK (0xfffffffc << 0)
213#define EXYNOS4_DEC_MODE (1 << 0) 213#define EXYNOS4_DEC_MODE (1 << 0)
214#define EXYNOS4_ENC_MODE (1 << 1) 214#define EXYNOS4_ENC_MODE (1 << 1)
215#define EXYNOS4_AUTO_RST_MARKER (1 << 2) 215#define EXYNOS4_AUTO_RST_MARKER (1 << 2)
216#define EXYNOS4_RST_INTERVAL_SHIFT 3 216#define EXYNOS4_RST_INTERVAL_SHIFT 3
217#define EXYNOS4_RST_INTERVAL(x) (((x) & 0xffff) \ 217#define EXYNOS4_RST_INTERVAL(x) (((x) & 0xffff) \
218 << EXYNOS4_RST_INTERVAL_SHIFT) 218 << EXYNOS4_RST_INTERVAL_SHIFT)
219#define EXYNOS4_HUF_TBL_EN (1 << 19) 219#define EXYNOS4_HUF_TBL_EN (1 << 19)
220#define EXYNOS4_HOR_SCALING_SHIFT 20 220#define EXYNOS4_HOR_SCALING_SHIFT 20
221#define EXYNOS4_HOR_SCALING_MASK (3 << EXYNOS4_HOR_SCALING_SHIFT) 221#define EXYNOS4_HOR_SCALING_MASK (3 << EXYNOS4_HOR_SCALING_SHIFT)
222#define EXYNOS4_HOR_SCALING(x) (((x) & 0x3) \ 222#define EXYNOS4_HOR_SCALING(x) (((x) & 0x3) \
223 << EXYNOS4_HOR_SCALING_SHIFT) 223 << EXYNOS4_HOR_SCALING_SHIFT)
224#define EXYNOS4_VER_SCALING_SHIFT 22 224#define EXYNOS4_VER_SCALING_SHIFT 22
225#define EXYNOS4_VER_SCALING_MASK (3 << EXYNOS4_VER_SCALING_SHIFT) 225#define EXYNOS4_VER_SCALING_MASK (3 << EXYNOS4_VER_SCALING_SHIFT)
226#define EXYNOS4_VER_SCALING(x) (((x) & 0x3) \ 226#define EXYNOS4_VER_SCALING(x) (((x) & 0x3) \
227 << EXYNOS4_VER_SCALING_SHIFT) 227 << EXYNOS4_VER_SCALING_SHIFT)
228#define EXYNOS4_PADDING (1 << 27) 228#define EXYNOS4_PADDING (1 << 27)
@@ -238,8 +238,8 @@
238#define EXYNOS4_FRAME_ERR_EN (1 << 4) 238#define EXYNOS4_FRAME_ERR_EN (1 << 4)
239#define EXYNOS4_INT_EN_ALL (0x1f << 0) 239#define EXYNOS4_INT_EN_ALL (0x1f << 0)
240 240
241#define EXYNOS4_MOD_REG_PROC_ENC (0 << 3) 241#define EXYNOS4_MOD_REG_PROC_ENC (0 << 3)
242#define EXYNOS4_MOD_REG_PROC_DEC (1 << 3) 242#define EXYNOS4_MOD_REG_PROC_DEC (1 << 3)
243 243
244#define EXYNOS4_MOD_REG_SUBSAMPLE_444 (0 << 0) 244#define EXYNOS4_MOD_REG_SUBSAMPLE_444 (0 << 0)
245#define EXYNOS4_MOD_REG_SUBSAMPLE_422 (1 << 0) 245#define EXYNOS4_MOD_REG_SUBSAMPLE_422 (1 << 0)
@@ -270,7 +270,7 @@
270#define EXYNOS4_DEC_YUV_420_IMG (4 << 0) 270#define EXYNOS4_DEC_YUV_420_IMG (4 << 0)
271 271
272#define EXYNOS4_GRAY_IMG_IP_SHIFT 3 272#define EXYNOS4_GRAY_IMG_IP_SHIFT 3
273#define EXYNOS4_GRAY_IMG_IP_MASK (7 << EXYNOS4_GRAY_IMG_IP_SHIFT) 273#define EXYNOS4_GRAY_IMG_IP_MASK (7 << EXYNOS4_GRAY_IMG_IP_SHIFT)
274#define EXYNOS4_GRAY_IMG_IP (4 << EXYNOS4_GRAY_IMG_IP_SHIFT) 274#define EXYNOS4_GRAY_IMG_IP (4 << EXYNOS4_GRAY_IMG_IP_SHIFT)
275 275
276#define EXYNOS4_RGB_IP_SHIFT 6 276#define EXYNOS4_RGB_IP_SHIFT 6
@@ -278,18 +278,18 @@
278#define EXYNOS4_RGB_IP_RGB_16BIT_IMG (4 << EXYNOS4_RGB_IP_SHIFT) 278#define EXYNOS4_RGB_IP_RGB_16BIT_IMG (4 << EXYNOS4_RGB_IP_SHIFT)
279#define EXYNOS4_RGB_IP_RGB_32BIT_IMG (5 << EXYNOS4_RGB_IP_SHIFT) 279#define EXYNOS4_RGB_IP_RGB_32BIT_IMG (5 << EXYNOS4_RGB_IP_SHIFT)
280 280
281#define EXYNOS4_YUV_444_IP_SHIFT 9 281#define EXYNOS4_YUV_444_IP_SHIFT 9
282#define EXYNOS4_YUV_444_IP_MASK (7 << EXYNOS4_YUV_444_IP_SHIFT) 282#define EXYNOS4_YUV_444_IP_MASK (7 << EXYNOS4_YUV_444_IP_SHIFT)
283#define EXYNOS4_YUV_444_IP_YUV_444_2P_IMG (4 << EXYNOS4_YUV_444_IP_SHIFT) 283#define EXYNOS4_YUV_444_IP_YUV_444_2P_IMG (4 << EXYNOS4_YUV_444_IP_SHIFT)
284#define EXYNOS4_YUV_444_IP_YUV_444_3P_IMG (5 << EXYNOS4_YUV_444_IP_SHIFT) 284#define EXYNOS4_YUV_444_IP_YUV_444_3P_IMG (5 << EXYNOS4_YUV_444_IP_SHIFT)
285 285
286#define EXYNOS4_YUV_422_IP_SHIFT 12 286#define EXYNOS4_YUV_422_IP_SHIFT 12
287#define EXYNOS4_YUV_422_IP_MASK (7 << EXYNOS4_YUV_422_IP_SHIFT) 287#define EXYNOS4_YUV_422_IP_MASK (7 << EXYNOS4_YUV_422_IP_SHIFT)
288#define EXYNOS4_YUV_422_IP_YUV_422_1P_IMG (4 << EXYNOS4_YUV_422_IP_SHIFT) 288#define EXYNOS4_YUV_422_IP_YUV_422_1P_IMG (4 << EXYNOS4_YUV_422_IP_SHIFT)
289#define EXYNOS4_YUV_422_IP_YUV_422_2P_IMG (5 << EXYNOS4_YUV_422_IP_SHIFT) 289#define EXYNOS4_YUV_422_IP_YUV_422_2P_IMG (5 << EXYNOS4_YUV_422_IP_SHIFT)
290#define EXYNOS4_YUV_422_IP_YUV_422_3P_IMG (6 << EXYNOS4_YUV_422_IP_SHIFT) 290#define EXYNOS4_YUV_422_IP_YUV_422_3P_IMG (6 << EXYNOS4_YUV_422_IP_SHIFT)
291 291
292#define EXYNOS4_YUV_420_IP_SHIFT 15 292#define EXYNOS4_YUV_420_IP_SHIFT 15
293#define EXYNOS4_YUV_420_IP_MASK (7 << EXYNOS4_YUV_420_IP_SHIFT) 293#define EXYNOS4_YUV_420_IP_MASK (7 << EXYNOS4_YUV_420_IP_SHIFT)
294#define EXYNOS4_YUV_420_IP_YUV_420_2P_IMG (4 << EXYNOS4_YUV_420_IP_SHIFT) 294#define EXYNOS4_YUV_420_IP_YUV_420_2P_IMG (4 << EXYNOS4_YUV_420_IP_SHIFT)
295#define EXYNOS4_YUV_420_IP_YUV_420_3P_IMG (5 << EXYNOS4_YUV_420_IP_SHIFT) 295#define EXYNOS4_YUV_420_IP_YUV_420_3P_IMG (5 << EXYNOS4_YUV_420_IP_SHIFT)
@@ -303,8 +303,8 @@
303 303
304#define EXYNOS4_JPEG_DECODED_IMG_FMT_MASK 0x03 304#define EXYNOS4_JPEG_DECODED_IMG_FMT_MASK 0x03
305 305
306#define EXYNOS4_SWAP_CHROMA_CRCB (1 << 26) 306#define EXYNOS4_SWAP_CHROMA_CRCB (1 << 26)
307#define EXYNOS4_SWAP_CHROMA_CBCR (0 << 26) 307#define EXYNOS4_SWAP_CHROMA_CBCR (0 << 26)
308 308
309/* JPEG HUFF count Register bit */ 309/* JPEG HUFF count Register bit */
310#define EXYNOS4_HUFF_COUNT_MASK 0xffff 310#define EXYNOS4_HUFF_COUNT_MASK 0xffff