X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=drivers%2Fmedia%2Fplatform%2Fsoc_camera%2Fsoc_camera.c;h=55370d74ff57aef45c1c2c48e79e7fd2bf73eae7;hb=676ee36be04985062522804c2de04f0764212be6;hp=cee7b56f840499440142bc598fbd588bd8469f67;hpb=10436cf8812edadcc1813dbda39a69e9965caee6;p=cascardo%2Flinux.git diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index cee7b56f8404..55370d74ff57 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -177,6 +177,30 @@ static int __soc_camera_power_off(struct soc_camera_device *icd) return 0; } +static int soc_camera_clock_start(struct soc_camera_host *ici) +{ + int ret; + + if (!ici->ops->clock_start) + return 0; + + mutex_lock(&ici->clk_lock); + ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); + + return ret; +} + +static void soc_camera_clock_stop(struct soc_camera_host *ici) +{ + if (!ici->ops->clock_stop) + return; + + mutex_lock(&ici->clk_lock); + ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); +} + const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc( struct soc_camera_device *icd, unsigned int fourcc) { @@ -584,9 +608,7 @@ static int soc_camera_add_device(struct soc_camera_device *icd) return -EBUSY; if (!icd->clk) { - mutex_lock(&ici->clk_lock); - ret = ici->ops->clock_start(ici); - mutex_unlock(&ici->clk_lock); + ret = soc_camera_clock_start(ici); if (ret < 0) return ret; } @@ -602,11 +624,8 @@ static int soc_camera_add_device(struct soc_camera_device *icd) return 0; eadd: - if (!icd->clk) { - mutex_lock(&ici->clk_lock); - ici->ops->clock_stop(ici); - mutex_unlock(&ici->clk_lock); - } + if (!icd->clk) + soc_camera_clock_stop(ici); return ret; } @@ -619,11 +638,8 @@ static void soc_camera_remove_device(struct soc_camera_device *icd) if (ici->ops->remove) ici->ops->remove(icd); - if (!icd->clk) { - mutex_lock(&ici->clk_lock); - ici->ops->clock_stop(ici); - mutex_unlock(&ici->clk_lock); - } + if (!icd->clk) + soc_camera_clock_stop(ici); ici->icd = NULL; } @@ -688,7 +704,8 @@ static int soc_camera_open(struct file *file) /* The camera could have been already on, try to reset */ if (sdesc->subdev_desc.reset) - sdesc->subdev_desc.reset(icd->pdev); + if (icd->control) + sdesc->subdev_desc.reset(icd->control); ret = soc_camera_add_device(icd); if (ret < 0) { @@ -1159,7 +1176,8 @@ static void scan_add_host(struct soc_camera_host *ici) /* The camera could have been already on, try to reset */ if (ssdd->reset) - ssdd->reset(icd->pdev); + if (icd->control) + ssdd->reset(icd->control); icd->parent = ici->v4l2_dev.dev; @@ -1178,7 +1196,6 @@ static int soc_camera_clk_enable(struct v4l2_clk *clk) { struct soc_camera_device *icd = clk->priv; struct soc_camera_host *ici; - int ret; if (!icd || !icd->parent) return -ENODEV; @@ -1192,10 +1209,7 @@ static int soc_camera_clk_enable(struct v4l2_clk *clk) * If a different client is currently being probed, the host will tell * you to go */ - mutex_lock(&ici->clk_lock); - ret = ici->ops->clock_start(ici); - mutex_unlock(&ici->clk_lock); - return ret; + return soc_camera_clock_start(ici); } static void soc_camera_clk_disable(struct v4l2_clk *clk) @@ -1208,9 +1222,7 @@ static void soc_camera_clk_disable(struct v4l2_clk *clk) ici = to_soc_camera_host(icd->parent); - mutex_lock(&ici->clk_lock); - ici->ops->clock_stop(ici); - mutex_unlock(&ici->clk_lock); + soc_camera_clock_stop(ici); module_put(ici->ops->owner); } @@ -1364,7 +1376,7 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd, snprintf(clk_name, sizeof(clk_name), "%d-%04x", shd->i2c_adapter_id, shd->board_info->addr); - icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd); if (IS_ERR(icd->clk)) { ret = PTR_ERR(icd->clk); goto eclkreg; @@ -1445,7 +1457,7 @@ static int soc_camera_async_bound(struct v4l2_async_notifier *notifier, memcpy(&sdesc->subdev_desc, ssdd, sizeof(sdesc->subdev_desc)); if (ssdd->reset) - ssdd->reset(icd->pdev); + ssdd->reset(&client->dev); } icd->control = &client->dev; @@ -1545,7 +1557,7 @@ static int scan_async_group(struct soc_camera_host *ici, snprintf(clk_name, sizeof(clk_name), "%d-%04x", sasd->asd.match.i2c.adapter_id, sasd->asd.match.i2c.address); - icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd); if (IS_ERR(icd->clk)) { ret = PTR_ERR(icd->clk); goto eclkreg; @@ -1650,7 +1662,7 @@ static int soc_of_bind(struct soc_camera_host *ici, snprintf(clk_name, sizeof(clk_name), "of-%s", of_node_full_name(remote)); - icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd); if (IS_ERR(icd->clk)) { ret = PTR_ERR(icd->clk); goto eclkreg; @@ -1659,13 +1671,15 @@ static int soc_of_bind(struct soc_camera_host *ici, ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); if (!ret) return 0; + + v4l2_clk_unregister(icd->clk); eclkreg: icd->clk = NULL; platform_device_del(sasc->pdev); eaddpdev: platform_device_put(sasc->pdev); eallocpdev: - devm_kfree(ici->v4l2_dev.dev, sasc); + devm_kfree(ici->v4l2_dev.dev, info); dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); return ret; @@ -1750,9 +1764,7 @@ static int soc_camera_probe(struct soc_camera_host *ici, ret = -EINVAL; goto eadd; } else { - mutex_lock(&ici->clk_lock); - ret = ici->ops->clock_start(ici); - mutex_unlock(&ici->clk_lock); + ret = soc_camera_clock_start(ici); if (ret < 0) goto eadd; @@ -1792,9 +1804,7 @@ efinish: module_put(control->driver->owner); enodrv: eadddev: - mutex_lock(&ici->clk_lock); - ici->ops->clock_stop(ici); - mutex_unlock(&ici->clk_lock); + soc_camera_clock_stop(ici); } eadd: if (icd->vdev) { @@ -1888,22 +1898,34 @@ static int default_enum_framesizes(struct soc_camera_device *icd, int ret; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); const struct soc_camera_format_xlate *xlate; - __u32 pixfmt = fsize->pixel_format; - struct v4l2_frmsizeenum fsize_mbus = *fsize; + struct v4l2_subdev_frame_size_enum fse = { + .index = fsize->index, + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + xlate = soc_camera_xlate_by_fourcc(icd, fsize->pixel_format); if (!xlate) return -EINVAL; - /* map xlate-code to pixel_format, sensor only handle xlate-code*/ - fsize_mbus.pixel_format = xlate->code; + fse.code = xlate->code; - ret = v4l2_subdev_call(sd, video, enum_framesizes, &fsize_mbus); + ret = v4l2_subdev_call(sd, pad, enum_frame_size, NULL, &fse); if (ret < 0) return ret; - *fsize = fsize_mbus; - fsize->pixel_format = pixfmt; - + if (fse.min_width == fse.max_width && + fse.min_height == fse.max_height) { + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.min_width; + fsize->discrete.height = fse.min_height; + return 0; + } + fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + fsize->stepwise.min_width = fse.min_width; + fsize->stepwise.max_width = fse.max_width; + fsize->stepwise.min_height = fse.min_height; + fsize->stepwise.max_height = fse.max_height; + fsize->stepwise.step_width = 1; + fsize->stepwise.step_height = 1; return 0; } @@ -1920,8 +1942,6 @@ int soc_camera_host_register(struct soc_camera_host *ici) ((!ici->ops->init_videobuf || !ici->ops->reqbufs) && !ici->ops->init_videobuf2) || - !ici->ops->clock_start || - !ici->ops->clock_stop || !ici->ops->poll || !ici->v4l2_dev.dev) return -EINVAL;