H A D | mt9p031.c | 29 #include <media/mt9p031.h> 122 struct mt9p031 { struct 149 static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd) to_mt9p031() 151 return container_of(sd, struct mt9p031, subdev); to_mt9p031() 164 static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear, mt9p031_set_output_control() argument 167 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_set_output_control() 168 u16 value = (mt9p031->output_control & ~clear) | set; mt9p031_set_output_control() 175 mt9p031->output_control = value; mt9p031_set_output_control() 179 static int mt9p031_set_mode2(struct mt9p031 *mt9p031, u16 clear, u16 set) mt9p031_set_mode2() argument 181 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_set_mode2() 182 u16 value = (mt9p031->mode2 & ~clear) | set; mt9p031_set_mode2() 189 mt9p031->mode2 = value; mt9p031_set_mode2() 193 static int mt9p031_reset(struct mt9p031 *mt9p031) mt9p031_reset() argument 195 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_reset() 207 MT9P031_PIXEL_CLOCK_DIVIDE(mt9p031->clk_div)); mt9p031_reset() 211 return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN, mt9p031_reset() 215 static int mt9p031_clk_setup(struct mt9p031 *mt9p031) mt9p031_clk_setup() argument 233 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_clk_setup() 234 struct mt9p031_platform_data *pdata = mt9p031->pdata; mt9p031_clk_setup() 237 mt9p031->clk = devm_clk_get(&client->dev, NULL); mt9p031_clk_setup() 238 if (IS_ERR(mt9p031->clk)) mt9p031_clk_setup() 239 return PTR_ERR(mt9p031->clk); mt9p031_clk_setup() 241 ret = clk_set_rate(mt9p031->clk, pdata->ext_freq); mt9p031_clk_setup() 254 mt9p031->clk_div = min_t(unsigned int, div, 64); mt9p031_clk_setup() 255 mt9p031->use_pll = false; mt9p031_clk_setup() 260 mt9p031->pll.ext_clock = pdata->ext_freq; mt9p031_clk_setup() 261 mt9p031->pll.pix_clock = pdata->target_freq; mt9p031_clk_setup() 262 mt9p031->use_pll = true; mt9p031_clk_setup() 264 return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll); mt9p031_clk_setup() 267 static int mt9p031_pll_enable(struct mt9p031 *mt9p031) mt9p031_pll_enable() argument 269 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_pll_enable() 272 if (!mt9p031->use_pll) mt9p031_pll_enable() 281 (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1)); mt9p031_pll_enable() 285 ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1); mt9p031_pll_enable() 296 static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) mt9p031_pll_disable() argument 298 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_pll_disable() 300 if (!mt9p031->use_pll) mt9p031_pll_disable() 307 static int mt9p031_power_on(struct mt9p031 *mt9p031) mt9p031_power_on() argument 312 if (mt9p031->reset) { mt9p031_power_on() 313 gpiod_set_value(mt9p031->reset, 1); mt9p031_power_on() 318 ret = regulator_bulk_enable(ARRAY_SIZE(mt9p031->regulators), mt9p031_power_on() 319 mt9p031->regulators); mt9p031_power_on() 324 if (mt9p031->clk) { mt9p031_power_on() 325 ret = clk_prepare_enable(mt9p031->clk); mt9p031_power_on() 327 regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), mt9p031_power_on() 328 mt9p031->regulators); mt9p031_power_on() 334 if (mt9p031->reset) { mt9p031_power_on() 335 gpiod_set_value(mt9p031->reset, 0); mt9p031_power_on() 342 static void mt9p031_power_off(struct mt9p031 *mt9p031) mt9p031_power_off() argument 344 if (mt9p031->reset) { mt9p031_power_off() 345 gpiod_set_value(mt9p031->reset, 1); mt9p031_power_off() 349 regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), mt9p031_power_off() 350 mt9p031->regulators); mt9p031_power_off() 352 if (mt9p031->clk) mt9p031_power_off() 353 clk_disable_unprepare(mt9p031->clk); mt9p031_power_off() 356 static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on) __mt9p031_set_power() argument 358 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); __mt9p031_set_power() 362 mt9p031_power_off(mt9p031); __mt9p031_set_power() 366 ret = mt9p031_power_on(mt9p031); __mt9p031_set_power() 370 ret = mt9p031_reset(mt9p031); __mt9p031_set_power() 376 return v4l2_ctrl_handler_setup(&mt9p031->ctrls); __mt9p031_set_power() 383 static int mt9p031_set_params(struct mt9p031 *mt9p031) mt9p031_set_params() argument 385 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_set_params() 386 struct v4l2_mbus_framefmt *format = &mt9p031->format; mt9p031_set_params() 387 const struct v4l2_rect *crop = &mt9p031->crop; mt9p031_set_params() 450 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_s_stream() local 455 ret = mt9p031_set_output_control(mt9p031, mt9p031_s_stream() 460 return mt9p031_pll_disable(mt9p031); mt9p031_s_stream() 463 ret = mt9p031_set_params(mt9p031); mt9p031_s_stream() 468 ret = mt9p031_set_output_control(mt9p031, 0, mt9p031_s_stream() 473 return mt9p031_pll_enable(mt9p031); mt9p031_s_stream() 480 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_enum_mbus_code() local 485 code->code = mt9p031->format.code; mt9p031_enum_mbus_code() 493 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_enum_frame_size() local 495 if (fse->index >= 8 || fse->code != mt9p031->format.code) mt9p031_enum_frame_size() 508 __mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_pad_config *cfg, __mt9p031_get_pad_format() argument 513 return v4l2_subdev_get_try_format(&mt9p031->subdev, cfg, pad); __mt9p031_get_pad_format() 515 return &mt9p031->format; __mt9p031_get_pad_format() 522 __mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_pad_config *cfg, __mt9p031_get_pad_crop() argument 527 return v4l2_subdev_get_try_crop(&mt9p031->subdev, cfg, pad); __mt9p031_get_pad_crop() 529 return &mt9p031->crop; __mt9p031_get_pad_crop() 539 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_get_format() local 541 fmt->format = *__mt9p031_get_pad_format(mt9p031, cfg, fmt->pad, mt9p031_get_format() 550 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_set_format() local 558 __crop = __mt9p031_get_pad_crop(mt9p031, cfg, format->pad, mt9p031_set_format() 574 __format = __mt9p031_get_pad_format(mt9p031, cfg, format->pad, mt9p031_set_format() 588 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_get_selection() local 593 sel->r = *__mt9p031_get_pad_crop(mt9p031, cfg, sel->pad, sel->which); mt9p031_get_selection() 601 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_set_selection() local 628 __crop = __mt9p031_get_pad_crop(mt9p031, cfg, sel->pad, sel->which); mt9p031_set_selection() 634 __format = __mt9p031_get_pad_format(mt9p031, cfg, sel->pad, mt9p031_set_selection() 655 static int mt9p031_restore_blc(struct mt9p031 *mt9p031) mt9p031_restore_blc() argument 657 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_restore_blc() 660 if (mt9p031->blc_auto->cur.val != 0) { mt9p031_restore_blc() 661 ret = mt9p031_set_mode2(mt9p031, 0, mt9p031_restore_blc() 667 if (mt9p031->blc_offset->cur.val != 0) { mt9p031_restore_blc() 669 mt9p031->blc_offset->cur.val); mt9p031_restore_blc() 679 struct mt9p031 *mt9p031 = mt9p031_s_ctrl() local 680 container_of(ctrl->handler, struct mt9p031, ctrls); mt9p031_s_ctrl() 681 struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev); mt9p031_s_ctrl() 727 return mt9p031_set_mode2(mt9p031, mt9p031_s_ctrl() 730 return mt9p031_set_mode2(mt9p031, mt9p031_s_ctrl() 735 return mt9p031_set_mode2(mt9p031, mt9p031_s_ctrl() 738 return mt9p031_set_mode2(mt9p031, mt9p031_s_ctrl() 747 v4l2_ctrl_activate(mt9p031->blc_auto, ctrl->val == 0); mt9p031_s_ctrl() 748 v4l2_ctrl_activate(mt9p031->blc_offset, ctrl->val == 0); mt9p031_s_ctrl() 752 ret = mt9p031_restore_blc(mt9p031); mt9p031_s_ctrl() 771 ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC, mt9p031_s_ctrl() 785 ret = mt9p031_set_mode2(mt9p031, mt9p031_s_ctrl() 887 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_set_power() local 890 mutex_lock(&mt9p031->power_lock); mt9p031_set_power() 895 if (mt9p031->power_count == !on) { mt9p031_set_power() 896 ret = __mt9p031_set_power(mt9p031, !!on); mt9p031_set_power() 902 mt9p031->power_count += on ? 1 : -1; mt9p031_set_power() 903 WARN_ON(mt9p031->power_count < 0); mt9p031_set_power() 906 mutex_unlock(&mt9p031->power_lock); mt9p031_set_power() 917 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_registered() local 921 ret = mt9p031_power_on(mt9p031); mt9p031_registered() 929 mt9p031_power_off(mt9p031); mt9p031_registered() 945 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_open() local 957 if (mt9p031->model == MT9P031_MODEL_MONOCHROME) mt9p031_open() 1038 struct mt9p031 *mt9p031; mt9p031_probe() local 1053 mt9p031 = devm_kzalloc(&client->dev, sizeof(*mt9p031), GFP_KERNEL); mt9p031_probe() 1054 if (mt9p031 == NULL) mt9p031_probe() 1057 mt9p031->pdata = pdata; mt9p031_probe() 1058 mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF; mt9p031_probe() 1059 mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC; mt9p031_probe() 1060 mt9p031->model = did->driver_data; mt9p031_probe() 1062 mt9p031->regulators[0].supply = "vdd"; mt9p031_probe() 1063 mt9p031->regulators[1].supply = "vdd_io"; mt9p031_probe() 1064 mt9p031->regulators[2].supply = "vaa"; mt9p031_probe() 1066 ret = devm_regulator_bulk_get(&client->dev, 3, mt9p031->regulators); mt9p031_probe() 1072 mutex_init(&mt9p031->power_lock); mt9p031_probe() 1074 v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6); mt9p031_probe() 1076 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, mt9p031_probe() 1080 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, mt9p031_probe() 1083 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, mt9p031_probe() 1085 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, mt9p031_probe() 1087 v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, mt9p031_probe() 1090 v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops, mt9p031_probe() 1096 v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL); mt9p031_probe() 1098 mt9p031->subdev.ctrl_handler = &mt9p031->ctrls; mt9p031_probe() 1100 if (mt9p031->ctrls.error) { mt9p031_probe() 1102 __func__, mt9p031->ctrls.error); mt9p031_probe() 1103 ret = mt9p031->ctrls.error; mt9p031_probe() 1107 mt9p031->blc_auto = v4l2_ctrl_find(&mt9p031->ctrls, V4L2_CID_BLC_AUTO); mt9p031_probe() 1108 mt9p031->blc_offset = v4l2_ctrl_find(&mt9p031->ctrls, mt9p031_probe() 1111 v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops); mt9p031_probe() 1112 mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops; mt9p031_probe() 1114 mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE; mt9p031_probe() 1115 ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0); mt9p031_probe() 1119 mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; mt9p031_probe() 1121 mt9p031->crop.width = MT9P031_WINDOW_WIDTH_DEF; mt9p031_probe() 1122 mt9p031->crop.height = MT9P031_WINDOW_HEIGHT_DEF; mt9p031_probe() 1123 mt9p031->crop.left = MT9P031_COLUMN_START_DEF; mt9p031_probe() 1124 mt9p031->crop.top = MT9P031_ROW_START_DEF; mt9p031_probe() 1126 if (mt9p031->model == MT9P031_MODEL_MONOCHROME) mt9p031_probe() 1127 mt9p031->format.code = MEDIA_BUS_FMT_Y12_1X12; mt9p031_probe() 1129 mt9p031->format.code = MEDIA_BUS_FMT_SGRBG12_1X12; mt9p031_probe() 1131 mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF; mt9p031_probe() 1132 mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF; mt9p031_probe() 1133 mt9p031->format.field = V4L2_FIELD_NONE; mt9p031_probe() 1134 mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; mt9p031_probe() 1136 mt9p031->reset = devm_gpiod_get_optional(&client->dev, "reset", mt9p031_probe() 1139 ret = mt9p031_clk_setup(mt9p031); mt9p031_probe() 1143 ret = v4l2_async_register_subdev(&mt9p031->subdev); mt9p031_probe() 1147 v4l2_ctrl_handler_free(&mt9p031->ctrls); mt9p031_probe() 1148 media_entity_cleanup(&mt9p031->subdev.entity); mt9p031_probe() 1149 mutex_destroy(&mt9p031->power_lock); mt9p031_probe() 1158 struct mt9p031 *mt9p031 = to_mt9p031(subdev); mt9p031_remove() local 1160 v4l2_ctrl_handler_free(&mt9p031->ctrls); mt9p031_remove() 1163 mutex_destroy(&mt9p031->power_lock); mt9p031_remove() 1169 { "mt9p031", MT9P031_MODEL_COLOR }, 1177 { .compatible = "aptina,mt9p031", }, 1187 .name = "mt9p031",
|