Commit 81034663159f39d005316b5c139038459cd16721
Committed by
Mauro Carvalho Chehab
1 parent
506c629a8e
Exists in
master
and in
7 other branches
V4L/DVB (8687): soc-camera: Move .power and .reset from soc_camera host to sensor driver
Make .power and .reset callbacks per camera instead of per host, also move their invocation to camera drivers. .arch/arm/mach-pxa/include/mach/camera.h | 2 - Signed-off-by: Stefan Herbrechtsmeier <hbmeier@hni.uni-paderborn.de> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Showing 8 changed files with 71 additions and 37 deletions Side-by-side Diff
arch/arm/mach-pxa/include/mach/camera.h
drivers/media/video/mt9m001.c
... | ... | @@ -117,13 +117,33 @@ |
117 | 117 | |
118 | 118 | static int mt9m001_init(struct soc_camera_device *icd) |
119 | 119 | { |
120 | + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | |
121 | + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | |
120 | 122 | int ret; |
121 | 123 | |
122 | 124 | dev_dbg(icd->vdev->parent, "%s\n", __func__); |
123 | 125 | |
124 | - ret = reg_write(icd, MT9M001_RESET, 1); | |
125 | - if (!ret) | |
126 | - ret = reg_write(icd, MT9M001_RESET, 0); | |
126 | + if (icl->power) { | |
127 | + ret = icl->power(&mt9m001->client->dev, 1); | |
128 | + if (ret < 0) { | |
129 | + dev_err(icd->vdev->parent, | |
130 | + "Platform failed to power-on the camera.\n"); | |
131 | + return ret; | |
132 | + } | |
133 | + } | |
134 | + | |
135 | + /* The camera could have been already on, we reset it additionally */ | |
136 | + if (icl->reset) | |
137 | + ret = icl->reset(&mt9m001->client->dev); | |
138 | + else | |
139 | + ret = -ENODEV; | |
140 | + | |
141 | + if (ret < 0) { | |
142 | + /* Either no platform reset, or platform reset failed */ | |
143 | + ret = reg_write(icd, MT9M001_RESET, 1); | |
144 | + if (!ret) | |
145 | + ret = reg_write(icd, MT9M001_RESET, 0); | |
146 | + } | |
127 | 147 | /* Disable chip, synchronous option update */ |
128 | 148 | if (!ret) |
129 | 149 | ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); |
130 | 150 | |
... | ... | @@ -133,8 +153,15 @@ |
133 | 153 | |
134 | 154 | static int mt9m001_release(struct soc_camera_device *icd) |
135 | 155 | { |
156 | + struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd); | |
157 | + struct soc_camera_link *icl = mt9m001->client->dev.platform_data; | |
158 | + | |
136 | 159 | /* Disable the chip */ |
137 | 160 | reg_write(icd, MT9M001_OUTPUT_CONTROL, 0); |
161 | + | |
162 | + if (icl->power) | |
163 | + icl->power(&mt9m001->client->dev, 0); | |
164 | + | |
138 | 165 | return 0; |
139 | 166 | } |
140 | 167 |
drivers/media/video/mt9m111.c
... | ... | @@ -351,8 +351,18 @@ |
351 | 351 | static int mt9m111_enable(struct soc_camera_device *icd) |
352 | 352 | { |
353 | 353 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); |
354 | + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | |
354 | 355 | int ret; |
355 | 356 | |
357 | + if (icl->power) { | |
358 | + ret = icl->power(&mt9m111->client->dev, 1); | |
359 | + if (ret < 0) { | |
360 | + dev_err(icd->vdev->parent, | |
361 | + "Platform failed to power-on the camera.\n"); | |
362 | + return ret; | |
363 | + } | |
364 | + } | |
365 | + | |
356 | 366 | ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); |
357 | 367 | if (!ret) |
358 | 368 | mt9m111->powered = 1; |
359 | 369 | |
... | ... | @@ -362,11 +372,16 @@ |
362 | 372 | static int mt9m111_disable(struct soc_camera_device *icd) |
363 | 373 | { |
364 | 374 | struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); |
375 | + struct soc_camera_link *icl = mt9m111->client->dev.platform_data; | |
365 | 376 | int ret; |
366 | 377 | |
367 | 378 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); |
368 | 379 | if (!ret) |
369 | 380 | mt9m111->powered = 0; |
381 | + | |
382 | + if (icl->power) | |
383 | + icl->power(&mt9m111->client->dev, 0); | |
384 | + | |
370 | 385 | return ret; |
371 | 386 | } |
372 | 387 |
drivers/media/video/mt9v022.c
... | ... | @@ -134,8 +134,25 @@ |
134 | 134 | static int mt9v022_init(struct soc_camera_device *icd) |
135 | 135 | { |
136 | 136 | struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); |
137 | + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | |
137 | 138 | int ret; |
138 | 139 | |
140 | + if (icl->power) { | |
141 | + ret = icl->power(&mt9v022->client->dev, 1); | |
142 | + if (ret < 0) { | |
143 | + dev_err(icd->vdev->parent, | |
144 | + "Platform failed to power-on the camera.\n"); | |
145 | + return ret; | |
146 | + } | |
147 | + } | |
148 | + | |
149 | + /* | |
150 | + * The camera could have been already on, we hard-reset it additionally, | |
151 | + * if available. Soft reset is done in video_probe(). | |
152 | + */ | |
153 | + if (icl->reset) | |
154 | + icl->reset(&mt9v022->client->dev); | |
155 | + | |
139 | 156 | /* Almost the default mode: master, parallel, simultaneous, and an |
140 | 157 | * undocumented bit 0x200, which is present in table 7, but not in 8, |
141 | 158 | * plus snapshot mode to disable scan for now */ |
... | ... | @@ -161,7 +178,12 @@ |
161 | 178 | |
162 | 179 | static int mt9v022_release(struct soc_camera_device *icd) |
163 | 180 | { |
164 | - /* Nothing? */ | |
181 | + struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); | |
182 | + struct soc_camera_link *icl = mt9v022->client->dev.platform_data; | |
183 | + | |
184 | + if (icl->power) | |
185 | + icl->power(&mt9v022->client->dev, 0); | |
186 | + | |
165 | 187 | return 0; |
166 | 188 | } |
167 | 189 |
drivers/media/video/pxa_camera.c
... | ... | @@ -629,17 +629,6 @@ |
629 | 629 | pdata->init(pcdev->dev); |
630 | 630 | } |
631 | 631 | |
632 | - if (pdata && pdata->power) { | |
633 | - dev_dbg(pcdev->dev, "%s: Power on camera\n", __func__); | |
634 | - pdata->power(pcdev->dev, 1); | |
635 | - } | |
636 | - | |
637 | - if (pdata && pdata->reset) { | |
638 | - dev_dbg(pcdev->dev, "%s: Releasing camera reset\n", | |
639 | - __func__); | |
640 | - pdata->reset(pcdev->dev, 1); | |
641 | - } | |
642 | - | |
643 | 632 | CICR0 = 0x3FF; /* disable all interrupts */ |
644 | 633 | |
645 | 634 | if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN) |
646 | 635 | |
... | ... | @@ -660,20 +649,7 @@ |
660 | 649 | |
661 | 650 | static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) |
662 | 651 | { |
663 | - struct pxacamera_platform_data *board = pcdev->pdata; | |
664 | - | |
665 | 652 | clk_disable(pcdev->clk); |
666 | - | |
667 | - if (board && board->reset) { | |
668 | - dev_dbg(pcdev->dev, "%s: Asserting camera reset\n", | |
669 | - __func__); | |
670 | - board->reset(pcdev->dev, 0); | |
671 | - } | |
672 | - | |
673 | - if (board && board->power) { | |
674 | - dev_dbg(pcdev->dev, "%s: Power off camera\n", __func__); | |
675 | - board->power(pcdev->dev, 0); | |
676 | - } | |
677 | 653 | } |
678 | 654 | |
679 | 655 | static irqreturn_t pxa_camera_irq(int irq, void *data) |
drivers/media/video/sh_mobile_ceu_camera.c
... | ... | @@ -304,9 +304,6 @@ |
304 | 304 | "SuperH Mobile CEU driver attached to camera %d\n", |
305 | 305 | icd->devnum); |
306 | 306 | |
307 | - if (pcdev->pdata->enable_camera) | |
308 | - pcdev->pdata->enable_camera(); | |
309 | - | |
310 | 307 | ret = icd->ops->init(icd); |
311 | 308 | if (ret) |
312 | 309 | goto err; |
... | ... | @@ -333,8 +330,6 @@ |
333 | 330 | ceu_write(pcdev, CEIER, 0); |
334 | 331 | ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ |
335 | 332 | icd->ops->release(icd); |
336 | - if (pcdev->pdata->disable_camera) | |
337 | - pcdev->pdata->disable_camera(); | |
338 | 333 | |
339 | 334 | dev_info(&icd->dev, |
340 | 335 | "SuperH Mobile CEU driver detached from camera %d\n", |
include/media/sh_mobile_ceu.h
include/media/soc_camera.h
... | ... | @@ -83,6 +83,9 @@ |
83 | 83 | int bus_id; |
84 | 84 | /* GPIO number to switch between 8 and 10 bit modes */ |
85 | 85 | unsigned int gpio; |
86 | + /* Optional callbacks to power on or off and reset the sensor */ | |
87 | + int (*power)(struct device *, int); | |
88 | + int (*reset)(struct device *); | |
86 | 89 | }; |
87 | 90 | |
88 | 91 | static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev) |