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, |