* [PATCH RFC v2 03/15] s5p-csis: Add device tree support
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
s5p-csis is platform device driver for MIPI-CSI frontend to the FIMC
device. This patch support for binding the driver to the MIPI-CSIS
devices instantiated from device tree and for parsing all SoC and
board specific properties.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../bindings/media/soc/samsung-mipi-csis.txt | 84 +++++++++++
drivers/media/platform/s5p-fimc/mipi-csis.c | 159 +++++++++++++++-----
drivers/media/platform/s5p-fimc/mipi-csis.h | 1 +
3 files changed, 208 insertions(+), 36 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
new file mode 100644
index 0000000..c06ef5a
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
@@ -0,0 +1,84 @@
+Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver (MIPI CSIS)
+-----------------------------------------------------
+
+Required properties:
+
+- compatible : "samsung,s5pv210-csis" for S5PV210 SoCs,
+ "samsung,exynos4210-csis" for Exynos4210 and later SoCs;
+- reg : physical base address and size of the device memory mapped
+ registers;
+- interrupts : should contain MIPI CSIS interrupt; the format of the
+ interrupt specifier depends on the interrupt controller;
+- max-data-lanes : maximum number of data lanes supported (SoC specific);
+- vddio-supply : MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V);
+- vddcore-supply : MIPI CSIS Core voltage supply (e.g. 1.1V).
+
+Optional properties:
+
+- clock-frequency : The IP's main (system bus) clock frequency in Hz, default
+ value when this property is not specified is 166 MHz;
+- samsung,csis,wclk : CSI-2 wrapper clock selection. If this property is present
+ external clock from CMU will be used, if not bus clock will
+ be selected.
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, as outlined in the common media bindings specification. See
+Documentation/devicetree/bindings/media/video-interfaces.txt for details.
+The following are properties specific to these nodes.
+
+port node
+---------
+
+- reg : (required) must be 3 for camera C input (CSIS0) or 4 for
+ camera D input (CSIS1);
+
+endpoint node
+-------------
+
+- data-lanes : (required) an array specifying active physical MIPI-CSI2
+ data input lanes and their mapping to logical lanes; the
+ array's content is unused, only its length is meaningful;
+
+- samsung,csis-hs-settle : (optional) differential receiver (HS-RX) settle time;
+
+- samsung,camclk-out : (optional) specifies clock output for remote sensor,
+ 0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
+
+Example:
+
+ reg0: regulator@0 {
+ };
+
+ reg1: regulator@1 {
+ };
+
+/* SoC properties */
+
+ aliases {
+ csis0 = &csis_0;
+ };
+
+ csis_0: csis@11880000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11880000 0x1000>;
+ interrupts = <0 78 0>;
+ max-data-lanes = <4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+/* Board properties */
+
+ csis_0: csis@11880000 {
+ clock-frequency = <166000000>;
+ vddio-supply = <®0>;
+ vddcore-supply = <®1>;
+ port {
+ reg = <3>; /* 3 - CSIS0, 4 - CSIS1 */
+ csis0_ep: endpoint {
+ remote-endpoint = <...>;
+ data-lanes = <1>, <2>;
+ samsung,csis-hs-settle = <12>;
+ };
+ };
+ };
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c
index 8a06f14..31c25a6 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.c
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.c
@@ -19,12 +19,14 @@
#include <linux/kernel.h>
#include <linux/memory.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/videodev2.h>
+#include <media/v4l2-of.h>
#include <media/v4l2-subdev.h>
#include <linux/platform_data/mipi-csis.h>
#include "mipi-csis.h"
@@ -113,6 +115,7 @@ static char *csi_clock_name[] = {
[CSIS_CLK_GATE] = "csis",
};
#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
+#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
static const char * const csis_supply_name[] = {
"vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
@@ -167,6 +170,11 @@ struct csis_pktbuf {
* @clock: CSIS clocks
* @irq: requested s5p-mipi-csis irq number
* @flags: the state variable for power and streaming control
+ * @clock_frequency: device bus clock frequency
+ * @hs_settle: HS-RX settle time
+ * @num_lanes: number of MIPI-CSI data lanes used
+ * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
+ * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
* @csis_fmt: current CSIS pixel format
* @format: common media bus format for the source and sink pad
* @slock: spinlock protecting structure members below
@@ -184,6 +192,13 @@ struct csis_state {
struct clk *clock[NUM_CSIS_CLOCKS];
int irq;
u32 flags;
+
+ u32 clk_frequency;
+ u32 hs_settle;
+ u32 num_lanes;
+ u32 max_num_lanes;
+ u8 wclk_ext;
+
const struct csis_pix_format *csis_fmt;
struct v4l2_mbus_framefmt format;
@@ -273,7 +288,6 @@ static void s5pcsis_reset(struct csis_state *state)
static void s5pcsis_system_enable(struct csis_state *state, int on)
{
- struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
u32 val, mask;
val = s5pcsis_read(state, S5PCSIS_CTRL);
@@ -286,7 +300,7 @@ static void s5pcsis_system_enable(struct csis_state *state, int on)
val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
val &= ~S5PCSIS_DPHYCTRL_ENABLE;
if (on) {
- mask = (1 << (pdata->lanes + 1)) - 1;
+ mask = (1 << (state->num_lanes + 1)) - 1;
val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
}
s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
@@ -321,15 +335,14 @@ static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
static void s5pcsis_set_params(struct csis_state *state)
{
- struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
u32 val;
val = s5pcsis_read(state, S5PCSIS_CONFIG);
- val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (pdata->lanes - 1);
+ val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
s5pcsis_write(state, S5PCSIS_CONFIG, val);
__s5pcsis_set_format(state);
- s5pcsis_set_hsync_settle(state, pdata->hs_settle);
+ s5pcsis_set_hsync_settle(state, state->hs_settle);
val = s5pcsis_read(state, S5PCSIS_CTRL);
if (state->csis_fmt->data_alignment == 32)
@@ -338,7 +351,7 @@ static void s5pcsis_set_params(struct csis_state *state)
val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
- if (pdata->wclk_source)
+ if (state->wclk_ext)
val |= S5PCSIS_CTRL_WCLK_EXTCLK;
s5pcsis_write(state, S5PCSIS_CTRL, val);
@@ -696,55 +709,118 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static int s5pcsis_get_platform_data(struct platform_device *pdev,
+ struct csis_state *state)
+{
+ struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data;
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "Platform data not specified\n");
+ return -EINVAL;
+ }
+ state->clk_frequency = pdata->clk_rate;
+ state->num_lanes = pdata->lanes;
+ state->hs_settle = pdata->hs_settle;
+ state->index = max(0, pdev->id);
+ if (state->index == 1)
+ state->max_num_lanes = CSIS1_MAX_LANES;
+ else
+ state->max_num_lanes = CSIS0_MAX_LANES;
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static int s5pcsis_parse_dt(struct platform_device *pdev,
+ struct csis_state *state)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct v4l2_of_endpoint endpoint;
+ int ret;
+
+ state->index = of_alias_get_id(node, "csis");
+ if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES)
+ return -EINVAL;
+
+ ret = of_property_read_u32(node, "max-data-lanes",
+ &state->max_num_lanes);
+ if (ret < 0)
+ return ret;
+
+ if (of_property_read_u32(node, "clock-frequency",
+ &state->clk_frequency))
+ state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+
+ state->wclk_ext = of_property_read_bool(node,
+ "samsung,csis-wclk");
+ /*
+ * Get endpoint node. We care only about first child
+ * nodes since these are the only ones available.
+ */
+ while ((node = of_get_next_child(node, NULL))) {
+ if (!of_node_cmp(node->name, "endpoint"))
+ break;
+ of_node_put(node);
+ };
+ if (!node)
+ return -EINVAL;
+ of_property_read_u32(node, "samsung,csis-hs-settle",
+ &state->hs_settle);
+
+ ret = v4l2_of_parse_mipi_csi2(node, &endpoint);
+ state->num_lanes = endpoint.mipi_csi_2.num_data_lanes;
+ of_node_put(node);
+ return 0;
+}
+#else
+#define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
+#endif
+
static int __devinit s5pcsis_probe(struct platform_device *pdev)
{
- struct s5p_platform_mipi_csis *pdata;
+ struct device *dev = &pdev->dev;
struct resource *mem_res;
struct csis_state *state;
int ret = -ENOMEM;
int i;
- state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
mutex_init(&state->lock);
spin_lock_init(&state->slock);
-
state->pdev = pdev;
- state->index = max(0, pdev->id);
- pdata = pdev->dev.platform_data;
- if (pdata == NULL) {
- dev_err(&pdev->dev, "Platform data not fully specified\n");
- return -EINVAL;
- }
+ if (dev->of_node)
+ ret = s5pcsis_parse_dt(pdev, state);
+ else
+ ret = s5pcsis_get_platform_data(pdev, state);
+ if (ret < 0)
+ return ret;
- if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
- pdata->lanes > CSIS0_MAX_LANES) {
- dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
- pdata->lanes);
+ if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
+ dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
+ state->num_lanes, state->max_num_lanes);
return -EINVAL;
}
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- state->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
+ state->regs = devm_request_and_ioremap(dev, mem_res);
if (state->regs == NULL) {
- dev_err(&pdev->dev, "Failed to request and remap io memory\n");
+ dev_err(dev, "Failed to request and remap io memory\n");
return -ENXIO;
}
state->irq = platform_get_irq(pdev, 0);
if (state->irq < 0) {
- dev_err(&pdev->dev, "Failed to get irq\n");
+ dev_err(dev, "Failed to get irq\n");
return state->irq;
}
for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
state->supplies[i].supply = csis_supply_name[i];
- ret = regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
- state->supplies);
+ ret = regulator_bulk_get(dev, CSIS_NUM_SUPPLIES, state->supplies);
if (ret)
return ret;
@@ -753,21 +829,22 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
goto e_clkput;
clk_enable(state->clock[CSIS_CLK_MUX]);
- if (pdata->clk_rate)
- clk_set_rate(state->clock[CSIS_CLK_MUX], pdata->clk_rate);
+ if (state->clk_frequency)
+ clk_set_rate(state->clock[CSIS_CLK_MUX], state->clk_frequency);
else
- dev_WARN(&pdev->dev, "No clock frequency specified!\n");
+ dev_WARN(dev, "No clock frequency specified!\n");
- ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler,
- 0, dev_name(&pdev->dev), state);
+ ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
+ 0, dev_name(dev), state);
if (ret) {
- dev_err(&pdev->dev, "Interrupt request failed\n");
+ dev_err(dev, "Interrupt request failed\n");
goto e_regput;
}
v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
state->sd.owner = THIS_MODULE;
- strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name));
+ snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
+ CSIS_SUBDEV_NAME, state->index);
state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
state->csis_fmt = &s5pcsis_formats[0];
@@ -787,10 +864,12 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
/* .. and a pointer to the subdev. */
platform_set_drvdata(pdev, &state->sd);
-
memcpy(state->events, s5pcsis_events, sizeof(state->events));
+ pm_runtime_enable(dev);
- pm_runtime_enable(&pdev->dev);
+ dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
+ state->num_lanes, state->hs_settle, state->wclk_ext,
+ state->clk_frequency);
return 0;
e_regput:
@@ -916,13 +995,21 @@ static const struct dev_pm_ops s5pcsis_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
};
+static const struct of_device_id s5pcsis_of_match[] __devinitconst = {
+ { .compatible = "samsung,s5pv210-csis" },
+ { .compatible = "samsung,exynos4210-csis" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
+
static struct platform_driver s5pcsis_driver = {
.probe = s5pcsis_probe,
.remove = __devexit_p(s5pcsis_remove),
.driver = {
- .name = CSIS_DRIVER_NAME,
- .owner = THIS_MODULE,
- .pm = &s5pcsis_pm_ops,
+ .of_match_table = of_match_ptr(s5pcsis_of_match),
+ .name = CSIS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &s5pcsis_pm_ops,
},
};
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.h b/drivers/media/platform/s5p-fimc/mipi-csis.h
index 2709286..28c11c4 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.h
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.h
@@ -11,6 +11,7 @@
#define S5P_MIPI_CSIS_H_
#define CSIS_DRIVER_NAME "s5p-mipi-csis"
+#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME
#define CSIS_MAX_ENTITIES 2
#define CSIS0_MAX_LANES 4
#define CSIS1_MAX_LANES 2
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 07/15] s5p-fimc: Support camera media device initialization on DT systems
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
This patch add changes required for the main camera media device
driver to be initialized on systems booted from the device tree.
The platform devices corresponding to child dt nodes of the 'camera'
node are looked up and and registered as sub-devices to the common
media device. The main driver's probing is deferred if any of the
sub-device drivers is not yet initialized and ready.
An OF matching table is added for the main driver associated with
the 'camera' node.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/platform/s5p-fimc/fimc-core.c | 1 -
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 67 +++++++++++++++++++++---
drivers/media/platform/s5p-fimc/fimc-mdevice.h | 4 ++
3 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c
index e7eabb7..b02edac 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.c
+++ b/drivers/media/platform/s5p-fimc/fimc-core.c
@@ -1280,7 +1280,6 @@ static const struct platform_device_id fimc_driver_ids[] = {
},
{ },
};
-MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
static const struct of_device_id fimc_of_match[] __devinitconst = {
{
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index bb73d17..105bb91 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -17,6 +17,8 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
@@ -456,6 +458,43 @@ static int fimc_md_pdev_match(struct device *dev, void *data)
return 0;
}
+/* Register FIMC, FIMC-LITE and CSIS media entities */
+#ifdef CONFIG_OF
+static int fimc_md_register_of_platform_entities(struct fimc_md *fmd)
+{
+ struct device_node *node;
+ int ret = 0;
+
+ for_each_available_child_of_node(fmd->pdev->dev.of_node, node) {
+ struct platform_device *pdev;
+ int plat_entity = -1;
+
+ pdev = of_find_device_by_node(node);
+ if (!pdev)
+ return -ENODEV;
+
+ /* If driver of any entity isn't ready try all again later. */
+ if (!strcmp(node->name, CSIS_OF_NODE_NAME))
+ plat_entity = IDX_CSIS;
+ else if (!strcmp(node->name, FIMC_LITE_OF_NODE_NAME))
+ plat_entity = IDX_FLITE;
+ else if (!strcmp(node->name, FIMC_OF_NODE_NAME))
+ plat_entity = IDX_FIMC;
+
+ if (plat_entity >= 0)
+ ret = fimc_md_register_platform_entity(fmd, pdev,
+ plat_entity);
+ put_device(&pdev->dev);
+ if (ret < 0)
+ break;
+ }
+
+ return ret;
+}
+#else
+#define fimc_md_register_platform_entities(fmd) (-ENOSYS)
+#endif
+
static void fimc_md_unregister_entities(struct fimc_md *fmd)
{
int i;
@@ -928,8 +967,8 @@ static int fimc_md_probe(struct platform_device *pdev)
v4l2_dev = &fmd->v4l2_dev;
v4l2_dev->mdev = &fmd->media_dev;
v4l2_dev->notify = fimc_sensor_notify;
- snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s",
- dev_name(&pdev->dev));
+ strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
+
ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
if (ret < 0) {
@@ -950,8 +989,11 @@ static int fimc_md_probe(struct platform_device *pdev)
/* Protect the media graph while we're registering entities */
mutex_lock(&fmd->media_dev.graph_mutex);
- ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
- fimc_md_pdev_match);
+ if (fmd->pdev->dev.of_node)
+ ret = fimc_md_register_of_platform_entities(fmd);
+ else
+ ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
+ fimc_md_pdev_match);
if (ret)
goto err_unlock;
@@ -999,12 +1041,25 @@ static int __devexit fimc_md_remove(struct platform_device *pdev)
return 0;
}
+static struct platform_device_id fimc_driver_ids[] __always_unused = {
+ { .name = "s5p-fimc-md" },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
+
+static const struct of_device_id fimc_md_of_match[] __initconst = {
+ { .compatible = "samsung,fimc" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, fimc_md_of_match);
+
static struct platform_driver fimc_md_driver = {
.probe = fimc_md_probe,
.remove = __devexit_p(fimc_md_remove),
.driver = {
- .name = "s5p-fimc-md",
- .owner = THIS_MODULE,
+ .of_match_table = fimc_md_of_match,
+ .name = "s5p-fimc-md",
+ .owner = THIS_MODULE,
}
};
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
index da7d992..1b7850c 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
@@ -21,6 +21,10 @@
#include "fimc-lite.h"
#include "mipi-csis.h"
+#define FIMC_OF_NODE_NAME "fimc"
+#define FIMC_LITE_OF_NODE_NAME "fimc_lite"
+#define CSIS_OF_NODE_NAME "csis"
+
/* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */
#define GRP_ID_SENSOR (1 << 8)
#define GRP_ID_FIMC_IS_SENSOR (1 << 9)
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 09/15] s5p-fimc: Use pinctrl API for camera ports configuration
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
Before the camera ports can be used the pinmux needs to be configured
properly. This patch adds a function to get the pinctrl states and to
set default camera port pinmux state during the media driver's probe().
The camera port(s) are configured for video bus operation in this way.
"inactive" pinctrl state is intended for setting clock output pin(s)
into high impedance state when camera sensors are powered off.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyugmin Park <kyungmin.park@samsung.com>
---
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 25 ++++++++++++++++++++++++
drivers/media/platform/s5p-fimc/fimc-mdevice.h | 6 ++++++
2 files changed, 31 insertions(+)
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 3ac6ea8..9e4ed9e 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -1123,6 +1123,25 @@ static ssize_t fimc_md_sysfs_store(struct device *dev,
static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
fimc_md_sysfs_show, fimc_md_sysfs_store);
+static int fimc_md_get_pinctrl(struct fimc_md *fmd)
+{
+ fmd->pinctl = devm_pinctrl_get_select_default(&fmd->pdev->dev);
+ if (IS_ERR(fmd->pinctl))
+ return PTR_ERR(fmd->pinctl);
+
+ fmd->pinctl_state_default = pinctrl_lookup_state(fmd->pinctl,
+ PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(fmd->pinctl_state_default))
+ return PTR_ERR(fmd->pinctl_state_default);
+
+ fmd->pinctl_state_idle = pinctrl_lookup_state(fmd->pinctl,
+ PINCTRL_STATE_INACTIVE);
+ if (IS_ERR(fmd->pinctl_state_idle))
+ return PTR_ERR(fmd->pinctl_state_idle);
+
+ return 0;
+}
+
static int fimc_md_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1167,6 +1186,12 @@ static int fimc_md_probe(struct platform_device *pdev)
/* Protect the media graph while we're registering entities */
mutex_lock(&fmd->media_dev.graph_mutex);
+ if (dev->of_node) {
+ ret = fimc_md_get_pinctrl(fmd);
+ if (ret < 0)
+ goto err_unlock;
+ }
+
if (fmd->pdev->dev.of_node)
ret = fimc_md_register_of_platform_entities(fmd);
else
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
index 1b7850c..89cecaa 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
@@ -10,6 +10,7 @@
#define FIMC_MDEVICE_H_
#include <linux/clk.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <media/media-device.h>
@@ -25,6 +26,8 @@
#define FIMC_LITE_OF_NODE_NAME "fimc_lite"
#define CSIS_OF_NODE_NAME "csis"
+#define PINCTRL_STATE_INACTIVE "inactive"
+
/* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */
#define GRP_ID_SENSOR (1 << 8)
#define GRP_ID_FIMC_IS_SENSOR (1 << 9)
@@ -85,6 +88,9 @@ struct fimc_md {
struct media_device media_dev;
struct v4l2_device v4l2_dev;
struct platform_device *pdev;
+ struct pinctrl *pinctl;
+ struct pinctrl_state *pinctl_state_default;
+ struct pinctrl_state *pinctl_state_idle;
bool user_subdev_api;
spinlock_t slock;
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 11/15] ARM: dts: Add camera node exynos4.dtsi
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
This adds common FIMC device nodes for all Exynos4 SoCs.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4.dtsi | 64 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index b853b11..30364ce 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -28,6 +28,12 @@
spi0 = &spi_0;
spi1 = &spi_1;
spi2 = &spi_2;
+ csis0 = &csis_0;
+ csis1 = &csis_1;
+ fimc0 = &fimc_0;
+ fimc1 = &fimc_1;
+ fimc2 = &fimc_2;
+ fimc3 = &fimc_3;
};
pd_mfc: mfc-power-domain@10023C40 {
@@ -92,6 +98,64 @@
power-domain = <&pd_lcd0>;
};
+ camera {
+ compatible = "samsung,fimc", "simple-bus";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ fimc_0: fimc@11800000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11800000 0x1000>;
+ interrupts = <0 84 0>;
+ power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ fimc_1: fimc@11810000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11810000 0x1000>;
+ interrupts = <0 85 0>;
+ power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ fimc_2: fimc@11820000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11820000 0x1000>;
+ interrupts = <0 86 0>;
+ power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ fimc_3: fimc@11830000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11830000 0x1000>;
+ interrupts = <0 87 0>;
+ power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ csis_0: csis@11880000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11880000 0x4000>;
+ interrupts = <0 78 0>;
+ max-data-lanes = <4>;
+ power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ csis_1: csis@11890000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11890000 0x4000>;
+ interrupts = <0 80 0>;
+ max-data-lanes = <2>;
+ power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+ };
+
watchdog@10060000 {
compatible = "samsung,s3c2410-wdt";
reg = <0x10060000 0x100>;
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 13/15] ARM: dts: Add FIMC and MIPI CSIS device nodes for Exynos4x12
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
Add common camera node and fimc nodes specific to Exynos4212 and
Exynos4412 SoCs. fimc-is is a node for the Exynos4x12 FIMC-IS
subsystem and fimc-lite nodes are created as its child nodes,
among others due to FIMC-LITE device dependencies on FIMC-IS
related clocks.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4x12.dtsi | 47 +++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 9c809b72..06fde30 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -26,6 +26,8 @@
pinctrl1 = &pinctrl_1;
pinctrl2 = &pinctrl_2;
pinctrl3 = &pinctrl_3;
+ fimc-lite0 = &fimc_lite_0;
+ fimc-lite1 = &fimc_lite_1;
};
pd_isp: isp-power-domain@10023CA0 {
@@ -71,4 +73,49 @@
reg = <0x106E0000 0x1000>;
interrupts = <0 72 0>;
};
+
+ camera {
+ fimc_0: fimc@11800000 {
+ compatible = "samsung,exynos4212-fimc";
+ };
+
+ fimc_1: fimc@11810000 {
+ compatible = "samsung,exynos4212-fimc";
+ };
+
+ fimc_2: fimc@11820000 {
+ compatible = "samsung,exynos4212-fimc";
+ };
+
+ fimc_3: fimc@11830000 {
+ compatible = "samsung,exynos4212-fimc";
+ };
+
+ fimc_is: fimc-is@12000000 {
+ compatible = "samsung,exynos4212-fimc-is", "simple-bus";
+ reg = <0x12000000 0x260000>;
+ interrupts = <0 90 0>, <0 95 0>;
+ power-domain = <&pd_isp>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ fimc_lite_0: fimc_lite@12390000 {
+ compatible = "samsung,exynos4212-fimc-lite";
+ reg = <0x12390000 0x1000>;
+ interrupts = <0 125 0>;
+ power-domain = <&pd_isp>;
+ status = "disabled";
+ };
+
+ fimc_lite_1: fimc_lite@123A0000 {
+ compatible = "samsung,exynos4212-fimc-lite";
+ reg = <0x123A0000 0x1000>;
+ interrupts = <0 126 0>;
+ power-domain = <&pd_isp>;
+ status = "disabled";
+ };
+ };
+ };
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 15/15] ARM: dts: Add camera device nodes nodes for PQ board
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
This patch adds all nodes for camera devices on example Exynos4412 SoC
based board. This is all what's required in the board dts file to enable
rear facing camera (S5C73M3 sensor).
The aliases node contains entries required for the camera processing
data path entity drivers.
The sensor nodes use standard port/remote-endpoint nodes convention.
Internal SoC links between entities are not specified this way and
are coded in the driver instead, as it seemed more reasonable.
The S5C73M3 sensor uses two control buses: I2C and SPI. There are
two, i2c_0 and spi_1 bus controller child nodes assigned to it.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4412-slp_pq.dts | 133 +++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4412-slp_pq.dts b/arch/arm/boot/dts/exynos4412-slp_pq.dts
index 3a5782d..97a4c2c 100644
--- a/arch/arm/boot/dts/exynos4412-slp_pq.dts
+++ b/arch/arm/boot/dts/exynos4412-slp_pq.dts
@@ -101,6 +101,34 @@
};
};
+ i2c_0: i2c@13860000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-slave-addr = <0x10>;
+ samsung,i2c-max-bus-freq = <400000>;
+ pinctrl-0 = <&i2c0_bus>;
+ status = "okay";
+
+ s5c73m3@3c {
+ compatible = "samsung,s5c73m3";
+ reg = <0x3c>;
+ gpios = <&gpm0 1 1>, /* ISP_STANDBY */
+ <&gpf1 3 1>; /* ISP_RESET */
+ vdd-int-supply = <&buck9_reg>;
+ vddio-cis-supply = <&ldo9_reg>;
+ vdda-supply = <&ldo17_reg>;
+ vddio-host-supply = <&ldo18_reg>;
+ vdd-af-supply = <&cam_af_reg>;
+ vdd-reg-supply = <&cam_io_reg>;
+ clock-frequency = <24000000>;
+
+ port {
+ s5c73m3_ep: endpoint {
+ remote-endpoint = <&csis0_ep>;
+ };
+ };
+ };
+ };
+
i2c@13890000 {
samsung,i2c-sda-delay = <100>;
samsung,i2c-slave-addr = <0x10>;
@@ -411,6 +439,34 @@
enable-active-high;
};
+ cam_af_reg: voltage-regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_AF";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&gpm0 4 0>;
+ enable-active-high;
+ };
+
+ cam_io_reg: voltage-regulator@3 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_SENSOR_A";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&gpm0 2 0>;
+ enable-active-high;
+ };
+
+ cam_isp_core_reg: voltage-regulator@4 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_ISP_CORE_1.2V_EN";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ gpio = <&gpm0 3 0>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
fimd0_lcd: panel {
compatible = "s6e8ax0";
reset-gpio = <&gpy4 5 0>;
@@ -462,4 +518,81 @@
vusb_d-supply = <&ldo15_reg>;
vusb_a-supply = <&ldo12_reg>;
};
+
+ spi_1: spi@13930000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_bus>;
+ status = "okay";
+
+ s5c73m3_spi: s5c73m3 {
+ compatible = "samsung,s5c73m3";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ controller-data {
+ cs-gpio = <&gpb 5 0>;
+ samsung,spi-feedback-delay = <2>;
+ };
+ };
+ };
+
+ camera {
+ compatible = "samsung,fimc", "simple-bus";
+ status = "okay";
+
+ pinctrl-names = "default", "inactive";
+ pinctrl-0 = <&cam_port_a_clk_active>;
+ pinctrl-1 = <&cam_port_a_clk_idle>;
+
+ fimc_0: fimc@11800000 {
+ status = "okay";
+ };
+
+ fimc_1: fimc@11810000 {
+ status = "okay";
+ };
+
+ fimc_2: fimc@11820000 {
+ status = "okay";
+ };
+
+ fimc_3: fimc@11830000 {
+ status = "okay";
+ };
+
+ csis_0: csis@11880000 {
+ status = "okay";
+ vddcore-supply = <&ldo8_reg>;
+ vddio-supply = <&ldo10_reg>;
+ clock-frequency = <160000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port {
+ reg = <3>; /* Camera C(3) MIPI */
+ csis0_ep: endpoint {
+ remote-endpoint = <&s5c73m3_ep>;
+ data-lanes = <1>, <2>, <3>, <4>;
+ samsung,csis-hs-settle = <12>;
+ };
+ };
+ };
+
+ csis_1: csis@11890000 {
+ vddcore-supply = <&ldo8_reg>;
+ vddio-supply = <&ldo10_reg>;
+ samsung,csis-hs-settle = <18>;
+ data-lanes = <1>;
+ };
+
+ fimc-is@12000000 {
+ status = "okay";
+
+ fimc_lite_0: fimc_lite@12390000 {
+ status = "okay";
+ };
+
+ fimc_lite_1: fimc_lite@123A0000 {
+ status = "okay";
+ };
+ };
+ };
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 04/15] s5p-fimc: Support for FIMC devices instantiated from the device tree
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
This patch adds support for FIMC devices instantiated from devicetree
for S5PV210 and Exynos4 SoCs. The FIMC IP features include colorspace
conversion and scaling (mem-to-mem) and parallel/MIPI CSI2 bus video
capture interface.
Multiple SoC revision specific parameters are defined statically
in the driver and are used for both dt and non-dt. Specific driver
static data is selected based on the compatible property, and
previously platform device name was used to match driver data with
a specific SoC/IP version.
Aliases are used to determine an index of the IP which is essential
for linking FIMC IP with other ones, like MIPI-CSIS (MIPI CSI2 bus
frontend) or FIMC-LITE and FIMC-IS ISP.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 92 ++++++++++++++++++++
drivers/media/platform/s5p-fimc/fimc-capture.c | 2 +-
drivers/media/platform/s5p-fimc/fimc-core.c | 84 ++++++++++++------
3 files changed, 148 insertions(+), 30 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
new file mode 100644
index 0000000..fab7e61
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -0,0 +1,92 @@
+Samsung S5P/EXYNOS SoC Camera Subsystem (FIMC)
+----------------------------------------------
+
+The Exynos Camera subsystem comprises of multiple sub-devices that are
+represented by separate platform devices. Some of the IPs come in different
+variants accross the SoC revisions (FIMC) and some remain mostly unchanged
+(MIPI CSIS, FIMC-LITE).
+
+All those sub-subdevices are defined as parent nodes of the common device
+node, which also includes common properties of the whole subsystem not really
+specific to any single sub-device, like common camera port pins or external
+clocks for image sensors attached to the SoC.
+
+Common 'camera' node
+--------------------
+
+Required properties:
+
+- compatible : must be "samsung,fimc", "simple-bus"
+
+- pinctrl-names : pinctrl names for camera port pinmux control, the values
+ must be "default, "inactive". "default" corresponds to
+ pinmux configured for camera parallel bus; "inactive" is
+ different from "default" only in that the CAMCLK pin is
+ in high impedance state.
+- pinctrl-0..1 : pinctrl properties corresponding to pinctrl-names
+
+The 'camera' node must include at least one 'fimc' child node.
+
+
+'fimc' device nodes
+-------------------
+
+Required properties:
+
+- compatible : "samsung,s5pv210-fimc" for S5PV210,
+ "samsung,exynos4210-fimc" for Exynos4210,
+ "samsung,exynos4212-fimc" for Exynos4212/4412 SoCs;
+- reg : physical base address and size of the device memory mapped
+ registers;
+- interrupts : FIMC interrupt to the CPU should be described here;
+
+For every fimc node a numbered alias should be present in the aliases node.
+Aliases are of the form fimc<n>, where <n> is an integer (0...N) specifying
+the IP's instance index.
+
+'parallel-ports' node
+-----------------------
+
+This node should contain child 'port' nodes specifying active parallel video
+input ports. It includes camera A and camera B inputs. 'reg' property in the
+port nodes specifies the input - 0, 1 indicates input A, B respectively.
+
+Optional properties
+
+- samsung,camclk-out : specifies clock output for remote sensor,
+ 0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
+
+
+Example:
+
+ aliases {
+ csis0 = &csis_0;
+ fimc0 = &fimc_0;
+ };
+
+ camera {
+ compatible = "samsung,fimc", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+
+ pinctrl-names = "default", "inactive";
+ pinctrl-0 = <&cam_port_a_clk_active>;
+ pinctrl-1 = <&cam_port_a_clk_idle>;
+
+ fimc_0: fimc@11800000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11800000 0x1000>;
+ interrupts = <0 85 0>;
+ status = "okay";
+ };
+
+ csis_0: csis@11880000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11880000 0x1000>;
+ interrupts = <0 78 0>;
+ max-data-lanes = <4>;
+ };
+ };
+
+[1] Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index 18a70e4..e716753 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -1888,7 +1888,7 @@ int fimc_initialize_capture_subdev(struct fimc_dev *fimc)
v4l2_subdev_init(sd, &fimc_subdev_ops);
sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
- snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
+ snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->id);
fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c
index 2a1558a..e7eabb7 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.c
+++ b/drivers/media/platform/s5p-fimc/fimc-core.c
@@ -21,6 +21,8 @@
#include <linux/pm_runtime.h>
#include <linux/list.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <media/v4l2-ioctl.h>
@@ -879,45 +881,54 @@ static int fimc_m2m_resume(struct fimc_dev *fimc)
return 0;
}
+static const struct of_device_id fimc_of_match[];
+
static int fimc_probe(struct platform_device *pdev)
{
- const struct fimc_drvdata *drv_data = fimc_get_drvdata(pdev);
- struct s5p_platform_fimc *pdata;
+ struct fimc_drvdata *drv_data = NULL;
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id;
struct fimc_dev *fimc;
struct resource *res;
int ret = 0;
- if (pdev->id >= drv_data->num_entities) {
- dev_err(&pdev->dev, "Invalid platform device id: %d\n",
- pdev->id);
- return -EINVAL;
- }
-
- fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL);
+ fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
if (!fimc)
return -ENOMEM;
- fimc->id = pdev->id;
+ if (dev->of_node) {
+ of_id = of_match_node(fimc_of_match, dev->of_node);
+ if (of_id)
+ drv_data = (struct fimc_drvdata *)of_id->data;
+
+ fimc->id = of_alias_get_id(dev->of_node, "fimc");
+ } else {
+ drv_data = fimc_get_drvdata(pdev);
+ fimc->id = pdev->id;
+ }
+
+ if (!drv_data || fimc->id < 0 || fimc->id >= drv_data->num_entities) {
+ dev_err(dev, "Invalid driver data or device index (%d)\n",
+ fimc->id);
+ return -EINVAL;
+ }
fimc->variant = drv_data->variant[fimc->id];
fimc->pdev = pdev;
- pdata = pdev->dev.platform_data;
- fimc->pdata = pdata;
-
init_waitqueue_head(&fimc->irq_queue);
spin_lock_init(&fimc->slock);
mutex_init(&fimc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- fimc->regs = devm_request_and_ioremap(&pdev->dev, res);
+ fimc->regs = devm_request_and_ioremap(dev, res);
if (fimc->regs == NULL) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ dev_err(dev, "Failed to obtain io memory\n");
return -ENOENT;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
- dev_err(&pdev->dev, "Failed to get IRQ resource\n");
+ dev_err(dev, "Failed to get IRQ resource\n");
return -ENXIO;
}
@@ -927,10 +938,10 @@ static int fimc_probe(struct platform_device *pdev)
clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
clk_enable(fimc->clock[CLK_BUS]);
- ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler,
- 0, dev_name(&pdev->dev), fimc);
+ ret = devm_request_irq(dev, res->start, fimc_irq_handler,
+ 0, dev_name(dev), fimc);
if (ret) {
- dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
+ dev_err(dev, "failed to install irq (%d)\n", ret);
goto err_clk;
}
@@ -939,23 +950,23 @@ static int fimc_probe(struct platform_device *pdev)
goto err_clk;
platform_set_drvdata(pdev, fimc);
- pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err_sd;
/* Initialize contiguous memory allocator */
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
goto err_pm;
}
- dev_dbg(&pdev->dev, "FIMC.%d registered successfully\n", fimc->id);
+ dev_dbg(dev, "FIMC.%d registered successfully\n", fimc->id);
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
return 0;
err_pm:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
err_sd:
fimc_unregister_capture_subdev(fimc);
err_clk:
@@ -1267,10 +1278,24 @@ static const struct platform_device_id fimc_driver_ids[] = {
.name = "exynos4x12-fimc",
.driver_data = (unsigned long)&fimc_drvdata_exynos4x12,
},
- {},
+ { },
};
MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
+static const struct of_device_id fimc_of_match[] __devinitconst = {
+ {
+ .compatible = "samsung,s5pv210-fimc",
+ .data = &fimc_drvdata_s5pv210,
+ }, {
+ .compatible = "samsung,exynos4210-fimc",
+ .data = &fimc_drvdata_exynos4210,
+ }, {
+ .compatible = "samsung,exynos4212-fimc",
+ .data = &fimc_drvdata_exynos4x12,
+ },
+ { /* sentinel */ },
+};
+
static const struct dev_pm_ops fimc_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
@@ -1281,9 +1306,10 @@ static struct platform_driver fimc_driver = {
.remove = __devexit_p(fimc_remove),
.id_table = fimc_driver_ids,
.driver = {
- .name = FIMC_MODULE_NAME,
- .owner = THIS_MODULE,
- .pm = &fimc_pm_ops,
+ .of_match_table = of_match_ptr(fimc_of_match),
+ .name = FIMC_MODULE_NAME,
+ .owner = THIS_MODULE,
+ .pm = &fimc_pm_ops,
}
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 05/15] s5p-fimc: Support for FIMC-LITE devices instantiated from the device tree
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
This patch add support for binding the driver to FIMC-LITE devices
instantiated from the device tree.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 16 +++++
drivers/media/platform/s5p-fimc/fimc-lite.c | 65 ++++++++++++++------
2 files changed, 62 insertions(+), 19 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
index fab7e61..5bbda07 100644
--- a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -57,6 +57,22 @@ Optional properties
0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
+'fimc-lite' device nodes
+-----------------------
+
+Required properties:
+
+- compatible : should be "samsung,exynos4212-fimc" for Exynos4212 and
+ Exynos4412 SoCs;
+- reg : physical base address and size of the device memory mapped
+ registers;
+- interrupts : should contain FIMC-LITE interrupt;
+
+For every fimc-lite node a numbered alias should be present in the aliases
+node. Aliases are in form of fimc-lite<n>, where <n> is an integer (0...N)
+specifying the IP's instance index.
+
+
Example:
aliases {
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c
index ef31c39..cfa3952 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -1490,18 +1491,34 @@ static int fimc_lite_clk_get(struct fimc_lite *fimc)
return ret;
}
+static const struct of_device_id flite_of_match[];
+
static int __devinit fimc_lite_probe(struct platform_device *pdev)
{
- struct flite_drvdata *drv_data = fimc_lite_get_drvdata(pdev);
+ struct flite_drvdata *drv_data = NULL;
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id;
struct fimc_lite *fimc;
struct resource *res;
int ret;
- fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL);
+ fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
if (!fimc)
return -ENOMEM;
- fimc->index = pdev->id;
+ if (dev->of_node) {
+ of_id = of_match_node(flite_of_match, dev->of_node);
+ if (of_id)
+ drv_data = (struct flite_drvdata *)of_id->data;
+ fimc->index = of_alias_get_id(dev->of_node, "fimc-lite");
+ } else {
+ drv_data = fimc_lite_get_drvdata(pdev);
+ fimc->index = pdev->id;
+ }
+
+ if (!drv_data || fimc->index < 0 || fimc->index >= FIMC_LITE_MAX_DEVS)
+ return -EINVAL;
+
fimc->variant = drv_data->variant[fimc->index];
fimc->pdev = pdev;
@@ -1510,15 +1527,15 @@ static int __devinit fimc_lite_probe(struct platform_device *pdev)
mutex_init(&fimc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- fimc->regs = devm_request_and_ioremap(&pdev->dev, res);
+ fimc->regs = devm_request_and_ioremap(dev, res);
if (fimc->regs == NULL) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ dev_err(dev, "Failed to obtain io memory\n");
return -ENOENT;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
- dev_err(&pdev->dev, "Failed to get IRQ resource\n");
+ dev_err(dev, "Failed to get IRQ resource\n");
return -ENXIO;
}
@@ -1526,10 +1543,10 @@ static int __devinit fimc_lite_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = devm_request_irq(&pdev->dev, res->start, flite_irq_handler,
- 0, dev_name(&pdev->dev), fimc);
+ ret = devm_request_irq(dev, res->start, flite_irq_handler,
+ 0, dev_name(dev), fimc);
if (ret) {
- dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
+ dev_err(dev, "Failed to install irq (%d)\n", ret);
goto err_clk;
}
@@ -1539,23 +1556,23 @@ static int __devinit fimc_lite_probe(struct platform_device *pdev)
goto err_clk;
platform_set_drvdata(pdev, fimc);
- pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err_sd;
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
goto err_pm;
}
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
- dev_dbg(&pdev->dev, "FIMC-LITE.%d registered successfully\n",
+ dev_dbg(dev, "FIMC-LITE.%d registered successfully\n",
fimc->index);
return 0;
err_pm:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
err_sd:
fimc_lite_unregister_capture_subdev(fimc);
err_clk:
@@ -1646,6 +1663,12 @@ static int __devexit fimc_lite_remove(struct platform_device *pdev)
return 0;
}
+static const struct dev_pm_ops fimc_lite_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume)
+ SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume,
+ NULL)
+};
+
static struct flite_variant fimc_lite0_variant_exynos4 = {
.max_width = 8192,
.max_height = 8192,
@@ -1671,17 +1694,21 @@ static struct platform_device_id fimc_lite_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, fimc_lite_driver_ids);
-static const struct dev_pm_ops fimc_lite_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume)
- SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume,
- NULL)
+static const struct of_device_id flite_of_match[] __devinitconst = {
+ {
+ .compatible = "samsung,exynos4212-fimc-lite",
+ .data = &fimc_lite_drvdata_exynos4,
+ },
+ { /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, flite_of_match);
static struct platform_driver fimc_lite_driver = {
.probe = fimc_lite_probe,
.remove = __devexit_p(fimc_lite_remove),
.id_table = fimc_lite_driver_ids,
.driver = {
+ .of_match_table = of_match_ptr(flite_of_match),
.name = FIMC_LITE_DRV_NAME,
.owner = THIS_MODULE,
.pm = &fimc_lite_pm_ops,
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 06/15] s5p-fimc: Change platform subdevs registration method
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
The previous method of registering platform entities into the main
driver using driver_find() and then iterating over devices bound to
a driver was racy and is being removed here. Nothing was preventing
module from unloading during a call to try_module_get(driver->owner).
Instead, we look up a device first and then check for its driver while
holding device lock.
The platform sub-devices are looked up and registered to the top
level driver. When any sub-device is not yet initialized and ready
the main driver's probe() will be deferred.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 206 +++++++++++++-----------
1 file changed, 109 insertions(+), 97 deletions(-)
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 80d8fd1..bb73d17 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -1,8 +1,8 @@
/*
* S5P/EXYNOS4 SoC series camera host interface media device driver
*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
@@ -312,138 +312,148 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
}
/*
- * MIPI CSIS and FIMC platform devices registration.
+ * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration.
*/
-static int fimc_register_callback(struct device *dev, void *p)
+
+static int register_fimc_lite_entity(struct fimc_md *fmd,
+ struct fimc_lite *fimc_lite)
{
- struct fimc_dev *fimc = dev_get_drvdata(dev);
struct v4l2_subdev *sd;
- struct fimc_md *fmd = p;
int ret;
- if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS)
- return 0;
+ if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS ||
+ fmd->fimc_lite[fimc_lite->index]))
+ return -EBUSY;
- sd = &fimc->vid_cap.subdev;
- sd->grp_id = GRP_ID_FIMC;
+ sd = &fimc_lite->subdev;
+ sd->grp_id = GRP_ID_FLITE;
v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
- if (ret) {
- v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
- fimc->id, ret);
- return ret;
- }
-
- fmd->fimc[fimc->id] = fimc;
- return 0;
+ if (!ret)
+ fmd->fimc_lite[fimc_lite->index] = fimc_lite;
+ else
+ v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.LITE%d\n",
+ fimc_lite->index);
+ return ret;
}
-static int fimc_lite_register_callback(struct device *dev, void *p)
+static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc)
{
- struct fimc_lite *fimc = dev_get_drvdata(dev);
- struct fimc_md *fmd = p;
+ struct v4l2_subdev *sd;
int ret;
- if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
- return 0;
-
- fimc->subdev.grp_id = GRP_ID_FLITE;
- v4l2_set_subdev_hostdata(&fimc->subdev, (void *)&fimc_pipeline_ops);
+ if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id]))
+ return -EBUSY;
- ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
- if (ret) {
- v4l2_err(&fmd->v4l2_dev,
- "Failed to register FIMC-LITE.%d (%d)\n",
- fimc->index, ret);
- return ret;
- }
+ sd = &fimc->vid_cap.subdev;
+ sd->grp_id = GRP_ID_FIMC;
+ v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
- fmd->fimc_lite[fimc->index] = fimc;
- return 0;
+ ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+ if (!ret)
+ fmd->fimc[fimc->id] = fimc;
+ else
+ v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
+ fimc->id, ret);
+ return ret;
}
-static int csis_register_callback(struct device *dev, void *p)
+static int register_csis_entity(struct fimc_md *fmd,
+ struct platform_device *pdev,
+ struct v4l2_subdev *sd)
{
- struct v4l2_subdev *sd = dev_get_drvdata(dev);
- struct platform_device *pdev;
- struct fimc_md *fmd = p;
- int id, ret;
+ struct device_node *node = pdev->dev.of_node;
+ int id = 0;
+ int ret;
- if (!sd)
- return 0;
- pdev = v4l2_get_subdevdata(sd);
- if (!pdev || pdev->id < 0 || pdev->id >= CSIS_MAX_ENTITIES)
+ if (WARN_ON(id >= CSIS_MAX_ENTITIES || fmd->csis[id].sd))
+ return -EBUSY;
+
+ id = node ? of_alias_get_id(node, "csis") : max(0, pdev->id);
+
+ if (WARN_ON(id >= CSIS_MAX_ENTITIES))
return 0;
- v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
- id = pdev->id < 0 ? 0 : pdev->id;
sd->grp_id = GRP_ID_CSIS;
-
ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
if (!ret)
fmd->csis[id].sd = sd;
else
v4l2_err(&fmd->v4l2_dev,
- "Failed to register CSIS subdevice: %d\n", ret);
+ "Failed to register MIPI-CSIS.%d (%d)\n", id, ret);
return ret;
}
-/**
- * fimc_md_register_platform_entities - register FIMC and CSIS media entities
- */
-static int fimc_md_register_platform_entities(struct fimc_md *fmd)
+static int fimc_md_register_platform_entity(struct fimc_md *fmd,
+ struct platform_device *pdev,
+ int plat_entity)
{
- struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
- struct device_driver *driver;
- int ret, i;
-
- driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type);
- if (!driver) {
- v4l2_warn(&fmd->v4l2_dev,
- "%s driver not found, deffering probe\n",
- FIMC_MODULE_NAME);
- return -EPROBE_DEFER;
- }
-
- ret = driver_for_each_device(driver, NULL, fmd,
- fimc_register_callback);
- if (ret)
- return ret;
-
- driver = driver_find(FIMC_LITE_DRV_NAME, &platform_bus_type);
- if (driver && try_module_get(driver->owner)) {
- ret = driver_for_each_device(driver, NULL, fmd,
- fimc_lite_register_callback);
- if (ret)
- return ret;
- module_put(driver->owner);
- }
- /*
- * Check if there is any sensor on the MIPI-CSI2 bus and
- * if not skip the s5p-csis module loading.
- */
- if (pdata == NULL)
- return 0;
- for (i = 0; i < pdata->num_clients; i++) {
- if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) {
- ret = 1;
+ struct device *dev = &pdev->dev;
+ int ret = -EPROBE_DEFER;
+ void *drvdata;
+
+ /* Lock to ensure dev->driver won't change. */
+ device_lock(dev);
+
+ if (!dev->driver || !try_module_get(dev->driver->owner))
+ goto dev_unlock;
+
+ drvdata = dev_get_drvdata(dev);
+ /* Some subdev didn't probe succesfully id drvdata is NULL */
+ if (drvdata) {
+ switch (plat_entity) {
+ case IDX_FIMC:
+ ret = register_fimc_entity(fmd, drvdata);
break;
+ case IDX_FLITE:
+ ret = register_fimc_lite_entity(fmd, drvdata);
+ break;
+ case IDX_CSIS:
+ ret = register_csis_entity(fmd, pdev, drvdata);
+ break;
+ default:
+ ret = -ENODEV;
}
}
- if (!ret)
- return 0;
- driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type);
- if (!driver || !try_module_get(driver->owner)) {
- v4l2_warn(&fmd->v4l2_dev,
- "%s driver not found, deffering probe\n",
- CSIS_DRIVER_NAME);
- return -EPROBE_DEFER;
+ module_put(dev->driver->owner);
+dev_unlock:
+ device_unlock(dev);
+ if (ret == -EPROBE_DEFER)
+ dev_info(&fmd->pdev->dev, "deferring %s device registration\n",
+ dev_name(dev));
+ else if (ret < 0)
+ dev_err(&fmd->pdev->dev, "%s device registration failed (%d)\n",
+ dev_name(dev), ret);
+ return ret;
+}
+
+static int fimc_md_pdev_match(struct device *dev, void *data)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ int plat_entity = -1;
+ int ret;
+ char *p;
+
+ if (!get_device(dev))
+ return -ENODEV;
+
+ if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) {
+ plat_entity = IDX_CSIS;
+ } else if (!strcmp(pdev->name, FIMC_LITE_DRV_NAME)) {
+ plat_entity = IDX_FLITE;
+ } else {
+ p = strstr(pdev->name, "fimc");
+ if (p && *(p + 4) == 0)
+ plat_entity = IDX_FIMC;
}
- return driver_for_each_device(driver, NULL, fmd,
- csis_register_callback);
+ if (plat_entity >= 0)
+ ret = fimc_md_register_platform_entity(data, pdev,
+ plat_entity);
+ put_device(dev);
+ return 0;
}
static void fimc_md_unregister_entities(struct fimc_md *fmd)
@@ -477,6 +487,7 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
fimc_md_unregister_sensor(fmd->sensor[i].subdev);
fmd->sensor[i].subdev = NULL;
}
+ v4l2_info(&fmd->v4l2_dev, "Unregistered all entities\n");
}
/**
@@ -939,7 +950,8 @@ static int fimc_md_probe(struct platform_device *pdev)
/* Protect the media graph while we're registering entities */
mutex_lock(&fmd->media_dev.graph_mutex);
- ret = fimc_md_register_platform_entities(fmd);
+ ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
+ fimc_md_pdev_match);
if (ret)
goto err_unlock;
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 08/15] s5p-fimc: Add device tree based sensors registration
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
The sensor (I2C and/or SPI client) devices are instantiated by their
corresponding control bus drivers. Since the I2C client's master clock
is often provided by a video bus receiver (host interface) or other
than I2C/SPI controller device, the drivers of those client devices
are not accessing hardware in their driver's probe() callback. Instead,
after enabling clock, the host driver calls back into a sub-device
when it wants to activate them. This pattern is used by some in-tree
drivers and this patch also uses it for DT case. This patch is
intended as a first step for adding device tree support to the
S5P/Exynos SoC camera drivers. The second one is adding support for
asynchronous sub-devices registration and clock control from
sub-device driver level. The bindings shall not change when
asynchronous probing support is added. The motivation behind this
approach is to have basic support for device tree based platforms
in the driver, while asynchronous subdev probing and related issues
are being discussed on LMML.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 75 +++++++
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 237 +++++++++++++++++---
include/media/s5p_fimc.h | 16 ++
3 files changed, 299 insertions(+), 29 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
index 5bbda07..82bd619 100644
--- a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -73,6 +73,15 @@ node. Aliases are in form of fimc-lite<n>, where <n> is an integer (0...N)
specifying the IP's instance index.
+Image sensor nodes
+------------------
+
+The sensor device nodes should be added as their control bus controller
+(e.g. I2C0) child nodes and linked to a port created under csis or
+parallel-ports node, using common bindings for video input interfaces,
+.i.e. port/endpoint node pairs. The implementation of this binding requires
+at clock-frequency property to be present under sensor device nodes.
+
Example:
aliases {
@@ -80,6 +89,47 @@ Example:
fimc0 = &fimc_0;
};
+ /* Parallel bus IF sensor */
+ i2c_0: i2c@13860000 {
+ s5k6aa: sensor@3c {
+ compatible = "samsung,s5k6aafx";
+ reg = <0x3c>;
+ vddio-supply = <...>;
+
+ clock-frequency = <24000000>;
+ clocks = <...>;
+ clock-names = "mclk";
+
+ port {
+ s5k6aa_ep: endpoint {
+ remote-endpoint = <&fimc0_ep>;
+ bus-width = <8>;
+ hsync-active = <0>;
+ hsync-active = <1>;
+ pclk-sample = <1>;
+ };
+ };
+ };
+ };
+
+ /* MIPI CSI-2 bus IF sensor */
+ s5c73m3: sensor@0x1a {
+ compatible = "samsung,s5c73m3";
+ reg = <0x1a>;
+ vddio-supply = <...>;
+
+ clock-frequency = <24000000>;
+ clocks = <...>;
+ clock-names = "mclk";
+
+ port {
+ s5c73m3_1: endpoint {
+ data-lanes = <1>, <2>, <3>, <4>;
+ remote-endpoint = <&csis0_ep>;
+ };
+ };
+ };
+
camera {
compatible = "samsung,fimc", "simple-bus";
#address-cells = <1>;
@@ -90,6 +140,21 @@ Example:
pinctrl-0 = <&cam_port_a_clk_active>;
pinctrl-1 = <&cam_port_a_clk_idle>;
+ /* parallel camera ports */
+ parallel-ports {
+ /* camera A input */
+ port@0 {
+ reg = <0>;
+ fimc0_ep: endpoint {
+ remote-endpoint = <&s5k6aa_ep>;
+ bus-width = <8>;
+ hsync-active = <0>;
+ hsync-active = <1>;
+ pclk-sample = <1>;
+ };
+ };
+ };
+
fimc_0: fimc@11800000 {
compatible = "samsung,exynos4210-fimc";
reg = <0x11800000 0x1000>;
@@ -102,6 +167,16 @@ Example:
reg = <0x11880000 0x1000>;
interrupts = <0 78 0>;
max-data-lanes = <4>;
+ /* camera C input */
+ port {
+ reg = <2>;
+ csis0_ep: endpoint {
+ remote-endpoint = <&s5c73m3_ep>;
+ data-lanes = <1>, <2>, <3>, <4>;
+ samsung,csis-hs-settle = <12>;
+ samsung,camclk-out = <0>;
+ };
+ };
};
};
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 105bb91..3ac6ea8 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -19,11 +19,15 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-of.h>
#include <media/media-device.h>
#include <media/s5p_fimc.h>
@@ -248,7 +252,7 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
sd->grp_id = GRP_ID_SENSOR;
v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
- s_info->pdata.board_info->type);
+ sd->name);
return sd;
}
@@ -260,17 +264,183 @@ static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
if (!client)
return;
v4l2_device_unregister_subdev(sd);
- adapter = client->adapter;
- i2c_unregister_device(client);
- if (adapter)
- i2c_put_adapter(adapter);
+
+ if (!client->dev.of_node) {
+ adapter = client->adapter;
+ i2c_unregister_device(client);
+ if (adapter)
+ i2c_put_adapter(adapter);
+ }
+}
+
+#ifdef CONFIG_OF
+/* Register I2C client subdev associated with @node. */
+static int fimc_md_of_add_sensor(struct fimc_md *fmd,
+ struct device_node *node, int index)
+{
+ struct fimc_sensor_info *si;
+ struct i2c_client *client;
+ struct v4l2_subdev *sd;
+ int ret;
+
+ if (index >= ARRAY_SIZE(fmd->sensor))
+ return -EINVAL;
+ si = &fmd->sensor[index];
+
+ client = of_find_i2c_device_by_node(node);
+ if (!client)
+ return -EPROBE_DEFER;
+
+ device_lock(&client->dev);
+
+ if (!client->driver ||
+ !try_module_get(client->driver->driver.owner)) {
+ ret = -EAGAIN;
+ goto dev_put;
+ }
+
+ /* Enable sensor's master clock */
+ ret = __fimc_md_set_camclk(fmd, si, true);
+ if (ret < 0)
+ goto mod_put;
+ sd = i2c_get_clientdata(client);
+
+ ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+ __fimc_md_set_camclk(fmd, si, false);
+ if (ret < 0)
+ goto mod_put;
+
+ v4l2_set_subdev_hostdata(sd, si);
+ sd->grp_id = GRP_ID_SENSOR;
+ si->subdev = sd;
+ v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
+ sd->name, fmd->num_sensors);
+ fmd->num_sensors++;
+
+mod_put:
+ module_put(client->driver->driver.owner);
+dev_put:
+ device_unlock(&client->dev);
+ put_device(&client->dev);
+ return ret;
}
+/* Parse port node and register as a sub-device any sensor specified there. */
+static int fimc_md_parse_port_node(struct fimc_md *fmd,
+ struct device_node *port,
+ unsigned int index)
+{
+ struct device_node *rem, *endpoint;
+ struct s5p_fimc_isp_info *pd;
+ struct v4l2_of_endpoint bus_cfg;
+ u32 tmp, reg;
+ int ret;
+
+ if (index >= FIMC_MAX_SENSORS ||
+ of_property_read_u32(port, "reg", ®))
+ return -EINVAL;
+
+ pd = &fmd->sensor[index].pdata;
+ pd->mux_id = (reg - 1) & 0x1;
+
+ endpoint = of_get_child_by_name(port, "endpoint");
+ if (!endpoint)
+ return -EINVAL;
+
+ rem = v4l2_of_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
+ if (!rem)
+ return -EINVAL;
+
+ if (!of_property_read_u32(rem, "samsung,camclk-out", &tmp))
+ pd->clk_id = tmp;
+
+ if (!of_property_read_u32(rem, "clock-frequency", &tmp))
+ pd->clk_frequency = tmp;
+
+ if (pd->clk_frequency == 0) {
+ v4l2_err(&fmd->v4l2_dev,
+ "Wrong or unspecified sensor clock frequency\n");
+ of_node_put(rem);
+ return -EINVAL;
+ }
+
+ if (fimc_input_is_parallel(reg)) {
+ v4l2_of_parse_parallel_bus(endpoint, &bus_cfg);
+ if (bus_cfg.mbus_type == V4L2_MBUS_PARALLEL)
+ pd->bus_type = FIMC_ITU_601;
+ else
+ pd->bus_type = FIMC_ITU_656;
+ pd->flags = bus_cfg.mbus_flags;
+ } else if (fimc_input_is_mipi_csi(reg)) {
+ /*
+ * MIPI CSI-2: only input mux selection
+ * and sensor's clock frequency is needed.
+ */
+ pd->bus_type = FIMC_MIPI_CSI2;
+ } else {
+ v4l2_err(&fmd->v4l2_dev,
+ "Wrong reg property value (%u) at node %s/endpoint\n",
+ reg, rem->name);
+ }
+
+ ret = fimc_md_of_add_sensor(fmd, rem, index);
+ of_node_put(rem);
+
+ return ret;
+}
+
+/* Register all SoC external sub-devices */
+static int fimc_md_of_sensors_register(struct fimc_md *fmd,
+ struct device_node *np)
+{
+ struct device_node *parent = fmd->pdev->dev.of_node;
+ struct device_node *node, *ports;
+ int index = 0;
+ int ret;
+
+ /* Attach sensors linked to MIPI CSI-2 receivers */
+ for_each_available_child_of_node(parent, node) {
+ struct device_node *port;
+
+ if (of_node_cmp(node->name, "csis"))
+ continue;
+
+ port = of_get_child_by_name(node, "port");
+ if (!port)
+ return -EINVAL;
+
+ ret = fimc_md_parse_port_node(fmd, port, index);
+ if (ret < 0)
+ return ret;
+ index++;
+ }
+
+ /* Attach sensors listed in the parallel-ports node */
+ ports = of_get_child_by_name(parent, "parallel-ports");
+ if (!ports)
+ return 0;
+
+ for_each_child_of_node(ports, node) {
+ ret = fimc_md_parse_port_node(fmd, node, index);
+ if (ret < 0)
+ break;
+ index++;
+ }
+
+ return 0;
+}
+#else
+#define fimc_md_of_sensors_register(fmd, np) (-ENOSYS)
+#endif
+
static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
{
struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
+ struct device_node *of_node = fmd->pdev->dev.of_node;
struct fimc_dev *fd = NULL;
- int num_clients, ret, i;
+ int num_clients = 0;
+ int ret, i;
/*
* Runtime resume one of the FIMC entities to make sure
@@ -281,34 +451,41 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
fd = fmd->fimc[i];
if (!fd)
return -ENXIO;
+
ret = pm_runtime_get_sync(&fd->pdev->dev);
if (ret < 0)
return ret;
- WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
- num_clients = min_t(u32, pdata->num_clients, ARRAY_SIZE(fmd->sensor));
+ if (of_node) {
+ fmd->num_sensors = 0;
+ ret = fimc_md_of_sensors_register(fmd, of_node);
+ } else if (pdata) {
+ WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
+ num_clients = min_t(u32, pdata->num_clients,
+ ARRAY_SIZE(fmd->sensor));
+ fmd->num_sensors = num_clients;
- fmd->num_sensors = num_clients;
- for (i = 0; i < num_clients; i++) {
- struct v4l2_subdev *sd;
+ for (i = 0; i < num_clients; i++) {
+ struct v4l2_subdev *sd;
- fmd->sensor[i].pdata = pdata->isp_info[i];
- ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
- if (ret)
- break;
- sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]);
- ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
-
- if (!IS_ERR(sd)) {
+ fmd->sensor[i].pdata = pdata->isp_info[i];
+ ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
+ if (ret)
+ break;
+ sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]);
+ ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
+
+ if (IS_ERR(sd)) {
+ fmd->sensor[i].subdev = NULL;
+ ret = PTR_ERR(sd);
+ break;
+ }
fmd->sensor[i].subdev = sd;
- } else {
- fmd->sensor[i].subdev = NULL;
- ret = PTR_ERR(sd);
- break;
+ if (ret)
+ break;
}
- if (ret)
- break;
}
+
pm_runtime_put(&fd->pdev->dev);
return ret;
}
@@ -948,11 +1125,12 @@ static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
static int fimc_md_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct v4l2_device *v4l2_dev;
struct fimc_md *fmd;
int ret;
- fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL);
+ fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL);
if (!fmd)
return -ENOMEM;
@@ -962,7 +1140,7 @@ static int fimc_md_probe(struct platform_device *pdev)
strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
sizeof(fmd->media_dev.model));
fmd->media_dev.link_notify = fimc_md_link_notify;
- fmd->media_dev.dev = &pdev->dev;
+ fmd->media_dev.dev = dev;
v4l2_dev = &fmd->v4l2_dev;
v4l2_dev->mdev = &fmd->media_dev;
@@ -970,7 +1148,7 @@ static int fimc_md_probe(struct platform_device *pdev)
strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
- ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
+ ret = v4l2_device_register(dev, &fmd->v4l2_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
return ret;
@@ -997,11 +1175,12 @@ static int fimc_md_probe(struct platform_device *pdev)
if (ret)
goto err_unlock;
- if (pdev->dev.platform_data) {
+ if (dev->platform_data || dev->of_node) {
ret = fimc_md_register_sensor_entities(fmd);
if (ret)
goto err_unlock;
}
+
ret = fimc_md_create_links(fmd);
if (ret)
goto err_unlock;
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index eaea62a..e8e03cf 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -14,6 +14,22 @@
#include <media/media-entity.h>
+/*
+ * Enumeration of data inputs to the camera subsystem.
+ */
+enum fimc_input {
+ FIMC_INPUT_PARALLEL_0 = 1,
+ FIMC_INPUT_PARALLEL_1,
+ FIMC_INPUT_MIPI_CSI2_0 = 3,
+ FIMC_INPUT_MIPI_CSI2_1,
+ FIMC_INPUT_WRITEBACK_A = 5,
+ FIMC_INPUT_WRITEBACK_B,
+ FIMC_INPUT_WRITEBACK_ISP = 5,
+};
+
+#define fimc_input_is_parallel(x) ((x) == 1 || (x) == 2)
+#define fimc_input_is_mipi_csi(x) ((x) == 3 || (x) == 4)
+
enum cam_bus_type {
FIMC_ITU_601 = 1,
FIMC_ITU_656,
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 10/15] ARM: EXYNOS4: Add OF_DEV_AUXDATA for FIMC, FIMC-LITE and CSIS
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
Add these temporary OF_DEV_AUXDATA entries so we can use clocks
before common clock framework support for Exynos4 is available.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-exynos/mach-exynos4-dt.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 2890bf7..3ce0c52 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -77,6 +77,22 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
"exynos4210-spi.2", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-csis", EXYNOS4_PA_MIPI_CSIS0,
+ "s5p-mipi-csis.0", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-csis", EXYNOS4_PA_MIPI_CSIS1,
+ "s5p-mipi-csis.1", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4212-fimc", EXYNOS4_PA_FIMC0,
+ "exynos4-fimc.0", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4212-fimc", EXYNOS4_PA_FIMC1,
+ "exynos4-fimc.1", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4212-fimc", EXYNOS4_PA_FIMC2,
+ "exynos4-fimc.2", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4212-fimc", EXYNOS4_PA_FIMC3,
+ "exynos4-fimc.3", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4212-fimc-lite", EXYNOS4_PA_FIMC_LITE(0),
+ "exynos-fimc-lite.0", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4212-fimc-lite", EXYNOS4_PA_FIMC_LITE(1),
+ "exynos-fimc-lite.1", NULL),
{},
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 12/15] ARM: dts: Add ISP power domain node for Exynos4x12
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
The ISP power domain is a common power domain for fimc-lite
and fimc-is (ISP) devices.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4x12.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 179a62e..9c809b72 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -28,6 +28,11 @@
pinctrl3 = &pinctrl_3;
};
+ pd_isp: isp-power-domain@10023CA0 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10023CA0 0x20>;
+ };
+
combiner:interrupt-controller@10440000 {
interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
--
1.7.9.5
^ permalink raw reply related
* [PATCH RFC v2 14/15] ARM: dts: Add camera pinctrl nodes for Exynos4x12 SoCs
From: Sylwester Nawrocki @ 2012-12-31 16:03 UTC (permalink / raw)
To: linux-media
Cc: g.liakhovetski, grant.likely, rob.herring, thomas.abraham, t.figa,
sw0312.kim, kyungmin.park, devicetree-discuss, linux-samsung-soc,
Sylwester Nawrocki
In-Reply-To: <1356969793-27268-1-git-send-email-s.nawrocki@samsung.com>
Add separate nodes for the CAMCLK pin and turn off pull-up on camera
port A. Default driver strength for CAMCLK pin is increased to maximum.
The driver strength change can be moved to board specific part if it
is considered more appropriate.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4x12-pinctrl.dtsi | 33 +++++++++++++++++++++++------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
index 56f4669..e3225d0 100644
--- a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
@@ -401,15 +401,28 @@
samsung,pin-drv = <0>;
};
- cam_port_a: cam-port-a {
+ cam_port_a_io: cam-port-a-io {
samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3",
"gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7",
- "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-3",
- "gpj1-4";
+ "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-4";
samsung,pin-function = <2>;
- samsung,pin-pud = <3>;
+ samsung,pin-pud = <0>;
samsung,pin-drv = <0>;
};
+
+ cam_port_a_clk_active: cam-port-a-clk-active {
+ samsung,pins = "gpj1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
+
+ cam_port_a_clk_idle: cam-port-a-clk-idle {
+ samsung,pins = "gpj1-3";
+ samsung,pin-function = <2>;
+ samsung,pin-pud = <0>;
+ samsung,pin-drv = <3>;
+ };
};
pinctrl@11000000 {
@@ -834,11 +847,17 @@
samsung,pin-drv = <0>;
};
- cam_port_b: cam-port-b {
+ cam_port_b_io: cam-port-b-io {
samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3",
"gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7",
- "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1",
- "gpm2-2";
+ "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1";
+ samsung,pin-function = <3>;
+ samsung,pin-pud = <3>;
+ samsung,pin-drv = <0>;
+ };
+
+ cam_port_b_clk: cam-port-b-clk {
+ samsung,pins = "gpm2-2";
samsung,pin-function = <3>;
samsung,pin-pud = <3>;
samsung,pin-drv = <0>;
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH v2 2/3] mm: Update file times when inodes are written after mmaped writes
From: Jan Kara @ 2012-12-31 16:11 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Christoph Hellwig, linux-kernel, linux-mm, Linux FS Devel,
Dave Chinner, Jan Kara, Al Viro
In-Reply-To: <CALCETrX423Au=Q0SgdpFp7hcVBAw0t4FprO18Wk9j0K=j8fg_w@mail.gmail.com>
On Sat 22-12-12 00:43:30, Andy Lutomirski wrote:
> On Sat, Dec 22, 2012 at 12:29 AM, Christoph Hellwig <hch@infradead.org> wrote:
> > NAK, we went through great trouble to get rid of the nasty layering
> > violation where the VM called file_update_time directly just a short
> > while ago, reintroducing that is a massive step back.
> >
> > Make sure whatever "solution" for your problem you come up with keeps
> > the file update in the filesystem or generic helpers.
>
>
> There's an inode operation ->update_time that is called (if it exists)
> in these patches to update the time. Is that insufficient?
Filesystems need more choice in when they modify time stamps because that
can mean complex work like starting a transaction which has various locking
implications. Just making a separate callback for this doesn't really solve
the problem. Although I don't see particular problem with the call sites you
chose Christoph is right we probably don't want to reintroduce updates of
time stamps from generic code because eventually someone will have problem
with that.
> I could add a new inode operation ->modified_by_mmap that would be
> called in mapping_flush_cmtime if that would be better.
Not really. That's only uglier ;)
> The original version of this patch did the update in ->writepage and
> ->writepages, but that may have had lock ordering issues. (I wasn't
> able to confirm that there was any actual problem.)
Well, your call of mapping_flush_cmtime() from do_writepages() is easy to
move to generic_writepages(). Thus filesystem can easily implement it's own
->writepages() callback if time update doesn't suit it. With the call from
remove_vma() it is more problematic (and the calling context there is
harder as well because we hold mmap_sem). We could maybe leave the call
upto filesystem's ->release callback (and provide generic ->release handler
which just calls mapping_flush_cmtime()). It won't be perfect because that
gets called only after the last file descriptor for that struct file is
closed (i.e., if a process forks and child inherits mappings, ->release gets
called only after both parent and the child unmap the file) but it should
catch 99% of the real world cases. Christoph, would the be OK with
you?
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH v2 2/3] mm: Update file times when inodes are written after mmaped writes
From: Jan Kara @ 2012-12-31 16:11 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Christoph Hellwig, linux-kernel, linux-mm, Linux FS Devel,
Dave Chinner, Jan Kara, Al Viro
In-Reply-To: <CALCETrX423Au=Q0SgdpFp7hcVBAw0t4FprO18Wk9j0K=j8fg_w@mail.gmail.com>
On Sat 22-12-12 00:43:30, Andy Lutomirski wrote:
> On Sat, Dec 22, 2012 at 12:29 AM, Christoph Hellwig <hch@infradead.org> wrote:
> > NAK, we went through great trouble to get rid of the nasty layering
> > violation where the VM called file_update_time directly just a short
> > while ago, reintroducing that is a massive step back.
> >
> > Make sure whatever "solution" for your problem you come up with keeps
> > the file update in the filesystem or generic helpers.
>
>
> There's an inode operation ->update_time that is called (if it exists)
> in these patches to update the time. Is that insufficient?
Filesystems need more choice in when they modify time stamps because that
can mean complex work like starting a transaction which has various locking
implications. Just making a separate callback for this doesn't really solve
the problem. Although I don't see particular problem with the call sites you
chose Christoph is right we probably don't want to reintroduce updates of
time stamps from generic code because eventually someone will have problem
with that.
> I could add a new inode operation ->modified_by_mmap that would be
> called in mapping_flush_cmtime if that would be better.
Not really. That's only uglier ;)
> The original version of this patch did the update in ->writepage and
> ->writepages, but that may have had lock ordering issues. (I wasn't
> able to confirm that there was any actual problem.)
Well, your call of mapping_flush_cmtime() from do_writepages() is easy to
move to generic_writepages(). Thus filesystem can easily implement it's own
->writepages() callback if time update doesn't suit it. With the call from
remove_vma() it is more problematic (and the calling context there is
harder as well because we hold mmap_sem). We could maybe leave the call
upto filesystem's ->release callback (and provide generic ->release handler
which just calls mapping_flush_cmtime()). It won't be perfect because that
gets called only after the last file descriptor for that struct file is
closed (i.e., if a process forks and child inherits mappings, ->release gets
called only after both parent and the child unmap the file) but it should
catch 99% of the real world cases. Christoph, would the be OK with
you?
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply
* Re: [kbd] kbd: additions to the Unicode map for 12x22 fonts
From: Ken Moffat @ 2012-12-31 16:16 UTC (permalink / raw)
To: Linux console tools development discussion
In-Reply-To: <CAJ127Vx5ZYA=FUPyzSuckYoub+81w9p7UptQAcnHqrm_Bm2G7Q@mail.gmail.com>
On Sun, Dec 30, 2012 at 09:14:31PM -0800, David Grayson wrote:
>
> >> I would
> >> like to submit the following additions to the unimap for the sun12x22,
> >> iso01-12x22, and iso02-12x22 fonts in the kbd package:
> >
> > Why only these specific fonts, but not other fonts?
> >
> >> # Different kinds of dashes and hyphens.
> >> 0x2d U+00ad U+2010 U+2012 U+2013
> >>
> >> # left/right single quotation mark
> >> 0x60 U+2018
> >> 0x27 U+2019
> >>
Just out of interest, what use-case did you find for the soft
hyphen, U+00AD ? I discovered a week or two ago that it was not in
LatGrkCyr-12x22 : someone who posted to lkml had one in his name (it
appeared to be spurious), but apart from that I've never needed it.
It's now on my ToDo list, but so are a lot of other things.
The others are already in that font.
ĸen
--
das eine Mal als Tragödie, das andere Mal als Farce
^ permalink raw reply
* Re: Uninitialized extent races
From: Zheng Liu @ 2012-12-31 16:31 UTC (permalink / raw)
To: Jan Kara; +Cc: Theodore Ts'o, Dmitry Monakhov, linux-ext4
In-Reply-To: <20121231083221.GA7564@quack.suse.cz>
On Mon, Dec 31, 2012 at 09:32:21AM +0100, Jan Kara wrote:
> On Mon 24-12-12 19:17:45, Zheng Liu wrote:
> > On Fri, Dec 21, 2012 at 01:02:43PM -0500, Theodore Ts'o wrote:
> > > On Fri, Dec 21, 2012 at 05:19:29PM +0100, Jan Kara wrote:
> > > > No, I'm speaking about merging currently uninitialized extents. I.e.
> > > > suppose someone does the following on a filesystem with dioread_nolock so
> > > > that writeback happens via unwritten extents:
> > > > fd = open("file", O_RDWR);
> > > > pwrite(fd, buf, 4096, 0);
> > > > flusher thread starts writing
> > > > we create uninitialized extent for
> > > > range 0-4096
> > > > fallocate(fd, 0, 4096, 4096);
> > > > - we merge extents and now have just 1 uninitialized extent for range
> > > > 0-8192
> > > > ext4_convert_unwritten_extents() now
> > > > has to split the extent to finish
> > > > the IO.
> > >
> > > Ah, I see. Disabling the the merging that might take place as a
> > > result of the fallocate. Yes, I agree that's a completely sane thing
> > > to do.
> > >
> > > The alternate approach would be to add a flag in the extent status
> > > tree indicating that an unwritten conversion is pending, but that
> > > would add more complexity.
> >
> > Sorry for delay reply. Indeed we could add a flag in extent status tree
> > to indicate an pending unwritten extent, and I believe that it can bring
> > us some benefits. But I wonder whether this case often happens. Do we
> > have some real workloads?
> It doesn't happen often but it *can* happen. Thus you have to implement
> a code which handles the case. I don't think bit in extent status tree is
> really necessary. Just disabling merging of uninitialized extents is
> simple. If we see there are some real workloads which have problems with
> it, we can resort to a more complex solution using extent tree...
Thanks for your explanation. I don't know whether or not you have
generated a patch for this problem. I am willing to make it in a proper
time. If you have begun to generate it, please let me know. :-)
Happy New Year,
- Zheng
^ permalink raw reply
* [PATCH 2/2] omap3isp: Use devm_* managed functions
From: Laurent Pinchart @ 2012-12-31 16:29 UTC (permalink / raw)
To: linux-media; +Cc: sakari.ailus
In-Reply-To: <1356971395-3135-1-git-send-email-laurent.pinchart@ideasonboard.com>
Replace kzalloc, request_mem_region, ioremap, clk_get and regulator_get
with their devm_* managed replacement.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/platform/omap3isp/isp.c | 74 ++++---------------------
drivers/media/platform/omap3isp/ispccp2.c | 8 +--
drivers/media/platform/omap3isp/isph3a_aewb.c | 27 ++-------
drivers/media/platform/omap3isp/isph3a_af.c | 27 ++-------
drivers/media/platform/omap3isp/isphist.c | 4 +-
5 files changed, 27 insertions(+), 113 deletions(-)
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index a9f6de5..50cea08 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -1408,28 +1408,15 @@ static const char *isp_clocks[] = {
"l3_ick",
};
-static void isp_put_clocks(struct isp_device *isp)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
- if (isp->clock[i]) {
- clk_put(isp->clock[i]);
- isp->clock[i] = NULL;
- }
- }
-}
-
static int isp_get_clocks(struct isp_device *isp)
{
struct clk *clk;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
- clk = clk_get(isp->dev, isp_clocks[i]);
+ clk = devm_clk_get(isp->dev, isp_clocks[i]);
if (IS_ERR(clk)) {
dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]);
- isp_put_clocks(isp);
return PTR_ERR(clk);
}
@@ -1995,7 +1982,6 @@ error_csiphy:
static int __devexit isp_remove(struct platform_device *pdev)
{
struct isp_device *isp = platform_get_drvdata(pdev);
- int i;
isp_unregister_entities(isp);
isp_cleanup_modules(isp);
@@ -2006,26 +1992,6 @@ static int __devexit isp_remove(struct platform_device *pdev)
isp->domain = NULL;
omap3isp_put(isp);
- free_irq(isp->irq_num, isp);
- isp_put_clocks(isp);
-
- for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
- if (isp->mmio_base[i]) {
- iounmap(isp->mmio_base[i]);
- isp->mmio_base[i] = NULL;
- }
-
- if (isp->mmio_base_phys[i]) {
- release_mem_region(isp->mmio_base_phys[i],
- isp->mmio_size[i]);
- isp->mmio_base_phys[i] = 0;
- }
- }
-
- regulator_put(isp->isp_csiphy1.vdd);
- regulator_put(isp->isp_csiphy2.vdd);
- kfree(isp);
-
return 0;
}
@@ -2043,7 +2009,8 @@ static int isp_map_mem_resource(struct platform_device *pdev,
return -ENODEV;
}
- if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
+ if (!devm_request_mem_region(isp->dev, mem->start, resource_size(mem),
+ pdev->name)) {
dev_err(isp->dev,
"cannot reserve camera register I/O region\n");
return -ENODEV;
@@ -2052,8 +2019,9 @@ static int isp_map_mem_resource(struct platform_device *pdev,
isp->mmio_size[res] = resource_size(mem);
/* map the region */
- isp->mmio_base[res] = ioremap_nocache(isp->mmio_base_phys[res],
- isp->mmio_size[res]);
+ isp->mmio_base[res] = devm_ioremap_nocache(isp->dev,
+ isp->mmio_base_phys[res],
+ isp->mmio_size[res]);
if (!isp->mmio_base[res]) {
dev_err(isp->dev, "cannot map camera register I/O region\n");
return -ENODEV;
@@ -2083,7 +2051,7 @@ static int __devinit isp_probe(struct platform_device *pdev)
if (pdata == NULL)
return -EINVAL;
- isp = kzalloc(sizeof(*isp), GFP_KERNEL);
+ isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
if (!isp) {
dev_err(&pdev->dev, "could not allocate memory\n");
return -ENOMEM;
@@ -2106,8 +2074,8 @@ static int __devinit isp_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, isp);
/* Regulators */
- isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
- isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
+ isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY1");
+ isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY2");
/* Clocks
*
@@ -2182,7 +2150,8 @@ static int __devinit isp_probe(struct platform_device *pdev)
goto detach_dev;
}
- if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
+ if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED,
+ "OMAP3 ISP", isp)) {
dev_err(isp->dev, "Unable to request IRQ\n");
ret = -EINVAL;
goto detach_dev;
@@ -2191,7 +2160,7 @@ static int __devinit isp_probe(struct platform_device *pdev)
/* Entities */
ret = isp_initialize_modules(isp);
if (ret < 0)
- goto error_irq;
+ goto detach_dev;
ret = isp_register_entities(isp);
if (ret < 0)
@@ -2204,8 +2173,6 @@ static int __devinit isp_probe(struct platform_device *pdev)
error_modules:
isp_cleanup_modules(isp);
-error_irq:
- free_irq(isp->irq_num, isp);
detach_dev:
iommu_detach_device(isp->domain, &pdev->dev);
free_domain:
@@ -2213,26 +2180,9 @@ free_domain:
error_isp:
omap3isp_put(isp);
error:
- isp_put_clocks(isp);
-
- for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
- if (isp->mmio_base[i]) {
- iounmap(isp->mmio_base[i]);
- isp->mmio_base[i] = NULL;
- }
-
- if (isp->mmio_base_phys[i]) {
- release_mem_region(isp->mmio_base_phys[i],
- isp->mmio_size[i]);
- isp->mmio_base_phys[i] = 0;
- }
- }
- regulator_put(isp->isp_csiphy2.vdd);
- regulator_put(isp->isp_csiphy1.vdd);
platform_set_drvdata(pdev, NULL);
mutex_destroy(&isp->isp_mutex);
- kfree(isp);
return ret;
}
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
index 85f0de8..c5d84c9 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -1136,7 +1136,7 @@ int omap3isp_ccp2_init(struct isp_device *isp)
* TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
*/
if (isp->revision == ISP_REVISION_2_0) {
- ccp2->vdds_csib = regulator_get(isp->dev, "vdds_csib");
+ ccp2->vdds_csib = devm_regulator_get(isp->dev, "vdds_csib");
if (IS_ERR(ccp2->vdds_csib)) {
dev_dbg(isp->dev,
"Could not get regulator vdds_csib\n");
@@ -1147,10 +1147,8 @@ int omap3isp_ccp2_init(struct isp_device *isp)
}
ret = ccp2_init_entities(ccp2);
- if (ret < 0) {
- regulator_put(ccp2->vdds_csib);
+ if (ret < 0)
return ret;
- }
ccp2_reset(ccp2);
return 0;
@@ -1166,6 +1164,4 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp)
omap3isp_video_cleanup(&ccp2->video_in);
media_entity_cleanup(&ccp2->subdev.entity);
-
- regulator_put(ccp2->vdds_csib);
}
diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c
index 1b908fd..75fd82b 100644
--- a/drivers/media/platform/omap3isp/isph3a_aewb.c
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -300,9 +300,8 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
struct ispstat *aewb = &isp->isp_aewb;
struct omap3isp_h3a_aewb_config *aewb_cfg;
struct omap3isp_h3a_aewb_config *aewb_recover_cfg;
- int ret;
- aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
+ aewb_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_cfg), GFP_KERNEL);
if (!aewb_cfg)
return -ENOMEM;
@@ -313,12 +312,12 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
aewb->isp = isp;
/* Set recover state configuration */
- aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
+ aewb_recover_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_recover_cfg),
+ GFP_KERNEL);
if (!aewb_recover_cfg) {
dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
"recover configuration.\n");
- ret = -ENOMEM;
- goto err_recover_alloc;
+ return -ENOMEM;
}
aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
@@ -335,25 +334,13 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
dev_err(aewb->isp->dev, "AEWB: recover configuration is "
"invalid.\n");
- ret = -EINVAL;
- goto err_conf;
+ return -EINVAL;
}
aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
aewb->recover_priv = aewb_recover_cfg;
- ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
- if (ret)
- goto err_conf;
-
- return 0;
-
-err_conf:
- kfree(aewb_recover_cfg);
-err_recover_alloc:
- kfree(aewb_cfg);
-
- return ret;
+ return omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
}
/*
@@ -361,7 +348,5 @@ err_recover_alloc:
*/
void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
{
- kfree(isp->isp_aewb.priv);
- kfree(isp->isp_aewb.recover_priv);
omap3isp_stat_cleanup(&isp->isp_aewb);
}
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c
index d645b41..a0bf5af 100644
--- a/drivers/media/platform/omap3isp/isph3a_af.c
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -363,9 +363,8 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
struct ispstat *af = &isp->isp_af;
struct omap3isp_h3a_af_config *af_cfg;
struct omap3isp_h3a_af_config *af_recover_cfg;
- int ret;
- af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
+ af_cfg = devm_kzalloc(isp->dev, sizeof(*af_cfg), GFP_KERNEL);
if (af_cfg == NULL)
return -ENOMEM;
@@ -376,12 +375,12 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
af->isp = isp;
/* Set recover state configuration */
- af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
+ af_recover_cfg = devm_kzalloc(isp->dev, sizeof(*af_recover_cfg),
+ GFP_KERNEL);
if (!af_recover_cfg) {
dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
"configuration.\n");
- ret = -ENOMEM;
- goto err_recover_alloc;
+ return -ENOMEM;
}
af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
@@ -393,30 +392,16 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
if (h3a_af_validate_params(af, af_recover_cfg)) {
dev_err(af->isp->dev, "AF: recover configuration is "
"invalid.\n");
- ret = -EINVAL;
- goto err_conf;
+ return -EINVAL;
}
af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
af->recover_priv = af_recover_cfg;
- ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
- if (ret)
- goto err_conf;
-
- return 0;
-
-err_conf:
- kfree(af_recover_cfg);
-err_recover_alloc:
- kfree(af_cfg);
-
- return ret;
+ return omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
}
void omap3isp_h3a_af_cleanup(struct isp_device *isp)
{
- kfree(isp->isp_af.priv);
- kfree(isp->isp_af.recover_priv);
omap3isp_stat_cleanup(&isp->isp_af);
}
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
index da2fa98..2ccc4e5 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -477,7 +477,7 @@ int omap3isp_hist_init(struct isp_device *isp)
struct omap3isp_hist_config *hist_cfg;
int ret = -1;
- hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL);
+ hist_cfg = devm_kzalloc(isp->dev, sizeof(*hist_cfg), GFP_KERNEL);
if (hist_cfg == NULL)
return -ENOMEM;
@@ -503,7 +503,6 @@ int omap3isp_hist_init(struct isp_device *isp)
ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
if (ret) {
- kfree(hist_cfg);
if (HIST_USING_DMA(hist))
omap_free_dma(hist->dma_ch);
}
@@ -518,6 +517,5 @@ void omap3isp_hist_cleanup(struct isp_device *isp)
{
if (HIST_USING_DMA(&isp->isp_hist))
omap_free_dma(isp->isp_hist.dma_ch);
- kfree(isp->isp_hist.priv);
omap3isp_stat_cleanup(&isp->isp_hist);
}
--
1.7.8.6
^ permalink raw reply related
* [PATCH 1/2] omap3isp: Remove unneeded memset after kzalloc
From: Laurent Pinchart @ 2012-12-31 16:29 UTC (permalink / raw)
To: linux-media; +Cc: sakari.ailus
kzalloc initializes the memory it allocates to 0, there's no need for an
explicit memset.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/media/platform/omap3isp/isph3a_aewb.c | 1 -
drivers/media/platform/omap3isp/isph3a_af.c | 1 -
drivers/media/platform/omap3isp/isphist.c | 1 -
3 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/omap3isp/isph3a_aewb.c b/drivers/media/platform/omap3isp/isph3a_aewb.c
index 036e996..1b908fd 100644
--- a/drivers/media/platform/omap3isp/isph3a_aewb.c
+++ b/drivers/media/platform/omap3isp/isph3a_aewb.c
@@ -306,7 +306,6 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
if (!aewb_cfg)
return -ENOMEM;
- memset(aewb, 0, sizeof(*aewb));
aewb->ops = &h3a_aewb_ops;
aewb->priv = aewb_cfg;
aewb->dma_ch = -1;
diff --git a/drivers/media/platform/omap3isp/isph3a_af.c b/drivers/media/platform/omap3isp/isph3a_af.c
index 42ccce3..d645b41 100644
--- a/drivers/media/platform/omap3isp/isph3a_af.c
+++ b/drivers/media/platform/omap3isp/isph3a_af.c
@@ -369,7 +369,6 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
if (af_cfg == NULL)
return -ENOMEM;
- memset(af, 0, sizeof(*af));
af->ops = &h3a_af_ops;
af->priv = af_cfg;
af->dma_ch = -1;
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
index 2d759c5..da2fa98 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -481,7 +481,6 @@ int omap3isp_hist_init(struct isp_device *isp)
if (hist_cfg == NULL)
return -ENOMEM;
- memset(hist, 0, sizeof(*hist));
hist->isp = isp;
if (HIST_CONFIG_DMA)
--
1.7.8.6
^ permalink raw reply related
* git filter-branch doesn't dereference annotated tags
From: Grégory Pakosz @ 2012-12-31 16:24 UTC (permalink / raw)
To: git
[-- Attachment #1: Type: text/plain, Size: 2067 bytes --]
Please disregard the previous email that contains an incorrect fix
suggestion. I wish my first contribution was flawless.
Here is what's happening.
git-filter-branch let git-update-ref -d verify that the value for $ref
matches $sha1.
However, when $ref points to an annotated tag that is being deleted,
that verification fails because $sha1 is the commit underneath.
I think there are two possible fixes:
1) either make git-filter-branch dereference annotated tags and do
the verification itself then use the two arguments version of git
update-ref
2) in the case of an annotated tag, pass another <old value> to git update-ref
Please find below a patch that implements solution 1). Please note the
patch doesn't contain a unit test for this situation as I wasn't sure
how to provide one. Yet I tested it on the repository I'm working on.
Gregory
>From 9d21960088a61bfbac1ffdb4b13e3038f88ab4d6 Mon Sep 17 00:00:00 2001
From: Gregory Pakosz <gpakosz@visionobjects.com>
Date: Mon, 31 Dec 2012 15:30:36 +0100
Subject: [PATCH] git-filter-branch: support annotated tags deletion
git-filter-branch let git-update-ref -d verify that the value for $ref matches
$sha1. However, when $ref is an annotated tag being deleted that verfication
fails because $sha1 corresponds to a commit object.
Instead of asking git-update-ref to verify values actually match, dereference
$ref ourselves and test against $sha1 first. Then invoke git-update-ref with two
arguments.
Signed-off-by: Gregory Pakosz <gpakosz@visionobjects.com>
---
git-filter-branch.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 5314249..bbee6d0 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -383,7 +383,7 @@ do
case "$rewritten" in
'')
echo "Ref '$ref' was deleted"
- git update-ref -m "filter-branch: delete" -d "$ref" $sha1 ||
+ test $(git rev-parse --verify "$ref^{commit}") = $sha1 && git
update-ref -m "filter-branch: delete" -d "$ref" ||
die "Could not delete $ref"
;;
$_x40)
--
1.8.0.1
[-- Attachment #2: 0001-git-filter-branch-support-annotated-tags-deletion.patch --]
[-- Type: application/octet-stream, Size: 1211 bytes --]
From 9d21960088a61bfbac1ffdb4b13e3038f88ab4d6 Mon Sep 17 00:00:00 2001
From: Gregory Pakosz <gpakosz@visionobjects.com>
Date: Mon, 31 Dec 2012 15:30:36 +0100
Subject: [PATCH] git-filter-branch: support annotated tags deletion
git-filter-branch let git-update-ref -d verify that the value for $ref matches
$sha1. However, when $ref is an annotated tag being deleted that verfication
fails because $sha1 corresponds to a commit object.
Instead of asking git-update-ref to verify values actually match, dereference
$ref ourselves and test against $sha1 first. Then invoke git-update-ref with two
arguments.
Signed-off-by: Gregory Pakosz <gpakosz@visionobjects.com>
---
git-filter-branch.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 5314249..bbee6d0 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -383,7 +383,7 @@ do
case "$rewritten" in
'')
echo "Ref '$ref' was deleted"
- git update-ref -m "filter-branch: delete" -d "$ref" $sha1 ||
+ test $(git rev-parse --verify "$ref^{commit}") = $sha1 && git update-ref -m "filter-branch: delete" -d "$ref" ||
die "Could not delete $ref"
;;
$_x40)
--
1.8.0.1
^ permalink raw reply related
* [Qemu-devel] [Qemu-trivial] [PATCH] configure: try pkg-config for curses
From: Vadim Evard @ 2012-12-31 16:30 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-trivial
configure: try pkg-config for curses
Static linkikng against ncurses may require explicit -ltinfo.
In case -lcurses and -lncurses both didn't work give pkg-config a
chance.
Signed-off-by: Vadim Evard <v.e.evard@gmail.com>
---
configure | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index b0c7e54..16280e2 100755
--- a/configure
+++ b/configure
@@ -2030,7 +2030,7 @@ fi
if test "$mingw32" = "yes" ; then
curses_list="-lpdcurses"
else
- curses_list="-lncurses -lcurses"
+ curses_list="-lncurses:-lcurses:$($pkg_config --libs ncurses)"
fi
if test "$curses" != "no" ; then
@@ -2043,7 +2043,9 @@ int main(void) {
return s != 0;
}
EOF
+ IFS=:
for curses_lib in $curses_list; do
+ unset IFS
if compile_prog "" "$curses_lib" ; then
curses_found=yes
libs_softmmu="$curses_lib $libs_softmmu"
--
1.7.10.4
^ permalink raw reply related
* [Qemu-trivial] [Qemu-devel] [PATCH] configure: try pkg-config for curses
From: Vadim Evard @ 2012-12-31 16:30 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-trivial
configure: try pkg-config for curses
Static linkikng against ncurses may require explicit -ltinfo.
In case -lcurses and -lncurses both didn't work give pkg-config a
chance.
Signed-off-by: Vadim Evard <v.e.evard@gmail.com>
---
configure | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
index b0c7e54..16280e2 100755
--- a/configure
+++ b/configure
@@ -2030,7 +2030,7 @@ fi
if test "$mingw32" = "yes" ; then
curses_list="-lpdcurses"
else
- curses_list="-lncurses -lcurses"
+ curses_list="-lncurses:-lcurses:$($pkg_config --libs ncurses)"
fi
if test "$curses" != "no" ; then
@@ -2043,7 +2043,9 @@ int main(void) {
return s != 0;
}
EOF
+ IFS=:
for curses_lib in $curses_list; do
+ unset IFS
if compile_prog "" "$curses_lib" ; then
curses_found=yes
libs_softmmu="$curses_lib $libs_softmmu"
--
1.7.10.4
^ permalink raw reply related
* [U-Boot] [PATCH 0/5] am335x_evm: support for booting via USB
From: Ilya Yanok @ 2012-12-31 16:32 UTC (permalink / raw)
To: u-boot
These series add support for booting via USB on TI AM335X based boards.
Tested on BeagleBone.
Ilya Yanok (5):
spl: support for booting via usbeth
am33xx: support for booting via usbeth
am335x_evm: enable support for booting via USB
spl: add possibility to force boot device
am335x_evm: add new config with forced USB booting
arch/arm/cpu/armv7/omap-common/boot-common.c | 3 +++
arch/arm/include/asm/arch-am33xx/spl.h | 1 +
board/ti/am335x/board.c | 3 ++-
boards.cfg | 1 +
common/spl/spl.c | 9 +++++++++
include/configs/am335x_evm.h | 8 ++++++++
spl/Makefile | 2 ++
7 files changed, 26 insertions(+), 1 deletion(-)
--
1.8.0.2
^ permalink raw reply
* [U-Boot] [PATCH 1/5] spl: support for booting via usbeth
From: Ilya Yanok @ 2012-12-31 16:32 UTC (permalink / raw)
To: u-boot
In-Reply-To: <1356971563-23478-1-git-send-email-ilya.yanok@cogentembedded.com>
In case of usbeth booting just call net_load_image("usb_ether").
This patch also adds CONFIG_SPL_USBETH_SUPPORT and
CONFIG_SPL_MUSB_NEW_SUPPORT config options to enable linking of SPL
against USB gagdet support and new MUSB driver resp.
Signed-off-by: Ilya Yanok <ilya.yanok@cogentembedded.com>
---
common/spl/spl.c | 5 +++++
spl/Makefile | 2 ++
2 files changed, 7 insertions(+)
diff --git a/common/spl/spl.c b/common/spl/spl.c
index ff9ba7b..6a5a136 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -221,6 +221,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
#endif
break;
#endif
+#ifdef CONFIG_SPL_USBETH_SUPPORT
+ case BOOT_DEVICE_USBETH:
+ spl_net_load_image("usb_ether");
+ break;
+#endif
default:
debug("SPL: Un-supported Boot Device\n");
hang();
diff --git a/spl/Makefile b/spl/Makefile
index 6dbb105..3333cde 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -81,6 +81,8 @@ LIBS-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/memory.o
LIBS-$(CONFIG_SPL_NET_SUPPORT) += net/libnet.o
LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/libnet.o
LIBS-$(CONFIG_SPL_ETH_SUPPORT) += drivers/net/phy/libphy.o
+LIBS-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/libusb_musb-new.o
+LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/libusb_gadget.o
ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
--
1.8.0.2
^ permalink raw reply related
* [U-Boot] [PATCH 2/5] am33xx: support for booting via usbeth
From: Ilya Yanok @ 2012-12-31 16:32 UTC (permalink / raw)
To: u-boot
In-Reply-To: <1356971563-23478-1-git-send-email-ilya.yanok@cogentembedded.com>
This patch adds BOOT_DEVICE define for USB booting and fixes
spl_board_init function to call arch_misc_init (this is the place there
musb is initialized).
Signed-off-by: Ilya Yanok <ilya.yanok@cogentembedded.com>
---
arch/arm/cpu/armv7/omap-common/boot-common.c | 3 +++
arch/arm/include/asm/arch-am33xx/spl.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/arch/arm/cpu/armv7/omap-common/boot-common.c b/arch/arm/cpu/armv7/omap-common/boot-common.c
index 0f19141..99dc9d8 100644
--- a/arch/arm/cpu/armv7/omap-common/boot-common.c
+++ b/arch/arm/cpu/armv7/omap-common/boot-common.c
@@ -54,6 +54,9 @@ void spl_board_init(void)
#ifdef CONFIG_SPL_NAND_SUPPORT
gpmc_init();
#endif
+#if defined(CONFIG_AM33XX) && defined(CONFIG_SPL_MUSB_NEW_SUPPORT)
+ arch_misc_init();
+#endif
}
int board_mmc_init(bd_t *bis)
diff --git a/arch/arm/include/asm/arch-am33xx/spl.h b/arch/arm/include/asm/arch-am33xx/spl.h
index 644ff35..e961ce0 100644
--- a/arch/arm/include/asm/arch-am33xx/spl.h
+++ b/arch/arm/include/asm/arch-am33xx/spl.h
@@ -29,6 +29,7 @@
#define BOOT_DEVICE_MMC2 9 /* eMMC or daughter card */
#define BOOT_DEVICE_SPI 11
#define BOOT_DEVICE_UART 65
+#define BOOT_DEVICE_USBETH 68
#define BOOT_DEVICE_CPGMAC 70
#define BOOT_DEVICE_MMC2_2 0xFF
#endif
--
1.8.0.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.