1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2022 Intel Corporation.
4 #include <linux/acpi.h>
6 #include <linux/module.h>
7 #include <linux/delay.h>
8 #include <linux/pm_runtime.h>
9 #include <media/v4l2-ctrls.h>
10 #include <media/v4l2-device.h>
11 #include <media/v4l2-fwnode.h>
13 #define OV08X40_REG_VALUE_08BIT 1
14 #define OV08X40_REG_VALUE_16BIT 2
15 #define OV08X40_REG_VALUE_24BIT 3
17 #define OV08X40_REG_MODE_SELECT 0x0100
18 #define OV08X40_MODE_STANDBY 0x00
19 #define OV08X40_MODE_STREAMING 0x01
21 #define OV08X40_REG_AO_STANDBY 0x1000
22 #define OV08X40_AO_STREAMING 0x04
24 #define OV08X40_REG_MS_SELECT 0x1001
25 #define OV08X40_MS_STANDBY 0x00
26 #define OV08X40_MS_STREAMING 0x04
28 #define OV08X40_REG_SOFTWARE_RST 0x0103
29 #define OV08X40_SOFTWARE_RST 0x01
32 #define OV08X40_REG_CHIP_ID 0x300a
33 #define OV08X40_CHIP_ID 0x560858
35 /* V_TIMING internal */
36 #define OV08X40_REG_VTS 0x380e
37 #define OV08X40_VTS_30FPS 0x1388
38 #define OV08X40_VTS_BIN_30FPS 0x115c
39 #define OV08X40_VTS_MAX 0x7fff
41 /* H TIMING internal */
42 #define OV08X40_REG_HTS 0x380c
43 #define OV08X40_HTS_30FPS 0x0280
45 /* Exposure control */
46 #define OV08X40_REG_EXPOSURE 0x3500
47 #define OV08X40_EXPOSURE_MAX_MARGIN 31
48 #define OV08X40_EXPOSURE_MIN 1
49 #define OV08X40_EXPOSURE_STEP 1
50 #define OV08X40_EXPOSURE_DEFAULT 0x40
52 /* Short Exposure control */
53 #define OV08X40_REG_SHORT_EXPOSURE 0x3540
55 /* Analog gain control */
56 #define OV08X40_REG_ANALOG_GAIN 0x3508
57 #define OV08X40_ANA_GAIN_MIN 0x80
58 #define OV08X40_ANA_GAIN_MAX 0x07c0
59 #define OV08X40_ANA_GAIN_STEP 1
60 #define OV08X40_ANA_GAIN_DEFAULT 0x80
62 /* Digital gain control */
63 #define OV08X40_REG_DGTL_GAIN_H 0x350a
64 #define OV08X40_REG_DGTL_GAIN_M 0x350b
65 #define OV08X40_REG_DGTL_GAIN_L 0x350c
67 #define OV08X40_DGTL_GAIN_MIN 1024 /* Min = 1 X */
68 #define OV08X40_DGTL_GAIN_MAX (4096 - 1) /* Max = 4 X */
69 #define OV08X40_DGTL_GAIN_DEFAULT 2560 /* Default gain = 2.5 X */
70 #define OV08X40_DGTL_GAIN_STEP 1 /* Each step = 1/1024 */
72 #define OV08X40_DGTL_GAIN_L_SHIFT 6
73 #define OV08X40_DGTL_GAIN_L_MASK 0x3
74 #define OV08X40_DGTL_GAIN_M_SHIFT 2
75 #define OV08X40_DGTL_GAIN_M_MASK 0xff
76 #define OV08X40_DGTL_GAIN_H_SHIFT 10
77 #define OV08X40_DGTL_GAIN_H_MASK 0x1F
79 /* Test Pattern Control */
80 #define OV08X40_REG_TEST_PATTERN 0x50C1
81 #define OV08X40_REG_ISP 0x5000
82 #define OV08X40_REG_SHORT_TEST_PATTERN 0x53C1
83 #define OV08X40_TEST_PATTERN_ENABLE BIT(0)
84 #define OV08X40_TEST_PATTERN_MASK 0xcf
85 #define OV08X40_TEST_PATTERN_BAR_SHIFT 4
88 #define OV08X40_REG_VFLIP 0x3820
89 #define OV08X40_REG_MIRROR 0x3821
91 /* Horizontal Window Offset */
92 #define OV08X40_REG_H_WIN_OFFSET 0x3811
94 /* Vertical Window Offset */
95 #define OV08X40_REG_V_WIN_OFFSET 0x3813
98 OV08X40_LINK_FREQ_400MHZ_INDEX,
106 struct ov08x40_reg_list {
108 const struct ov08x40_reg *regs;
111 /* Link frequency config */
112 struct ov08x40_link_freq_config {
115 /* registers for this link frequency */
116 struct ov08x40_reg_list reg_list;
119 /* Mode : resolution and related config&values */
120 struct ov08x40_mode {
131 /* Index of Link frequency config to be used */
133 /* Default register values */
134 struct ov08x40_reg_list reg_list;
137 static const struct ov08x40_reg mipi_data_rate_800mbps[] = {
157 static const struct ov08x40_reg mode_3856x2416_regs[] = {
1821 static const struct ov08x40_reg mode_1928x1208_regs[] = {
2346 static const char * const ov08x40_test_pattern_menu[] = {
2348 "Vertical Color Bar Type 1",
2349 "Vertical Color Bar Type 2",
2350 "Vertical Color Bar Type 3",
2351 "Vertical Color Bar Type 4"
2354 /* Configurations for supported link frequencies */
2355 #define OV08X40_LINK_FREQ_400MHZ 400000000ULL
2357 #define OV08X40_EXT_CLK 19200000
2358 #define OV08X40_DATA_LANES 4
2361 * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
2362 * data rate => double data rate; number of lanes => 4; bits per pixel => 10
2364 static u64 link_freq_to_pixel_rate(u64 f)
2366 f *= 2 * OV08X40_DATA_LANES;
2372 /* Menu items for LINK_FREQ V4L2 control */
2373 static const s64 link_freq_menu_items[] = {
2374 OV08X40_LINK_FREQ_400MHZ,
2377 /* Link frequency configs */
2378 static const struct ov08x40_link_freq_config link_freq_configs[] = {
2379 [OV08X40_LINK_FREQ_400MHZ_INDEX] = {
2381 .num_of_regs = ARRAY_SIZE(mipi_data_rate_800mbps),
2382 .regs = mipi_data_rate_800mbps,
2388 static const struct ov08x40_mode supported_modes[] = {
2392 .vts_def = OV08X40_VTS_30FPS,
2393 .vts_min = OV08X40_VTS_30FPS,
2396 .num_of_regs = ARRAY_SIZE(mode_3856x2416_regs),
2397 .regs = mode_3856x2416_regs,
2399 .link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX,
2404 .vts_def = OV08X40_VTS_BIN_30FPS,
2405 .vts_min = OV08X40_VTS_BIN_30FPS,
2408 .num_of_regs = ARRAY_SIZE(mode_1928x1208_regs),
2409 .regs = mode_1928x1208_regs,
2411 .link_freq_index = OV08X40_LINK_FREQ_400MHZ_INDEX,
2416 struct v4l2_subdev sd;
2417 struct media_pad pad;
2419 struct v4l2_ctrl_handler ctrl_handler;
2421 struct v4l2_ctrl *link_freq;
2422 struct v4l2_ctrl *pixel_rate;
2423 struct v4l2_ctrl *vblank;
2424 struct v4l2_ctrl *hblank;
2425 struct v4l2_ctrl *exposure;
2428 const struct ov08x40_mode *cur_mode;
2430 /* Mutex for serialized access */
2433 /* Streaming on/off */
2437 #define to_ov08x40(_sd) container_of(_sd, struct ov08x40, sd)
2439 /* Read registers up to 4 at a time */
2440 static int ov08x40_read_reg(struct ov08x40 *ov08x,
2441 u16 reg, u32 len, u32 *val)
2443 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
2444 struct i2c_msg msgs[2];
2448 __be16 reg_addr_be = cpu_to_be16(reg);
2453 data_be_p = (u8 *)&data_be;
2454 /* Write register address */
2455 msgs[0].addr = client->addr;
2458 msgs[0].buf = (u8 *)®_addr_be;
2460 /* Read data from register */
2461 msgs[1].addr = client->addr;
2462 msgs[1].flags = I2C_M_RD;
2464 msgs[1].buf = &data_be_p[4 - len];
2466 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
2467 if (ret != ARRAY_SIZE(msgs))
2470 *val = be32_to_cpu(data_be);
2475 /* Write registers up to 4 at a time */
2476 static int ov08x40_write_reg(struct ov08x40 *ov08x,
2477 u16 reg, u32 len, u32 __val)
2479 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
2488 buf[1] = reg & 0xff;
2490 val = cpu_to_be32(__val);
2496 buf[buf_i++] = val_p[val_i++];
2498 if (i2c_master_send(client, buf, len + 2) != len + 2)
2504 /* Write a list of registers */
2505 static int ov08x40_write_regs(struct ov08x40 *ov08x,
2506 const struct ov08x40_reg *regs, u32 len)
2508 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
2512 for (i = 0; i < len; i++) {
2513 ret = ov08x40_write_reg(ov08x, regs[i].address, 1,
2517 dev_err_ratelimited(&client->dev,
2518 "Failed to write reg 0x%4.4x. error = %d\n",
2519 regs[i].address, ret);
2528 static int ov08x40_write_reg_list(struct ov08x40 *ov08x,
2529 const struct ov08x40_reg_list *r_list)
2531 return ov08x40_write_regs(ov08x, r_list->regs, r_list->num_of_regs);
2534 static int ov08x40_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
2536 const struct ov08x40_mode *default_mode = &supported_modes[0];
2537 struct ov08x40 *ov08x = to_ov08x40(sd);
2538 struct v4l2_mbus_framefmt *try_fmt =
2539 v4l2_subdev_get_try_format(sd, fh->state, 0);
2541 mutex_lock(&ov08x->mutex);
2543 /* Initialize try_fmt */
2544 try_fmt->width = default_mode->width;
2545 try_fmt->height = default_mode->height;
2546 try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
2547 try_fmt->field = V4L2_FIELD_NONE;
2549 /* No crop or compose */
2550 mutex_unlock(&ov08x->mutex);
2555 static int ov08x40_update_digital_gain(struct ov08x40 *ov08x, u32 d_gain)
2561 * 0x350C[1:0], 0x350B[7:0], 0x350A[4:0]
2564 val = (d_gain & OV08X40_DGTL_GAIN_L_MASK) << OV08X40_DGTL_GAIN_L_SHIFT;
2565 ret = ov08x40_write_reg(ov08x, OV08X40_REG_DGTL_GAIN_L,
2566 OV08X40_REG_VALUE_08BIT, val);
2570 val = (d_gain >> OV08X40_DGTL_GAIN_M_SHIFT) & OV08X40_DGTL_GAIN_M_MASK;
2571 ret = ov08x40_write_reg(ov08x, OV08X40_REG_DGTL_GAIN_M,
2572 OV08X40_REG_VALUE_08BIT, val);
2576 val = (d_gain >> OV08X40_DGTL_GAIN_H_SHIFT) & OV08X40_DGTL_GAIN_H_MASK;
2578 return ov08x40_write_reg(ov08x, OV08X40_REG_DGTL_GAIN_H,
2579 OV08X40_REG_VALUE_08BIT, val);
2582 static int ov08x40_enable_test_pattern(struct ov08x40 *ov08x, u32 pattern)
2587 ret = ov08x40_read_reg(ov08x, OV08X40_REG_TEST_PATTERN,
2588 OV08X40_REG_VALUE_08BIT, &val);
2593 ret = ov08x40_read_reg(ov08x, OV08X40_REG_ISP,
2594 OV08X40_REG_VALUE_08BIT, &val);
2598 ret = ov08x40_write_reg(ov08x, OV08X40_REG_ISP,
2599 OV08X40_REG_VALUE_08BIT,
2604 ret = ov08x40_read_reg(ov08x, OV08X40_REG_SHORT_TEST_PATTERN,
2605 OV08X40_REG_VALUE_08BIT, &val);
2609 ret = ov08x40_write_reg(ov08x, OV08X40_REG_SHORT_TEST_PATTERN,
2610 OV08X40_REG_VALUE_08BIT,
2615 ret = ov08x40_read_reg(ov08x, OV08X40_REG_TEST_PATTERN,
2616 OV08X40_REG_VALUE_08BIT, &val);
2620 val &= OV08X40_TEST_PATTERN_MASK;
2621 val |= ((pattern - 1) << OV08X40_TEST_PATTERN_BAR_SHIFT) |
2622 OV08X40_TEST_PATTERN_ENABLE;
2624 val &= ~OV08X40_TEST_PATTERN_ENABLE;
2627 return ov08x40_write_reg(ov08x, OV08X40_REG_TEST_PATTERN,
2628 OV08X40_REG_VALUE_08BIT, val);
2631 static int ov08x40_set_ctrl_hflip(struct ov08x40 *ov08x, u32 ctrl_val)
2636 ret = ov08x40_read_reg(ov08x, OV08X40_REG_MIRROR,
2637 OV08X40_REG_VALUE_08BIT, &val);
2641 return ov08x40_write_reg(ov08x, OV08X40_REG_MIRROR,
2642 OV08X40_REG_VALUE_08BIT,
2643 ctrl_val ? val | BIT(2) : val & ~BIT(2));
2646 static int ov08x40_set_ctrl_vflip(struct ov08x40 *ov08x, u32 ctrl_val)
2651 ret = ov08x40_read_reg(ov08x, OV08X40_REG_VFLIP,
2652 OV08X40_REG_VALUE_08BIT, &val);
2656 return ov08x40_write_reg(ov08x, OV08X40_REG_VFLIP,
2657 OV08X40_REG_VALUE_08BIT,
2658 ctrl_val ? val | BIT(2) : val & ~BIT(2));
2661 static int ov08x40_set_ctrl(struct v4l2_ctrl *ctrl)
2663 struct ov08x40 *ov08x = container_of(ctrl->handler,
2664 struct ov08x40, ctrl_handler);
2665 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
2669 /* Propagate change of current control to all related controls */
2671 case V4L2_CID_VBLANK:
2672 /* Update max exposure while meeting expected vblanking */
2673 max = ov08x->cur_mode->height + ctrl->val - OV08X40_EXPOSURE_MAX_MARGIN;
2674 __v4l2_ctrl_modify_range(ov08x->exposure,
2675 ov08x->exposure->minimum,
2676 max, ov08x->exposure->step, max);
2681 * Applying V4L2 control value only happens
2682 * when power is up for streaming
2684 if (!pm_runtime_get_if_in_use(&client->dev))
2688 case V4L2_CID_ANALOGUE_GAIN:
2689 ret = ov08x40_write_reg(ov08x, OV08X40_REG_ANALOG_GAIN,
2690 OV08X40_REG_VALUE_16BIT,
2693 case V4L2_CID_DIGITAL_GAIN:
2694 ret = ov08x40_update_digital_gain(ov08x, ctrl->val);
2696 case V4L2_CID_EXPOSURE:
2697 ret = ov08x40_write_reg(ov08x, OV08X40_REG_EXPOSURE,
2698 OV08X40_REG_VALUE_24BIT,
2701 case V4L2_CID_VBLANK:
2702 ret = ov08x40_write_reg(ov08x, OV08X40_REG_VTS,
2703 OV08X40_REG_VALUE_16BIT,
2704 ov08x->cur_mode->height
2707 case V4L2_CID_TEST_PATTERN:
2708 ret = ov08x40_enable_test_pattern(ov08x, ctrl->val);
2710 case V4L2_CID_HFLIP:
2711 ov08x40_set_ctrl_hflip(ov08x, ctrl->val);
2713 case V4L2_CID_VFLIP:
2714 ov08x40_set_ctrl_vflip(ov08x, ctrl->val);
2717 dev_info(&client->dev,
2718 "ctrl(id:0x%x,val:0x%x) is not handled\n",
2719 ctrl->id, ctrl->val);
2723 pm_runtime_put(&client->dev);
2728 static const struct v4l2_ctrl_ops ov08x40_ctrl_ops = {
2729 .s_ctrl = ov08x40_set_ctrl,
2732 static int ov08x40_enum_mbus_code(struct v4l2_subdev *sd,
2733 struct v4l2_subdev_state *sd_state,
2734 struct v4l2_subdev_mbus_code_enum *code)
2736 /* Only one bayer order(GRBG) is supported */
2737 if (code->index > 0)
2740 code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
2745 static int ov08x40_enum_frame_size(struct v4l2_subdev *sd,
2746 struct v4l2_subdev_state *sd_state,
2747 struct v4l2_subdev_frame_size_enum *fse)
2749 if (fse->index >= ARRAY_SIZE(supported_modes))
2752 if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
2755 fse->min_width = supported_modes[fse->index].width;
2756 fse->max_width = fse->min_width;
2757 fse->min_height = supported_modes[fse->index].height;
2758 fse->max_height = fse->min_height;
2763 static void ov08x40_update_pad_format(const struct ov08x40_mode *mode,
2764 struct v4l2_subdev_format *fmt)
2766 fmt->format.width = mode->width;
2767 fmt->format.height = mode->height;
2768 fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
2769 fmt->format.field = V4L2_FIELD_NONE;
2772 static int ov08x40_do_get_pad_format(struct ov08x40 *ov08x,
2773 struct v4l2_subdev_state *sd_state,
2774 struct v4l2_subdev_format *fmt)
2776 struct v4l2_mbus_framefmt *framefmt;
2777 struct v4l2_subdev *sd = &ov08x->sd;
2779 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
2780 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
2781 fmt->format = *framefmt;
2783 ov08x40_update_pad_format(ov08x->cur_mode, fmt);
2789 static int ov08x40_get_pad_format(struct v4l2_subdev *sd,
2790 struct v4l2_subdev_state *sd_state,
2791 struct v4l2_subdev_format *fmt)
2793 struct ov08x40 *ov08x = to_ov08x40(sd);
2796 mutex_lock(&ov08x->mutex);
2797 ret = ov08x40_do_get_pad_format(ov08x, sd_state, fmt);
2798 mutex_unlock(&ov08x->mutex);
2804 ov08x40_set_pad_format(struct v4l2_subdev *sd,
2805 struct v4l2_subdev_state *sd_state,
2806 struct v4l2_subdev_format *fmt)
2808 struct ov08x40 *ov08x = to_ov08x40(sd);
2809 const struct ov08x40_mode *mode;
2810 struct v4l2_mbus_framefmt *framefmt;
2817 mutex_lock(&ov08x->mutex);
2819 /* Only one raw bayer(GRBG) order is supported */
2820 if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10)
2821 fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
2823 mode = v4l2_find_nearest_size(supported_modes,
2824 ARRAY_SIZE(supported_modes),
2826 fmt->format.width, fmt->format.height);
2827 ov08x40_update_pad_format(mode, fmt);
2828 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
2829 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
2830 *framefmt = fmt->format;
2832 ov08x->cur_mode = mode;
2833 __v4l2_ctrl_s_ctrl(ov08x->link_freq, mode->link_freq_index);
2834 link_freq = link_freq_menu_items[mode->link_freq_index];
2835 pixel_rate = link_freq_to_pixel_rate(link_freq);
2836 __v4l2_ctrl_s_ctrl_int64(ov08x->pixel_rate, pixel_rate);
2838 /* Update limits and set FPS to default */
2839 vblank_def = ov08x->cur_mode->vts_def -
2840 ov08x->cur_mode->height;
2841 vblank_min = ov08x->cur_mode->vts_min -
2842 ov08x->cur_mode->height;
2843 __v4l2_ctrl_modify_range(ov08x->vblank, vblank_min,
2845 - ov08x->cur_mode->height,
2848 __v4l2_ctrl_s_ctrl(ov08x->vblank, vblank_def);
2850 link_freq_configs[mode->link_freq_index].pixels_per_line
2851 - ov08x->cur_mode->width;
2852 __v4l2_ctrl_modify_range(ov08x->hblank, h_blank,
2853 h_blank, 1, h_blank);
2856 mutex_unlock(&ov08x->mutex);
2861 static int ov08x40_start_streaming(struct ov08x40 *ov08x)
2863 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
2864 const struct ov08x40_reg_list *reg_list;
2865 int ret, link_freq_index;
2867 /* Get out of from software reset */
2868 ret = ov08x40_write_reg(ov08x, OV08X40_REG_SOFTWARE_RST,
2869 OV08X40_REG_VALUE_08BIT, OV08X40_SOFTWARE_RST);
2871 dev_err(&client->dev, "%s failed to set powerup registers\n",
2876 link_freq_index = ov08x->cur_mode->link_freq_index;
2877 reg_list = &link_freq_configs[link_freq_index].reg_list;
2879 ret = ov08x40_write_reg_list(ov08x, reg_list);
2881 dev_err(&client->dev, "%s failed to set plls\n", __func__);
2885 /* Apply default values of current mode */
2886 reg_list = &ov08x->cur_mode->reg_list;
2887 ret = ov08x40_write_reg_list(ov08x, reg_list);
2889 dev_err(&client->dev, "%s failed to set mode\n", __func__);
2893 /* Apply customized values from user */
2894 ret = __v4l2_ctrl_handler_setup(ov08x->sd.ctrl_handler);
2898 return ov08x40_write_reg(ov08x, OV08X40_REG_MODE_SELECT,
2899 OV08X40_REG_VALUE_08BIT,
2900 OV08X40_MODE_STREAMING);
2903 /* Stop streaming */
2904 static int ov08x40_stop_streaming(struct ov08x40 *ov08x)
2906 return ov08x40_write_reg(ov08x, OV08X40_REG_MODE_SELECT,
2907 OV08X40_REG_VALUE_08BIT, OV08X40_MODE_STANDBY);
2910 static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable)
2912 struct ov08x40 *ov08x = to_ov08x40(sd);
2913 struct i2c_client *client = v4l2_get_subdevdata(sd);
2916 mutex_lock(&ov08x->mutex);
2917 if (ov08x->streaming == enable) {
2918 mutex_unlock(&ov08x->mutex);
2923 ret = pm_runtime_resume_and_get(&client->dev);
2928 * Apply default & customized values
2929 * and then start streaming.
2931 ret = ov08x40_start_streaming(ov08x);
2935 ov08x40_stop_streaming(ov08x);
2936 pm_runtime_put(&client->dev);
2939 ov08x->streaming = enable;
2940 mutex_unlock(&ov08x->mutex);
2945 pm_runtime_put(&client->dev);
2947 mutex_unlock(&ov08x->mutex);
2952 static int __maybe_unused ov08x40_suspend(struct device *dev)
2954 struct v4l2_subdev *sd = dev_get_drvdata(dev);
2955 struct ov08x40 *ov08x = to_ov08x40(sd);
2957 if (ov08x->streaming)
2958 ov08x40_stop_streaming(ov08x);
2963 static int __maybe_unused ov08x40_resume(struct device *dev)
2965 struct v4l2_subdev *sd = dev_get_drvdata(dev);
2966 struct ov08x40 *ov08x = to_ov08x40(sd);
2969 if (ov08x->streaming) {
2970 ret = ov08x40_start_streaming(ov08x);
2978 ov08x40_stop_streaming(ov08x);
2979 ov08x->streaming = false;
2983 /* Verify chip ID */
2984 static int ov08x40_identify_module(struct ov08x40 *ov08x)
2986 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
2990 ret = ov08x40_read_reg(ov08x, OV08X40_REG_CHIP_ID,
2991 OV08X40_REG_VALUE_24BIT, &val);
2995 if (val != OV08X40_CHIP_ID) {
2996 dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
2997 OV08X40_CHIP_ID, val);
3004 static const struct v4l2_subdev_video_ops ov08x40_video_ops = {
3005 .s_stream = ov08x40_set_stream,
3008 static const struct v4l2_subdev_pad_ops ov08x40_pad_ops = {
3009 .enum_mbus_code = ov08x40_enum_mbus_code,
3010 .get_fmt = ov08x40_get_pad_format,
3011 .set_fmt = ov08x40_set_pad_format,
3012 .enum_frame_size = ov08x40_enum_frame_size,
3015 static const struct v4l2_subdev_ops ov08x40_subdev_ops = {
3016 .video = &ov08x40_video_ops,
3017 .pad = &ov08x40_pad_ops,
3020 static const struct media_entity_operations ov08x40_subdev_entity_ops = {
3021 .link_validate = v4l2_subdev_link_validate,
3024 static const struct v4l2_subdev_internal_ops ov08x40_internal_ops = {
3025 .open = ov08x40_open,
3028 static int ov08x40_init_controls(struct ov08x40 *ov08x)
3030 struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
3031 struct v4l2_fwnode_device_properties props;
3032 struct v4l2_ctrl_handler *ctrl_hdlr;
3039 const struct ov08x40_mode *mode;
3043 ctrl_hdlr = &ov08x->ctrl_handler;
3044 ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
3048 mutex_init(&ov08x->mutex);
3049 ctrl_hdlr->lock = &ov08x->mutex;
3050 max = ARRAY_SIZE(link_freq_menu_items) - 1;
3051 ov08x->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr,
3056 link_freq_menu_items);
3057 if (ov08x->link_freq)
3058 ov08x->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
3060 pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
3062 /* By default, PIXEL_RATE is read only */
3063 ov08x->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
3064 V4L2_CID_PIXEL_RATE,
3065 pixel_rate_min, pixel_rate_max,
3068 mode = ov08x->cur_mode;
3069 vblank_def = mode->vts_def - mode->height;
3070 vblank_min = mode->vts_min - mode->height;
3071 ov08x->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
3074 OV08X40_VTS_MAX - mode->height, 1,
3077 hblank = link_freq_configs[mode->link_freq_index].pixels_per_line -
3079 ov08x->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
3081 hblank, hblank, 1, hblank);
3083 ov08x->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
3085 exposure_max = mode->vts_def - OV08X40_EXPOSURE_MAX_MARGIN;
3086 ov08x->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
3088 OV08X40_EXPOSURE_MIN,
3089 exposure_max, OV08X40_EXPOSURE_STEP,
3092 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
3093 OV08X40_ANA_GAIN_MIN, OV08X40_ANA_GAIN_MAX,
3094 OV08X40_ANA_GAIN_STEP, OV08X40_ANA_GAIN_DEFAULT);
3097 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
3098 OV08X40_DGTL_GAIN_MIN, OV08X40_DGTL_GAIN_MAX,
3099 OV08X40_DGTL_GAIN_STEP, OV08X40_DGTL_GAIN_DEFAULT);
3101 v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov08x40_ctrl_ops,
3102 V4L2_CID_TEST_PATTERN,
3103 ARRAY_SIZE(ov08x40_test_pattern_menu) - 1,
3104 0, 0, ov08x40_test_pattern_menu);
3106 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
3107 V4L2_CID_HFLIP, 0, 1, 1, 0);
3108 v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
3109 V4L2_CID_VFLIP, 0, 1, 1, 0);
3111 if (ctrl_hdlr->error) {
3112 ret = ctrl_hdlr->error;
3113 dev_err(&client->dev, "%s control init failed (%d)\n",
3118 ret = v4l2_fwnode_device_parse(&client->dev, &props);
3122 ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov08x40_ctrl_ops,
3127 ov08x->sd.ctrl_handler = ctrl_hdlr;
3132 v4l2_ctrl_handler_free(ctrl_hdlr);
3133 mutex_destroy(&ov08x->mutex);
3138 static void ov08x40_free_controls(struct ov08x40 *ov08x)
3140 v4l2_ctrl_handler_free(ov08x->sd.ctrl_handler);
3141 mutex_destroy(&ov08x->mutex);
3144 static int ov08x40_check_hwcfg(struct device *dev)
3146 struct v4l2_fwnode_endpoint bus_cfg = {
3147 .bus_type = V4L2_MBUS_CSI2_DPHY
3149 struct fwnode_handle *ep;
3150 struct fwnode_handle *fwnode = dev_fwnode(dev);
3158 ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
3161 dev_err(dev, "can't get clock frequency");
3165 if (ext_clk != OV08X40_EXT_CLK) {
3166 dev_err(dev, "external clock %d is not supported",
3171 ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
3175 ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
3176 fwnode_handle_put(ep);
3180 if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV08X40_DATA_LANES) {
3181 dev_err(dev, "number of CSI2 data lanes %d is not supported",
3182 bus_cfg.bus.mipi_csi2.num_data_lanes);
3187 if (!bus_cfg.nr_of_link_frequencies) {
3188 dev_err(dev, "no link frequencies defined");
3193 for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) {
3194 for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) {
3195 if (link_freq_menu_items[i] ==
3196 bus_cfg.link_frequencies[j])
3200 if (j == bus_cfg.nr_of_link_frequencies) {
3201 dev_err(dev, "no link frequency %lld supported",
3202 link_freq_menu_items[i]);
3209 v4l2_fwnode_endpoint_free(&bus_cfg);
3214 static int ov08x40_probe(struct i2c_client *client)
3216 struct ov08x40 *ov08x;
3219 /* Check HW config */
3220 ret = ov08x40_check_hwcfg(&client->dev);
3222 dev_err(&client->dev, "failed to check hwcfg: %d", ret);
3226 ov08x = devm_kzalloc(&client->dev, sizeof(*ov08x), GFP_KERNEL);
3230 /* Initialize subdev */
3231 v4l2_i2c_subdev_init(&ov08x->sd, client, &ov08x40_subdev_ops);
3233 /* Check module identity */
3234 ret = ov08x40_identify_module(ov08x);
3236 dev_err(&client->dev, "failed to find sensor: %d\n", ret);
3240 /* Set default mode to max resolution */
3241 ov08x->cur_mode = &supported_modes[0];
3243 ret = ov08x40_init_controls(ov08x);
3247 /* Initialize subdev */
3248 ov08x->sd.internal_ops = &ov08x40_internal_ops;
3249 ov08x->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
3250 ov08x->sd.entity.ops = &ov08x40_subdev_entity_ops;
3251 ov08x->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
3253 /* Initialize source pad */
3254 ov08x->pad.flags = MEDIA_PAD_FL_SOURCE;
3255 ret = media_entity_pads_init(&ov08x->sd.entity, 1, &ov08x->pad);
3257 dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
3258 goto error_handler_free;
3261 ret = v4l2_async_register_subdev_sensor(&ov08x->sd);
3263 goto error_media_entity;
3266 * Device is already turned on by i2c-core with ACPI domain PM.
3267 * Enable runtime PM and turn off the device.
3269 pm_runtime_set_active(&client->dev);
3270 pm_runtime_enable(&client->dev);
3271 pm_runtime_idle(&client->dev);
3276 media_entity_cleanup(&ov08x->sd.entity);
3279 ov08x40_free_controls(ov08x);
3284 static void ov08x40_remove(struct i2c_client *client)
3286 struct v4l2_subdev *sd = i2c_get_clientdata(client);
3287 struct ov08x40 *ov08x = to_ov08x40(sd);
3289 v4l2_async_unregister_subdev(sd);
3290 media_entity_cleanup(&sd->entity);
3291 ov08x40_free_controls(ov08x);
3293 pm_runtime_disable(&client->dev);
3294 pm_runtime_set_suspended(&client->dev);
3297 static const struct dev_pm_ops ov08x40_pm_ops = {
3298 SET_SYSTEM_SLEEP_PM_OPS(ov08x40_suspend, ov08x40_resume)
3302 static const struct acpi_device_id ov08x40_acpi_ids[] = {
3307 MODULE_DEVICE_TABLE(acpi, ov08x40_acpi_ids);
3310 static struct i2c_driver ov08x40_i2c_driver = {
3313 .pm = &ov08x40_pm_ops,
3314 .acpi_match_table = ACPI_PTR(ov08x40_acpi_ids),
3316 .probe = ov08x40_probe,
3317 .remove = ov08x40_remove,
3320 module_i2c_driver(ov08x40_i2c_driver);
3324 MODULE_DESCRIPTION("OmniVision OV08X40 sensor driver");
3325 MODULE_LICENSE("GPL");