Lines Matching +full:clk +full:- +full:output +full:- +full:sel

1 // SPDX-License-Identifier: GPL-2.0
10 #include <linux/clk.h>
16 #include <linux/v4l2-mediabus.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ctrls.h>
22 #include <media/v4l2-subdev.h>
154 struct clk *clk; member
162 unsigned short width; /* Output window */
164 unsigned short resize; /* Sensor * 1024 / resize = Output */
416 /* Clock dividers - these are default register values, divider = register + 1 */
436 if (rj54n1->bank != reg >> 8) { in reg_read()
437 dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8); in reg_read()
441 rj54n1->bank = reg >> 8; in reg_read()
453 if (rj54n1->bank != reg >> 8) { in reg_write()
454 dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8); in reg_write()
458 rj54n1->bank = reg >> 8; in reg_write()
460 dev_dbg(&client->dev, "[0x%x] = 0x%x\n", reg & 0xff, data); in reg_write()
481 ret = reg_write(client, rv->reg, rv->val); in reg_write_multiple()
494 if (code->pad || code->index >= ARRAY_SIZE(rj54n1_colour_fmts)) in rj54n1_enum_mbus_code()
495 return -EINVAL; in rj54n1_enum_mbus_code()
497 code->code = rj54n1_colour_fmts[code->index].code; in rj54n1_enum_mbus_code()
545 struct v4l2_subdev_selection *sel) in rj54n1_set_selection() argument
549 const struct v4l2_rect *rect = &sel->r; in rj54n1_set_selection()
550 int output_w, output_h, input_w = rect->width, input_h = rect->height; in rj54n1_set_selection()
553 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || in rj54n1_set_selection()
554 sel->target != V4L2_SEL_TGT_CROP) in rj54n1_set_selection()
555 return -EINVAL; in rj54n1_set_selection()
561 output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize; in rj54n1_set_selection()
562 output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize; in rj54n1_set_selection()
564 dev_dbg(&client->dev, "Scaling for %dx%d : %u = %dx%d\n", in rj54n1_set_selection()
565 input_w, input_h, rj54n1->resize, output_w, output_h); in rj54n1_set_selection()
571 rj54n1->width = output_w; in rj54n1_set_selection()
572 rj54n1->height = output_h; in rj54n1_set_selection()
573 rj54n1->resize = ret; in rj54n1_set_selection()
574 rj54n1->rect.width = input_w; in rj54n1_set_selection()
575 rj54n1->rect.height = input_h; in rj54n1_set_selection()
582 struct v4l2_subdev_selection *sel) in rj54n1_get_selection() argument
587 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) in rj54n1_get_selection()
588 return -EINVAL; in rj54n1_get_selection()
590 switch (sel->target) { in rj54n1_get_selection()
592 sel->r.left = RJ54N1_COLUMN_SKIP; in rj54n1_get_selection()
593 sel->r.top = RJ54N1_ROW_SKIP; in rj54n1_get_selection()
594 sel->r.width = RJ54N1_MAX_WIDTH; in rj54n1_get_selection()
595 sel->r.height = RJ54N1_MAX_HEIGHT; in rj54n1_get_selection()
598 sel->r = rj54n1->rect; in rj54n1_get_selection()
601 return -EINVAL; in rj54n1_get_selection()
609 struct v4l2_mbus_framefmt *mf = &format->format; in rj54n1_get_fmt()
613 if (format->pad) in rj54n1_get_fmt()
614 return -EINVAL; in rj54n1_get_fmt()
616 mf->code = rj54n1->fmt->code; in rj54n1_get_fmt()
617 mf->colorspace = rj54n1->fmt->colorspace; in rj54n1_get_fmt()
618 mf->ycbcr_enc = V4L2_YCBCR_ENC_601; in rj54n1_get_fmt()
619 mf->xfer_func = V4L2_XFER_FUNC_SRGB; in rj54n1_get_fmt()
620 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in rj54n1_get_fmt()
621 mf->field = V4L2_FIELD_NONE; in rj54n1_get_fmt()
622 mf->width = rj54n1->width; in rj54n1_get_fmt()
623 mf->height = rj54n1->height; in rj54n1_get_fmt()
630 * the output one, updates the window sizes and returns an error or the resize
646 * and output window is larger than a half of the input one. In this in rj54n1_sensor_scale()
648 * 512x384 or the output window to equal or below 1/2 of the input. in rj54n1_sensor_scale()
658 dev_dbg(&client->dev, "Adjusted output width: in %u, out %u\n", in rj54n1_sensor_scale()
670 dev_dbg(&client->dev, "Adjusted output height: in %u, out %u\n", in rj54n1_sensor_scale()
757 if (!rj54n1->auto_wb) { in rj54n1_sensor_scale()
760 wb_right = (3 * output_w / 4 - 3) / 4; in rj54n1_sensor_scale()
762 wb_bottom = (3 * output_h / 4 - 3) / 4; in rj54n1_sensor_scale()
779 peak = 12 * RJ54N1_MAX_WIDTH * (1 << 14) * resize / rj54n1->tgclk_mhz / in rj54n1_sensor_scale()
814 dev_dbg(&client->dev, "Scaled for %dx%d : %u = %ux%u, skip %u\n", in rj54n1_sensor_scale()
827 /* Leave stand-by. Note: use this when implementing suspend / resume */ in rj54n1_set_clock()
839 rj54n1->clk_div.ratio_tg); in rj54n1_set_clock()
842 rj54n1->clk_div.ratio_t); in rj54n1_set_clock()
845 rj54n1->clk_div.ratio_r); in rj54n1_set_clock()
851 /* Disable clock output */ in rj54n1_set_clock()
858 rj54n1->clk_div.ratio_op); in rj54n1_set_clock()
861 rj54n1->clk_div.ratio_o); in rj54n1_set_clock()
889 dev_err(&client->dev, in rj54n1_set_clock()
891 return -EIO; in rj54n1_set_clock()
930 * Mirror the image back: default is upside down and left-to-right... in rj54n1_reg_init()
946 rj54n1->auto_wb = ret & 0x80; in rj54n1_reg_init()
979 struct v4l2_mbus_framefmt *mf = &format->format; in rj54n1_set_fmt()
984 input_w = rj54n1->rect.width, input_h = rj54n1->rect.height; in rj54n1_set_fmt()
985 int align = mf->code == MEDIA_BUS_FMT_SBGGR10_1X10 || in rj54n1_set_fmt()
986 mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE || in rj54n1_set_fmt()
987 mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE || in rj54n1_set_fmt()
988 mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE || in rj54n1_set_fmt()
989 mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE; in rj54n1_set_fmt()
992 if (format->pad) in rj54n1_set_fmt()
993 return -EINVAL; in rj54n1_set_fmt()
995 dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n", in rj54n1_set_fmt()
996 __func__, mf->code, mf->width, mf->height); in rj54n1_set_fmt()
998 fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts, in rj54n1_set_fmt()
1001 fmt = rj54n1->fmt; in rj54n1_set_fmt()
1002 mf->code = fmt->code; in rj54n1_set_fmt()
1005 mf->field = V4L2_FIELD_NONE; in rj54n1_set_fmt()
1006 mf->colorspace = fmt->colorspace; in rj54n1_set_fmt()
1008 v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align, in rj54n1_set_fmt()
1009 &mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0); in rj54n1_set_fmt()
1011 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in rj54n1_set_fmt()
1029 switch (mf->code) { in rj54n1_set_fmt()
1082 ret = -EINVAL; in rj54n1_set_fmt()
1088 (mf->code == MEDIA_BUS_FMT_SBGGR10_1X10) << 1, 2); in rj54n1_set_fmt()
1094 max_w = mf->width * (16 * 1024 - 1) / 1024; in rj54n1_set_fmt()
1097 max_h = mf->height * (16 * 1024 - 1) / 1024; in rj54n1_set_fmt()
1101 output_w = mf->width; in rj54n1_set_fmt()
1102 output_h = mf->height; in rj54n1_set_fmt()
1108 fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts, in rj54n1_set_fmt()
1111 rj54n1->fmt = fmt; in rj54n1_set_fmt()
1112 rj54n1->resize = ret; in rj54n1_set_fmt()
1113 rj54n1->rect.width = input_w; in rj54n1_set_fmt()
1114 rj54n1->rect.height = input_h; in rj54n1_set_fmt()
1115 rj54n1->width = output_w; in rj54n1_set_fmt()
1116 rj54n1->height = output_h; in rj54n1_set_fmt()
1118 mf->width = output_w; in rj54n1_set_fmt()
1119 mf->height = output_h; in rj54n1_set_fmt()
1120 mf->field = V4L2_FIELD_NONE; in rj54n1_set_fmt()
1121 mf->colorspace = fmt->colorspace; in rj54n1_set_fmt()
1132 if (reg->reg < 0x400 || reg->reg > 0x1fff) in rj54n1_g_register()
1134 return -EINVAL; in rj54n1_g_register()
1136 reg->size = 1; in rj54n1_g_register()
1137 reg->val = reg_read(client, reg->reg); in rj54n1_g_register()
1139 if (reg->val > 0xff) in rj54n1_g_register()
1140 return -EIO; in rj54n1_g_register()
1150 if (reg->reg < 0x400 || reg->reg > 0x1fff) in rj54n1_s_register()
1152 return -EINVAL; in rj54n1_s_register()
1154 if (reg_write(client, reg->reg, reg->val) < 0) in rj54n1_s_register()
1155 return -EIO; in rj54n1_s_register()
1167 if (rj54n1->pwup_gpio) in rj54n1_s_power()
1168 gpiod_set_value(rj54n1->pwup_gpio, 1); in rj54n1_s_power()
1169 if (rj54n1->enable_gpio) in rj54n1_s_power()
1170 gpiod_set_value(rj54n1->enable_gpio, 1); in rj54n1_s_power()
1174 return clk_prepare_enable(rj54n1->clk); in rj54n1_s_power()
1177 clk_disable_unprepare(rj54n1->clk); in rj54n1_s_power()
1179 if (rj54n1->enable_gpio) in rj54n1_s_power()
1180 gpiod_set_value(rj54n1->enable_gpio, 0); in rj54n1_s_power()
1181 if (rj54n1->pwup_gpio) in rj54n1_s_power()
1182 gpiod_set_value(rj54n1->pwup_gpio, 0); in rj54n1_s_power()
1189 struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl); in rj54n1_s_ctrl()
1190 struct v4l2_subdev *sd = &rj54n1->subdev; in rj54n1_s_ctrl()
1194 switch (ctrl->id) { in rj54n1_s_ctrl()
1196 if (ctrl->val) in rj54n1_s_ctrl()
1201 return -EIO; in rj54n1_s_ctrl()
1204 if (ctrl->val) in rj54n1_s_ctrl()
1209 return -EIO; in rj54n1_s_ctrl()
1212 if (reg_write(client, RJ54N1_Y_GAIN, ctrl->val * 2) < 0) in rj54n1_s_ctrl()
1213 return -EIO; in rj54n1_s_ctrl()
1216 /* Auto WB area - whole image */ in rj54n1_s_ctrl()
1217 if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->val << 7, in rj54n1_s_ctrl()
1219 return -EIO; in rj54n1_s_ctrl()
1220 rj54n1->auto_wb = ctrl->val; in rj54n1_s_ctrl()
1224 return -EINVAL; in rj54n1_s_ctrl()
1268 ret = rj54n1_s_power(&rj54n1->subdev, 1); in rj54n1_video_probe()
1277 ret = -ENODEV; in rj54n1_video_probe()
1278 dev_info(&client->dev, "No RJ54N1CB0C found, read 0x%x:0x%x\n", in rj54n1_video_probe()
1284 ret = reg_write(client, RJ54N1_IOC, priv->ioctl_high << 7); in rj54n1_video_probe()
1288 dev_info(&client->dev, "Detected a RJ54N1CB0C chip ID 0x%x:0x%x\n", in rj54n1_video_probe()
1291 ret = v4l2_ctrl_handler_setup(&rj54n1->hdl); in rj54n1_video_probe()
1294 rj54n1_s_power(&rj54n1->subdev, 0); in rj54n1_video_probe()
1301 struct i2c_adapter *adapter = client->adapter; in rj54n1_probe()
1305 if (!client->dev.platform_data) { in rj54n1_probe()
1306 dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n"); in rj54n1_probe()
1307 return -EINVAL; in rj54n1_probe()
1310 rj54n1_priv = client->dev.platform_data; in rj54n1_probe()
1313 dev_warn(&adapter->dev, in rj54n1_probe()
1314 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); in rj54n1_probe()
1315 return -EIO; in rj54n1_probe()
1318 rj54n1 = devm_kzalloc(&client->dev, sizeof(struct rj54n1), GFP_KERNEL); in rj54n1_probe()
1320 return -ENOMEM; in rj54n1_probe()
1322 v4l2_i2c_subdev_init(&rj54n1->subdev, client, &rj54n1_subdev_ops); in rj54n1_probe()
1323 v4l2_ctrl_handler_init(&rj54n1->hdl, 4); in rj54n1_probe()
1324 v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops, in rj54n1_probe()
1326 v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops, in rj54n1_probe()
1328 v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops, in rj54n1_probe()
1330 v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops, in rj54n1_probe()
1332 rj54n1->subdev.ctrl_handler = &rj54n1->hdl; in rj54n1_probe()
1333 if (rj54n1->hdl.error) in rj54n1_probe()
1334 return rj54n1->hdl.error; in rj54n1_probe()
1336 rj54n1->clk_div = clk_div; in rj54n1_probe()
1337 rj54n1->rect.left = RJ54N1_COLUMN_SKIP; in rj54n1_probe()
1338 rj54n1->rect.top = RJ54N1_ROW_SKIP; in rj54n1_probe()
1339 rj54n1->rect.width = RJ54N1_MAX_WIDTH; in rj54n1_probe()
1340 rj54n1->rect.height = RJ54N1_MAX_HEIGHT; in rj54n1_probe()
1341 rj54n1->width = RJ54N1_MAX_WIDTH; in rj54n1_probe()
1342 rj54n1->height = RJ54N1_MAX_HEIGHT; in rj54n1_probe()
1343 rj54n1->fmt = &rj54n1_colour_fmts[0]; in rj54n1_probe()
1344 rj54n1->resize = 1024; in rj54n1_probe()
1345 rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) / in rj54n1_probe()
1348 rj54n1->clk = clk_get(&client->dev, NULL); in rj54n1_probe()
1349 if (IS_ERR(rj54n1->clk)) { in rj54n1_probe()
1350 ret = PTR_ERR(rj54n1->clk); in rj54n1_probe()
1354 rj54n1->pwup_gpio = gpiod_get_optional(&client->dev, "powerup", in rj54n1_probe()
1356 if (IS_ERR(rj54n1->pwup_gpio)) { in rj54n1_probe()
1357 dev_info(&client->dev, "Unable to get GPIO \"powerup\": %ld\n", in rj54n1_probe()
1358 PTR_ERR(rj54n1->pwup_gpio)); in rj54n1_probe()
1359 ret = PTR_ERR(rj54n1->pwup_gpio); in rj54n1_probe()
1363 rj54n1->enable_gpio = gpiod_get_optional(&client->dev, "enable", in rj54n1_probe()
1365 if (IS_ERR(rj54n1->enable_gpio)) { in rj54n1_probe()
1366 dev_info(&client->dev, "Unable to get GPIO \"enable\": %ld\n", in rj54n1_probe()
1367 PTR_ERR(rj54n1->enable_gpio)); in rj54n1_probe()
1368 ret = PTR_ERR(rj54n1->enable_gpio); in rj54n1_probe()
1376 ret = v4l2_async_register_subdev(&rj54n1->subdev); in rj54n1_probe()
1383 if (rj54n1->enable_gpio) in rj54n1_probe()
1384 gpiod_put(rj54n1->enable_gpio); in rj54n1_probe()
1386 if (rj54n1->pwup_gpio) in rj54n1_probe()
1387 gpiod_put(rj54n1->pwup_gpio); in rj54n1_probe()
1390 clk_put(rj54n1->clk); in rj54n1_probe()
1393 v4l2_ctrl_handler_free(&rj54n1->hdl); in rj54n1_probe()
1402 if (rj54n1->enable_gpio) in rj54n1_remove()
1403 gpiod_put(rj54n1->enable_gpio); in rj54n1_remove()
1404 if (rj54n1->pwup_gpio) in rj54n1_remove()
1405 gpiod_put(rj54n1->pwup_gpio); in rj54n1_remove()
1407 clk_put(rj54n1->clk); in rj54n1_remove()
1408 v4l2_ctrl_handler_free(&rj54n1->hdl); in rj54n1_remove()
1409 v4l2_async_unregister_subdev(&rj54n1->subdev); in rj54n1_remove()