Lines Matching +full:0 +full:- +full:1152

1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2010-2011 Lund Engineering
18 #include <linux/v4l2-mediabus.h>
20 #include <media/media-entity.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-device.h>
24 #include <media/v4l2-subdev.h>
26 #include "aptina-pll.h"
31 * column 0- 15 active boundary
32 * column 16-1455 image
33 * column 1456-1471 active boundary
34 * column 1472-1599 black
36 * row 0- 51 black
37 * row 53- 59 active boundary
38 * row 60-1139 image
39 * row 1140-1147 active boundary
40 * row 1148-1151 black
44 #define MT9M032_PIXEL_ARRAY_HEIGHT 1152
46 #define MT9M032_CHIP_VERSION 0x00
47 #define MT9M032_CHIP_VERSION_VALUE 0x1402
48 #define MT9M032_ROW_START 0x01
49 #define MT9M032_ROW_START_MIN 0
50 #define MT9M032_ROW_START_MAX 1152
52 #define MT9M032_COLUMN_START 0x02
53 #define MT9M032_COLUMN_START_MIN 0
56 #define MT9M032_ROW_SIZE 0x03
58 #define MT9M032_ROW_SIZE_MAX 1152
60 #define MT9M032_COLUMN_SIZE 0x04
64 #define MT9M032_HBLANK 0x05
65 #define MT9M032_VBLANK 0x06
66 #define MT9M032_VBLANK_MAX 0x7ff
67 #define MT9M032_SHUTTER_WIDTH_HIGH 0x08
68 #define MT9M032_SHUTTER_WIDTH_LOW 0x09
72 #define MT9M032_PIX_CLK_CTRL 0x0a
73 #define MT9M032_PIX_CLK_CTRL_INV_PIXCLK 0x8000
74 #define MT9M032_RESTART 0x0b
75 #define MT9M032_RESET 0x0d
76 #define MT9M032_PLL_CONFIG1 0x11
77 #define MT9M032_PLL_CONFIG1_PREDIV_MASK 0x3f
79 #define MT9M032_READ_MODE1 0x1e
90 #define MT9M032_READ_MODE1_STROBE_START_TRIG1 (0 << 2)
94 #define MT9M032_READ_MODE1_STROBE_END_TRIG1 (0 << 0)
95 #define MT9M032_READ_MODE1_STROBE_END_EXP (1 << 0)
96 #define MT9M032_READ_MODE1_STROBE_END_SHUTTER (2 << 0)
97 #define MT9M032_READ_MODE1_STROBE_END_TRIG2 (3 << 0)
98 #define MT9M032_READ_MODE2 0x20
101 #define MT9M032_READ_MODE2_ROW_BLC 0x40
102 #define MT9M032_GAIN_GREEN1 0x2b
103 #define MT9M032_GAIN_BLUE 0x2c
104 #define MT9M032_GAIN_RED 0x2d
105 #define MT9M032_GAIN_GREEN2 0x2e
108 #define MT9M032_GAIN_ALL 0x35
109 #define MT9M032_GAIN_DIGITAL_MASK 0x7f
112 #define MT9M032_GAIN_ANALOG_MASK 0x3f
113 #define MT9M032_FORMATTER1 0x9e
116 #define MT9M032_FORMATTER2 0x9f
117 #define MT9M032_FORMATTER2_DOUT_EN 0x1000
118 #define MT9M032_FORMATTER2_PIXCLK_EN 0x2000
121 * The available MT9M032 datasheet is missing documentation for register 0x10
127 #define MT9P031_PLL_CONTROL 0x10
128 #define MT9P031_PLL_CONTROL_PWROFF 0x0050
129 #define MT9P031_PLL_CONTROL_PWRON 0x0051
130 #define MT9P031_PLL_CONTROL_USEPLL 0x0052
156 (&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev)
174 ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock); in mt9m032_row_time()
182 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_update_timing()
183 struct v4l2_rect *crop = &sensor->crop; in mt9m032_update_timing()
189 interval = &sensor->frame_interval; in mt9m032_update_timing()
191 row_time = mt9m032_row_time(sensor, crop->width); in mt9m032_update_timing()
193 vblank = div_u64(1000000000ULL * interval->numerator, in mt9m032_update_timing()
194 (u64)row_time * interval->denominator) in mt9m032_update_timing()
195 - crop->height; in mt9m032_update_timing()
199 interval->denominator = 1000; in mt9m032_update_timing()
200 interval->numerator = in mt9m032_update_timing()
201 div_u64((crop->height + MT9M032_VBLANK_MAX) * in mt9m032_update_timing()
202 (u64)row_time * interval->denominator, in mt9m032_update_timing()
204 vblank = div_u64(1000000000ULL * interval->numerator, in mt9m032_update_timing()
205 (u64)row_time * interval->denominator) in mt9m032_update_timing()
206 - crop->height; in mt9m032_update_timing()
217 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_update_geom_timing()
221 sensor->crop.width - 1); in mt9m032_update_geom_timing()
224 sensor->crop.height - 1); in mt9m032_update_geom_timing()
227 sensor->crop.left); in mt9m032_update_geom_timing()
230 sensor->crop.top); in mt9m032_update_geom_timing()
238 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in update_formatter2()
240 | 0x0070; /* parts reserved! */ in update_formatter2()
241 /* possibly for changing to 14-bit mode */ in update_formatter2()
267 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_setup_pll()
268 struct mt9m032_platform_data *pdata = sensor->pdata; in mt9m032_setup_pll()
273 pll.ext_clock = pdata->ext_clock; in mt9m032_setup_pll()
274 pll.pix_clock = pdata->pix_clock; in mt9m032_setup_pll()
276 ret = aptina_pll_calculate(&client->dev, &limits, &pll); in mt9m032_setup_pll()
277 if (ret < 0) in mt9m032_setup_pll()
280 sensor->pix_clock = pdata->pix_clock; in mt9m032_setup_pll()
284 ((pll.n - 1) & MT9M032_PLL_CONFIG1_PREDIV_MASK)); in mt9m032_setup_pll()
290 ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8000 | in mt9m032_setup_pll()
294 reg_val = (pll.p1 == 6 ? MT9M032_FORMATTER1_PLL_P1_6 : 0) in mt9m032_setup_pll()
295 | MT9M032_FORMATTER1_PARALLEL | 0x001e; /* 14-bit */ in mt9m032_setup_pll()
302 /* -----------------------------------------------------------------------------
310 if (code->index != 0) in mt9m032_enum_mbus_code()
311 return -EINVAL; in mt9m032_enum_mbus_code()
313 code->code = MEDIA_BUS_FMT_Y8_1X8; in mt9m032_enum_mbus_code()
314 return 0; in mt9m032_enum_mbus_code()
321 if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8) in mt9m032_enum_frame_size()
322 return -EINVAL; in mt9m032_enum_frame_size()
324 fse->min_width = MT9M032_COLUMN_SIZE_DEF; in mt9m032_enum_frame_size()
325 fse->max_width = MT9M032_COLUMN_SIZE_DEF; in mt9m032_enum_frame_size()
326 fse->min_height = MT9M032_ROW_SIZE_DEF; in mt9m032_enum_frame_size()
327 fse->max_height = MT9M032_ROW_SIZE_DEF; in mt9m032_enum_frame_size()
329 return 0; in mt9m032_enum_frame_size()
333 * __mt9m032_get_pad_crop() - get crop rect
347 return v4l2_subdev_get_try_crop(&sensor->subdev, sd_state, 0); in __mt9m032_get_pad_crop()
349 return &sensor->crop; in __mt9m032_get_pad_crop()
356 * __mt9m032_get_pad_format() - get format
370 return v4l2_subdev_get_try_format(&sensor->subdev, sd_state, in __mt9m032_get_pad_format()
371 0); in __mt9m032_get_pad_format()
373 return &sensor->format; in __mt9m032_get_pad_format()
385 mutex_lock(&sensor->lock); in mt9m032_get_pad_format()
386 fmt->format = *__mt9m032_get_pad_format(sensor, sd_state, fmt->which); in mt9m032_get_pad_format()
387 mutex_unlock(&sensor->lock); in mt9m032_get_pad_format()
389 return 0; in mt9m032_get_pad_format()
399 mutex_lock(&sensor->lock); in mt9m032_set_pad_format()
401 if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { in mt9m032_set_pad_format()
402 ret = -EBUSY; in mt9m032_set_pad_format()
407 fmt->format = *__mt9m032_get_pad_format(sensor, sd_state, fmt->which); in mt9m032_set_pad_format()
408 ret = 0; in mt9m032_set_pad_format()
411 mutex_unlock(&sensor->lock); in mt9m032_set_pad_format()
421 if (sel->target != V4L2_SEL_TGT_CROP) in mt9m032_get_pad_selection()
422 return -EINVAL; in mt9m032_get_pad_selection()
424 mutex_lock(&sensor->lock); in mt9m032_get_pad_selection()
425 sel->r = *__mt9m032_get_pad_crop(sensor, sd_state, sel->which); in mt9m032_get_pad_selection()
426 mutex_unlock(&sensor->lock); in mt9m032_get_pad_selection()
428 return 0; in mt9m032_get_pad_selection()
439 int ret = 0; in mt9m032_set_pad_selection()
441 if (sel->target != V4L2_SEL_TGT_CROP) in mt9m032_set_pad_selection()
442 return -EINVAL; in mt9m032_set_pad_selection()
444 mutex_lock(&sensor->lock); in mt9m032_set_pad_selection()
446 if (sensor->streaming && sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { in mt9m032_set_pad_selection()
447 ret = -EBUSY; in mt9m032_set_pad_selection()
454 rect.left = clamp(ALIGN(sel->r.left, 2), MT9M032_COLUMN_START_MIN, in mt9m032_set_pad_selection()
456 rect.top = clamp(ALIGN(sel->r.top, 2), MT9M032_ROW_START_MIN, in mt9m032_set_pad_selection()
458 rect.width = clamp_t(unsigned int, ALIGN(sel->r.width, 2), in mt9m032_set_pad_selection()
460 rect.height = clamp_t(unsigned int, ALIGN(sel->r.height, 2), in mt9m032_set_pad_selection()
464 MT9M032_PIXEL_ARRAY_WIDTH - rect.left); in mt9m032_set_pad_selection()
466 MT9M032_PIXEL_ARRAY_HEIGHT - rect.top); in mt9m032_set_pad_selection()
468 __crop = __mt9m032_get_pad_crop(sensor, sd_state, sel->which); in mt9m032_set_pad_selection()
470 if (rect.width != __crop->width || rect.height != __crop->height) { in mt9m032_set_pad_selection()
475 sel->which); in mt9m032_set_pad_selection()
476 format->width = rect.width; in mt9m032_set_pad_selection()
477 format->height = rect.height; in mt9m032_set_pad_selection()
481 sel->r = rect; in mt9m032_set_pad_selection()
483 if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) in mt9m032_set_pad_selection()
487 mutex_unlock(&sensor->lock); in mt9m032_set_pad_selection()
496 mutex_lock(&sensor->lock); in mt9m032_get_frame_interval()
497 memset(fi, 0, sizeof(*fi)); in mt9m032_get_frame_interval()
498 fi->interval = sensor->frame_interval; in mt9m032_get_frame_interval()
499 mutex_unlock(&sensor->lock); in mt9m032_get_frame_interval()
501 return 0; in mt9m032_get_frame_interval()
510 mutex_lock(&sensor->lock); in mt9m032_set_frame_interval()
512 if (sensor->streaming) { in mt9m032_set_frame_interval()
513 ret = -EBUSY; in mt9m032_set_frame_interval()
517 /* Avoid divisions by 0. */ in mt9m032_set_frame_interval()
518 if (fi->interval.denominator == 0) in mt9m032_set_frame_interval()
519 fi->interval.denominator = 1; in mt9m032_set_frame_interval()
521 ret = mt9m032_update_timing(sensor, &fi->interval); in mt9m032_set_frame_interval()
523 sensor->frame_interval = fi->interval; in mt9m032_set_frame_interval()
526 mutex_unlock(&sensor->lock); in mt9m032_set_frame_interval()
535 mutex_lock(&sensor->lock); in mt9m032_s_stream()
538 sensor->streaming = streaming; in mt9m032_s_stream()
539 mutex_unlock(&sensor->lock); in mt9m032_s_stream()
544 /* -----------------------------------------------------------------------------
553 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_g_register()
556 if (reg->reg > 0xff) in mt9m032_g_register()
557 return -EINVAL; in mt9m032_g_register()
559 val = mt9m032_read(client, reg->reg); in mt9m032_g_register()
560 if (val < 0) in mt9m032_g_register()
561 return -EIO; in mt9m032_g_register()
563 reg->size = 2; in mt9m032_g_register()
564 reg->val = val; in mt9m032_g_register()
566 return 0; in mt9m032_g_register()
573 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_s_register()
575 if (reg->reg > 0xff) in mt9m032_s_register()
576 return -EINVAL; in mt9m032_s_register()
578 return mt9m032_write(client, reg->reg, reg->val); in mt9m032_s_register()
582 /* -----------------------------------------------------------------------------
588 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in update_read_mode2()
592 | 0x0007; in update_read_mode2()
599 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_set_gain()
600 int digital_gain_val; /* in 1/8th (0..127) */ in mt9m032_set_gain()
601 int analog_mul; /* 0 or 1 */ in mt9m032_set_gain()
602 int analog_gain_val; /* in 1/16th. (0..63) */ in mt9m032_set_gain()
608 analog_mul = 0; in mt9m032_set_gain()
628 if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) { in mt9m032_try_ctrl()
630 ctrl->val &= ~1; in mt9m032_try_ctrl()
633 return 0; in mt9m032_try_ctrl()
639 container_of(ctrl->handler, struct mt9m032, ctrls); in mt9m032_set_ctrl()
640 struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); in mt9m032_set_ctrl()
643 switch (ctrl->id) { in mt9m032_set_ctrl()
645 return mt9m032_set_gain(sensor, ctrl->val); in mt9m032_set_ctrl()
648 /* case V4L2_CID_VFLIP: -- In the same cluster */ in mt9m032_set_ctrl()
649 return update_read_mode2(sensor, sensor->vflip->val, in mt9m032_set_ctrl()
650 sensor->hflip->val); in mt9m032_set_ctrl()
654 (ctrl->val >> 16) & 0xffff); in mt9m032_set_ctrl()
655 if (ret < 0) in mt9m032_set_ctrl()
659 ctrl->val & 0xffff); in mt9m032_set_ctrl()
662 return 0; in mt9m032_set_ctrl()
670 /* -------------------------------------------------------------------------- */
700 /* -----------------------------------------------------------------------------
707 struct mt9m032_platform_data *pdata = client->dev.platform_data; in mt9m032_probe()
708 struct i2c_adapter *adapter = client->adapter; in mt9m032_probe()
714 dev_err(&client->dev, "No platform data\n"); in mt9m032_probe()
715 return -EINVAL; in mt9m032_probe()
719 dev_warn(&client->dev, in mt9m032_probe()
720 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); in mt9m032_probe()
721 return -EIO; in mt9m032_probe()
724 if (!client->dev.platform_data) in mt9m032_probe()
725 return -ENODEV; in mt9m032_probe()
727 sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); in mt9m032_probe()
729 return -ENOMEM; in mt9m032_probe()
731 mutex_init(&sensor->lock); in mt9m032_probe()
733 sensor->pdata = pdata; in mt9m032_probe()
735 v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); in mt9m032_probe()
736 sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in mt9m032_probe()
740 dev_err(&client->dev, "MT9M032 not detected, wrong version " in mt9m032_probe()
741 "0x%04x\n", chip_version); in mt9m032_probe()
742 ret = -ENODEV; in mt9m032_probe()
746 dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n", in mt9m032_probe()
747 client->addr); in mt9m032_probe()
749 sensor->frame_interval.numerator = 1; in mt9m032_probe()
750 sensor->frame_interval.denominator = 30; in mt9m032_probe()
752 sensor->crop.left = MT9M032_COLUMN_START_DEF; in mt9m032_probe()
753 sensor->crop.top = MT9M032_ROW_START_DEF; in mt9m032_probe()
754 sensor->crop.width = MT9M032_COLUMN_SIZE_DEF; in mt9m032_probe()
755 sensor->crop.height = MT9M032_ROW_SIZE_DEF; in mt9m032_probe()
757 sensor->format.width = sensor->crop.width; in mt9m032_probe()
758 sensor->format.height = sensor->crop.height; in mt9m032_probe()
759 sensor->format.code = MEDIA_BUS_FMT_Y8_1X8; in mt9m032_probe()
760 sensor->format.field = V4L2_FIELD_NONE; in mt9m032_probe()
761 sensor->format.colorspace = V4L2_COLORSPACE_SRGB; in mt9m032_probe()
763 v4l2_ctrl_handler_init(&sensor->ctrls, 5); in mt9m032_probe()
765 v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, in mt9m032_probe()
766 V4L2_CID_GAIN, 0, 127, 1, 64); in mt9m032_probe()
768 sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls, in mt9m032_probe()
770 V4L2_CID_HFLIP, 0, 1, 1, 0); in mt9m032_probe()
771 sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls, in mt9m032_probe()
773 V4L2_CID_VFLIP, 0, 1, 1, 0); in mt9m032_probe()
775 v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, in mt9m032_probe()
779 v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, in mt9m032_probe()
780 V4L2_CID_PIXEL_RATE, pdata->pix_clock, in mt9m032_probe()
781 pdata->pix_clock, 1, pdata->pix_clock); in mt9m032_probe()
783 if (sensor->ctrls.error) { in mt9m032_probe()
784 ret = sensor->ctrls.error; in mt9m032_probe()
785 dev_err(&client->dev, "control initialization error %d\n", ret); in mt9m032_probe()
789 v4l2_ctrl_cluster(2, &sensor->hflip); in mt9m032_probe()
791 sensor->subdev.ctrl_handler = &sensor->ctrls; in mt9m032_probe()
792 sensor->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in mt9m032_probe()
793 sensor->pad.flags = MEDIA_PAD_FL_SOURCE; in mt9m032_probe()
794 ret = media_entity_pads_init(&sensor->subdev.entity, 1, &sensor->pad); in mt9m032_probe()
795 if (ret < 0) in mt9m032_probe()
799 if (ret < 0) in mt9m032_probe()
801 ret = mt9m032_write(client, MT9M032_RESET, 0); /* reset off */ in mt9m032_probe()
802 if (ret < 0) in mt9m032_probe()
806 if (ret < 0) in mt9m032_probe()
810 ret = v4l2_ctrl_handler_setup(&sensor->ctrls); in mt9m032_probe()
811 if (ret < 0) in mt9m032_probe()
816 if (ret < 0) in mt9m032_probe()
819 ret = mt9m032_write(client, 0x41, 0x0000); /* reserved !!! */ in mt9m032_probe()
820 if (ret < 0) in mt9m032_probe()
822 ret = mt9m032_write(client, 0x42, 0x0003); /* reserved !!! */ in mt9m032_probe()
823 if (ret < 0) in mt9m032_probe()
825 ret = mt9m032_write(client, 0x43, 0x0003); /* reserved !!! */ in mt9m032_probe()
826 if (ret < 0) in mt9m032_probe()
828 ret = mt9m032_write(client, 0x7f, 0x0000); /* reserved !!! */ in mt9m032_probe()
829 if (ret < 0) in mt9m032_probe()
831 if (sensor->pdata->invert_pixclock) { in mt9m032_probe()
834 if (ret < 0) in mt9m032_probe()
839 if (ret < 0) in mt9m032_probe()
842 ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */ in mt9m032_probe()
843 if (ret < 0) in mt9m032_probe()
847 if (ret < 0) in mt9m032_probe()
853 media_entity_cleanup(&sensor->subdev.entity); in mt9m032_probe()
855 v4l2_ctrl_handler_free(&sensor->ctrls); in mt9m032_probe()
857 mutex_destroy(&sensor->lock); in mt9m032_probe()
867 v4l2_ctrl_handler_free(&sensor->ctrls); in mt9m032_remove()
868 media_entity_cleanup(&subdev->entity); in mt9m032_remove()
869 mutex_destroy(&sensor->lock); in mt9m032_remove()
873 { MT9M032_NAME, 0 },