diff options
27 files changed, 314 insertions, 254 deletions
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index ff21cd4744d3..4fbe4e18570e 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -403,7 +403,7 @@ adv7343_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = of_graph_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!np) return NULL; diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 810fa8826f30..319db3e847c4 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -3204,8 +3204,8 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node; - /* Parse the endpoint. */ - endpoint = of_graph_get_next_endpoint(np, NULL); + /* FIXME: Parse the endpoint. */ + endpoint = of_graph_get_endpoint_by_regs(np, -1, -1); if (!endpoint) return -EINVAL; diff --git a/drivers/media/i2c/alvium-csi2.c b/drivers/media/i2c/alvium-csi2.c index 389dac50fee9..e65702e3f73e 100644 --- a/drivers/media/i2c/alvium-csi2.c +++ b/drivers/media/i2c/alvium-csi2.c @@ -1170,40 +1170,32 @@ static int alvium_set_bayer_pattern(struct alvium_dev *alvium, return 0; } -static int alvium_get_frame_interval(struct alvium_dev *alvium) +static int alvium_get_frame_interval(struct alvium_dev *alvium, + u64 *min_fr, u64 *max_fr) { - u64 dft_fr, min_fr, max_fr; int ret = 0; - alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW, - &dft_fr, &ret); alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MIN_R, - &min_fr, &ret); + min_fr, &ret); alvium_read(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_MAX_R, - &max_fr, &ret); - if (ret) - return ret; - - alvium->dft_fr = dft_fr; - alvium->min_fr = min_fr; - alvium->max_fr = max_fr; + max_fr, &ret); - return 0; + return ret; } -static int alvium_set_frame_rate(struct alvium_dev *alvium) +static int alvium_set_frame_rate(struct alvium_dev *alvium, u64 fr) { struct device *dev = &alvium->i2c_client->dev; int ret; ret = alvium_write_hshake(alvium, REG_BCRM_ACQUISITION_FRAME_RATE_RW, - alvium->fr); + fr); if (ret) { dev_err(dev, "Fail to set frame rate lanes reg\n"); return ret; } - dev_dbg(dev, "set frame rate: %llu us\n", alvium->fr); + dev_dbg(dev, "set frame rate: %llu us\n", fr); return 0; } @@ -1647,44 +1639,28 @@ static int alvium_hw_init(struct alvium_dev *alvium) } /* --------------- Subdev Operations --------------- */ - -static int alvium_g_frame_interval(struct v4l2_subdev *sd, +static int alvium_s_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_frame_interval *fi) { struct alvium_dev *alvium = sd_to_alvium(sd); - - /* - * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 - * subdev active state API. - */ - if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - - fi->interval = alvium->frame_interval; - - return 0; -} - -static int alvium_set_frame_interval(struct alvium_dev *alvium, - struct v4l2_subdev_frame_interval *fi) -{ struct device *dev = &alvium->i2c_client->dev; u64 req_fr, min_fr, max_fr; + struct v4l2_fract *interval; int ret; + if (alvium->streaming) + return -EBUSY; + if (fi->interval.denominator == 0) return -EINVAL; - ret = alvium_get_frame_interval(alvium); + ret = alvium_get_frame_interval(alvium, &min_fr, &max_fr); if (ret) { dev_err(dev, "Fail to get frame interval\n"); return ret; } - min_fr = alvium->min_fr; - max_fr = alvium->max_fr; - dev_dbg(dev, "fi->interval.numerator = %d\n", fi->interval.numerator); dev_dbg(dev, "fi->interval.denominator = %d\n", @@ -1692,39 +1668,17 @@ static int alvium_set_frame_interval(struct alvium_dev *alvium, req_fr = (u64)((fi->interval.denominator * USEC_PER_SEC) / fi->interval.numerator); + req_fr = clamp(req_fr, min_fr, max_fr); - if (req_fr >= max_fr && req_fr <= min_fr) - req_fr = alvium->dft_fr; + interval = v4l2_subdev_state_get_interval(sd_state, 0); - alvium->fr = req_fr; - alvium->frame_interval.numerator = fi->interval.numerator; - alvium->frame_interval.denominator = fi->interval.denominator; + interval->numerator = fi->interval.numerator; + interval->denominator = fi->interval.denominator; - return 0; -} - -static int alvium_s_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_frame_interval *fi) -{ - struct alvium_dev *alvium = sd_to_alvium(sd); - int ret; - - /* - * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 - * subdev active state API. - */ if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - - if (alvium->streaming) - return -EBUSY; - - ret = alvium_set_frame_interval(alvium, fi); - if (!ret) - ret = alvium_set_frame_rate(alvium); + return 0; - return ret; + return alvium_set_frame_rate(alvium, req_fr); } static int alvium_enum_mbus_code(struct v4l2_subdev *sd, @@ -1872,6 +1826,7 @@ static int alvium_init_state(struct v4l2_subdev *sd, { struct alvium_dev *alvium = sd_to_alvium(sd); struct alvium_mode *mode = &alvium->mode; + struct v4l2_fract *interval; struct v4l2_subdev_format sd_fmt = { .which = V4L2_SUBDEV_FORMAT_TRY, .format = alvium_csi2_default_fmt, @@ -1889,6 +1844,11 @@ static int alvium_init_state(struct v4l2_subdev *sd, *v4l2_subdev_state_get_crop(state, 0) = sd_crop.rect; *v4l2_subdev_state_get_format(state, 0) = sd_fmt.format; + /* Setup initial frame interval*/ + interval = v4l2_subdev_state_get_interval(state, 0); + interval->numerator = 1; + interval->denominator = ALVIUM_DEFAULT_FR_HZ; + return 0; } @@ -2258,7 +2218,7 @@ static const struct v4l2_subdev_pad_ops alvium_pad_ops = { .set_fmt = alvium_set_fmt, .get_selection = alvium_get_selection, .set_selection = alvium_set_selection, - .get_frame_interval = alvium_g_frame_interval, + .get_frame_interval = v4l2_subdev_get_frame_interval, .set_frame_interval = alvium_s_frame_interval, }; @@ -2279,11 +2239,6 @@ static int alvium_subdev_init(struct alvium_dev *alvium) struct v4l2_subdev *sd = &alvium->sd; int ret; - /* Setup initial frame interval*/ - alvium->frame_interval.numerator = 1; - alvium->frame_interval.denominator = ALVIUM_DEFAULT_FR_HZ; - alvium->fr = ALVIUM_DEFAULT_FR_HZ; - /* Setup the initial mode */ alvium->mode.fmt = alvium_csi2_default_fmt; alvium->mode.width = alvium_csi2_default_fmt.width; diff --git a/drivers/media/i2c/alvium-csi2.h b/drivers/media/i2c/alvium-csi2.h index b85a25169e79..9463f8604fbc 100644 --- a/drivers/media/i2c/alvium-csi2.h +++ b/drivers/media/i2c/alvium-csi2.h @@ -442,11 +442,6 @@ struct alvium_dev { s32 inc_sharp; struct alvium_mode mode; - struct v4l2_fract frame_interval; - u64 dft_fr; - u64 min_fr; - u64 max_fr; - u64 fr; u8 h_sup_csi_lanes; u64 link_freq; diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c index cc09b32ede60..84d29bcf0ccd 100644 --- a/drivers/media/i2c/dw9714.c +++ b/drivers/media/i2c/dw9714.c @@ -157,6 +157,8 @@ static int dw9714_probe(struct i2c_client *client) return rval; } + usleep_range(1000, 2000); + v4l2_i2c_subdev_init(&dw9714_dev->sd, client, &dw9714_ops); dw9714_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c index 9967f3477433..4150e6e4b9a6 100644 --- a/drivers/media/i2c/imx290.c +++ b/drivers/media/i2c/imx290.c @@ -150,10 +150,10 @@ #define IMX290_PIXEL_ARRAY_WIDTH 1945 #define IMX290_PIXEL_ARRAY_HEIGHT 1097 -#define IMX920_PIXEL_ARRAY_MARGIN_LEFT 12 -#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT 13 -#define IMX920_PIXEL_ARRAY_MARGIN_TOP 8 -#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM 9 +#define IMX290_PIXEL_ARRAY_MARGIN_LEFT 12 +#define IMX290_PIXEL_ARRAY_MARGIN_RIGHT 13 +#define IMX290_PIXEL_ARRAY_MARGIN_TOP 8 +#define IMX290_PIXEL_ARRAY_MARGIN_BOTTOM 9 #define IMX290_PIXEL_ARRAY_RECORDING_WIDTH 1920 #define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT 1080 @@ -1161,10 +1161,10 @@ static int imx290_get_selection(struct v4l2_subdev *sd, * The sensor moves the readout by 1 pixel based on flips to * keep the Bayer order the same. */ - sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP + sel->r.top = IMX290_PIXEL_ARRAY_MARGIN_TOP + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2 + imx290->vflip->val; - sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT + sel->r.left = IMX290_PIXEL_ARRAY_MARGIN_LEFT + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2 + imx290->hflip->val; sel->r.width = format->width; @@ -1183,8 +1183,8 @@ static int imx290_get_selection(struct v4l2_subdev *sd, return 0; case V4L2_SEL_TGT_CROP_DEFAULT: - sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP; - sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT; + sel->r.top = IMX290_PIXEL_ARRAY_MARGIN_TOP; + sel->r.left = IMX290_PIXEL_ARRAY_MARGIN_LEFT; sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH; sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT; diff --git a/drivers/media/i2c/imx335.c b/drivers/media/i2c/imx335.c index 7a37eb327ff4..dab6d080bc4c 100644 --- a/drivers/media/i2c/imx335.c +++ b/drivers/media/i2c/imx335.c @@ -45,11 +45,28 @@ /* Group hold register */ #define IMX335_REG_HOLD 0x3001 +/* Test pattern generator */ +#define IMX335_REG_TPG 0x329e +#define IMX335_TPG_ALL_000 0 +#define IMX335_TPG_ALL_FFF 1 +#define IMX335_TPG_ALL_555 2 +#define IMX335_TPG_ALL_AAA 3 +#define IMX335_TPG_TOG_555_AAA 4 +#define IMX335_TPG_TOG_AAA_555 5 +#define IMX335_TPG_TOG_000_555 6 +#define IMX335_TPG_TOG_555_000 7 +#define IMX335_TPG_TOG_000_FFF 8 +#define IMX335_TPG_TOG_FFF_000 9 +#define IMX335_TPG_H_COLOR_BARS 10 +#define IMX335_TPG_V_COLOR_BARS 11 + /* Input clock rate */ #define IMX335_INCLK_RATE 24000000 /* CSI2 HW configuration */ -#define IMX335_LINK_FREQ 594000000 +#define IMX335_LINK_FREQ_594MHz 594000000LL +#define IMX335_LINK_FREQ_445MHz 445500000LL + #define IMX335_NUM_DATA_LANES 4 #define IMX335_REG_MIN 0x00 @@ -99,7 +116,6 @@ static const char * const imx335_supply_name[] = { * @vblank_min: Minimum vertical blanking in lines * @vblank_max: Maximum vertical blanking in lines * @pclk: Sensor pixel clock - * @link_freq_idx: Link frequency index * @reg_list: Register list for sensor mode */ struct imx335_mode { @@ -111,7 +127,6 @@ struct imx335_mode { u32 vblank_min; u32 vblank_max; u64 pclk; - u32 link_freq_idx; struct imx335_reg_list reg_list; }; @@ -134,6 +149,7 @@ struct imx335_mode { * @vblank: Vertical blanking in lines * @cur_mode: Pointer to current selected sensor mode * @mutex: Mutex for serializing sensor controls + * @link_freq_bitmap: Menu bitmap for link_freq_ctrl * @cur_mbus_code: Currently selected media bus format code */ struct imx335 { @@ -157,19 +173,46 @@ struct imx335 { u32 vblank; const struct imx335_mode *cur_mode; struct mutex mutex; + unsigned long link_freq_bitmap; u32 cur_mbus_code; }; -static const s64 link_freq[] = { - IMX335_LINK_FREQ, +static const char * const imx335_tpg_menu[] = { + "Disabled", + "All 000h", + "All FFFh", + "All 555h", + "All AAAh", + "Toggle 555/AAAh", + "Toggle AAA/555h", + "Toggle 000/555h", + "Toggle 555/000h", + "Toggle 000/FFFh", + "Toggle FFF/000h", + "Horizontal color bars", + "Vertical color bars", +}; + +static const int imx335_tpg_val[] = { + IMX335_TPG_ALL_000, + IMX335_TPG_ALL_000, + IMX335_TPG_ALL_FFF, + IMX335_TPG_ALL_555, + IMX335_TPG_ALL_AAA, + IMX335_TPG_TOG_555_AAA, + IMX335_TPG_TOG_AAA_555, + IMX335_TPG_TOG_000_555, + IMX335_TPG_TOG_555_000, + IMX335_TPG_TOG_000_FFF, + IMX335_TPG_TOG_FFF_000, + IMX335_TPG_H_COLOR_BARS, + IMX335_TPG_V_COLOR_BARS, }; /* Sensor mode registers */ static const struct imx335_reg mode_2592x1940_regs[] = { {0x3000, 0x01}, {0x3002, 0x00}, - {0x300c, 0x3b}, - {0x300d, 0x2a}, {0x3018, 0x04}, {0x302c, 0x3c}, {0x302e, 0x20}, @@ -177,10 +220,6 @@ static const struct imx335_reg mode_2592x1940_regs[] = { {0x3074, 0xc8}, {0x3076, 0x28}, {0x304c, 0x00}, - {0x314c, 0xc6}, - {0x315a, 0x02}, - {0x3168, 0xa0}, - {0x316a, 0x7e}, {0x31a1, 0x00}, {0x3288, 0x21}, {0x328a, 0x02}, @@ -249,7 +288,7 @@ static const struct imx335_reg mode_2592x1940_regs[] = { {0x3794, 0x7a}, {0x3796, 0xa1}, {0x37b0, 0x36}, - {0x3a00, 0x01}, + {0x3a00, 0x00}, }; static const struct imx335_reg raw10_framefmt_regs[] = { @@ -266,6 +305,65 @@ static const struct imx335_reg raw12_framefmt_regs[] = { {0x341d, 0x00}, }; +static const struct imx335_reg mipi_data_rate_1188Mbps[] = { + {0x300c, 0x3b}, + {0x300d, 0x2a}, + {0x314c, 0xc6}, + {0x314d, 0x00}, + {0x315a, 0x02}, + {0x3168, 0xa0}, + {0x316a, 0x7e}, + {0x319e, 0x01}, + {0x3a18, 0x8f}, + {0x3a1a, 0x4f}, + {0x3a1c, 0x47}, + {0x3a1e, 0x37}, + {0x3a1f, 0x01}, + {0x3a20, 0x4f}, + {0x3a22, 0x87}, + {0x3a24, 0x4f}, + {0x3a26, 0x7f}, + {0x3a28, 0x3f}, +}; + +static const struct imx335_reg mipi_data_rate_891Mbps[] = { + {0x300c, 0x3b}, + {0x300d, 0x2a}, + {0x314c, 0x29}, + {0x314d, 0x01}, + {0x315a, 0x06}, + {0x3168, 0xa0}, + {0x316a, 0x7e}, + {0x319e, 0x02}, + {0x3a18, 0x7f}, + {0x3a1a, 0x37}, + {0x3a1c, 0x37}, + {0x3a1e, 0xf7}, + {0x3a20, 0x3f}, + {0x3a22, 0x6f}, + {0x3a24, 0x3f}, + {0x3a26, 0x5f}, + {0x3a28, 0x2f}, +}; + +static const s64 link_freq[] = { + /* Corresponds to 1188Mbps data lane rate */ + IMX335_LINK_FREQ_594MHz, + /* Corresponds to 891Mbps data lane rate */ + IMX335_LINK_FREQ_445MHz, +}; + +static const struct imx335_reg_list link_freq_reglist[] = { + { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_1188Mbps), + .regs = mipi_data_rate_1188Mbps, + }, + { + .num_of_regs = ARRAY_SIZE(mipi_data_rate_891Mbps), + .regs = mipi_data_rate_891Mbps, + }, +}; + static const u32 imx335_mbus_codes[] = { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10, @@ -280,7 +378,6 @@ static const struct imx335_mode supported_mode = { .vblank_min = 2560, .vblank_max = 133060, .pclk = 396000000, - .link_freq_idx = 0, .reg_list = { .num_of_regs = ARRAY_SIZE(mode_2592x1940_regs), .regs = mode_2592x1940_regs, @@ -405,7 +502,8 @@ static int imx335_update_controls(struct imx335 *imx335, { int ret; - ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, mode->link_freq_idx); + ret = __v4l2_ctrl_s_ctrl(imx335->link_freq_ctrl, + __ffs(imx335->link_freq_bitmap)); if (ret) return ret; @@ -456,6 +554,49 @@ error_release_group_hold: return ret; } +static int imx335_update_test_pattern(struct imx335 *imx335, u32 pattern_index) +{ + int ret; + + if (pattern_index >= ARRAY_SIZE(imx335_tpg_val)) + return -EINVAL; + + if (pattern_index) { + const struct imx335_reg tpg_enable_regs[] = { + { 0x3148, 0x10 }, + { 0x3280, 0x00 }, + { 0x329c, 0x01 }, + { 0x32a0, 0x11 }, + { 0x3302, 0x00 }, + { 0x3303, 0x00 }, + { 0x336c, 0x00 }, + }; + + ret = imx335_write_reg(imx335, IMX335_REG_TPG, 1, + imx335_tpg_val[pattern_index]); + if (ret) + return ret; + + ret = imx335_write_regs(imx335, tpg_enable_regs, + ARRAY_SIZE(tpg_enable_regs)); + } else { + const struct imx335_reg tpg_disable_regs[] = { + { 0x3148, 0x00 }, + { 0x3280, 0x01 }, + { 0x329c, 0x00 }, + { 0x32a0, 0x10 }, + { 0x3302, 0x32 }, + { 0x3303, 0x00 }, + { 0x336c, 0x01 }, + }; + + ret = imx335_write_regs(imx335, tpg_disable_regs, + ARRAY_SIZE(tpg_disable_regs)); + } + + return ret; +} + /** * imx335_set_ctrl() - Set subdevice control * @ctrl: pointer to v4l2_ctrl structure @@ -476,26 +617,31 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) u32 exposure; int ret; - switch (ctrl->id) { - case V4L2_CID_VBLANK: + /* Propagate change of current control to all related controls */ + if (ctrl->id == V4L2_CID_VBLANK) { imx335->vblank = imx335->vblank_ctrl->val; dev_dbg(imx335->dev, "Received vblank %u, new lpfr %u\n", imx335->vblank, imx335->vblank + imx335->cur_mode->height); - ret = __v4l2_ctrl_modify_range(imx335->exp_ctrl, - IMX335_EXPOSURE_MIN, - imx335->vblank + - imx335->cur_mode->height - - IMX335_EXPOSURE_OFFSET, - 1, IMX335_EXPOSURE_DEFAULT); - break; - case V4L2_CID_EXPOSURE: - /* Set controls only if sensor is in power on state */ - if (!pm_runtime_get_if_in_use(imx335->dev)) - return 0; + return __v4l2_ctrl_modify_range(imx335->exp_ctrl, + IMX335_EXPOSURE_MIN, + imx335->vblank + + imx335->cur_mode->height - + IMX335_EXPOSURE_OFFSET, + 1, IMX335_EXPOSURE_DEFAULT); + } + /* + * Applying V4L2 control value only happens + * when power is up for streaming. + */ + if (pm_runtime_get_if_in_use(imx335->dev) == 0) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: exposure = ctrl->val; analog_gain = imx335->again_ctrl->val; @@ -504,7 +650,9 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) ret = imx335_update_exp_gain(imx335, exposure, analog_gain); - pm_runtime_put(imx335->dev); + break; + case V4L2_CID_TEST_PATTERN: + ret = imx335_update_test_pattern(imx335, ctrl->val); break; default: @@ -512,6 +660,8 @@ static int imx335_set_ctrl(struct v4l2_ctrl *ctrl) ret = -EINVAL; } + pm_runtime_put(imx335->dev); + return ret; } @@ -691,6 +841,13 @@ static int imx335_init_state(struct v4l2_subdev *sd, fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; imx335_fill_pad_format(imx335, &supported_mode, &fmt); + mutex_lock(&imx335->mutex); + __v4l2_ctrl_modify_range(imx335->link_freq_ctrl, 0, + __fls(imx335->link_freq_bitmap), + ~(imx335->link_freq_bitmap), + __ffs(imx335->link_freq_bitmap)); + mutex_unlock(&imx335->mutex); + return imx335_set_pad_format(sd, sd_state, &fmt); } @@ -755,6 +912,14 @@ static int imx335_start_streaming(struct imx335 *imx335) const struct imx335_reg_list *reg_list; int ret; + /* Setup PLL */ + reg_list = &link_freq_reglist[__ffs(imx335->link_freq_bitmap)]; + ret = imx335_write_regs(imx335, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(imx335->dev, "%s failed to set plls\n", __func__); + return ret; + } + /* Write sensor mode registers */ reg_list = &imx335->cur_mode->reg_list; ret = imx335_write_regs(imx335, reg_list->regs, @@ -939,19 +1104,10 @@ static int imx335_parse_hw_config(struct imx335 *imx335) goto done_endpoint_free; } - if (!bus_cfg.nr_of_link_frequencies) { - dev_err(imx335->dev, "no link frequencies defined\n"); - ret = -EINVAL; - goto done_endpoint_free; - } - - for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) - if (bus_cfg.link_frequencies[i] == IMX335_LINK_FREQ) - goto done_endpoint_free; - - dev_err(imx335->dev, "no compatible link frequencies found\n"); - - ret = -EINVAL; + ret = v4l2_link_freq_to_bitmap(imx335->dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + link_freq, ARRAY_SIZE(link_freq), + &imx335->link_freq_bitmap); done_endpoint_free: v4l2_fwnode_endpoint_free(&bus_cfg); @@ -1055,7 +1211,7 @@ static int imx335_init_controls(struct imx335 *imx335) u32 lpfr; int ret; - ret = v4l2_ctrl_handler_init(ctrl_hdlr, 6); + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 7); if (ret) return ret; @@ -1089,6 +1245,12 @@ static int imx335_init_controls(struct imx335 *imx335) mode->vblank_max, 1, mode->vblank); + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, + &imx335_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx335_tpg_menu) - 1, + 0, 0, imx335_tpg_menu); + /* Read only controls */ imx335->pclk_ctrl = v4l2_ctrl_new_std(ctrl_hdlr, &imx335_ctrl_ops, @@ -1099,9 +1261,8 @@ static int imx335_init_controls(struct imx335 *imx335) imx335->link_freq_ctrl = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx335_ctrl_ops, V4L2_CID_LINK_FREQ, - ARRAY_SIZE(link_freq) - - 1, - mode->link_freq_idx, + __fls(imx335->link_freq_bitmap), + __ffs(imx335->link_freq_bitmap), link_freq); if (imx335->link_freq_ctrl) imx335->link_freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 596200d0248c..f4b481212356 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -1078,7 +1078,7 @@ mt9p031_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = of_graph_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!np) return NULL; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 6dfbd1c56c22..302120ff125e 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -1006,7 +1006,7 @@ mt9v032_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - np = of_graph_get_next_endpoint(client->dev.of_node, NULL); + np = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!np) return NULL; diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 1d0ef72a6403..d1653d7431d0 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1388,7 +1388,7 @@ ov2659_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!endpoint) return NULL; diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index a26ac11c989d..3b22b9e12787 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -118,7 +118,6 @@ static inline struct ov5645 *to_ov5645(struct v4l2_subdev *sd) static const struct reg_value ov5645_global_init_setting[] = { { 0x3103, 0x11 }, - { 0x3008, 0x82 }, { 0x3008, 0x42 }, { 0x3103, 0x03 }, { 0x3503, 0x07 }, @@ -627,6 +626,10 @@ static int ov5645_set_register_array(struct ov5645 *ov5645, ret = ov5645_write_reg(ov5645, settings->reg, settings->val); if (ret < 0) return ret; + + if (settings->reg == OV5645_SYSTEM_CTRL0 && + settings->val == OV5645_SYSTEM_CTRL0_START) + usleep_range(1000, 2000); } return 0; @@ -1056,7 +1059,7 @@ static int ov5645_probe(struct i2c_client *client) ov5645->i2c_client = client; ov5645->dev = dev; - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); if (!endpoint) { dev_err(dev, "endpoint node not found\n"); return -EINVAL; diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index 96c0fd4ff5ab..7e1ecdf2485f 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -1363,7 +1363,7 @@ static int ov5647_parse_dt(struct ov5647 *sensor, struct device_node *np) struct device_node *ep; int ret; - ep = of_graph_get_next_endpoint(np, NULL); + ep = of_graph_get_endpoint_by_regs(np, 0, -1); if (!ep) return -EINVAL; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index af8d01f78c32..cf6be509af33 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1568,7 +1568,7 @@ static int s5c73m3_get_dt_data(struct s5c73m3 *state) "failed to request gpio S5C73M3_RST\n"); gpiod_set_consumer_name(state->reset, "S5C73M3_RST"); - node_ep = of_graph_get_next_endpoint(node, NULL); + node_ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!node_ep) { dev_warn(dev, "no endpoint defined for node: %pOF\n", node); return 0; diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index de079d2c9282..6b11039c3579 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1849,7 +1849,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) state->mclk_frequency); } - node_ep = of_graph_get_next_endpoint(node, NULL); + node_ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!node_ep) { dev_err(dev, "no endpoint defined at node %pOF\n", node); return -EINVAL; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 558152575d10..3192a334aaab 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1895,7 +1895,7 @@ static int tc358743_probe_of(struct tc358743_state *state) return dev_err_probe(dev, PTR_ERR(refclk), "failed to get refclk\n"); - ep = of_graph_get_next_endpoint(dev->of_node, NULL); + ep = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); if (!ep) { dev_err(dev, "missing endpoint node\n"); return -EINVAL; diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 1ea703a9909f..8e4a0718c4b6 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -2310,7 +2310,7 @@ static int tda1997x_parse_dt(struct tda1997x_state *state) pdata->vidout_sel_de = DE_FREF_SEL_DE_VHREF; np = state->client->dev.of_node; - ep = of_graph_get_next_endpoint(np, NULL); + ep = of_graph_get_endpoint_by_regs(np, 0, -1); if (!ep) return -EINVAL; diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 5a561e5bf659..f9c9c80c33ac 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -987,7 +987,7 @@ tvp514x_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!endpoint) return NULL; diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 30831b4b56d6..6a04ffae5343 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -893,7 +893,7 @@ tvp7002_get_pdata(struct i2c_client *client) if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; - endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL); + endpoint = of_graph_get_endpoint_by_regs(client->dev.of_node, 0, -1); if (!endpoint) return NULL; diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c index f980e3125a7b..e994db4f4d91 100644 --- a/drivers/media/pci/intel/ipu-bridge.c +++ b/drivers/media/pci/intel/ipu-bridge.c @@ -2,6 +2,7 @@ /* Author: Dan Scally <djrscally@gmail.com> */ #include <linux/acpi.h> +#include <linux/cleanup.h> #include <linux/device.h> #include <linux/i2c.h> #include <linux/mei_cl_bus.h> @@ -60,6 +61,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000), /* GalaxyCore GC0310 */ IPU_SENSOR_CONFIG("INT0310", 0), + /* Omnivision ov01a10 */ + IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000), }; static const struct ipu_property_names prop_names = { @@ -747,6 +750,24 @@ static int ipu_bridge_ivsc_is_ready(void) return ready; } +static int ipu_bridge_check_fwnode_graph(struct fwnode_handle *fwnode) +{ + struct fwnode_handle *endpoint; + + if (IS_ERR_OR_NULL(fwnode)) + return -EINVAL; + + endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (endpoint) { + fwnode_handle_put(endpoint); + return 0; + } + + return ipu_bridge_check_fwnode_graph(fwnode->secondary); +} + +static DEFINE_MUTEX(ipu_bridge_mutex); + int ipu_bridge_init(struct device *dev, ipu_parse_sensor_fwnode_t parse_sensor_fwnode) { @@ -755,6 +776,11 @@ int ipu_bridge_init(struct device *dev, unsigned int i; int ret; + guard(mutex)(&ipu_bridge_mutex); + + if (!ipu_bridge_check_fwnode_graph(dev_fwnode(dev))) + return 0; + if (!ipu_bridge_ivsc_is_ready()) return -EPROBE_DEFER; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 83e29c56fe33..c42adc5a408d 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1667,29 +1667,12 @@ static void cio2_queues_exit(struct cio2_device *cio2) cio2_queue_exit(cio2, &cio2->queue[i]); } -static int cio2_check_fwnode_graph(struct fwnode_handle *fwnode) -{ - struct fwnode_handle *endpoint; - - if (IS_ERR_OR_NULL(fwnode)) - return -EINVAL; - - endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); - if (endpoint) { - fwnode_handle_put(endpoint); - return 0; - } - - return cio2_check_fwnode_graph(fwnode->secondary); -} - /**************** PCI interface ****************/ static int cio2_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { struct device *dev = &pci_dev->dev; - struct fwnode_handle *fwnode = dev_fwnode(dev); struct cio2_device *cio2; int r; @@ -1698,17 +1681,9 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, * if the device has no endpoints then we can try to build those as * software_nodes parsed from SSDB. */ - r = cio2_check_fwnode_graph(fwnode); - if (r) { - if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) { - dev_err(dev, "fwnode graph has no endpoints connected\n"); - return -EINVAL; - } - - r = ipu_bridge_init(dev, ipu_bridge_parse_ssdb); - if (r) - return r; - } + r = ipu_bridge_init(dev, ipu_bridge_parse_ssdb); + if (r) + return r; cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL); if (!cio2) diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c index 15b905f66ab7..55e0c60c420c 100644 --- a/drivers/media/pci/intel/ivsc/mei_csi.c +++ b/drivers/media/pci/intel/ivsc/mei_csi.c @@ -71,8 +71,8 @@ enum ivsc_privacy_status { }; enum csi_pads { - CSI_PAD_SOURCE, CSI_PAD_SINK, + CSI_PAD_SOURCE, CSI_NUM_PADS }; @@ -128,7 +128,6 @@ struct mei_csi { int streaming; struct media_pad pads[CSI_NUM_PADS]; - struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS]; /* number of data lanes used on the CSI-2 link */ u32 nr_of_lanes; @@ -329,58 +328,17 @@ err: return ret; } -static struct v4l2_mbus_framefmt * -mei_csi_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - struct mei_csi *csi = sd_to_csi(sd); - - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_state_get_format(sd_state, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &csi->format_mbus[pad]; - default: - return NULL; - } -} - static int mei_csi_init_state(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state) { struct v4l2_mbus_framefmt *mbusformat; - struct mei_csi *csi = sd_to_csi(sd); unsigned int i; - mutex_lock(&csi->lock); - for (i = 0; i < sd->entity.num_pads; i++) { mbusformat = v4l2_subdev_state_get_format(sd_state, i); *mbusformat = mei_csi_format_mbus_default; } - mutex_unlock(&csi->lock); - - return 0; -} - -static int mei_csi_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct v4l2_mbus_framefmt *mbusformat; - struct mei_csi *csi = sd_to_csi(sd); - - mutex_lock(&csi->lock); - - mbusformat = mei_csi_get_pad_format(sd, sd_state, format->pad, - format->which); - if (mbusformat) - format->format = *mbusformat; - - mutex_unlock(&csi->lock); - return 0; } @@ -388,20 +346,17 @@ static int mei_csi_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct v4l2_mbus_framefmt *source_mbusformat; - struct v4l2_mbus_framefmt *mbusformat; - struct mei_csi *csi = sd_to_csi(sd); - struct media_pad *pad; + struct v4l2_mbus_framefmt *source_fmt; + struct v4l2_mbus_framefmt *sink_fmt; - mbusformat = mei_csi_get_pad_format(sd, sd_state, format->pad, - format->which); - if (!mbusformat) - return -EINVAL; + sink_fmt = v4l2_subdev_state_get_format(sd_state, CSI_PAD_SINK); + source_fmt = v4l2_subdev_state_get_format(sd_state, CSI_PAD_SOURCE); - source_mbusformat = mei_csi_get_pad_format(sd, sd_state, CSI_PAD_SOURCE, - format->which); - if (!source_mbusformat) - return -EINVAL; + if (format->pad) { + *source_fmt = *sink_fmt; + + return 0; + } v4l_bound_align_image(&format->format.width, 1, 65536, 0, &format->format.height, 1, 65536, 0, 0); @@ -504,18 +459,8 @@ static int mei_csi_set_fmt(struct v4l2_subdev *sd, if (format->format.field == V4L2_FIELD_ANY) format->format.field = V4L2_FIELD_NONE; - mutex_lock(&csi->lock); - - pad = &csi->pads[format->pad]; - if (pad->flags & MEDIA_PAD_FL_SOURCE) - format->format = csi->format_mbus[CSI_PAD_SINK]; - - *mbusformat = format->format; - - if (pad->flags & MEDIA_PAD_FL_SINK) - *source_mbusformat = format->format; - - mutex_unlock(&csi->lock); + *sink_fmt = format->format; + *source_fmt = *sink_fmt; return 0; } @@ -554,7 +499,7 @@ static const struct v4l2_subdev_video_ops mei_csi_video_ops = { }; static const struct v4l2_subdev_pad_ops mei_csi_pad_ops = { - .get_fmt = mei_csi_get_fmt, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = mei_csi_set_fmt, }; @@ -587,7 +532,7 @@ static int mei_csi_notify_bound(struct v4l2_async_notifier *notifier, csi->remote_pad = pad; return media_create_pad_link(&subdev->entity, pad, - &csi->subdev.entity, 1, + &csi->subdev.entity, CSI_PAD_SINK, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); } @@ -749,6 +694,7 @@ static int mei_csi_probe(struct mei_cl_device *cldev, goto err_disable; csi->subdev.dev = &cldev->dev; + csi->subdev.state_lock = &csi->lock; v4l2_subdev_init(&csi->subdev, &mei_csi_subdev_ops); csi->subdev.internal_ops = &mei_csi_internal_ops; v4l2_set_subdevdata(&csi->subdev, csi); @@ -764,9 +710,6 @@ static int mei_csi_probe(struct mei_cl_device *cldev, if (ret) goto err_ctrl_handler; - csi->format_mbus[CSI_PAD_SOURCE] = mei_csi_format_mbus_default; - csi->format_mbus[CSI_PAD_SINK] = mei_csi_format_mbus_default; - csi->pads[CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; csi->pads[CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK; ret = media_entity_pads_init(&csi->subdev.entity, CSI_NUM_PADS, diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index f8450a8ccda6..c1108df72dd5 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -834,7 +834,7 @@ static int atmel_isi_parse_dt(struct atmel_isi *isi, isi->pdata.full_mode = 1; isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL; - np = of_graph_get_next_endpoint(np, NULL); + np = of_graph_get_endpoint_by_regs(np, 0, -1); if (!np) { dev_err(&pdev->dev, "Could not find the endpoint\n"); return -EINVAL; @@ -1158,7 +1158,7 @@ static int isi_graph_init(struct atmel_isi *isi) struct device_node *ep; int ret; - ep = of_graph_get_next_endpoint(isi->dev->of_node, NULL); + ep = of_graph_get_endpoint_by_regs(isi->dev->of_node, 0, -1); if (!ep) return -EINVAL; diff --git a/drivers/media/platform/intel/pxa_camera.c b/drivers/media/platform/intel/pxa_camera.c index 59b89e421dc2..d904952bf00e 100644 --- a/drivers/media/platform/intel/pxa_camera.c +++ b/drivers/media/platform/intel/pxa_camera.c @@ -2207,7 +2207,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, pcdev->mclk = mclk_rate; } - np = of_graph_get_next_endpoint(np, NULL); + np = of_graph_get_endpoint_by_regs(np, 0, -1); if (!np) { dev_err(dev, "could not find endpoint\n"); return -EINVAL; diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-is.c b/drivers/media/platform/samsung/exynos4-is/fimc-is.c index a08c87ef6e2d..39aab667910d 100644 --- a/drivers/media/platform/samsung/exynos4-is/fimc-is.c +++ b/drivers/media/platform/samsung/exynos4-is/fimc-is.c @@ -175,7 +175,7 @@ static int fimc_is_parse_sensor_config(struct fimc_is *is, unsigned int index, return -EINVAL; } - ep = of_graph_get_next_endpoint(node, NULL); + ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!ep) return -ENXIO; diff --git a/drivers/media/platform/samsung/exynos4-is/mipi-csis.c b/drivers/media/platform/samsung/exynos4-is/mipi-csis.c index aae8a8b2c0f4..4b9b20ba3504 100644 --- a/drivers/media/platform/samsung/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/samsung/exynos4-is/mipi-csis.c @@ -727,7 +727,8 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, &state->max_num_lanes)) return -EINVAL; - node = of_graph_get_next_endpoint(node, NULL); + /* from port@3 or port@4 */ + node = of_graph_get_endpoint_by_regs(node, -1, -1); if (!node) { dev_err(&pdev->dev, "No port node at %pOF\n", pdev->dev.of_node); diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c index c4610e305546..ff3331af9406 100644 --- a/drivers/media/platform/st/stm32/stm32-dcmi.c +++ b/drivers/media/platform/st/stm32/stm32-dcmi.c @@ -1855,7 +1855,7 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) struct device_node *ep; int ret; - ep = of_graph_get_next_endpoint(dcmi->dev->of_node, NULL); + ep = of_graph_get_endpoint_by_regs(dcmi->dev->of_node, 0, -1); if (!ep) { dev_err(dcmi->dev, "Failed to get next endpoint\n"); return -EINVAL; @@ -1907,7 +1907,7 @@ static int dcmi_probe(struct platform_device *pdev) "Could not get reset control\n"); /* Get bus characteristics from devicetree */ - np = of_graph_get_next_endpoint(np, NULL); + np = of_graph_get_endpoint_by_regs(np, 0, -1); if (!np) { dev_err(&pdev->dev, "Could not find the endpoint\n"); return -ENODEV; diff --git a/drivers/media/platform/ti/davinci/vpif.c b/drivers/media/platform/ti/davinci/vpif.c index 63cdfed37bc9..f4e1fa76bf37 100644 --- a/drivers/media/platform/ti/davinci/vpif.c +++ b/drivers/media/platform/ti/davinci/vpif.c @@ -465,8 +465,7 @@ static int vpif_probe(struct platform_device *pdev) * so their devices need to be registered manually here * for their legacy platform_drivers to work. */ - endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, - endpoint); + endpoint = of_graph_get_endpoint_by_regs(pdev->dev.of_node, 0, -1); if (!endpoint) return 0; of_node_put(endpoint); |