From 697cca21b09ce4c641bce821b90e90b3e95d17f6 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:25 -0300 Subject: [media] omap3isp: Fix error handling in probe The mutex was not destroyed correctly if dma_coerce_mask_and_coherent() failed for some reason. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index deca80903c3a..fb193b65b5ce 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2252,7 +2252,7 @@ static int isp_probe(struct platform_device *pdev) ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32)); if (ret) - return ret; + goto error; platform_set_drvdata(pdev, isp); -- cgit v1.2.3 From 8b3aff7cdd6c2e7c9a3df755b23525e393195102 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:26 -0300 Subject: [media] omap3isp: Avoid a BUG_ON() in media_entity_create_link() If an uninitialised v4l2_subdev struct was passed to media_entity_create_link(), one of the BUG_ON()'s in the function will be hit since media_entity.num_pads will be zero. Avoid this by checking whether the num_pads field is non-zero for the interface. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index fb193b65b5ce..4ab674dd43c1 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1946,6 +1946,19 @@ static int isp_register_entities(struct isp_device *isp) goto done; } + /* + * Not all interfaces are available on all revisions + * of the ISP. The sub-devices of those interfaces + * aren't initialised in such a case. Check this by + * ensuring the num_pads is non-zero. + */ + if (!input->num_pads) { + dev_err(isp->dev, "%s: invalid input %u\n", + entity->name, subdevs->interface); + ret = -EINVAL; + goto done; + } + for (i = 0; i < sensor->entity.num_pads; i++) { if (sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) break; -- cgit v1.2.3 From 703e6f625bd9400e76fd9dcda56011b67b954a10 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:27 -0300 Subject: [media] omap3isp: Separate external link creation from platform data parsing Move the code which connects the external entity to an ISP entity into a separate function. This disconnects it from parsing the platform data. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 143 +++++++++++++++++----------------- 1 file changed, 72 insertions(+), 71 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 4ab674dd43c1..f694615f32c4 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1832,6 +1832,77 @@ isp_register_subdev_group(struct isp_device *isp, return sensor; } +static int isp_link_entity( + struct isp_device *isp, struct media_entity *entity, + enum isp_interface_type interface) +{ + struct media_entity *input; + unsigned int flags; + unsigned int pad; + unsigned int i; + + /* Connect the sensor to the correct interface module. + * Parallel sensors are connected directly to the CCDC, while + * serial sensors are connected to the CSI2a, CCP2b or CSI2c + * receiver through CSIPHY1 or CSIPHY2. + */ + switch (interface) { + case ISP_INTERFACE_PARALLEL: + input = &isp->isp_ccdc.subdev.entity; + pad = CCDC_PAD_SINK; + flags = 0; + break; + + case ISP_INTERFACE_CSI2A_PHY2: + input = &isp->isp_csi2a.subdev.entity; + pad = CSI2_PAD_SINK; + flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; + break; + + case ISP_INTERFACE_CCP2B_PHY1: + case ISP_INTERFACE_CCP2B_PHY2: + input = &isp->isp_ccp2.subdev.entity; + pad = CCP2_PAD_SINK; + flags = 0; + break; + + case ISP_INTERFACE_CSI2C_PHY1: + input = &isp->isp_csi2c.subdev.entity; + pad = CSI2_PAD_SINK; + flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED; + break; + + default: + dev_err(isp->dev, "%s: invalid interface type %u\n", __func__, + interface); + return -EINVAL; + } + + /* + * Not all interfaces are available on all revisions of the + * ISP. The sub-devices of those interfaces aren't initialised + * in such a case. Check this by ensuring the num_pads is + * non-zero. + */ + if (!input->num_pads) { + dev_err(isp->dev, "%s: invalid input %u\n", entity->name, + interface); + return -EINVAL; + } + + for (i = 0; i < entity->num_pads; i++) { + if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE) + break; + } + if (i == entity->num_pads) { + dev_err(isp->dev, "%s: no source pad in external entity\n", + __func__); + return -EINVAL; + } + + return media_entity_create_link(entity, i, input, pad, flags); +} + static int isp_register_entities(struct isp_device *isp) { struct isp_platform_data *pdata = isp->pdata; @@ -1895,10 +1966,6 @@ static int isp_register_entities(struct isp_device *isp) /* Register external entities */ for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { struct v4l2_subdev *sensor; - struct media_entity *input; - unsigned int flags; - unsigned int pad; - unsigned int i; sensor = isp_register_subdev_group(isp, subdevs->subdevs); if (sensor == NULL) @@ -1906,73 +1973,7 @@ static int isp_register_entities(struct isp_device *isp) sensor->host_priv = subdevs; - /* Connect the sensor to the correct interface module. Parallel - * sensors are connected directly to the CCDC, while serial - * sensors are connected to the CSI2a, CCP2b or CSI2c receiver - * through CSIPHY1 or CSIPHY2. - */ - switch (subdevs->interface) { - case ISP_INTERFACE_PARALLEL: - input = &isp->isp_ccdc.subdev.entity; - pad = CCDC_PAD_SINK; - flags = 0; - break; - - case ISP_INTERFACE_CSI2A_PHY2: - input = &isp->isp_csi2a.subdev.entity; - pad = CSI2_PAD_SINK; - flags = MEDIA_LNK_FL_IMMUTABLE - | MEDIA_LNK_FL_ENABLED; - break; - - case ISP_INTERFACE_CCP2B_PHY1: - case ISP_INTERFACE_CCP2B_PHY2: - input = &isp->isp_ccp2.subdev.entity; - pad = CCP2_PAD_SINK; - flags = 0; - break; - - case ISP_INTERFACE_CSI2C_PHY1: - input = &isp->isp_csi2c.subdev.entity; - pad = CSI2_PAD_SINK; - flags = MEDIA_LNK_FL_IMMUTABLE - | MEDIA_LNK_FL_ENABLED; - break; - - default: - dev_err(isp->dev, "%s: invalid interface type %u\n", - __func__, subdevs->interface); - ret = -EINVAL; - goto done; - } - - /* - * Not all interfaces are available on all revisions - * of the ISP. The sub-devices of those interfaces - * aren't initialised in such a case. Check this by - * ensuring the num_pads is non-zero. - */ - if (!input->num_pads) { - dev_err(isp->dev, "%s: invalid input %u\n", - entity->name, subdevs->interface); - ret = -EINVAL; - goto done; - } - - for (i = 0; i < sensor->entity.num_pads; i++) { - if (sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE) - break; - } - if (i == sensor->entity.num_pads) { - dev_err(isp->dev, - "%s: no source pad in external entity\n", - __func__); - ret = -EINVAL; - goto done; - } - - ret = media_entity_create_link(&sensor->entity, i, input, pad, - flags); + ret = isp_link_entity(isp, &sensor->entity, subdevs->interface); if (ret < 0) goto done; } -- cgit v1.2.3 From 64904b574e33f897cc425fcbe64cebab92b3c6fb Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Mar 2015 19:57:28 -0300 Subject: [media] omap3isp: DT support for clocks Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index f694615f32c4..82499cd7c3d7 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -279,9 +279,21 @@ static const struct clk_init_data isp_xclk_init_data = { .num_parents = 1, }; +static struct clk *isp_xclk_src_get(struct of_phandle_args *clkspec, void *data) +{ + unsigned int idx = clkspec->args[0]; + struct isp_device *isp = data; + + if (idx >= ARRAY_SIZE(isp->xclks)) + return ERR_PTR(-ENOENT); + + return isp->xclks[idx].clk; +} + static int isp_xclk_init(struct isp_device *isp) { struct isp_platform_data *pdata = isp->pdata; + struct device_node *np = isp->dev->of_node; struct clk_init_data init; unsigned int i; @@ -312,6 +324,12 @@ static int isp_xclk_init(struct isp_device *isp) if (IS_ERR(xclk->clk)) return PTR_ERR(xclk->clk); + /* When instantiated from DT we don't need to register clock + * aliases. + */ + if (np) + continue; + if (pdata->xclks[i].con_id == NULL && pdata->xclks[i].dev_id == NULL) continue; @@ -327,13 +345,20 @@ static int isp_xclk_init(struct isp_device *isp) clkdev_add(xclk->lookup); } + if (np) + of_clk_add_provider(np, isp_xclk_src_get, isp); + return 0; } static void isp_xclk_cleanup(struct isp_device *isp) { + struct device_node *np = isp->dev->of_node; unsigned int i; + if (np) + of_clk_del_provider(np); + for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) { struct isp_xclk *xclk = &isp->xclks[i]; -- cgit v1.2.3 From 4c8f14861cccb7b19cfd582e135847aa772f3854 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:29 -0300 Subject: [media] omap3isp: Platform data could be NULL Only check for call platform data callback functions if there's platform data. Also take care of a few other cases where the NULL pdata pointer could have been accessed, and remove the check for NULL dev->platform_data pointer. Removing the check for NULL dev->platform_data isn't strictly needed by the DT support but there's no harm from that either: the device now can be used without sensors, for instance. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 10 ++++------ drivers/media/platform/omap3isp/ispvideo.c | 6 +++--- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 82499cd7c3d7..537377b43083 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -330,8 +330,8 @@ static int isp_xclk_init(struct isp_device *isp) if (np) continue; - if (pdata->xclks[i].con_id == NULL && - pdata->xclks[i].dev_id == NULL) + if (!pdata || (pdata->xclks[i].con_id == NULL && + pdata->xclks[i].dev_id == NULL)) continue; xclk->lookup = kzalloc(sizeof(*xclk->lookup), GFP_KERNEL); @@ -1989,7 +1989,8 @@ static int isp_register_entities(struct isp_device *isp) goto done; /* Register external entities */ - for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) { + for (subdevs = pdata ? pdata->subdevs : NULL; + subdevs && subdevs->subdevs; ++subdevs) { struct v4l2_subdev *sensor; sensor = isp_register_subdev_group(isp, subdevs->subdevs); @@ -2271,9 +2272,6 @@ static int isp_probe(struct platform_device *pdev) int ret; int i, m; - if (pdata == NULL) - return -EINVAL; - isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); if (!isp) { dev_err(&pdev->dev, "could not allocate memory\n"); diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 0b5967ecd455..d285af18df7f 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -1018,7 +1018,7 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) pipe->entities = 0; - if (video->isp->pdata->set_constraints) + if (video->isp->pdata && video->isp->pdata->set_constraints) video->isp->pdata->set_constraints(video->isp, true); pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]); pipe->max_rate = pipe->l3_ick; @@ -1100,7 +1100,7 @@ err_set_stream: err_check_format: media_entity_pipeline_stop(&video->video.entity); err_pipeline_start: - if (video->isp->pdata->set_constraints) + if (video->isp->pdata && video->isp->pdata->set_constraints) video->isp->pdata->set_constraints(video->isp, false); /* The DMA queue must be emptied here, otherwise CCDC interrupts that * will get triggered the next time the CCDC is powered up will try to @@ -1161,7 +1161,7 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) video->queue = NULL; video->error = false; - if (video->isp->pdata->set_constraints) + if (video->isp->pdata && video->isp->pdata->set_constraints) video->isp->pdata->set_constraints(video->isp, false); media_entity_pipeline_stop(&video->video.entity); -- cgit v1.2.3 From 6890874772e4c5e2925187f262893df0eb0322ba Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:30 -0300 Subject: [media] omap3isp: Refactor device configuration structs for Device Tree Make omap3isp configuration data structures more suitable for consumption by the DT by separating the I2C bus information of all the sub-devices in a group and the ISP bus information from each other. The ISP bus information is made a pointer instead of being directly embedded in the struct. In the case of the DT only the sensor specific information on the ISP bus configuration is retained. The structs are renamed to reflect that. After this change the structs needed to describe device configuration can be allocated and accessed separately without those needed only in the case of platform data. The platform data related structs can be later removed once the support for platform data can be removed. Signed-off-by: Sakari Ailus Acked-by: Igor Grinberg (for cm-t35) Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-omap2/board-cm-t35.c | 57 +++++++------------ drivers/media/platform/omap3isp/isp.c | 86 ++++++++++++++--------------- drivers/media/platform/omap3isp/isp.h | 2 +- drivers/media/platform/omap3isp/ispccdc.c | 26 ++++----- drivers/media/platform/omap3isp/ispccp2.c | 22 ++++---- drivers/media/platform/omap3isp/ispcsi2.c | 8 +-- drivers/media/platform/omap3isp/ispcsiphy.c | 21 ++++--- include/media/omap3isp.h | 34 ++++++------ 8 files changed, 119 insertions(+), 137 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 91738a14ecbe..b5dfbc1b1fc6 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -492,51 +492,36 @@ static struct twl4030_platform_data cm_t35_twldata = { #include #include "devices.h" -static struct i2c_board_info cm_t35_isp_i2c_boardinfo[] = { +static struct isp_platform_subdev cm_t35_isp_subdevs[] = { { - I2C_BOARD_INFO("mt9t001", 0x5d), - }, - { - I2C_BOARD_INFO("tvp5150", 0x5c), - }, -}; - -static struct isp_subdev_i2c_board_info cm_t35_isp_primary_subdevs[] = { - { - .board_info = &cm_t35_isp_i2c_boardinfo[0], - .i2c_adapter_id = 3, - }, - { NULL, 0, }, -}; - -static struct isp_subdev_i2c_board_info cm_t35_isp_secondary_subdevs[] = { - { - .board_info = &cm_t35_isp_i2c_boardinfo[1], + .board_info = &(struct i2c_board_info){ + I2C_BOARD_INFO("mt9t001", 0x5d) + }, .i2c_adapter_id = 3, - }, - { NULL, 0, }, -}; - -static struct isp_v4l2_subdevs_group cm_t35_isp_subdevs[] = { - { - .subdevs = cm_t35_isp_primary_subdevs, - .interface = ISP_INTERFACE_PARALLEL, - .bus = { - .parallel = { - .clk_pol = 1, + .bus = &(struct isp_bus_cfg){ + .interface = ISP_INTERFACE_PARALLEL, + .bus = { + .parallel = { + .clk_pol = 1, + }, }, }, }, { - .subdevs = cm_t35_isp_secondary_subdevs, - .interface = ISP_INTERFACE_PARALLEL, - .bus = { - .parallel = { - .clk_pol = 0, + .board_info = &(struct i2c_board_info){ + I2C_BOARD_INFO("tvp5150", 0x5c), + }, + .i2c_adapter_id = 3, + .bus = &(struct isp_bus_cfg){ + .interface = ISP_INTERFACE_PARALLEL, + .bus = { + .parallel = { + .clk_pol = 0, + }, }, }, }, - { NULL, 0, }, + { 0 }, }; static struct isp_platform_data cm_t35_isp_pdata = { diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 537377b43083..1b5c6df3b645 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -447,7 +447,7 @@ static void isp_core_init(struct isp_device *isp, int idle) */ void omap3isp_configure_bridge(struct isp_device *isp, enum ccdc_input_entity input, - const struct isp_parallel_platform_data *pdata, + const struct isp_parallel_cfg *parcfg, unsigned int shift, unsigned int bridge) { u32 ispctrl_val; @@ -462,8 +462,8 @@ void omap3isp_configure_bridge(struct isp_device *isp, switch (input) { case CCDC_INPUT_PARALLEL: ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL; - ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT; - shift += pdata->data_lane_shift * 2; + ispctrl_val |= parcfg->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT; + shift += parcfg->data_lane_shift * 2; break; case CCDC_INPUT_CSI2A: @@ -1809,52 +1809,44 @@ static void isp_unregister_entities(struct isp_device *isp) } /* - * isp_register_subdev_group - Register a group of subdevices + * isp_register_subdev - Register a sub-device * @isp: OMAP3 ISP device - * @board_info: I2C subdevs board information array + * @isp_subdev: platform data related to a sub-device * - * Register all I2C subdevices in the board_info array. The array must be - * terminated by a NULL entry, and the first entry must be the sensor. + * Register an I2C sub-device which has not been registered by other + * means (such as the Device Tree). * - * Return a pointer to the sensor media entity if it has been successfully + * Return a pointer to the sub-device if it has been successfully * registered, or NULL otherwise. */ static struct v4l2_subdev * -isp_register_subdev_group(struct isp_device *isp, - struct isp_subdev_i2c_board_info *board_info) +isp_register_subdev(struct isp_device *isp, + struct isp_platform_subdev *isp_subdev) { - struct v4l2_subdev *sensor = NULL; - unsigned int first; + struct i2c_adapter *adapter; + struct v4l2_subdev *sd; - if (board_info->board_info == NULL) + if (isp_subdev->board_info == NULL) return NULL; - for (first = 1; board_info->board_info; ++board_info, first = 0) { - struct v4l2_subdev *subdev; - struct i2c_adapter *adapter; - - adapter = i2c_get_adapter(board_info->i2c_adapter_id); - if (adapter == NULL) { - dev_err(isp->dev, "%s: Unable to get I2C adapter %d for " - "device %s\n", __func__, - board_info->i2c_adapter_id, - board_info->board_info->type); - continue; - } - - subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter, - board_info->board_info, NULL); - if (subdev == NULL) { - dev_err(isp->dev, "%s: Unable to register subdev %s\n", - __func__, board_info->board_info->type); - continue; - } + adapter = i2c_get_adapter(isp_subdev->i2c_adapter_id); + if (adapter == NULL) { + dev_err(isp->dev, + "%s: Unable to get I2C adapter %d for device %s\n", + __func__, isp_subdev->i2c_adapter_id, + isp_subdev->board_info->type); + return NULL; + } - if (first) - sensor = subdev; + sd = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter, + isp_subdev->board_info, NULL); + if (sd == NULL) { + dev_err(isp->dev, "%s: Unable to register subdev %s\n", + __func__, isp_subdev->board_info->type); + return NULL; } - return sensor; + return sd; } static int isp_link_entity( @@ -1931,7 +1923,7 @@ static int isp_link_entity( static int isp_register_entities(struct isp_device *isp) { struct isp_platform_data *pdata = isp->pdata; - struct isp_v4l2_subdevs_group *subdevs; + struct isp_platform_subdev *isp_subdev; int ret; isp->media_dev.dev = isp->dev; @@ -1989,17 +1981,23 @@ static int isp_register_entities(struct isp_device *isp) goto done; /* Register external entities */ - for (subdevs = pdata ? pdata->subdevs : NULL; - subdevs && subdevs->subdevs; ++subdevs) { - struct v4l2_subdev *sensor; + for (isp_subdev = pdata ? pdata->subdevs : NULL; + isp_subdev && isp_subdev->board_info; isp_subdev++) { + struct v4l2_subdev *sd; - sensor = isp_register_subdev_group(isp, subdevs->subdevs); - if (sensor == NULL) + sd = isp_register_subdev(isp, isp_subdev); + + /* + * No bus information --- this is either a flash or a + * lens subdev. + */ + if (!sd || !isp_subdev->bus) continue; - sensor->host_priv = subdevs; + sd->host_priv = isp_subdev->bus; - ret = isp_link_entity(isp, &sensor->entity, subdevs->interface); + ret = isp_link_entity(isp, &sd->entity, + isp_subdev->bus->interface); if (ret < 0) goto done; } diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index cfdfc8714b6b..b932a6f22b52 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -229,7 +229,7 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe, void omap3isp_pipeline_cancel_stream(struct isp_pipeline *pipe); void omap3isp_configure_bridge(struct isp_device *isp, enum ccdc_input_entity input, - const struct isp_parallel_platform_data *pdata, + const struct isp_parallel_cfg *buscfg, unsigned int shift, unsigned int bridge); struct isp_device *omap3isp_get(struct isp_device *isp); diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index 6e0291bca73f..a6a61cce43dd 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -958,11 +958,11 @@ void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc, /* * ccdc_config_sync_if - Set CCDC sync interface configuration * @ccdc: Pointer to ISP CCDC device. - * @pdata: Parallel interface platform data (may be NULL) + * @parcfg: Parallel interface platform data (may be NULL) * @data_size: Data size */ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc, - struct isp_parallel_platform_data *pdata, + struct isp_parallel_cfg *parcfg, unsigned int data_size) { struct isp_device *isp = to_isp_device(ccdc); @@ -1000,19 +1000,19 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc, break; } - if (pdata && pdata->data_pol) + if (parcfg && parcfg->data_pol) syn_mode |= ISPCCDC_SYN_MODE_DATAPOL; - if (pdata && pdata->hs_pol) + if (parcfg && parcfg->hs_pol) syn_mode |= ISPCCDC_SYN_MODE_HDPOL; /* The polarity of the vertical sync signal output by the BT.656 * decoder is not documented and seems to be active low. */ - if ((pdata && pdata->vs_pol) || ccdc->bt656) + if ((parcfg && parcfg->vs_pol) || ccdc->bt656) syn_mode |= ISPCCDC_SYN_MODE_VDPOL; - if (pdata && pdata->fld_pol) + if (parcfg && parcfg->fld_pol) syn_mode |= ISPCCDC_SYN_MODE_FLDPOL; isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); @@ -1115,7 +1115,7 @@ static const u32 ccdc_sgbrg_pattern = static void ccdc_configure(struct isp_ccdc_device *ccdc) { struct isp_device *isp = to_isp_device(ccdc); - struct isp_parallel_platform_data *pdata = NULL; + struct isp_parallel_cfg *parcfg = NULL; struct v4l2_subdev *sensor; struct v4l2_mbus_framefmt *format; const struct v4l2_rect *crop; @@ -1145,7 +1145,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) if (!ret) ccdc->bt656 = cfg.type == V4L2_MBUS_BT656; - pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv) + parcfg = &((struct isp_bus_cfg *)sensor->host_priv) ->bus.parallel; } @@ -1175,10 +1175,10 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) else bridge = ISPCTRL_PAR_BRIDGE_DISABLE; - omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge); + omap3isp_configure_bridge(isp, ccdc->input, parcfg, shift, bridge); /* Configure the sync interface. */ - ccdc_config_sync_if(ccdc, pdata, depth_out); + ccdc_config_sync_if(ccdc, parcfg, depth_out); syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE); @@ -2417,11 +2417,11 @@ static int ccdc_link_validate(struct v4l2_subdev *sd, /* We've got a parallel sensor here. */ if (ccdc->input == CCDC_INPUT_PARALLEL) { - struct isp_parallel_platform_data *pdata = - &((struct isp_v4l2_subdevs_group *) + struct isp_parallel_cfg *parcfg = + &((struct isp_bus_cfg *) media_entity_to_v4l2_subdev(link->source->entity) ->host_priv)->bus.parallel; - parallel_shift = pdata->data_lane_shift * 2; + parallel_shift = parcfg->data_lane_shift * 2; } else { parallel_shift = 0; } diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index 44c20fa8501a..38e6a974c5b1 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c @@ -201,14 +201,14 @@ static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable) /* * ccp2_phyif_config - Initialize CCP2 phy interface config * @ccp2: Pointer to ISP CCP2 device - * @pdata: CCP2 platform data + * @buscfg: CCP2 platform data * * Configure the CCP2 physical interface module from platform data. * * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success. */ static int ccp2_phyif_config(struct isp_ccp2_device *ccp2, - const struct isp_ccp2_platform_data *pdata) + const struct isp_ccp2_cfg *buscfg) { struct isp_device *isp = to_isp_device(ccp2); u32 val; @@ -218,16 +218,16 @@ static int ccp2_phyif_config(struct isp_ccp2_device *ccp2, ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE; /* Data/strobe physical layer */ BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK, - pdata->phy_layer); + buscfg->phy_layer); BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK, - pdata->strobe_clk_pol); + buscfg->strobe_clk_pol); isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL); val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL); if (!(val & ISPCCP2_CTRL_MODE)) { - if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2) + if (buscfg->ccp2_mode == ISP_CCP2_MODE_CCP2) dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n"); - if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE) + if (buscfg->phy_layer == ISP_CCP2_PHY_DATA_STROBE) /* Strobe mode requires CCP2 */ return -EIO; } @@ -347,7 +347,7 @@ static void ccp2_lcx_config(struct isp_ccp2_device *ccp2, */ static int ccp2_if_configure(struct isp_ccp2_device *ccp2) { - const struct isp_v4l2_subdevs_group *pdata; + const struct isp_bus_cfg *buscfg; struct v4l2_mbus_framefmt *format; struct media_pad *pad; struct v4l2_subdev *sensor; @@ -358,20 +358,20 @@ static int ccp2_if_configure(struct isp_ccp2_device *ccp2) pad = media_entity_remote_pad(&ccp2->pads[CCP2_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); - pdata = sensor->host_priv; + buscfg = sensor->host_priv; - ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2); + ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2); if (ret < 0) return ret; - ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1); + ccp2_vp_config(ccp2, buscfg->bus.ccp2.vpclk_div + 1); v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines); format = &ccp2->formats[CCP2_PAD_SINK]; ccp2->if_cfg.data_start = lines; - ccp2->if_cfg.crc = pdata->bus.ccp2.crc; + ccp2->if_cfg.crc = buscfg->bus.ccp2.crc; ccp2->if_cfg.format = format->code; ccp2->if_cfg.data_size = format->height; diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index bbadf6653db7..45ac90a49889 100644 --- a/drivers/media/platform/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c @@ -548,7 +548,7 @@ int omap3isp_csi2_reset(struct isp_csi2_device *csi2) static int csi2_configure(struct isp_csi2_device *csi2) { - const struct isp_v4l2_subdevs_group *pdata; + const struct isp_bus_cfg *buscfg; struct isp_device *isp = csi2->isp; struct isp_csi2_timing_cfg *timing = &csi2->timing[0]; struct v4l2_subdev *sensor; @@ -565,14 +565,14 @@ static int csi2_configure(struct isp_csi2_device *csi2) pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); - pdata = sensor->host_priv; + buscfg = sensor->host_priv; csi2->frame_skip = 0; v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip); - csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div; + csi2->ctrl.vp_out_ctrl = buscfg->bus.csi2.vpclk_div; csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE; - csi2->ctrl.ecc_enable = pdata->bus.csi2.crc; + csi2->ctrl.ecc_enable = buscfg->bus.csi2.crc; timing->ionum = 1; timing->force_rx_mode = 1; diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c index e033f2237a72..4486e9f492df 100644 --- a/drivers/media/platform/omap3isp/ispcsiphy.c +++ b/drivers/media/platform/omap3isp/ispcsiphy.c @@ -168,18 +168,18 @@ static int omap3isp_csiphy_config(struct isp_csiphy *phy) { struct isp_csi2_device *csi2 = phy->csi2; struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity); - struct isp_v4l2_subdevs_group *subdevs = pipe->external->host_priv; + struct isp_bus_cfg *buscfg = pipe->external->host_priv; struct isp_csiphy_lanes_cfg *lanes; int csi2_ddrclk_khz; unsigned int used_lanes = 0; unsigned int i; u32 reg; - if (subdevs->interface == ISP_INTERFACE_CCP2B_PHY1 - || subdevs->interface == ISP_INTERFACE_CCP2B_PHY2) - lanes = &subdevs->bus.ccp2.lanecfg; + if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1 + || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2) + lanes = &buscfg->bus.ccp2.lanecfg; else - lanes = &subdevs->bus.csi2.lanecfg; + lanes = &buscfg->bus.csi2.lanecfg; /* Clock and data lanes verification */ for (i = 0; i < phy->num_data_lanes; i++) { @@ -203,8 +203,8 @@ static int omap3isp_csiphy_config(struct isp_csiphy *phy) * issue since the MPU power domain is forced on whilst the * ISP is in use. */ - csiphy_routing_cfg(phy, subdevs->interface, true, - subdevs->bus.ccp2.phy_layer); + csiphy_routing_cfg(phy, buscfg->interface, true, + buscfg->bus.ccp2.phy_layer); /* DPHY timing configuration */ /* CSI-2 is DDR and we only count used lanes. */ @@ -302,11 +302,10 @@ void omap3isp_csiphy_release(struct isp_csiphy *phy) struct isp_csi2_device *csi2 = phy->csi2; struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity); - struct isp_v4l2_subdevs_group *subdevs = - pipe->external->host_priv; + struct isp_bus_cfg *buscfg = pipe->external->host_priv; - csiphy_routing_cfg(phy, subdevs->interface, false, - subdevs->bus.ccp2.phy_layer); + csiphy_routing_cfg(phy, buscfg->interface, false, + buscfg->bus.ccp2.phy_layer); csiphy_power_autoswitch_enable(phy, false); csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF); regulator_disable(phy->vdd); diff --git a/include/media/omap3isp.h b/include/media/omap3isp.h index 398279dd1922..39e0748b0d31 100644 --- a/include/media/omap3isp.h +++ b/include/media/omap3isp.h @@ -45,7 +45,7 @@ enum { }; /** - * struct isp_parallel_platform_data - Parallel interface platform data + * struct isp_parallel_cfg - Parallel interface configuration * @data_lane_shift: Data lane shifter * ISP_LANE_SHIFT_0 - CAMEXT[13:0] -> CAM[13:0] * ISP_LANE_SHIFT_2 - CAMEXT[13:2] -> CAM[11:0] @@ -62,7 +62,7 @@ enum { * @data_pol: Data polarity * 0 - Normal, 1 - One's complement */ -struct isp_parallel_platform_data { +struct isp_parallel_cfg { unsigned int data_lane_shift:2; unsigned int clk_pol:1; unsigned int hs_pol:1; @@ -105,7 +105,7 @@ struct isp_csiphy_lanes_cfg { }; /** - * struct isp_ccp2_platform_data - CCP2 interface platform data + * struct isp_ccp2_cfg - CCP2 interface configuration * @strobe_clk_pol: Strobe/clock polarity * 0 - Non Inverted, 1 - Inverted * @crc: Enable the cyclic redundancy check @@ -117,7 +117,7 @@ struct isp_csiphy_lanes_cfg { * ISP_CCP2_PHY_DATA_STROBE - Data/strobe physical layer * @vpclk_div: Video port output clock control */ -struct isp_ccp2_platform_data { +struct isp_ccp2_cfg { unsigned int strobe_clk_pol:1; unsigned int crc:1; unsigned int ccp2_mode:1; @@ -127,31 +127,31 @@ struct isp_ccp2_platform_data { }; /** - * struct isp_csi2_platform_data - CSI2 interface platform data + * struct isp_csi2_cfg - CSI2 interface configuration * @crc: Enable the cyclic redundancy check * @vpclk_div: Video port output clock control */ -struct isp_csi2_platform_data { +struct isp_csi2_cfg { unsigned crc:1; unsigned vpclk_div:2; struct isp_csiphy_lanes_cfg lanecfg; }; -struct isp_subdev_i2c_board_info { - struct i2c_board_info *board_info; - int i2c_adapter_id; -}; - -struct isp_v4l2_subdevs_group { - struct isp_subdev_i2c_board_info *subdevs; +struct isp_bus_cfg { enum isp_interface_type interface; union { - struct isp_parallel_platform_data parallel; - struct isp_ccp2_platform_data ccp2; - struct isp_csi2_platform_data csi2; + struct isp_parallel_cfg parallel; + struct isp_ccp2_cfg ccp2; + struct isp_csi2_cfg csi2; } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */ }; +struct isp_platform_subdev { + struct i2c_board_info *board_info; + int i2c_adapter_id; + struct isp_bus_cfg *bus; +}; + struct isp_platform_xclk { const char *dev_id; const char *con_id; @@ -159,7 +159,7 @@ struct isp_platform_xclk { struct isp_platform_data { struct isp_platform_xclk xclks[2]; - struct isp_v4l2_subdevs_group *subdevs; + struct isp_platform_subdev *subdevs; void (*set_constraints)(struct isp_device *isp, bool enable); }; -- cgit v1.2.3 From 3494bb05940e4c392baeb85f77c1e7c8a78b4e1a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:31 -0300 Subject: [media] omap3isp: Rename regulators to better suit the Device Tree Rename VDD_CSIPHY1 as vdd-csiphy1 and VDD_CSIPHY2 as vdd-csiphy2. Signed-off-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1b5c6df3b645..c0453187dfcb 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2292,8 +2292,8 @@ static int isp_probe(struct platform_device *pdev) platform_set_drvdata(pdev, isp); /* Regulators */ - isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY1"); - isp->isp_csiphy2.vdd = devm_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 * -- cgit v1.2.3 From 4fcfeca833c48e8cb899ae9cff31de481ae52ca2 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:33 -0300 Subject: [media] omap3isp: Replace mmio_base_phys array with the histogram block base Only the histogram sub-block driver uses the physical address. Do not store it for other sub-blocks. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 3 ++- drivers/media/platform/omap3isp/isp.h | 6 +++--- drivers/media/platform/omap3isp/isphist.c | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index c0453187dfcb..68d7edfc6553 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2247,7 +2247,8 @@ static int isp_map_mem_resource(struct platform_device *pdev, if (IS_ERR(isp->mmio_base[res])) return PTR_ERR(isp->mmio_base[res]); - isp->mmio_base_phys[res] = mem->start; + if (res == OMAP3_ISP_IOMEM_HIST) + isp->mmio_hist_base_phys = mem->start; return 0; } diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index b932a6f22b52..9535524a21f6 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -138,8 +138,8 @@ struct isp_xclk { * @irq_num: Currently used IRQ number. * @mmio_base: Array with kernel base addresses for ioremapped ISP register * regions. - * @mmio_base_phys: Array with physical L4 bus addresses for ISP register - * regions. + * @mmio_hist_base_phys: Physical L4 bus address for ISP hist block register + * region. * @mapping: IOMMU mapping * @stat_lock: Spinlock for handling statistics * @isp_mutex: Mutex for serializing requests to ISP. @@ -175,7 +175,7 @@ struct isp_device { unsigned int irq_num; void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST]; - unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST]; + unsigned long mmio_hist_base_phys; struct dma_iommu_mapping *mapping; diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c index 738b946ddb37..7138b043a4aa 100644 --- a/drivers/media/platform/omap3isp/isphist.c +++ b/drivers/media/platform/omap3isp/isphist.c @@ -193,8 +193,7 @@ static int hist_buf_dma(struct ispstat *hist) omap3isp_flush(hist->isp); memset(&cfg, 0, sizeof(cfg)); - cfg.src_addr = hist->isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST] - + ISPHIST_DATA; + cfg.src_addr = hist->isp->mmio_hist_base_phys + ISPHIST_DATA; cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.src_maxburst = hist->buf_size / 4; -- cgit v1.2.3 From 503596a15225e00bdf24f0805567d5195f6c749f Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:34 -0300 Subject: [media] omap3isp: Move the syscon register out of the ISP register maps The syscon register isn't part of the ISP, use it through the syscom driver regmap instead. The syscom block is considered to be from 343x on ISP revision 2.0 whereas 15.0 is assumed to have 3630 syscon. Signed-off-by: Sakari Ailus Acked-by: Tony Lindgren Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-omap2/devices.c | 10 ---------- drivers/media/platform/Kconfig | 1 + drivers/media/platform/omap3isp/isp.c | 20 ++++++++++++++++---- drivers/media/platform/omap3isp/isp.h | 19 +++++++++++++++++-- drivers/media/platform/omap3isp/ispcsiphy.c | 20 +++++++++----------- 5 files changed, 43 insertions(+), 27 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 1afb50d6d636..e945957c1604 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -142,16 +142,6 @@ static struct resource omap3isp_resources[] = { .end = OMAP3630_ISP_CSI2C_REGS2_END, .flags = IORESOURCE_MEM, }, - { - .start = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE, - .end = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE + 3, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL, - .end = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL + 3, - .flags = IORESOURCE_MEM, - }, { .start = 24 + OMAP_INTC_START, .flags = IORESOURCE_IRQ, diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 2e30be55d17a..272dc8c40f57 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -90,6 +90,7 @@ config VIDEO_OMAP3 select ARM_DMA_USE_IOMMU select OMAP_IOMMU select VIDEOBUF2_DMA_CONTIG + select MFD_SYSCON ---help--- Driver for an OMAP 3 camera controller. diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 68d7edfc6553..83b4368380cf 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -94,8 +95,9 @@ static const struct isp_res_mapping isp_res_maps[] = { 1 << OMAP3_ISP_IOMEM_RESZ | 1 << OMAP3_ISP_IOMEM_SBL | 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 | - 1 << OMAP3_ISP_IOMEM_CSIPHY2 | - 1 << OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, + 1 << OMAP3_ISP_IOMEM_CSIPHY2, + .syscon_offset = 0xdc, + .phy_type = ISP_PHY_TYPE_3430, }, { .isp_rev = ISP_REVISION_15_0, @@ -112,8 +114,9 @@ static const struct isp_res_mapping isp_res_maps[] = { 1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 | 1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 | 1 << OMAP3_ISP_IOMEM_CSIPHY1 | - 1 << OMAP3_ISP_IOMEM_CSI2C_REGS2 | - 1 << OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, + 1 << OMAP3_ISP_IOMEM_CSI2C_REGS2, + .syscon_offset = 0x2f0, + .phy_type = ISP_PHY_TYPE_3630, }, }; @@ -2352,6 +2355,15 @@ static int isp_probe(struct platform_device *pdev) } } + isp->syscon = syscon_regmap_lookup_by_pdevname("syscon.0"); + if (IS_ERR(isp->syscon)) { + ret = PTR_ERR(isp->syscon); + goto error_isp; + } + + isp->syscon_offset = isp_res_maps[m].syscon_offset; + isp->phy_type = isp_res_maps[m].phy_type; + /* IOMMU */ ret = isp_attach_iommu(isp); if (ret < 0) { diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index 9535524a21f6..03d21298c1f5 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -59,8 +59,6 @@ enum isp_mem_resources { OMAP3_ISP_IOMEM_CSI2C_REGS1, OMAP3_ISP_IOMEM_CSIPHY1, OMAP3_ISP_IOMEM_CSI2C_REGS2, - OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, - OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, OMAP3_ISP_IOMEM_LAST }; @@ -93,14 +91,25 @@ enum isp_subclk_resource { /* ISP2P: OMAP 36xx */ #define ISP_REVISION_15_0 0xF0 +#define ISP_PHY_TYPE_3430 0 +#define ISP_PHY_TYPE_3630 1 + +struct regmap; + /* * struct isp_res_mapping - Map ISP io resources to ISP revision. * @isp_rev: ISP_REVISION_x_x * @map: bitmap for enum isp_mem_resources + * @syscon_offset: offset of the syscon register for 343x / 3630 + * (CONTROL_CSIRXFE / CONTROL_CAMERA_PHY_CTRL, respectively) + * from the syscon base address + * @phy_type: ISP_PHY_TYPE_{3430,3630} */ struct isp_res_mapping { u32 isp_rev; u32 map; + u32 syscon_offset; + u32 phy_type; }; /* @@ -140,6 +149,9 @@ struct isp_xclk { * regions. * @mmio_hist_base_phys: Physical L4 bus address for ISP hist block register * region. + * @syscon: Regmap for the syscon register space + * @syscon_offset: Offset of the CSIPHY control register in syscon + * @phy_type: ISP_PHY_TYPE_{3430,3630} * @mapping: IOMMU mapping * @stat_lock: Spinlock for handling statistics * @isp_mutex: Mutex for serializing requests to ISP. @@ -176,6 +188,9 @@ struct isp_device { void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST]; unsigned long mmio_hist_base_phys; + struct regmap *syscon; + u32 syscon_offset; + u32 phy_type; struct dma_iommu_mapping *mapping; diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c index 4486e9f492df..d91dde19eb14 100644 --- a/drivers/media/platform/omap3isp/ispcsiphy.c +++ b/drivers/media/platform/omap3isp/ispcsiphy.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "isp.h" @@ -26,10 +27,11 @@ static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, enum isp_interface_type iface, bool ccp2_strobe) { - u32 reg = isp_reg_readl( - phy->isp, OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0); + u32 reg; u32 shift, mode; + regmap_read(phy->isp->syscon, phy->isp->syscon_offset, ®); + switch (iface) { default: /* Should not happen in practice, but let's keep the compiler happy. */ @@ -63,8 +65,7 @@ static void csiphy_routing_cfg_3630(struct isp_csiphy *phy, reg &= ~(OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK << shift); reg |= mode << shift; - isp_reg_writel(phy->isp, reg, - OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0); + regmap_write(phy->isp->syscon, phy->isp->syscon_offset, reg); } static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on, @@ -78,16 +79,14 @@ static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on, return; if (!on) { - isp_reg_writel(phy->isp, 0, - OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0); + regmap_write(phy->isp->syscon, phy->isp->syscon_offset, 0); return; } if (ccp2_strobe) csirxfe |= OMAP343X_CONTROL_CSIRXFE_SELFORM; - isp_reg_writel(phy->isp, csirxfe, - OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0); + regmap_write(phy->isp->syscon, phy->isp->syscon_offset, csirxfe); } /* @@ -106,10 +105,9 @@ static void csiphy_routing_cfg(struct isp_csiphy *phy, enum isp_interface_type iface, bool on, bool ccp2_strobe) { - if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL] - && on) + if (phy->isp->phy_type == ISP_PHY_TYPE_3630 && on) return csiphy_routing_cfg_3630(phy, iface, ccp2_strobe); - if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE]) + if (phy->isp->phy_type == ISP_PHY_TYPE_3430) return csiphy_routing_cfg_3430(phy, iface, on, ccp2_strobe); } -- cgit v1.2.3 From 8644cdf972dd6dfebf98161025900f6a9d1ad58a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:35 -0300 Subject: [media] omap3isp: Replace many MMIO regions by two The omap3isp MMIO register block is contiguous in the MMIO register space apart from the fact that the ISP IOMMU register block is in the middle of the area. Ioremap it at two occasions, and keep the rest of the layout of the register space internal to the omap3isp driver. Signed-off-by: Sakari Ailus Acked-by: Tony Lindgren Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- arch/arm/mach-omap2/devices.c | 66 +------------------- arch/arm/mach-omap2/omap34xx.h | 36 +---------- drivers/media/platform/omap3isp/isp.c | 113 +++++++++++++++++----------------- drivers/media/platform/omap3isp/isp.h | 4 +- 4 files changed, 66 insertions(+), 153 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index e945957c1604..990338fbaa59 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -74,72 +74,12 @@ omap_postcore_initcall(omap3_l3_init); static struct resource omap3isp_resources[] = { { .start = OMAP3430_ISP_BASE, - .end = OMAP3430_ISP_END, + .end = OMAP3430_ISP_BASE + 0x12fc, .flags = IORESOURCE_MEM, }, { - .start = OMAP3430_ISP_CCP2_BASE, - .end = OMAP3430_ISP_CCP2_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_CCDC_BASE, - .end = OMAP3430_ISP_CCDC_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_HIST_BASE, - .end = OMAP3430_ISP_HIST_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_H3A_BASE, - .end = OMAP3430_ISP_H3A_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_PREV_BASE, - .end = OMAP3430_ISP_PREV_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_RESZ_BASE, - .end = OMAP3430_ISP_RESZ_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_SBL_BASE, - .end = OMAP3430_ISP_SBL_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_CSI2A_REGS1_BASE, - .end = OMAP3430_ISP_CSI2A_REGS1_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3430_ISP_CSIPHY2_BASE, - .end = OMAP3430_ISP_CSIPHY2_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3630_ISP_CSI2A_REGS2_BASE, - .end = OMAP3630_ISP_CSI2A_REGS2_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3630_ISP_CSI2C_REGS1_BASE, - .end = OMAP3630_ISP_CSI2C_REGS1_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3630_ISP_CSIPHY1_BASE, - .end = OMAP3630_ISP_CSIPHY1_END, - .flags = IORESOURCE_MEM, - }, - { - .start = OMAP3630_ISP_CSI2C_REGS2_BASE, - .end = OMAP3630_ISP_CSI2C_REGS2_END, + .start = OMAP3430_ISP_BASE2, + .end = OMAP3430_ISP_BASE2 + 0x0600, .flags = IORESOURCE_MEM, }, { diff --git a/arch/arm/mach-omap2/omap34xx.h b/arch/arm/mach-omap2/omap34xx.h index c0d1b4b1653f..ed0024dda133 100644 --- a/arch/arm/mach-omap2/omap34xx.h +++ b/arch/arm/mach-omap2/omap34xx.h @@ -46,39 +46,9 @@ #define OMAP34XX_IC_BASE 0x48200000 -#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000) -#define OMAP3430_ISP_CBUFF_BASE (OMAP3430_ISP_BASE + 0x0100) -#define OMAP3430_ISP_CCP2_BASE (OMAP3430_ISP_BASE + 0x0400) -#define OMAP3430_ISP_CCDC_BASE (OMAP3430_ISP_BASE + 0x0600) -#define OMAP3430_ISP_HIST_BASE (OMAP3430_ISP_BASE + 0x0A00) -#define OMAP3430_ISP_H3A_BASE (OMAP3430_ISP_BASE + 0x0C00) -#define OMAP3430_ISP_PREV_BASE (OMAP3430_ISP_BASE + 0x0E00) -#define OMAP3430_ISP_RESZ_BASE (OMAP3430_ISP_BASE + 0x1000) -#define OMAP3430_ISP_SBL_BASE (OMAP3430_ISP_BASE + 0x1200) -#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400) -#define OMAP3430_ISP_CSI2A_REGS1_BASE (OMAP3430_ISP_BASE + 0x1800) -#define OMAP3430_ISP_CSIPHY2_BASE (OMAP3430_ISP_BASE + 0x1970) -#define OMAP3630_ISP_CSI2A_REGS2_BASE (OMAP3430_ISP_BASE + 0x19C0) -#define OMAP3630_ISP_CSI2C_REGS1_BASE (OMAP3430_ISP_BASE + 0x1C00) -#define OMAP3630_ISP_CSIPHY1_BASE (OMAP3430_ISP_BASE + 0x1D70) -#define OMAP3630_ISP_CSI2C_REGS2_BASE (OMAP3430_ISP_BASE + 0x1DC0) - -#define OMAP3430_ISP_END (OMAP3430_ISP_BASE + 0x06F) -#define OMAP3430_ISP_CBUFF_END (OMAP3430_ISP_CBUFF_BASE + 0x077) -#define OMAP3430_ISP_CCP2_END (OMAP3430_ISP_CCP2_BASE + 0x1EF) -#define OMAP3430_ISP_CCDC_END (OMAP3430_ISP_CCDC_BASE + 0x0A7) -#define OMAP3430_ISP_HIST_END (OMAP3430_ISP_HIST_BASE + 0x047) -#define OMAP3430_ISP_H3A_END (OMAP3430_ISP_H3A_BASE + 0x05F) -#define OMAP3430_ISP_PREV_END (OMAP3430_ISP_PREV_BASE + 0x09F) -#define OMAP3430_ISP_RESZ_END (OMAP3430_ISP_RESZ_BASE + 0x0AB) -#define OMAP3430_ISP_SBL_END (OMAP3430_ISP_SBL_BASE + 0x0FB) -#define OMAP3430_ISP_MMU_END (OMAP3430_ISP_MMU_BASE + 0x06F) -#define OMAP3430_ISP_CSI2A_REGS1_END (OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F) -#define OMAP3430_ISP_CSIPHY2_END (OMAP3430_ISP_CSIPHY2_BASE + 0x00B) -#define OMAP3630_ISP_CSI2A_REGS2_END (OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F) -#define OMAP3630_ISP_CSI2C_REGS1_END (OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F) -#define OMAP3630_ISP_CSIPHY1_END (OMAP3630_ISP_CSIPHY1_BASE + 0x00B) -#define OMAP3630_ISP_CSI2C_REGS2_END (OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F) +#define OMAP3430_ISP_BASE (L4_34XX_BASE + 0xBC000) +#define OMAP3430_ISP_MMU_BASE (OMAP3430_ISP_BASE + 0x1400) +#define OMAP3430_ISP_BASE2 (OMAP3430_ISP_BASE + 0x1800) #define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000) #define OMAP34XX_USBTLL_BASE (L4_34XX_BASE + 0x62000) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 83b4368380cf..992e74c3471d 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -86,35 +86,43 @@ static void isp_restore_ctx(struct isp_device *isp); static const struct isp_res_mapping isp_res_maps[] = { { .isp_rev = ISP_REVISION_2_0, - .map = 1 << OMAP3_ISP_IOMEM_MAIN | - 1 << OMAP3_ISP_IOMEM_CCP2 | - 1 << OMAP3_ISP_IOMEM_CCDC | - 1 << OMAP3_ISP_IOMEM_HIST | - 1 << OMAP3_ISP_IOMEM_H3A | - 1 << OMAP3_ISP_IOMEM_PREV | - 1 << OMAP3_ISP_IOMEM_RESZ | - 1 << OMAP3_ISP_IOMEM_SBL | - 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 | - 1 << OMAP3_ISP_IOMEM_CSIPHY2, + .offset = { + /* first MMIO area */ + 0x0000, /* base, len 0x0070 */ + 0x0400, /* ccp2, len 0x01f0 */ + 0x0600, /* ccdc, len 0x00a8 */ + 0x0a00, /* hist, len 0x0048 */ + 0x0c00, /* h3a, len 0x0060 */ + 0x0e00, /* preview, len 0x00a0 */ + 0x1000, /* resizer, len 0x00ac */ + 0x1200, /* sbl, len 0x00fc */ + /* second MMIO area */ + 0x0000, /* csi2a, len 0x0170 */ + 0x0170, /* csiphy2, len 0x000c */ + }, .syscon_offset = 0xdc, .phy_type = ISP_PHY_TYPE_3430, }, { .isp_rev = ISP_REVISION_15_0, - .map = 1 << OMAP3_ISP_IOMEM_MAIN | - 1 << OMAP3_ISP_IOMEM_CCP2 | - 1 << OMAP3_ISP_IOMEM_CCDC | - 1 << OMAP3_ISP_IOMEM_HIST | - 1 << OMAP3_ISP_IOMEM_H3A | - 1 << OMAP3_ISP_IOMEM_PREV | - 1 << OMAP3_ISP_IOMEM_RESZ | - 1 << OMAP3_ISP_IOMEM_SBL | - 1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 | - 1 << OMAP3_ISP_IOMEM_CSIPHY2 | - 1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 | - 1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 | - 1 << OMAP3_ISP_IOMEM_CSIPHY1 | - 1 << OMAP3_ISP_IOMEM_CSI2C_REGS2, + .offset = { + /* first MMIO area */ + 0x0000, /* base, len 0x0070 */ + 0x0400, /* ccp2, len 0x01f0 */ + 0x0600, /* ccdc, len 0x00a8 */ + 0x0a00, /* hist, len 0x0048 */ + 0x0c00, /* h3a, len 0x0060 */ + 0x0e00, /* preview, len 0x00a0 */ + 0x1000, /* resizer, len 0x00ac */ + 0x1200, /* sbl, len 0x00fc */ + /* second MMIO area */ + 0x0000, /* csi2a, len 0x0170 (1st area) */ + 0x0170, /* csiphy2, len 0x000c */ + 0x01c0, /* csi2a, len 0x0040 (2nd area) */ + 0x0400, /* csi2c, len 0x0170 (1st area) */ + 0x0570, /* csiphy1, len 0x000c */ + 0x05c0, /* csi2c, len 0x0040 (2nd area) */ + }, .syscon_offset = 0x2f0, .phy_type = ISP_PHY_TYPE_3630, }, @@ -2235,27 +2243,6 @@ static int isp_remove(struct platform_device *pdev) return 0; } -static int isp_map_mem_resource(struct platform_device *pdev, - struct isp_device *isp, - enum isp_mem_resources res) -{ - struct resource *mem; - - /* request the mem region for the camera registers */ - - mem = platform_get_resource(pdev, IORESOURCE_MEM, res); - - /* map the region */ - isp->mmio_base[res] = devm_ioremap_resource(isp->dev, mem); - if (IS_ERR(isp->mmio_base[res])) - return PTR_ERR(isp->mmio_base[res]); - - if (res == OMAP3_ISP_IOMEM_HIST) - isp->mmio_hist_base_phys = mem->start; - - return 0; -} - /* * isp_probe - Probe ISP platform device * @pdev: Pointer to ISP platform device @@ -2271,6 +2258,7 @@ static int isp_probe(struct platform_device *pdev) { struct isp_platform_data *pdata = pdev->dev.platform_data; struct isp_device *isp; + struct resource *mem; int ret; int i, m; @@ -2303,10 +2291,21 @@ static int isp_probe(struct platform_device *pdev) * * The ISP clock tree is revision-dependent. We thus need to enable ICLK * manually to read the revision before calling __omap3isp_get(). + * + * Start by mapping the ISP MMIO area, which is in two pieces. + * The ISP IOMMU is in between. Map both now, and fill in the + * ISP revision specific portions a little later in the + * function. */ - ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN); - if (ret < 0) - goto error; + for (i = 0; i < 2; i++) { + unsigned int map_idx = i ? OMAP3_ISP_IOMEM_CSI2A_REGS1 : 0; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, i); + isp->mmio_base[map_idx] = + devm_ioremap_resource(isp->dev, mem); + if (IS_ERR(isp->mmio_base[map_idx])) + return PTR_ERR(isp->mmio_base[map_idx]); + } ret = isp_get_clocks(isp); if (ret < 0) @@ -2347,13 +2346,17 @@ static int isp_probe(struct platform_device *pdev) goto error_isp; } - for (i = 1; i < OMAP3_ISP_IOMEM_LAST; i++) { - if (isp_res_maps[m].map & 1 << i) { - ret = isp_map_mem_resource(pdev, isp, i); - if (ret) - goto error_isp; - } - } + for (i = 1; i < OMAP3_ISP_IOMEM_CSI2A_REGS1; i++) + isp->mmio_base[i] = + isp->mmio_base[0] + isp_res_maps[m].offset[i]; + + for (i = OMAP3_ISP_IOMEM_CSIPHY2; i < OMAP3_ISP_IOMEM_LAST; i++) + isp->mmio_base[i] = + isp->mmio_base[OMAP3_ISP_IOMEM_CSI2A_REGS1] + + isp_res_maps[m].offset[i]; + + isp->mmio_hist_base_phys = + mem->start + isp_res_maps[m].offset[OMAP3_ISP_IOMEM_HIST]; isp->syscon = syscon_regmap_lookup_by_pdevname("syscon.0"); if (IS_ERR(isp->syscon)) { diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index 03d21298c1f5..dcb7d20a2e53 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -99,7 +99,7 @@ struct regmap; /* * struct isp_res_mapping - Map ISP io resources to ISP revision. * @isp_rev: ISP_REVISION_x_x - * @map: bitmap for enum isp_mem_resources + * @offset: register offsets of various ISP sub-blocks * @syscon_offset: offset of the syscon register for 343x / 3630 * (CONTROL_CSIRXFE / CONTROL_CAMERA_PHY_CTRL, respectively) * from the syscon base address @@ -107,7 +107,7 @@ struct regmap; */ struct isp_res_mapping { u32 isp_rev; - u32 map; + u32 offset[OMAP3_ISP_IOMEM_LAST]; u32 syscon_offset; u32 phy_type; }; -- cgit v1.2.3 From da7f3843d2c797419af6befcc0fdd54f6e13b6f4 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:38 -0300 Subject: [media] omap3isp: Add support for the Device Tree Add the ISP device to omap3 DT include file and add support to the driver to use it. Also obtain information on the external entities and the ISP configuration related to them through the Device Tree in addition to the platform data. Signed-off-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 218 ++++++++++++++++++++++++++-- drivers/media/platform/omap3isp/isp.h | 11 ++ drivers/media/platform/omap3isp/ispcsiphy.c | 7 + 3 files changed, 224 insertions(+), 12 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 992e74c3471d..9ef7e035aa6c 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -64,6 +64,7 @@ #include #include +#include #include "isp.h" #include "ispreg.h" @@ -1991,6 +1992,13 @@ static int isp_register_entities(struct isp_device *isp) if (ret < 0) goto done; + /* + * Device Tree --- the external sub-devices will be registered + * later. The same goes for the sub-device node registration. + */ + if (isp->dev->of_node) + return 0; + /* Register external entities */ for (isp_subdev = pdata ? pdata->subdevs : NULL; isp_subdev && isp_subdev->board_info; isp_subdev++) { @@ -2016,8 +2024,10 @@ static int isp_register_entities(struct isp_device *isp) ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev); done: - if (ret < 0) + if (ret < 0) { isp_unregister_entities(isp); + v4l2_async_notifier_unregister(&isp->notifier); + } return ret; } @@ -2232,6 +2242,7 @@ static int isp_remove(struct platform_device *pdev) { struct isp_device *isp = platform_get_drvdata(pdev); + v4l2_async_notifier_unregister(&isp->notifier); isp_unregister_entities(isp); isp_cleanup_modules(isp); isp_xclk_cleanup(isp); @@ -2243,6 +2254,156 @@ static int isp_remove(struct platform_device *pdev) return 0; } +enum isp_of_phy { + ISP_OF_PHY_PARALLEL = 0, + ISP_OF_PHY_CSIPHY1, + ISP_OF_PHY_CSIPHY2, +}; + +static int isp_of_parse_node(struct device *dev, struct device_node *node, + struct isp_async_subdev *isd) +{ + struct isp_bus_cfg *buscfg = &isd->bus; + struct v4l2_of_endpoint vep; + unsigned int i; + + v4l2_of_parse_endpoint(node, &vep); + + dev_dbg(dev, "parsing endpoint %s, interface %u\n", node->full_name, + vep.base.port); + + switch (vep.base.port) { + case ISP_OF_PHY_PARALLEL: + buscfg->interface = ISP_INTERFACE_PARALLEL; + buscfg->bus.parallel.data_lane_shift = + vep.bus.parallel.data_shift; + buscfg->bus.parallel.clk_pol = + !!(vep.bus.parallel.flags + & V4L2_MBUS_PCLK_SAMPLE_FALLING); + buscfg->bus.parallel.hs_pol = + !!(vep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); + buscfg->bus.parallel.vs_pol = + !!(vep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); + buscfg->bus.parallel.fld_pol = + !!(vep.bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); + buscfg->bus.parallel.data_pol = + !!(vep.bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); + break; + + case ISP_OF_PHY_CSIPHY1: + case ISP_OF_PHY_CSIPHY2: + /* FIXME: always assume CSI-2 for now. */ + switch (vep.base.port) { + case ISP_OF_PHY_CSIPHY1: + buscfg->interface = ISP_INTERFACE_CSI2C_PHY1; + break; + case ISP_OF_PHY_CSIPHY2: + buscfg->interface = ISP_INTERFACE_CSI2A_PHY2; + break; + } + buscfg->bus.csi2.lanecfg.clk.pos = vep.bus.mipi_csi2.clock_lane; + buscfg->bus.csi2.lanecfg.clk.pol = + vep.bus.mipi_csi2.lane_polarities[0]; + dev_dbg(dev, "clock lane polarity %u, pos %u\n", + buscfg->bus.csi2.lanecfg.clk.pol, + buscfg->bus.csi2.lanecfg.clk.pos); + + for (i = 0; i < ISP_CSIPHY2_NUM_DATA_LANES; i++) { + buscfg->bus.csi2.lanecfg.data[i].pos = + vep.bus.mipi_csi2.data_lanes[i]; + buscfg->bus.csi2.lanecfg.data[i].pol = + vep.bus.mipi_csi2.lane_polarities[i + 1]; + dev_dbg(dev, "data lane %u polarity %u, pos %u\n", i, + buscfg->bus.csi2.lanecfg.data[i].pol, + buscfg->bus.csi2.lanecfg.data[i].pos); + } + + /* + * FIXME: now we assume the CRC is always there. + * Implement a way to obtain this information from the + * sensor. Frame descriptors, perhaps? + */ + buscfg->bus.csi2.crc = 1; + break; + + default: + dev_warn(dev, "%s: invalid interface %u\n", node->full_name, + vep.base.port); + break; + } + + return 0; +} + +static int isp_of_parse_nodes(struct device *dev, + struct v4l2_async_notifier *notifier) +{ + struct device_node *node = NULL; + + notifier->subdevs = devm_kcalloc( + dev, ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL); + if (!notifier->subdevs) + return -ENOMEM; + + while (notifier->num_subdevs < ISP_MAX_SUBDEVS && + (node = of_graph_get_next_endpoint(dev->of_node, node))) { + struct isp_async_subdev *isd; + + isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL); + if (!isd) { + of_node_put(node); + return -ENOMEM; + } + + notifier->subdevs[notifier->num_subdevs] = &isd->asd; + + if (isp_of_parse_node(dev, node, isd)) { + of_node_put(node); + return -EINVAL; + } + + isd->asd.match.of.node = of_graph_get_remote_port_parent(node); + of_node_put(node); + if (!isd->asd.match.of.node) { + dev_warn(dev, "bad remote port parent\n"); + return -EINVAL; + } + + isd->asd.match_type = V4L2_ASYNC_MATCH_OF; + notifier->num_subdevs++; + } + + return notifier->num_subdevs; +} + +static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct isp_device *isp = container_of(async, struct isp_device, + notifier); + struct isp_async_subdev *isd = + container_of(asd, struct isp_async_subdev, asd); + int ret; + + ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface); + if (ret < 0) + return ret; + + isd->sd = subdev; + isd->sd->host_priv = &isd->bus; + + return ret; +} + +static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) +{ + struct isp_device *isp = container_of(async, struct isp_device, + notifier); + + return v4l2_device_register_subdev_nodes(&isp->v4l2_dev); +} + /* * isp_probe - Probe ISP platform device * @pdev: Pointer to ISP platform device @@ -2256,7 +2417,6 @@ static int isp_remove(struct platform_device *pdev) */ static int isp_probe(struct platform_device *pdev) { - struct isp_platform_data *pdata = pdev->dev.platform_data; struct isp_device *isp; struct resource *mem; int ret; @@ -2268,13 +2428,42 @@ static int isp_probe(struct platform_device *pdev) return -ENOMEM; } + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + ret = of_property_read_u32(pdev->dev.of_node, "ti,phy-type", + &isp->phy_type); + if (ret) + return ret; + + isp->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "syscon"); + if (IS_ERR(isp->syscon)) + return PTR_ERR(isp->syscon); + + ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1, + &isp->syscon_offset); + if (ret) + return ret; + + ret = isp_of_parse_nodes(&pdev->dev, &isp->notifier); + if (ret < 0) + return ret; + ret = v4l2_async_notifier_register(&isp->v4l2_dev, + &isp->notifier); + if (ret) + return ret; + } else { + isp->pdata = pdev->dev.platform_data; + isp->syscon = syscon_regmap_lookup_by_pdevname("syscon.0"); + if (IS_ERR(isp->syscon)) + return PTR_ERR(isp->syscon); + } + isp->autoidle = autoidle; mutex_init(&isp->isp_mutex); spin_lock_init(&isp->stat_lock); isp->dev = &pdev->dev; - isp->pdata = pdata; isp->ref_count = 0; ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32)); @@ -2346,6 +2535,11 @@ static int isp_probe(struct platform_device *pdev) goto error_isp; } + if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) { + isp->syscon_offset = isp_res_maps[m].syscon_offset; + isp->phy_type = isp_res_maps[m].phy_type; + } + for (i = 1; i < OMAP3_ISP_IOMEM_CSI2A_REGS1; i++) isp->mmio_base[i] = isp->mmio_base[0] + isp_res_maps[m].offset[i]; @@ -2358,15 +2552,6 @@ static int isp_probe(struct platform_device *pdev) isp->mmio_hist_base_phys = mem->start + isp_res_maps[m].offset[OMAP3_ISP_IOMEM_HIST]; - isp->syscon = syscon_regmap_lookup_by_pdevname("syscon.0"); - if (IS_ERR(isp->syscon)) { - ret = PTR_ERR(isp->syscon); - goto error_isp; - } - - isp->syscon_offset = isp_res_maps[m].syscon_offset; - isp->phy_type = isp_res_maps[m].phy_type; - /* IOMMU */ ret = isp_attach_iommu(isp); if (ret < 0) { @@ -2394,6 +2579,9 @@ static int isp_probe(struct platform_device *pdev) if (ret < 0) goto error_iommu; + isp->notifier.bound = isp_subdev_notifier_bound; + isp->notifier.complete = isp_subdev_notifier_complete; + ret = isp_register_entities(isp); if (ret < 0) goto error_modules; @@ -2429,6 +2617,11 @@ static struct platform_device_id omap3isp_id_table[] = { }; MODULE_DEVICE_TABLE(platform, omap3isp_id_table); +static const struct of_device_id omap3isp_of_table[] = { + { .compatible = "ti,omap3-isp" }, + { }, +}; + static struct platform_driver omap3isp_driver = { .probe = isp_probe, .remove = isp_remove, @@ -2436,6 +2629,7 @@ static struct platform_driver omap3isp_driver = { .driver = { .name = "omap3isp", .pm = &omap3isp_pm_ops, + .of_match_table = omap3isp_of_table, }, }; diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index dcb7d20a2e53..431224ec09ed 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -18,6 +18,7 @@ #define OMAP3_ISP_CORE_H #include +#include #include #include #include @@ -178,6 +179,7 @@ struct isp_xclk { */ struct isp_device { struct v4l2_device v4l2_dev; + struct v4l2_async_notifier notifier; struct media_device media_dev; struct device *dev; u32 revision; @@ -224,6 +226,15 @@ struct isp_device { unsigned int sbl_resources; unsigned int subclk_resources; + +#define ISP_MAX_SUBDEVS 8 + struct v4l2_subdev *subdevs[ISP_MAX_SUBDEVS]; +}; + +struct isp_async_subdev { + struct v4l2_subdev *sd; + struct isp_bus_cfg bus; + struct v4l2_async_subdev asd; }; #define v4l2_dev_to_isp_device(dev) \ diff --git a/drivers/media/platform/omap3isp/ispcsiphy.c b/drivers/media/platform/omap3isp/ispcsiphy.c index d91dde19eb14..495447d66cfd 100644 --- a/drivers/media/platform/omap3isp/ispcsiphy.c +++ b/drivers/media/platform/omap3isp/ispcsiphy.c @@ -173,6 +173,13 @@ static int omap3isp_csiphy_config(struct isp_csiphy *phy) unsigned int i; u32 reg; + if (!buscfg) { + struct isp_async_subdev *isd = + container_of(pipe->external->asd, + struct isp_async_subdev, asd); + buscfg = &isd->bus; + } + if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1 || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2) lanes = &buscfg->bus.ccp2.lanecfg; -- cgit v1.2.3 From f95c16ea70cac9987f5cdc28b937ba83ce8f0f98 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 25 Mar 2015 19:57:39 -0300 Subject: [media] omap3isp: Deprecate platform data support Print a warning when the driver is used with platform data. Existing platform data users should move to DT now. Signed-off-by: Sakari Ailus Acked-by: Laurent Pinchart Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 9ef7e035aa6c..ff51c4f9d35e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2456,6 +2456,8 @@ static int isp_probe(struct platform_device *pdev) isp->syscon = syscon_regmap_lookup_by_pdevname("syscon.0"); if (IS_ERR(isp->syscon)) return PTR_ERR(isp->syscon); + dev_warn(&pdev->dev, + "Platform data support is deprecated! Please move to DT now!\n"); } isp->autoidle = autoidle; -- cgit v1.2.3 From befd25a2bd61f1706508280f705e18be8b283e3e Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 3 Apr 2015 14:12:58 -0300 Subject: [media] media: omap3isp: remove unused clkdev No merged platform supplies xclks via platform data. As we want to slightly change the clkdev interface, rather than fixing this unused code, remove it instead. Signed-off-by: Russell King Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 24 ------------------------ drivers/media/platform/omap3isp/isp.h | 1 - include/media/omap3isp.h | 6 ------ 3 files changed, 31 deletions(-) (limited to 'drivers/media/platform/omap3isp/isp.c') diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index ff51c4f9d35e..18d0a871747f 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -304,7 +304,6 @@ static struct clk *isp_xclk_src_get(struct of_phandle_args *clkspec, void *data) static int isp_xclk_init(struct isp_device *isp) { - struct isp_platform_data *pdata = isp->pdata; struct device_node *np = isp->dev->of_node; struct clk_init_data init; unsigned int i; @@ -335,26 +334,6 @@ static int isp_xclk_init(struct isp_device *isp) xclk->clk = clk_register(NULL, &xclk->hw); if (IS_ERR(xclk->clk)) return PTR_ERR(xclk->clk); - - /* When instantiated from DT we don't need to register clock - * aliases. - */ - if (np) - continue; - - if (!pdata || (pdata->xclks[i].con_id == NULL && - pdata->xclks[i].dev_id == NULL)) - continue; - - xclk->lookup = kzalloc(sizeof(*xclk->lookup), GFP_KERNEL); - if (xclk->lookup == NULL) - return -ENOMEM; - - xclk->lookup->con_id = pdata->xclks[i].con_id; - xclk->lookup->dev_id = pdata->xclks[i].dev_id; - xclk->lookup->clk = xclk->clk; - - clkdev_add(xclk->lookup); } if (np) @@ -376,9 +355,6 @@ static void isp_xclk_cleanup(struct isp_device *isp) if (!IS_ERR(xclk->clk)) clk_unregister(xclk->clk); - - if (xclk->lookup) - clkdev_drop(xclk->lookup); } } diff --git a/drivers/media/platform/omap3isp/isp.h b/drivers/media/platform/omap3isp/isp.h index 431224ec09ed..e579943175c4 100644 --- a/drivers/media/platform/omap3isp/isp.h +++ b/drivers/media/platform/omap3isp/isp.h @@ -132,7 +132,6 @@ enum isp_xclk_id { struct isp_xclk { struct isp_device *isp; struct clk_hw hw; - struct clk_lookup *lookup; struct clk *clk; enum isp_xclk_id id; diff --git a/include/media/omap3isp.h b/include/media/omap3isp.h index 0f0c08b48829..048f8f9117ef 100644 --- a/include/media/omap3isp.h +++ b/include/media/omap3isp.h @@ -150,13 +150,7 @@ struct isp_platform_subdev { struct isp_bus_cfg *bus; }; -struct isp_platform_xclk { - const char *dev_id; - const char *con_id; -}; - struct isp_platform_data { - struct isp_platform_xclk xclks[2]; struct isp_platform_subdev *subdevs; void (*set_constraints)(struct isp_device *isp, bool enable); }; -- cgit v1.2.3