aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m111.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9m111.c')
-rw-r--r--drivers/media/video/mt9m111.c121
1 files changed, 88 insertions, 33 deletions
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index da0b2d553fd0..c89ea41fe259 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Driver for MT9M111 CMOS Image Sensor from Micron 2 * Driver for MT9M111/MT9M112 CMOS Image Sensor from Micron
3 * 3 *
4 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr> 4 * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
5 * 5 *
@@ -19,7 +19,7 @@
19#include <media/soc_camera.h> 19#include <media/soc_camera.h>
20 20
21/* 21/*
22 * mt9m111 i2c address is 0x5d or 0x48 (depending on SAddr pin) 22 * mt9m111 and mt9m112 i2c address is 0x5d or 0x48 (depending on SAddr pin)
23 * The platform has to define i2c_board_info and call i2c_register_board_info() 23 * The platform has to define i2c_board_info and call i2c_register_board_info()
24 */ 24 */
25 25
@@ -90,7 +90,7 @@
90#define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b 90#define MT9M111_OUTPUT_FORMAT_CTRL2_B 0x19b
91 91
92#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14) 92#define MT9M111_OPMODE_AUTOEXPO_EN (1 << 14)
93 93#define MT9M111_OPMODE_AUTOWHITEBAL_EN (1 << 1)
94 94
95#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14) 95#define MT9M111_OUTFMT_PROCESSED_BAYER (1 << 14)
96#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10) 96#define MT9M111_OUTFMT_BYPASS_IFP (1 << 10)
@@ -128,9 +128,14 @@
128 .colorspace = _colorspace } 128 .colorspace = _colorspace }
129#define RGB_FMT(_name, _depth, _fourcc) \ 129#define RGB_FMT(_name, _depth, _fourcc) \
130 COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB) 130 COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB)
131#define JPG_FMT(_name, _depth, _fourcc) \
132 COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
131 133
132static const struct soc_camera_data_format mt9m111_colour_formats[] = { 134static const struct soc_camera_data_format mt9m111_colour_formats[] = {
133 COL_FMT("YCrYCb 8 bit", 8, V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_JPEG), 135 JPG_FMT("CbYCrY 16 bit", 16, V4L2_PIX_FMT_UYVY),
136 JPG_FMT("CrYCbY 16 bit", 16, V4L2_PIX_FMT_VYUY),
137 JPG_FMT("YCbYCr 16 bit", 16, V4L2_PIX_FMT_YUYV),
138 JPG_FMT("YCrYCb 16 bit", 16, V4L2_PIX_FMT_YVYU),
134 RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565), 139 RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565),
135 RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555), 140 RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555),
136 RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16), 141 RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16),
@@ -145,7 +150,7 @@ enum mt9m111_context {
145struct mt9m111 { 150struct mt9m111 {
146 struct i2c_client *client; 151 struct i2c_client *client;
147 struct soc_camera_device icd; 152 struct soc_camera_device icd;
148 int model; /* V4L2_IDENT_MT9M111* codes from v4l2-chip-ident.h */ 153 int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
149 enum mt9m111_context context; 154 enum mt9m111_context context;
150 unsigned int left, top, width, height; 155 unsigned int left, top, width, height;
151 u32 pixfmt; 156 u32 pixfmt;
@@ -158,6 +163,7 @@ struct mt9m111 {
158 unsigned int swap_rgb_red_blue:1; 163 unsigned int swap_rgb_red_blue:1;
159 unsigned int swap_yuv_y_chromas:1; 164 unsigned int swap_yuv_y_chromas:1;
160 unsigned int swap_yuv_cb_cr:1; 165 unsigned int swap_yuv_cb_cr:1;
166 unsigned int autowhitebalance:1;
161}; 167};
162 168
163static int reg_page_map_set(struct i2c_client *client, const u16 reg) 169static int reg_page_map_set(struct i2c_client *client, const u16 reg)
@@ -410,9 +416,13 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
410 416
411static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd) 417static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
412{ 418{
413 return SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING | 419 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
420 struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
421 unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
414 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH | 422 SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
415 SOCAM_DATAWIDTH_8; 423 SOCAM_DATAWIDTH_8;
424
425 return soc_camera_apply_sensor_flags(icl, flags);
416} 426}
417 427
418static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f) 428static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
@@ -438,7 +448,24 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
438 case V4L2_PIX_FMT_RGB565: 448 case V4L2_PIX_FMT_RGB565:
439 ret = mt9m111_setfmt_rgb565(icd); 449 ret = mt9m111_setfmt_rgb565(icd);
440 break; 450 break;
451 case V4L2_PIX_FMT_UYVY:
452 mt9m111->swap_yuv_y_chromas = 0;
453 mt9m111->swap_yuv_cb_cr = 0;
454 ret = mt9m111_setfmt_yuv(icd);
455 break;
456 case V4L2_PIX_FMT_VYUY:
457 mt9m111->swap_yuv_y_chromas = 0;
458 mt9m111->swap_yuv_cb_cr = 1;
459 ret = mt9m111_setfmt_yuv(icd);
460 break;
441 case V4L2_PIX_FMT_YUYV: 461 case V4L2_PIX_FMT_YUYV:
462 mt9m111->swap_yuv_y_chromas = 1;
463 mt9m111->swap_yuv_cb_cr = 0;
464 ret = mt9m111_setfmt_yuv(icd);
465 break;
466 case V4L2_PIX_FMT_YVYU:
467 mt9m111->swap_yuv_y_chromas = 1;
468 mt9m111->swap_yuv_cb_cr = 1;
442 ret = mt9m111_setfmt_yuv(icd); 469 ret = mt9m111_setfmt_yuv(icd);
443 break; 470 break;
444 default: 471 default:
@@ -452,8 +479,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
452 return ret; 479 return ret;
453} 480}
454 481
455static int mt9m111_set_fmt_cap(struct soc_camera_device *icd, 482static int mt9m111_set_fmt(struct soc_camera_device *icd,
456 __u32 pixfmt, struct v4l2_rect *rect) 483 __u32 pixfmt, struct v4l2_rect *rect)
457{ 484{
458 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd); 485 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
459 int ret; 486 int ret;
@@ -473,13 +500,15 @@ static int mt9m111_set_fmt_cap(struct soc_camera_device *icd,
473 return ret; 500 return ret;
474} 501}
475 502
476static int mt9m111_try_fmt_cap(struct soc_camera_device *icd, 503static int mt9m111_try_fmt(struct soc_camera_device *icd,
477 struct v4l2_format *f) 504 struct v4l2_format *f)
478{ 505{
479 if (f->fmt.pix.height > MT9M111_MAX_HEIGHT) 506 struct v4l2_pix_format *pix = &f->fmt.pix;
480 f->fmt.pix.height = MT9M111_MAX_HEIGHT; 507
481 if (f->fmt.pix.width > MT9M111_MAX_WIDTH) 508 if (pix->height > MT9M111_MAX_HEIGHT)
482 f->fmt.pix.width = MT9M111_MAX_WIDTH; 509 pix->height = MT9M111_MAX_HEIGHT;
510 if (pix->width > MT9M111_MAX_WIDTH)
511 pix->width = MT9M111_MAX_WIDTH;
483 512
484 return 0; 513 return 0;
485} 514}
@@ -597,8 +626,8 @@ static struct soc_camera_ops mt9m111_ops = {
597 .release = mt9m111_release, 626 .release = mt9m111_release,
598 .start_capture = mt9m111_start_capture, 627 .start_capture = mt9m111_start_capture,
599 .stop_capture = mt9m111_stop_capture, 628 .stop_capture = mt9m111_stop_capture,
600 .set_fmt_cap = mt9m111_set_fmt_cap, 629 .set_fmt = mt9m111_set_fmt,
601 .try_fmt_cap = mt9m111_try_fmt_cap, 630 .try_fmt = mt9m111_try_fmt,
602 .query_bus_param = mt9m111_query_bus_param, 631 .query_bus_param = mt9m111_query_bus_param,
603 .set_bus_param = mt9m111_set_bus_param, 632 .set_bus_param = mt9m111_set_bus_param,
604 .controls = mt9m111_controls, 633 .controls = mt9m111_controls,
@@ -634,18 +663,15 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
634 663
635static int mt9m111_get_global_gain(struct soc_camera_device *icd) 664static int mt9m111_get_global_gain(struct soc_camera_device *icd)
636{ 665{
637 unsigned int data, gain; 666 int data;
638 667
639 data = reg_read(GLOBAL_GAIN); 668 data = reg_read(GLOBAL_GAIN);
640 if (data >= 0) 669 if (data >= 0)
641 gain = ((data & (1 << 10)) * 2) 670 return (data & 0x2f) * (1 << ((data >> 10) & 1)) *
642 | ((data & (1 << 9)) * 2) 671 (1 << ((data >> 9) & 1));
643 | (data & 0x2f); 672 return data;
644 else
645 gain = data;
646
647 return gain;
648} 673}
674
649static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain) 675static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
650{ 676{
651 u16 val; 677 u16 val;
@@ -679,6 +705,23 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
679 705
680 return ret; 706 return ret;
681} 707}
708
709static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
710{
711 struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
712 int ret;
713
714 if (on)
715 ret = reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
716 else
717 ret = reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
718
719 if (!ret)
720 mt9m111->autowhitebalance = on;
721
722 return ret;
723}
724
682static int mt9m111_get_control(struct soc_camera_device *icd, 725static int mt9m111_get_control(struct soc_camera_device *icd,
683 struct v4l2_control *ctrl) 726 struct v4l2_control *ctrl)
684{ 727{
@@ -715,6 +758,9 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
715 case V4L2_CID_EXPOSURE_AUTO: 758 case V4L2_CID_EXPOSURE_AUTO:
716 ctrl->value = mt9m111->autoexposure; 759 ctrl->value = mt9m111->autoexposure;
717 break; 760 break;
761 case V4L2_CID_AUTO_WHITE_BALANCE:
762 ctrl->value = mt9m111->autowhitebalance;
763 break;
718 } 764 }
719 return 0; 765 return 0;
720} 766}
@@ -748,6 +794,9 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
748 case V4L2_CID_EXPOSURE_AUTO: 794 case V4L2_CID_EXPOSURE_AUTO:
749 ret = mt9m111_set_autoexposure(icd, ctrl->value); 795 ret = mt9m111_set_autoexposure(icd, ctrl->value);
750 break; 796 break;
797 case V4L2_CID_AUTO_WHITE_BALANCE:
798 ret = mt9m111_set_autowhitebalance(icd, ctrl->value);
799 break;
751 default: 800 default:
752 ret = -EINVAL; 801 ret = -EINVAL;
753 } 802 }
@@ -766,6 +815,7 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
766 mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS); 815 mt9m111_set_flip(icd, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
767 mt9m111_set_global_gain(icd, icd->gain); 816 mt9m111_set_global_gain(icd, icd->gain);
768 mt9m111_set_autoexposure(icd, mt9m111->autoexposure); 817 mt9m111_set_autoexposure(icd, mt9m111->autoexposure);
818 mt9m111_set_autowhitebalance(icd, mt9m111->autowhitebalance);
769 return 0; 819 return 0;
770} 820}
771 821
@@ -798,7 +848,7 @@ static int mt9m111_init(struct soc_camera_device *icd)
798 if (!ret) 848 if (!ret)
799 ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure); 849 ret = mt9m111_set_autoexposure(icd, mt9m111->autoexposure);
800 if (ret) 850 if (ret)
801 dev_err(&icd->dev, "mt9m111 init failed: %d\n", ret); 851 dev_err(&icd->dev, "mt9m11x init failed: %d\n", ret);
802 return ret; 852 return ret;
803} 853}
804 854
@@ -808,7 +858,7 @@ static int mt9m111_release(struct soc_camera_device *icd)
808 858
809 ret = mt9m111_disable(icd); 859 ret = mt9m111_disable(icd);
810 if (ret < 0) 860 if (ret < 0)
811 dev_err(&icd->dev, "mt9m111 release failed: %d\n", ret); 861 dev_err(&icd->dev, "mt9m11x release failed: %d\n", ret);
812 862
813 return ret; 863 return ret;
814} 864}
@@ -841,25 +891,30 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
841 data = reg_read(CHIP_VERSION); 891 data = reg_read(CHIP_VERSION);
842 892
843 switch (data) { 893 switch (data) {
844 case 0x143a: 894 case 0x143a: /* MT9M111 */
845 mt9m111->model = V4L2_IDENT_MT9M111; 895 mt9m111->model = V4L2_IDENT_MT9M111;
846 icd->formats = mt9m111_colour_formats; 896 break;
847 icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats); 897 case 0x148c: /* MT9M112 */
898 mt9m111->model = V4L2_IDENT_MT9M112;
848 break; 899 break;
849 default: 900 default:
850 ret = -ENODEV; 901 ret = -ENODEV;
851 dev_err(&icd->dev, 902 dev_err(&icd->dev,
852 "No MT9M111 chip detected, register read %x\n", data); 903 "No MT9M11x chip detected, register read %x\n", data);
853 goto ei2c; 904 goto ei2c;
854 } 905 }
855 906
856 dev_info(&icd->dev, "Detected a MT9M111 chip ID 0x143a\n"); 907 icd->formats = mt9m111_colour_formats;
908 icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats);
909
910 dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
857 911
858 ret = soc_camera_video_start(icd); 912 ret = soc_camera_video_start(icd);
859 if (ret) 913 if (ret)
860 goto eisis; 914 goto eisis;
861 915
862 mt9m111->autoexposure = 1; 916 mt9m111->autoexposure = 1;
917 mt9m111->autowhitebalance = 1;
863 918
864 mt9m111->swap_rgb_even_odd = 1; 919 mt9m111->swap_rgb_even_odd = 1;
865 mt9m111->swap_rgb_red_blue = 1; 920 mt9m111->swap_rgb_red_blue = 1;
@@ -889,7 +944,7 @@ static int mt9m111_probe(struct i2c_client *client,
889 int ret; 944 int ret;
890 945
891 if (!icl) { 946 if (!icl) {
892 dev_err(&client->dev, "MT9M111 driver needs platform data\n"); 947 dev_err(&client->dev, "MT9M11x driver needs platform data\n");
893 return -EINVAL; 948 return -EINVAL;
894 } 949 }
895 950
@@ -968,6 +1023,6 @@ static void __exit mt9m111_mod_exit(void)
968module_init(mt9m111_mod_init); 1023module_init(mt9m111_mod_init);
969module_exit(mt9m111_mod_exit); 1024module_exit(mt9m111_mod_exit);
970 1025
971MODULE_DESCRIPTION("Micron MT9M111 Camera driver"); 1026MODULE_DESCRIPTION("Micron MT9M111/MT9M112 Camera driver");
972MODULE_AUTHOR("Robert Jarzmik"); 1027MODULE_AUTHOR("Robert Jarzmik");
973MODULE_LICENSE("GPL"); 1028MODULE_LICENSE("GPL");