aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov9640.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-04 10:58:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-04 10:58:25 -0400
commit1046a2c428bedd64c960dcfd0c57cc69a82fea2f (patch)
treed34b83e0ac61b51305cece031f7ff49579e3fe76 /drivers/media/video/ov9640.c
parent46e85f5f1c2a1d106c1ec0fa2a06280276b8e052 (diff)
parentb3f4e1eba45eda5d1213810ef3bc53e5247df2df (diff)
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (144 commits) [media] saa7134.h: Suppress compiler warnings when CONFIG_VIDEO_SAA7134_RC is not set [media] it913x [VER 1.07] Support for single ITE 9135 devices [media] Support for Terratec G1 [media] cx25821: off by one in cx25821_vidioc_s_input() [media] media: tea5764: reconcile Kconfig symbol and macro [media] omap_vout: Add poll() support [media] omap3isp: preview: Add crop support on the sink pad [media] omap3isp: preview: Rename min/max input/output sizes defines [media] omap3isp: preview: Remove horizontal averager support [media] omap3isp: Report the ISP revision through the media controller API [media] omap3isp: ccdc: remove redundant operation [media] omap3isp: Fix memory leaks in initialization error paths [media] omap3isp: Add missing mutex_destroy() calls [media] omap3isp: Move *_init_entities() functions to the init/cleanup section [media] omap3isp: Move media_entity_cleanup() from unregister() to cleanup() [media] MFC: Change MFC firmware binary name [media] vb2: add vb2_get_unmapped_area in vb2 core [media] v4l: Add v4l2 subdev driver for S5K6AAFX sensor [media] v4l: Add AUTO option for the V4L2_CID_POWER_LINE_FREQUENCY control [media] media: ov6650: stylistic improvements ...
Diffstat (limited to 'drivers/media/video/ov9640.c')
-rw-r--r--drivers/media/video/ov9640.c186
1 files changed, 60 insertions, 126 deletions
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c
index 3681a6ff081..a4f99797eb5 100644
--- a/drivers/media/video/ov9640.c
+++ b/drivers/media/video/ov9640.c
@@ -24,10 +24,13 @@
24#include <linux/i2c.h> 24#include <linux/i2c.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/v4l2-mediabus.h>
27#include <linux/videodev2.h> 28#include <linux/videodev2.h>
29
30#include <media/soc_camera.h>
28#include <media/v4l2-chip-ident.h> 31#include <media/v4l2-chip-ident.h>
29#include <media/v4l2-common.h> 32#include <media/v4l2-common.h>
30#include <media/soc_camera.h> 33#include <media/v4l2-ctrls.h>
31 34
32#include "ov9640.h" 35#include "ov9640.h"
33 36
@@ -162,27 +165,6 @@ static enum v4l2_mbus_pixelcode ov9640_codes[] = {
162 V4L2_MBUS_FMT_RGB565_2X8_LE, 165 V4L2_MBUS_FMT_RGB565_2X8_LE,
163}; 166};
164 167
165static const struct v4l2_queryctrl ov9640_controls[] = {
166 {
167 .id = V4L2_CID_VFLIP,
168 .type = V4L2_CTRL_TYPE_BOOLEAN,
169 .name = "Flip Vertically",
170 .minimum = 0,
171 .maximum = 1,
172 .step = 1,
173 .default_value = 0,
174 },
175 {
176 .id = V4L2_CID_HFLIP,
177 .type = V4L2_CTRL_TYPE_BOOLEAN,
178 .name = "Flip Horizontally",
179 .minimum = 0,
180 .maximum = 1,
181 .step = 1,
182 .default_value = 0,
183 },
184};
185
186/* read a register */ 168/* read a register */
187static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val) 169static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val)
188{ 170{
@@ -284,75 +266,25 @@ static int ov9640_s_stream(struct v4l2_subdev *sd, int enable)
284 return 0; 266 return 0;
285} 267}
286 268
287/* Alter bus settings on camera side */
288static int ov9640_set_bus_param(struct soc_camera_device *icd,
289 unsigned long flags)
290{
291 return 0;
292}
293
294/* Request bus settings on camera side */
295static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd)
296{
297 struct soc_camera_link *icl = to_soc_camera_link(icd);
298
299 /*
300 * REVISIT: the camera probably can do 10 bit transfers, but I don't
301 * have those pins connected on my hardware.
302 */
303 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
304 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
305 SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
306
307 return soc_camera_apply_sensor_flags(icl, flags);
308}
309
310/* Get status of additional camera capabilities */
311static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
312{
313 struct ov9640_priv *priv = to_ov9640_sensor(sd);
314
315 switch (ctrl->id) {
316 case V4L2_CID_VFLIP:
317 ctrl->value = priv->flag_vflip;
318 break;
319 case V4L2_CID_HFLIP:
320 ctrl->value = priv->flag_hflip;
321 break;
322 }
323 return 0;
324}
325
326/* Set status of additional camera capabilities */ 269/* Set status of additional camera capabilities */
327static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) 270static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl)
328{ 271{
329 struct i2c_client *client = v4l2_get_subdevdata(sd); 272 struct ov9640_priv *priv = container_of(ctrl->handler, struct ov9640_priv, hdl);
330 struct ov9640_priv *priv = to_ov9640_sensor(sd); 273 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
331
332 int ret = 0;
333 274
334 switch (ctrl->id) { 275 switch (ctrl->id) {
335 case V4L2_CID_VFLIP: 276 case V4L2_CID_VFLIP:
336 priv->flag_vflip = ctrl->value; 277 if (ctrl->val)
337 if (ctrl->value) 278 return ov9640_reg_rmw(client, OV9640_MVFP,
338 ret = ov9640_reg_rmw(client, OV9640_MVFP,
339 OV9640_MVFP_V, 0); 279 OV9640_MVFP_V, 0);
340 else 280 return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_V);
341 ret = ov9640_reg_rmw(client, OV9640_MVFP,
342 0, OV9640_MVFP_V);
343 break;
344 case V4L2_CID_HFLIP: 281 case V4L2_CID_HFLIP:
345 priv->flag_hflip = ctrl->value; 282 if (ctrl->val)
346 if (ctrl->value) 283 return ov9640_reg_rmw(client, OV9640_MVFP,
347 ret = ov9640_reg_rmw(client, OV9640_MVFP,
348 OV9640_MVFP_H, 0); 284 OV9640_MVFP_H, 0);
349 else 285 return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_H);
350 ret = ov9640_reg_rmw(client, OV9640_MVFP,
351 0, OV9640_MVFP_H);
352 break;
353 } 286 }
354 287 return -EINVAL;
355 return ret;
356} 288}
357 289
358/* Get chip identification */ 290/* Get chip identification */
@@ -646,10 +578,7 @@ static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
646 return 0; 578 return 0;
647} 579}
648 580
649 581static int ov9640_video_probe(struct i2c_client *client)
650
651static int ov9640_video_probe(struct soc_camera_device *icd,
652 struct i2c_client *client)
653{ 582{
654 struct v4l2_subdev *sd = i2c_get_clientdata(client); 583 struct v4l2_subdev *sd = i2c_get_clientdata(client);
655 struct ov9640_priv *priv = to_ov9640_sensor(sd); 584 struct ov9640_priv *priv = to_ov9640_sensor(sd);
@@ -657,29 +586,19 @@ static int ov9640_video_probe(struct soc_camera_device *icd,
657 const char *devname; 586 const char *devname;
658 int ret = 0; 587 int ret = 0;
659 588
660 /* We must have a parent by now. And it cannot be a wrong one. */
661 BUG_ON(!icd->parent ||
662 to_soc_camera_host(icd->parent)->nr != icd->iface);
663
664 /* 589 /*
665 * check and show product ID and manufacturer ID 590 * check and show product ID and manufacturer ID
666 */ 591 */
667 592
668 ret = ov9640_reg_read(client, OV9640_PID, &pid); 593 ret = ov9640_reg_read(client, OV9640_PID, &pid);
594 if (!ret)
595 ret = ov9640_reg_read(client, OV9640_VER, &ver);
596 if (!ret)
597 ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
598 if (!ret)
599 ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
669 if (ret) 600 if (ret)
670 goto err; 601 return ret;
671
672 ret = ov9640_reg_read(client, OV9640_VER, &ver);
673 if (ret)
674 goto err;
675
676 ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
677 if (ret)
678 goto err;
679
680 ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
681 if (ret)
682 goto err;
683 602
684 switch (VERSION(pid, ver)) { 603 switch (VERSION(pid, ver)) {
685 case OV9640_V2: 604 case OV9640_V2:
@@ -693,27 +612,20 @@ static int ov9640_video_probe(struct soc_camera_device *icd,
693 break; 612 break;
694 default: 613 default:
695 dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); 614 dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
696 ret = -ENODEV; 615 return -ENODEV;
697 goto err;
698 } 616 }
699 617
700 dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", 618 dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
701 devname, pid, ver, midh, midl); 619 devname, pid, ver, midh, midl);
702 620
703err: 621 return v4l2_ctrl_handler_setup(&priv->hdl);
704 return ret;
705} 622}
706 623
707static struct soc_camera_ops ov9640_ops = { 624static const struct v4l2_ctrl_ops ov9640_ctrl_ops = {
708 .set_bus_param = ov9640_set_bus_param, 625 .s_ctrl = ov9640_s_ctrl,
709 .query_bus_param = ov9640_query_bus_param,
710 .controls = ov9640_controls,
711 .num_controls = ARRAY_SIZE(ov9640_controls),
712}; 626};
713 627
714static struct v4l2_subdev_core_ops ov9640_core_ops = { 628static struct v4l2_subdev_core_ops ov9640_core_ops = {
715 .g_ctrl = ov9640_g_ctrl,
716 .s_ctrl = ov9640_s_ctrl,
717 .g_chip_ident = ov9640_g_chip_ident, 629 .g_chip_ident = ov9640_g_chip_ident,
718#ifdef CONFIG_VIDEO_ADV_DEBUG 630#ifdef CONFIG_VIDEO_ADV_DEBUG
719 .g_register = ov9640_get_register, 631 .g_register = ov9640_get_register,
@@ -722,6 +634,22 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = {
722 634
723}; 635};
724 636
637/* Request bus settings on camera side */
638static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
639 struct v4l2_mbus_config *cfg)
640{
641 struct i2c_client *client = v4l2_get_subdevdata(sd);
642 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
643
644 cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
645 V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
646 V4L2_MBUS_DATA_ACTIVE_HIGH;
647 cfg->type = V4L2_MBUS_PARALLEL;
648 cfg->flags = soc_camera_apply_board_flags(icl, cfg);
649
650 return 0;
651}
652
725static struct v4l2_subdev_video_ops ov9640_video_ops = { 653static struct v4l2_subdev_video_ops ov9640_video_ops = {
726 .s_stream = ov9640_s_stream, 654 .s_stream = ov9640_s_stream,
727 .s_mbus_fmt = ov9640_s_fmt, 655 .s_mbus_fmt = ov9640_s_fmt,
@@ -729,7 +657,7 @@ static struct v4l2_subdev_video_ops ov9640_video_ops = {
729 .enum_mbus_fmt = ov9640_enum_fmt, 657 .enum_mbus_fmt = ov9640_enum_fmt,
730 .cropcap = ov9640_cropcap, 658 .cropcap = ov9640_cropcap,
731 .g_crop = ov9640_g_crop, 659 .g_crop = ov9640_g_crop,
732 660 .g_mbus_config = ov9640_g_mbus_config,
733}; 661};
734 662
735static struct v4l2_subdev_ops ov9640_subdev_ops = { 663static struct v4l2_subdev_ops ov9640_subdev_ops = {
@@ -744,16 +672,9 @@ static int ov9640_probe(struct i2c_client *client,
744 const struct i2c_device_id *did) 672 const struct i2c_device_id *did)
745{ 673{
746 struct ov9640_priv *priv; 674 struct ov9640_priv *priv;
747 struct soc_camera_device *icd = client->dev.platform_data; 675 struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
748 struct soc_camera_link *icl;
749 int ret; 676 int ret;
750 677
751 if (!icd) {
752 dev_err(&client->dev, "Missing soc-camera data!\n");
753 return -EINVAL;
754 }
755
756 icl = to_soc_camera_link(icd);
757 if (!icl) { 678 if (!icl) {
758 dev_err(&client->dev, "Missing platform_data for driver\n"); 679 dev_err(&client->dev, "Missing platform_data for driver\n");
759 return -EINVAL; 680 return -EINVAL;
@@ -768,12 +689,23 @@ static int ov9640_probe(struct i2c_client *client,
768 689
769 v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops); 690 v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
770 691
771 icd->ops = &ov9640_ops; 692 v4l2_ctrl_handler_init(&priv->hdl, 2);
693 v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
694 V4L2_CID_VFLIP, 0, 1, 1, 0);
695 v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
696 V4L2_CID_HFLIP, 0, 1, 1, 0);
697 priv->subdev.ctrl_handler = &priv->hdl;
698 if (priv->hdl.error) {
699 int err = priv->hdl.error;
700
701 kfree(priv);
702 return err;
703 }
772 704
773 ret = ov9640_video_probe(icd, client); 705 ret = ov9640_video_probe(client);
774 706
775 if (ret) { 707 if (ret) {
776 icd->ops = NULL; 708 v4l2_ctrl_handler_free(&priv->hdl);
777 kfree(priv); 709 kfree(priv);
778 } 710 }
779 711
@@ -785,6 +717,8 @@ static int ov9640_remove(struct i2c_client *client)
785 struct v4l2_subdev *sd = i2c_get_clientdata(client); 717 struct v4l2_subdev *sd = i2c_get_clientdata(client);
786 struct ov9640_priv *priv = to_ov9640_sensor(sd); 718 struct ov9640_priv *priv = to_ov9640_sensor(sd);
787 719
720 v4l2_device_unregister_subdev(&priv->subdev);
721 v4l2_ctrl_handler_free(&priv->hdl);
788 kfree(priv); 722 kfree(priv);
789 return 0; 723 return 0;
790} 724}