Merge branch 'topic/exynos' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[linux-2.6-microblaze.git] / drivers / media / platform / exynos4-is / fimc-is.c
index 9bdfa45..128b73b 100644 (file)
@@ -161,78 +161,69 @@ static void fimc_is_disable_clocks(struct fimc_is *is)
        }
 }
 
-static int fimc_is_parse_sensor_config(struct fimc_is_sensor *sensor,
-                                      struct device_node *np)
+static int fimc_is_parse_sensor_config(struct fimc_is *is, unsigned int index,
+                                               struct device_node *node)
 {
+       struct fimc_is_sensor *sensor = &is->sensor[index];
        u32 tmp = 0;
        int ret;
 
-       np = of_graph_get_next_endpoint(np, NULL);
-       if (!np)
+       sensor->drvdata = fimc_is_sensor_get_drvdata(node);
+       if (!sensor->drvdata) {
+               dev_err(&is->pdev->dev, "no driver data found for: %s\n",
+                                                        node->full_name);
+               return -EINVAL;
+       }
+
+       node = of_graph_get_next_endpoint(node, NULL);
+       if (!node)
                return -ENXIO;
-       np = of_graph_get_remote_port(np);
-       if (!np)
+
+       node = of_graph_get_remote_port(node);
+       if (!node)
                return -ENXIO;
 
        /* Use MIPI-CSIS channel id to determine the ISP I2C bus index. */
-       ret = of_property_read_u32(np, "reg", &tmp);
-       sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
+       ret = of_property_read_u32(node, "reg", &tmp);
+       if (ret < 0) {
+               dev_err(&is->pdev->dev, "reg property not found at: %s\n",
+                                                        node->full_name);
+               return ret;
+       }
 
-       return ret;
+       sensor->i2c_bus = tmp - FIMC_INPUT_MIPI_CSI2_0;
+       return 0;
 }
 
 static int fimc_is_register_subdevs(struct fimc_is *is)
 {
-       struct device_node *adapter, *child;
-       int ret;
+       struct device_node *i2c_bus, *child;
+       int ret, index = 0;
 
        ret = fimc_isp_subdev_create(&is->isp);
        if (ret < 0)
                return ret;
 
-       for_each_compatible_node(adapter, NULL, FIMC_IS_I2C_COMPATIBLE) {
-               if (!of_find_device_by_node(adapter)) {
-                       of_node_put(adapter);
-                       return -EPROBE_DEFER;
-               }
-
-               for_each_available_child_of_node(adapter, child) {
-                       struct i2c_client *client;
-                       struct v4l2_subdev *sd;
-
-                       client = of_find_i2c_device_by_node(child);
-                       if (!client)
-                               goto e_retry;
-
-                       sd = i2c_get_clientdata(client);
-                       if (!sd)
-                               goto e_retry;
+       /* Initialize memory allocator context for the ISP DMA. */
+       is->isp.alloc_ctx = is->alloc_ctx;
 
-                       /* FIXME: Add support for multiple sensors. */
-                       if (WARN_ON(is->sensor))
-                               continue;
+       for_each_compatible_node(i2c_bus, NULL, FIMC_IS_I2C_COMPATIBLE) {
+               for_each_available_child_of_node(i2c_bus, child) {
+                       ret = fimc_is_parse_sensor_config(is, index, child);
 
-                       is->sensor = sd_to_fimc_is_sensor(sd);
-
-                       if (fimc_is_parse_sensor_config(is->sensor, child)) {
-                               dev_warn(&is->pdev->dev, "DT parse error: %s\n",
-                                                        child->full_name);
+                       if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) {
+                               of_node_put(child);
+                               return ret;
                        }
-                       pr_debug("%s(): registered subdev: %p\n",
-                                __func__, sd->name);
+                       index++;
                }
        }
        return 0;
-
-e_retry:
-       of_node_put(child);
-       return -EPROBE_DEFER;
 }
 
 static int fimc_is_unregister_subdevs(struct fimc_is *is)
 {
        fimc_isp_subdev_destroy(&is->isp);
-       is->sensor = NULL;
        return 0;
 }
 
@@ -647,7 +638,7 @@ static int fimc_is_hw_open_sensor(struct fimc_is *is,
        fimc_is_hw_set_intgr0_gd0(is);
 
        return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1,
-                                 FIMC_IS_SENSOR_OPEN_TIMEOUT);
+                                 sensor->drvdata->open_timeout);
 }
 
 
@@ -661,8 +652,8 @@ int fimc_is_hw_initialize(struct fimc_is *is)
        u32 prev_id;
        int i, ret;
 
-       /* Sensor initialization. */
-       ret = fimc_is_hw_open_sensor(is, is->sensor);
+       /* Sensor initialization. Only one sensor is currently supported. */
+       ret = fimc_is_hw_open_sensor(is, &is->sensor[0]);
        if (ret < 0)
                return ret;
 
@@ -977,27 +968,20 @@ static int fimc_is_module_init(void)
 {
        int ret;
 
-       ret = fimc_is_register_sensor_driver();
-       if (ret < 0)
-               return ret;
-
        ret = fimc_is_register_i2c_driver();
        if (ret < 0)
-               goto err_sens;
+               return ret;
 
        ret = platform_driver_register(&fimc_is_driver);
-       if (!ret)
-               return ret;
 
-       fimc_is_unregister_i2c_driver();
-err_sens:
-       fimc_is_unregister_sensor_driver();
+       if (ret < 0)
+               fimc_is_unregister_i2c_driver();
+
        return ret;
 }
 
 static void fimc_is_module_exit(void)
 {
-       fimc_is_unregister_sensor_driver();
        fimc_is_unregister_i2c_driver();
        platform_driver_unregister(&fimc_is_driver);
 }