diff options
Diffstat (limited to 'drivers/media/platform/pxa_camera.c')
-rw-r--r-- | drivers/media/platform/pxa_camera.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index c71a00736541..d85ffbfb7c1f 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -1021,7 +1021,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, * - a videobuffer is queued on the pcdev->capture list * * Please check the "DMA hot chaining timeslice issue" in - * Documentation/video4linux/pxa_camera.txt + * Documentation/media/v4l-drivers/pxa_camera.rst * * Context: should only be called within the dma irq handler */ @@ -1443,7 +1443,7 @@ static void pxac_vb2_queue(struct vb2_buffer *vb) /* * Please check the DMA prepared buffer structure in : - * Documentation/video4linux/pxa_camera.txt + * Documentation/media/v4l-drivers/pxa_camera.rst * Please check also in pxa_camera_check_link_miss() to understand why DMA chain * modification while DMA chain is running will work anyway. */ @@ -2030,6 +2030,22 @@ static int pxac_vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } +static int pxac_sensor_set_power(struct pxa_camera_dev *pcdev, int on) +{ + int ret; + + ret = sensor_call(pcdev, core, s_power, on); + if (ret == -ENOIOCTLCMD) + ret = 0; + if (ret) { + dev_warn(pcdev_to_dev(pcdev), + "Failed to put subdevice in %s mode: %d\n", + on ? "normal operation" : "power saving", ret); + } + + return ret; +} + static int pxac_fops_camera_open(struct file *filp) { struct pxa_camera_dev *pcdev = video_drvdata(filp); @@ -2040,7 +2056,10 @@ static int pxac_fops_camera_open(struct file *filp) if (ret < 0) goto out; - ret = sensor_call(pcdev, core, s_power, 1); + if (!v4l2_fh_is_singular_file(filp)) + goto out; + + ret = pxac_sensor_set_power(pcdev, 1); if (ret) v4l2_fh_release(filp); out: @@ -2052,13 +2071,17 @@ static int pxac_fops_camera_release(struct file *filp) { struct pxa_camera_dev *pcdev = video_drvdata(filp); int ret; - - ret = vb2_fop_release(filp); - if (ret < 0) - return ret; + bool fh_singular; mutex_lock(&pcdev->mlock); - ret = sensor_call(pcdev, core, s_power, 0); + + fh_singular = v4l2_fh_is_singular_file(filp); + + ret = _vb2_fop_release(filp, NULL); + + if (fh_singular) + ret = pxac_sensor_set_power(pcdev, 0); + mutex_unlock(&pcdev->mlock); return ret; @@ -2160,7 +2183,7 @@ static int pxa_camera_sensor_bound(struct v4l2_async_notifier *notifier, pix->pixelformat = pcdev->current_fmt->host_fmt->fourcc; v4l2_fill_mbus_format(mf, pix, pcdev->current_fmt->code); - err = sensor_call(pcdev, core, s_power, 1); + err = pxac_sensor_set_power(pcdev, 1); if (err) goto out; @@ -2187,7 +2210,7 @@ static int pxa_camera_sensor_bound(struct v4l2_async_notifier *notifier, } out_sensor_poweroff: - err = sensor_call(pcdev, core, s_power, 0); + err = pxac_sensor_set_power(pcdev, 0); out: mutex_unlock(&pcdev->mlock); return err; @@ -2242,11 +2265,8 @@ static int pxa_camera_suspend(struct device *dev) pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3); pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4); - if (pcdev->sensor) { - ret = sensor_call(pcdev, core, s_power, 0); - if (ret == -ENOIOCTLCMD) - ret = 0; - } + if (pcdev->sensor) + ret = pxac_sensor_set_power(pcdev, 0); return ret; } @@ -2263,9 +2283,7 @@ static int pxa_camera_resume(struct device *dev) __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4); if (pcdev->sensor) { - ret = sensor_call(pcdev, core, s_power, 1); - if (ret == -ENOIOCTLCMD) - ret = 0; + ret = pxac_sensor_set_power(pcdev, 1); } /* Restart frame capture if active buffer exists */ |