diff options
| author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2013-04-04 11:54:20 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-06-21 14:46:13 -0400 |
| commit | 0ff6a6e8fb6915e68b93ff169b1eb66c0ba15d56 (patch) | |
| tree | 07f1324c9da59b4dc7b41c3c30d2af2500e6fad9 | |
| parent | d71042c1fa1c3b32bfd55151eef6b2e104301a11 (diff) | |
[media] sh-mobile-ceu-camera: move interface activation and deactivation to clock callbacks
When adding and removing a client, the sh-mobile-ceu-camera driver activates
and, respectively, deactivates its camera interface and, if necessary, the
CSI2 controller. Only handling of the CSI2 interface is client-specific and
is only needed, when a data-exchange with the client is taking place. Move
the rest to .clock_start() and .clock_stop() callbacks.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 5b7d8e1dd448..9037472e9ced 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | |||
| @@ -162,7 +162,6 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) | |||
| 162 | static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) | 162 | static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) |
| 163 | { | 163 | { |
| 164 | int i, success = 0; | 164 | int i, success = 0; |
| 165 | struct soc_camera_device *icd = pcdev->ici.icd; | ||
| 166 | 165 | ||
| 167 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ | 166 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ |
| 168 | 167 | ||
| @@ -186,7 +185,7 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) | |||
| 186 | 185 | ||
| 187 | 186 | ||
| 188 | if (2 != success) { | 187 | if (2 != success) { |
| 189 | dev_warn(icd->pdev, "soft reset time out\n"); | 188 | dev_warn(pcdev->ici.v4l2_dev.dev, "soft reset time out\n"); |
| 190 | return -EIO; | 189 | return -EIO; |
| 191 | } | 190 | } |
| 192 | 191 | ||
| @@ -543,35 +542,21 @@ static struct v4l2_subdev *find_csi2(struct sh_mobile_ceu_dev *pcdev) | |||
| 543 | return NULL; | 542 | return NULL; |
| 544 | } | 543 | } |
| 545 | 544 | ||
| 546 | /* Called with .host_lock held */ | ||
| 547 | static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | 545 | static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) |
| 548 | { | 546 | { |
| 549 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 547 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
| 550 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 548 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
| 551 | struct v4l2_subdev *csi2_sd; | 549 | struct v4l2_subdev *csi2_sd = find_csi2(pcdev); |
| 552 | int ret; | 550 | int ret; |
| 553 | 551 | ||
| 554 | dev_info(icd->parent, | ||
| 555 | "SuperH Mobile CEU driver attached to camera %d\n", | ||
| 556 | icd->devnum); | ||
| 557 | |||
| 558 | pm_runtime_get_sync(ici->v4l2_dev.dev); | ||
| 559 | |||
| 560 | pcdev->buf_total = 0; | ||
| 561 | |||
| 562 | ret = sh_mobile_ceu_soft_reset(pcdev); | ||
| 563 | |||
| 564 | csi2_sd = find_csi2(pcdev); | ||
| 565 | if (csi2_sd) { | 552 | if (csi2_sd) { |
| 566 | csi2_sd->grp_id = soc_camera_grp_id(icd); | 553 | csi2_sd->grp_id = soc_camera_grp_id(icd); |
| 567 | v4l2_set_subdev_hostdata(csi2_sd, icd); | 554 | v4l2_set_subdev_hostdata(csi2_sd, icd); |
| 568 | } | 555 | } |
| 569 | 556 | ||
| 570 | ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); | 557 | ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); |
| 571 | if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { | 558 | if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) |
| 572 | pm_runtime_put(ici->v4l2_dev.dev); | ||
| 573 | return ret; | 559 | return ret; |
| 574 | } | ||
| 575 | 560 | ||
| 576 | /* | 561 | /* |
| 577 | * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver | 562 | * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver |
| @@ -580,19 +565,48 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) | |||
| 580 | if (ret == -ENODEV && csi2_sd) | 565 | if (ret == -ENODEV && csi2_sd) |
| 581 | csi2_sd->grp_id = 0; | 566 | csi2_sd->grp_id = 0; |
| 582 | 567 | ||
| 568 | dev_info(icd->parent, | ||
| 569 | "SuperH Mobile CEU driver attached to camera %d\n", | ||
| 570 | icd->devnum); | ||
| 571 | |||
| 583 | return 0; | 572 | return 0; |
| 584 | } | 573 | } |
| 585 | 574 | ||
| 586 | /* Called with .host_lock held */ | ||
| 587 | static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | 575 | static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) |
| 588 | { | 576 | { |
| 589 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 577 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
| 590 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 578 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
| 591 | struct v4l2_subdev *csi2_sd = find_csi2(pcdev); | 579 | struct v4l2_subdev *csi2_sd = find_csi2(pcdev); |
| 592 | 580 | ||
| 581 | dev_info(icd->parent, | ||
| 582 | "SuperH Mobile CEU driver detached from camera %d\n", | ||
| 583 | icd->devnum); | ||
| 584 | |||
| 593 | v4l2_subdev_call(csi2_sd, core, s_power, 0); | 585 | v4l2_subdev_call(csi2_sd, core, s_power, 0); |
| 594 | if (csi2_sd) | 586 | if (csi2_sd) |
| 595 | csi2_sd->grp_id = 0; | 587 | csi2_sd->grp_id = 0; |
| 588 | } | ||
| 589 | |||
| 590 | /* Called with .host_lock held */ | ||
| 591 | static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) | ||
| 592 | { | ||
| 593 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
| 594 | int ret; | ||
| 595 | |||
| 596 | pm_runtime_get_sync(ici->v4l2_dev.dev); | ||
| 597 | |||
| 598 | pcdev->buf_total = 0; | ||
| 599 | |||
| 600 | ret = sh_mobile_ceu_soft_reset(pcdev); | ||
| 601 | |||
| 602 | return 0; | ||
| 603 | } | ||
| 604 | |||
| 605 | /* Called with .host_lock held */ | ||
| 606 | static void sh_mobile_ceu_clock_stop(struct soc_camera_host *ici) | ||
| 607 | { | ||
| 608 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | ||
| 609 | |||
| 596 | /* disable capture, disable interrupts */ | 610 | /* disable capture, disable interrupts */ |
| 597 | ceu_write(pcdev, CEIER, 0); | 611 | ceu_write(pcdev, CEIER, 0); |
| 598 | sh_mobile_ceu_soft_reset(pcdev); | 612 | sh_mobile_ceu_soft_reset(pcdev); |
| @@ -607,10 +621,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
| 607 | spin_unlock_irq(&pcdev->lock); | 621 | spin_unlock_irq(&pcdev->lock); |
| 608 | 622 | ||
| 609 | pm_runtime_put(ici->v4l2_dev.dev); | 623 | pm_runtime_put(ici->v4l2_dev.dev); |
| 610 | |||
| 611 | dev_info(icd->parent, | ||
| 612 | "SuperH Mobile CEU driver detached from camera %d\n", | ||
| 613 | icd->devnum); | ||
| 614 | } | 624 | } |
| 615 | 625 | ||
| 616 | /* | 626 | /* |
| @@ -2027,6 +2037,8 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
| 2027 | .owner = THIS_MODULE, | 2037 | .owner = THIS_MODULE, |
| 2028 | .add = sh_mobile_ceu_add_device, | 2038 | .add = sh_mobile_ceu_add_device, |
| 2029 | .remove = sh_mobile_ceu_remove_device, | 2039 | .remove = sh_mobile_ceu_remove_device, |
| 2040 | .clock_start = sh_mobile_ceu_clock_start, | ||
| 2041 | .clock_stop = sh_mobile_ceu_clock_stop, | ||
| 2030 | .get_formats = sh_mobile_ceu_get_formats, | 2042 | .get_formats = sh_mobile_ceu_get_formats, |
| 2031 | .put_formats = sh_mobile_ceu_put_formats, | 2043 | .put_formats = sh_mobile_ceu_put_formats, |
| 2032 | .get_crop = sh_mobile_ceu_get_crop, | 2044 | .get_crop = sh_mobile_ceu_get_crop, |
