--- zzzz-none-000/linux-3.10.107/drivers/media/platform/exynos4-is/fimc-is.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/platform/exynos4-is/fimc-is.c 2021-02-04 17:41:59.000000000 +0000 @@ -21,16 +21,16 @@ #include #include #include -#include +#include #include #include +#include #include #include #include #include #include #include -#include #include #include "media-dev.h" @@ -129,7 +129,7 @@ ATCLK_MCUISP_FREQUENCY); } -int fimc_is_enable_clocks(struct fimc_is *is) +static int fimc_is_enable_clocks(struct fimc_is *is) { int i, ret; @@ -149,7 +149,7 @@ return 0; } -void fimc_is_disable_clocks(struct fimc_is *is) +static void fimc_is_disable_clocks(struct fimc_is *is) { int i; @@ -161,78 +161,69 @@ } } -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 = v4l2_of_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 = v4l2_of_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; - } + /* Initialize memory allocator context for the ISP DMA. */ + is->isp.alloc_ctx = is->alloc_ctx; - 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; - - /* FIXME: Add support for multiple sensors. */ - if (WARN_ON(is->sensor)) - continue; - - 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); + 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); + + 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; } @@ -376,6 +367,9 @@ { struct device *dev = &is->pdev->dev; + if (is->memory.vaddr == NULL) + return; + dma_free_coherent(dev, is->memory.size, is->memory.vaddr, is->memory.paddr); } @@ -394,7 +388,7 @@ mutex_lock(&is->lock); if (fw->size < FIMC_IS_FW_SIZE_MIN || fw->size > FIMC_IS_FW_SIZE_MAX) { - dev_err(dev, "wrong firmware size: %d\n", fw->size); + dev_err(dev, "wrong firmware size: %zu\n", fw->size); goto done; } @@ -422,7 +416,7 @@ dev_info(dev, "loaded firmware: %s, rev. %s\n", is->fw.info, is->fw.version); - dev_dbg(dev, "FW size: %d, paddr: %#x\n", fw->size, is->memory.paddr); + dev_dbg(dev, "FW size: %zu, paddr: %pad\n", fw->size, &is->memory.paddr); is->is_shared_region->chip_id = 0xe4412; is->is_shared_region->chip_rev_no = 1; @@ -434,8 +428,7 @@ * needed around for copying to the IS working memory every * time before the Cortex-A5 is restarted. */ - if (is->fw.f_w) - release_firmware(is->fw.f_w); + release_firmware(is->fw.f_w); is->fw.f_w = fw; done: mutex_unlock(&is->lock); @@ -527,8 +520,8 @@ break; case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); pr_debug("HIC_SET_PARAMETER\n"); break; @@ -587,8 +580,8 @@ switch (is->i2h_cmd.args[0]) { case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); break; } @@ -647,7 +640,7 @@ 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 +654,8 @@ 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; @@ -699,9 +692,9 @@ return -EIO; } - pr_debug("shared region: %#x, parameter region: %#x\n", - is->memory.paddr + FIMC_IS_SHARED_REGION_OFFSET, - is->is_dma_p_region); + pr_debug("shared region: %pad, parameter region: %pad\n", + &is->memory.paddr + FIMC_IS_SHARED_REGION_OFFSET, + &is->is_dma_p_region); is->setfile.sub_index = 0; @@ -781,6 +774,9 @@ return is->debugfs_entry == NULL ? -EIO : 0; } +static int fimc_is_runtime_resume(struct device *dev); +static int fimc_is_runtime_suspend(struct device *dev); + static int fimc_is_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -817,9 +813,9 @@ return -ENOMEM; is->irq = irq_of_parse_and_map(dev->of_node, 0); - if (is->irq < 0) { + if (!is->irq) { dev_err(dev, "no irq found\n"); - return is->irq; + return -EINVAL; } ret = fimc_is_get_clocks(is); @@ -835,14 +831,20 @@ } pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = fimc_is_runtime_resume(dev); + if (ret < 0) + goto err_irq; + } + ret = pm_runtime_get_sync(dev); if (ret < 0) - goto err_irq; + goto err_pm; is->alloc_ctx = vb2_dma_contig_init_ctx(dev); if (IS_ERR(is->alloc_ctx)) { ret = PTR_ERR(is->alloc_ctx); - goto err_irq; + goto err_pm; } /* * Register FIMC-IS V4L2 subdevs to this driver. The video nodes @@ -867,10 +869,13 @@ err_dfs: fimc_is_debugfs_remove(is); -err_vb: - vb2_dma_contig_cleanup_ctx(is->alloc_ctx); err_sd: fimc_is_unregister_subdevs(is); +err_vb: + vb2_dma_contig_cleanup_ctx(is->alloc_ctx); +err_pm: + if (!pm_runtime_enabled(dev)) + fimc_is_runtime_suspend(dev); err_irq: free_irq(is->irq, is); err_clk: @@ -919,17 +924,19 @@ static int fimc_is_remove(struct platform_device *pdev) { - struct fimc_is *is = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + struct fimc_is *is = dev_get_drvdata(dev); - pm_runtime_disable(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + if (!pm_runtime_status_suspended(dev)) + fimc_is_runtime_suspend(dev); free_irq(is->irq, is); fimc_is_unregister_subdevs(is); vb2_dma_contig_cleanup_ctx(is->alloc_ctx); fimc_is_put_clocks(is); fimc_is_debugfs_remove(is); - if (is->fw.f_w) - release_firmware(is->fw.f_w); + release_firmware(is->fw.f_w); fimc_is_free_cpu_memory(is); return 0; @@ -953,7 +960,6 @@ .driver = { .of_match_table = fimc_is_of_match, .name = FIMC_IS_DRV_NAME, - .owner = THIS_MODULE, .pm = &fimc_is_pm_ops, } }; @@ -962,27 +968,20 @@ { 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); } @@ -993,3 +992,4 @@ MODULE_ALIAS("platform:" FIMC_IS_DRV_NAME); MODULE_AUTHOR("Younghwan Joo "); MODULE_AUTHOR("Sylwester Nawrocki "); +MODULE_LICENSE("GPL v2");