Lines Matching +full:sd +full:- +full:hs
1 // SPDX-License-Identifier: GPL-2.0
5 * lt7911d type-c/DP to MIPI CSI-2 bridge driver.
7 * Author: Jianwei Fan <jianwei.fan@rock-chips.com>
24 #include <linux/rk-camera-module.h>
27 #include <linux/v4l2-dv-timings.h>
32 #include <media/v4l2-controls_rockchip.h>
33 #include <media/v4l2-ctrls.h>
34 #include <media/v4l2-device.h>
35 #include <media/v4l2-dv-timings.h>
36 #include <media/v4l2-event.h>
37 #include <media/v4l2-fwnode.h>
44 MODULE_PARM_DESC(debug, "debug level (0-3)");
66 struct v4l2_subdev sd; member
168 static void lt7911d_format_change(struct v4l2_subdev *sd);
169 static int lt7911d_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd);
170 static int lt7911d_s_dv_timings(struct v4l2_subdev *sd,
173 static inline struct lt7911d_state *to_state(struct v4l2_subdev *sd) in to_state() argument
175 return container_of(sd, struct lt7911d_state, sd); in to_state()
178 static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) in i2c_rd() argument
180 struct lt7911d_state *lt7911d = to_state(sd); in i2c_rd()
181 struct i2c_client *client = lt7911d->i2c_client; in i2c_rd()
187 msgs[0].addr = client->addr; in i2c_rd()
192 msgs[1].addr = client->addr; in i2c_rd()
197 msgs[2].addr = client->addr; in i2c_rd()
202 err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in i2c_rd()
204 v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n", in i2c_rd()
205 __func__, reg, client->addr); in i2c_rd()
213 v4l2_info(sd, "I2C read 0x%04x = 0x%02x\n", in i2c_rd()
217 v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x\n", in i2c_rd()
221 v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x%02x%02x\n", in i2c_rd()
225 v4l2_info(sd, "I2C read %d bytes from address 0x%04x\n", in i2c_rd()
230 static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) in i2c_wr() argument
232 struct lt7911d_state *lt7911d = to_state(sd); in i2c_wr()
233 struct i2c_client *client = lt7911d->i2c_client; in i2c_wr()
240 n = I2C_MAX_XFER_SIZE - 1; in i2c_wr()
241 v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", in i2c_wr()
245 msgs[0].addr = client->addr; in i2c_wr()
250 msgs[1].addr = client->addr; in i2c_wr()
259 err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in i2c_wr()
261 v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n", in i2c_wr()
262 __func__, reg, client->addr); in i2c_wr()
271 v4l2_info(sd, "I2C write 0x%04x = 0x%02x\n", in i2c_wr()
275 v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x\n", in i2c_wr()
279 v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x%02x%02x\n", in i2c_wr()
283 v4l2_info(sd, "I2C write %d bytes from address 0x%04x\n", in i2c_wr()
288 static u8 i2c_rd8(struct v4l2_subdev *sd, u16 reg) in i2c_rd8() argument
292 i2c_rd(sd, reg, (u8 __force *)&val, 1); in i2c_rd8()
296 static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val) in i2c_wr8() argument
298 i2c_wr(sd, reg, &val, 1); in i2c_wr8()
301 static void lt7911d_i2c_enable(struct v4l2_subdev *sd) in lt7911d_i2c_enable() argument
303 i2c_wr8(sd, I2C_EN_REG, I2C_ENABLE); in lt7911d_i2c_enable()
306 static void lt7911d_i2c_disable(struct v4l2_subdev *sd) in lt7911d_i2c_disable() argument
308 i2c_wr8(sd, I2C_EN_REG, I2C_DISABLE); in lt7911d_i2c_disable()
311 static inline bool tx_5v_power_present(struct v4l2_subdev *sd) in tx_5v_power_present() argument
315 struct lt7911d_state *lt7911d = to_state(sd); in tx_5v_power_present()
318 if (!lt7911d->plugin_det_gpio) in tx_5v_power_present()
323 val = gpiod_get_value(lt7911d->plugin_det_gpio); in tx_5v_power_present()
330 v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret); in tx_5v_power_present()
335 static inline bool no_signal(struct v4l2_subdev *sd) in no_signal() argument
337 struct lt7911d_state *lt7911d = to_state(sd); in no_signal()
339 v4l2_dbg(1, debug, sd, "%s no signal:%d\n", __func__, in no_signal()
340 lt7911d->nosignal); in no_signal()
342 return lt7911d->nosignal; in no_signal()
345 static inline bool audio_present(struct v4l2_subdev *sd) in audio_present() argument
347 struct lt7911d_state *lt7911d = to_state(sd); in audio_present()
349 return lt7911d->is_audio_present; in audio_present()
352 static int get_audio_sampling_rate(struct v4l2_subdev *sd) in get_audio_sampling_rate() argument
359 if (no_signal(sd)) in get_audio_sampling_rate()
370 return DIV_ROUND_CLOSEST((unsigned int)t->pixelclock, in fps_calc()
374 static bool lt7911d_rcv_supported_res(struct v4l2_subdev *sd, u32 width, in lt7911d_rcv_supported_res() argument
387 v4l2_err(sd, "%s do not support res wxh: %dx%d\n", __func__, in lt7911d_rcv_supported_res()
395 static int lt7911d_get_detected_timings(struct v4l2_subdev *sd, in lt7911d_get_detected_timings() argument
398 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_get_detected_timings()
399 struct v4l2_bt_timings *bt = &timings->bt; in lt7911d_get_detected_timings()
401 u32 hbp, hs, hfp, vbp, vs, vfp; in lt7911d_get_detected_timings() local
408 lt7911d_i2c_enable(sd); in lt7911d_get_detected_timings()
409 i2c_wr8(sd, FM_CLK_SEL, AD_HALF_PIX_CLK); in lt7911d_get_detected_timings()
411 clk_h = i2c_rd8(sd, FREQ_METER_H); in lt7911d_get_detected_timings()
412 clk_m = i2c_rd8(sd, FREQ_METER_M); in lt7911d_get_detected_timings()
413 clk_l = i2c_rd8(sd, FREQ_METER_L); in lt7911d_get_detected_timings()
417 i2c_wr8(sd, RG_MK_PRESET_SEL, SOURCE_DP_RX); in lt7911d_get_detected_timings()
419 val_h = i2c_rd8(sd, HTOTAL_H); in lt7911d_get_detected_timings()
420 val_l = i2c_rd8(sd, HTOTAL_L); in lt7911d_get_detected_timings()
422 val_h = i2c_rd8(sd, VTOTAL_H); in lt7911d_get_detected_timings()
423 val_l = i2c_rd8(sd, VTOTAL_L); in lt7911d_get_detected_timings()
425 val_h = i2c_rd8(sd, HACT_H); in lt7911d_get_detected_timings()
426 val_l = i2c_rd8(sd, HACT_L); in lt7911d_get_detected_timings()
428 val_h = i2c_rd8(sd, VACT_H); in lt7911d_get_detected_timings()
429 val_l = i2c_rd8(sd, VACT_L); in lt7911d_get_detected_timings()
431 val_h = i2c_rd8(sd, HS_H); in lt7911d_get_detected_timings()
432 val_l = i2c_rd8(sd, HS_L); in lt7911d_get_detected_timings()
433 hs = ((val_h << 8) | val_l) * 2; in lt7911d_get_detected_timings()
434 value = i2c_rd8(sd, VS); in lt7911d_get_detected_timings()
436 val_h = i2c_rd8(sd, HFP_H); in lt7911d_get_detected_timings()
437 val_l = i2c_rd8(sd, HFP_L); in lt7911d_get_detected_timings()
439 value = i2c_rd8(sd, VFP); in lt7911d_get_detected_timings()
441 val_h = i2c_rd8(sd, HBP_H); in lt7911d_get_detected_timings()
442 val_l = i2c_rd8(sd, HBP_L); in lt7911d_get_detected_timings()
444 value = i2c_rd8(sd, VBP); in lt7911d_get_detected_timings()
447 lt7911d_i2c_disable(sd); in lt7911d_get_detected_timings()
449 if (!lt7911d_rcv_supported_res(sd, hact, vact)) { in lt7911d_get_detected_timings()
450 lt7911d->nosignal = true; in lt7911d_get_detected_timings()
451 v4l2_err(sd, "%s: rcv err res, return no signal!\n", __func__); in lt7911d_get_detected_timings()
452 return -EINVAL; in lt7911d_get_detected_timings()
455 lt7911d->nosignal = false; in lt7911d_get_detected_timings()
456 lt7911d->is_audio_present = true; in lt7911d_get_detected_timings()
457 timings->type = V4L2_DV_BT_656_1120; in lt7911d_get_detected_timings()
458 bt->interlaced = V4L2_DV_PROGRESSIVE; in lt7911d_get_detected_timings()
459 bt->width = hact; in lt7911d_get_detected_timings()
460 bt->height = vact; in lt7911d_get_detected_timings()
461 bt->vsync = vs; in lt7911d_get_detected_timings()
462 bt->hsync = hs; in lt7911d_get_detected_timings()
463 bt->pixelclock = pixel_clock; in lt7911d_get_detected_timings()
464 bt->hfrontporch = hfp; in lt7911d_get_detected_timings()
465 bt->vfrontporch = vfp; in lt7911d_get_detected_timings()
466 bt->hbackporch = hbp; in lt7911d_get_detected_timings()
467 bt->vbackporch = vbp; in lt7911d_get_detected_timings()
470 v4l2_info(sd, "act:%dx%d, total:%dx%d, pixclk:%d, fps:%d\n", in lt7911d_get_detected_timings()
472 v4l2_info(sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d\n", in lt7911d_get_detected_timings()
473 bt->hfrontporch, bt->hsync, bt->hbackporch, in lt7911d_get_detected_timings()
474 bt->vfrontporch, bt->vsync, bt->vbackporch); in lt7911d_get_detected_timings()
475 v4l2_info(sd, "inerlaced:%d,\n", bt->interlaced); in lt7911d_get_detected_timings()
485 struct v4l2_subdev *sd = <7911d->sd; in lt7911d_delayed_work_enable_hotplug() local
487 v4l2_ctrl_s_ctrl(lt7911d->detect_tx_5v_ctrl, tx_5v_power_present(sd)); in lt7911d_delayed_work_enable_hotplug()
495 struct v4l2_subdev *sd = <7911d->sd; in lt7911d_delayed_work_res_change() local
497 lt7911d_format_change(sd); in lt7911d_delayed_work_res_change()
500 static int lt7911d_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd) in lt7911d_s_ctrl_detect_tx_5v() argument
502 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_s_ctrl_detect_tx_5v()
504 return v4l2_ctrl_s_ctrl(lt7911d->detect_tx_5v_ctrl, in lt7911d_s_ctrl_detect_tx_5v()
505 tx_5v_power_present(sd)); in lt7911d_s_ctrl_detect_tx_5v()
508 static int lt7911d_s_ctrl_audio_sampling_rate(struct v4l2_subdev *sd) in lt7911d_s_ctrl_audio_sampling_rate() argument
510 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_s_ctrl_audio_sampling_rate()
512 return v4l2_ctrl_s_ctrl(lt7911d->audio_sampling_rate_ctrl, in lt7911d_s_ctrl_audio_sampling_rate()
513 get_audio_sampling_rate(sd)); in lt7911d_s_ctrl_audio_sampling_rate()
516 static int lt7911d_s_ctrl_audio_present(struct v4l2_subdev *sd) in lt7911d_s_ctrl_audio_present() argument
518 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_s_ctrl_audio_present()
520 return v4l2_ctrl_s_ctrl(lt7911d->audio_present_ctrl, in lt7911d_s_ctrl_audio_present()
521 audio_present(sd)); in lt7911d_s_ctrl_audio_present()
524 static int lt7911d_update_controls(struct v4l2_subdev *sd) in lt7911d_update_controls() argument
528 ret |= lt7911d_s_ctrl_detect_tx_5v(sd); in lt7911d_update_controls()
529 ret |= lt7911d_s_ctrl_audio_sampling_rate(sd); in lt7911d_update_controls()
530 ret |= lt7911d_s_ctrl_audio_present(sd); in lt7911d_update_controls()
535 static inline void enable_stream(struct v4l2_subdev *sd, bool enable) in enable_stream() argument
537 v4l2_dbg(2, debug, sd, "%s: %sable\n", in enable_stream()
541 static void lt7911d_format_change(struct v4l2_subdev *sd) in lt7911d_format_change() argument
543 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_format_change()
550 if (lt7911d_get_detected_timings(sd, &timings)) { in lt7911d_format_change()
551 enable_stream(sd, false); in lt7911d_format_change()
553 v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); in lt7911d_format_change()
555 if (!v4l2_match_dv_timings(<7911d->timings, &timings, 0, false)) { in lt7911d_format_change()
556 enable_stream(sd, false); in lt7911d_format_change()
558 lt7911d_s_dv_timings(sd, &timings); in lt7911d_format_change()
559 v4l2_print_dv_timings(sd->name, in lt7911d_format_change()
565 if (sd->devnode) in lt7911d_format_change()
566 v4l2_subdev_notify_event(sd, <7911d_ev_fmt); in lt7911d_format_change()
569 static int lt7911d_isr(struct v4l2_subdev *sd, u32 status, bool *handled) in lt7911d_isr() argument
571 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_isr()
573 schedule_delayed_work(<7911d->delayed_work_res_change, HZ / 20); in lt7911d_isr()
584 lt7911d_isr(<7911d->sd, 0, &handled); in lt7911d_res_change_irq_handler()
594 schedule_delayed_work(<7911d->delayed_work_enable_hotplug, in plugin_detect_irq_handler()
604 schedule_work(<7911d->work_i2c_poll); in lt7911d_irq_poll_timer()
605 mod_timer(<7911d->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS)); in lt7911d_irq_poll_timer()
612 struct v4l2_subdev *sd = <7911d->sd; in lt7911d_work_i2c_poll() local
614 lt7911d_format_change(sd); in lt7911d_work_i2c_poll()
617 static int lt7911d_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, in lt7911d_subscribe_event() argument
620 switch (sub->type) { in lt7911d_subscribe_event()
622 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); in lt7911d_subscribe_event()
624 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); in lt7911d_subscribe_event()
626 return -EINVAL; in lt7911d_subscribe_event()
630 static int lt7911d_g_input_status(struct v4l2_subdev *sd, u32 *status) in lt7911d_g_input_status() argument
633 *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0; in lt7911d_g_input_status()
635 v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status); in lt7911d_g_input_status()
640 static int lt7911d_s_dv_timings(struct v4l2_subdev *sd, in lt7911d_s_dv_timings() argument
643 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_s_dv_timings()
646 return -EINVAL; in lt7911d_s_dv_timings()
649 v4l2_print_dv_timings(sd->name, "s_dv_timings: ", in lt7911d_s_dv_timings()
652 if (v4l2_match_dv_timings(<7911d->timings, timings, 0, false)) { in lt7911d_s_dv_timings()
653 v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); in lt7911d_s_dv_timings()
659 v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); in lt7911d_s_dv_timings()
660 return -ERANGE; in lt7911d_s_dv_timings()
663 lt7911d->timings = *timings; in lt7911d_s_dv_timings()
665 enable_stream(sd, false); in lt7911d_s_dv_timings()
670 static int lt7911d_g_dv_timings(struct v4l2_subdev *sd, in lt7911d_g_dv_timings() argument
673 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_g_dv_timings()
675 *timings = lt7911d->timings; in lt7911d_g_dv_timings()
680 static int lt7911d_enum_dv_timings(struct v4l2_subdev *sd, in lt7911d_enum_dv_timings() argument
683 if (timings->pad != 0) in lt7911d_enum_dv_timings()
684 return -EINVAL; in lt7911d_enum_dv_timings()
690 static int lt7911d_query_dv_timings(struct v4l2_subdev *sd, in lt7911d_query_dv_timings() argument
693 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_query_dv_timings()
695 *timings = lt7911d->timings; in lt7911d_query_dv_timings()
697 v4l2_print_dv_timings(sd->name, in lt7911d_query_dv_timings()
702 v4l2_dbg(1, debug, sd, "%s: timings out of range\n", in lt7911d_query_dv_timings()
705 return -ERANGE; in lt7911d_query_dv_timings()
711 static int lt7911d_dv_timings_cap(struct v4l2_subdev *sd, in lt7911d_dv_timings_cap() argument
714 if (cap->pad != 0) in lt7911d_dv_timings_cap()
715 return -EINVAL; in lt7911d_dv_timings_cap()
722 static int lt7911d_g_mbus_config(struct v4l2_subdev *sd, in lt7911d_g_mbus_config() argument
725 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_g_mbus_config()
727 cfg->type = V4L2_MBUS_CSI2_DPHY; in lt7911d_g_mbus_config()
728 cfg->flags = V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | in lt7911d_g_mbus_config()
731 switch (lt7911d->csi_lanes_in_use) { in lt7911d_g_mbus_config()
733 cfg->flags |= V4L2_MBUS_CSI2_1_LANE; in lt7911d_g_mbus_config()
736 cfg->flags |= V4L2_MBUS_CSI2_2_LANE; in lt7911d_g_mbus_config()
739 cfg->flags |= V4L2_MBUS_CSI2_3_LANE; in lt7911d_g_mbus_config()
742 cfg->flags |= V4L2_MBUS_CSI2_4_LANE; in lt7911d_g_mbus_config()
746 return -EINVAL; in lt7911d_g_mbus_config()
752 static int lt7911d_s_stream(struct v4l2_subdev *sd, int enable) in lt7911d_s_stream() argument
754 enable_stream(sd, enable); in lt7911d_s_stream()
759 static int lt7911d_enum_mbus_code(struct v4l2_subdev *sd, in lt7911d_enum_mbus_code() argument
763 switch (code->index) { in lt7911d_enum_mbus_code()
765 code->code = LT7911D_MEDIA_BUS_FMT; in lt7911d_enum_mbus_code()
769 return -EINVAL; in lt7911d_enum_mbus_code()
775 static int lt7911d_enum_frame_sizes(struct v4l2_subdev *sd, in lt7911d_enum_frame_sizes() argument
779 if (fse->index >= ARRAY_SIZE(supported_modes)) in lt7911d_enum_frame_sizes()
780 return -EINVAL; in lt7911d_enum_frame_sizes()
782 if (fse->code != LT7911D_MEDIA_BUS_FMT) in lt7911d_enum_frame_sizes()
783 return -EINVAL; in lt7911d_enum_frame_sizes()
785 fse->min_width = supported_modes[fse->index].width; in lt7911d_enum_frame_sizes()
786 fse->max_width = supported_modes[fse->index].width; in lt7911d_enum_frame_sizes()
787 fse->max_height = supported_modes[fse->index].height; in lt7911d_enum_frame_sizes()
788 fse->min_height = supported_modes[fse->index].height; in lt7911d_enum_frame_sizes()
793 static int lt7911d_get_fmt(struct v4l2_subdev *sd, in lt7911d_get_fmt() argument
797 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_get_fmt()
799 mutex_lock(<7911d->confctl_mutex); in lt7911d_get_fmt()
800 format->format.code = lt7911d->mbus_fmt_code; in lt7911d_get_fmt()
801 format->format.width = lt7911d->timings.bt.width; in lt7911d_get_fmt()
802 format->format.height = lt7911d->timings.bt.height; in lt7911d_get_fmt()
803 format->format.field = in lt7911d_get_fmt()
804 lt7911d->timings.bt.interlaced ? in lt7911d_get_fmt()
806 format->format.colorspace = V4L2_COLORSPACE_SRGB; in lt7911d_get_fmt()
807 mutex_unlock(<7911d->confctl_mutex); in lt7911d_get_fmt()
809 v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n", in lt7911d_get_fmt()
810 __func__, format->format.code, format->format.width, in lt7911d_get_fmt()
811 format->format.height, format->format.field); in lt7911d_get_fmt()
816 static int lt7911d_enum_frame_interval(struct v4l2_subdev *sd, in lt7911d_enum_frame_interval() argument
820 if (fie->index >= ARRAY_SIZE(supported_modes)) in lt7911d_enum_frame_interval()
821 return -EINVAL; in lt7911d_enum_frame_interval()
823 fie->code = LT7911D_MEDIA_BUS_FMT; in lt7911d_enum_frame_interval()
825 fie->width = supported_modes[fie->index].width; in lt7911d_enum_frame_interval()
826 fie->height = supported_modes[fie->index].height; in lt7911d_enum_frame_interval()
827 fie->interval = supported_modes[fie->index].max_fps; in lt7911d_enum_frame_interval()
835 return abs(mode->width - framefmt->width) + in lt7911d_get_reso_dist()
836 abs(mode->height - framefmt->height); in lt7911d_get_reso_dist()
842 struct v4l2_mbus_framefmt *framefmt = &fmt->format; in lt7911d_find_best_fit()
845 int cur_best_fit_dist = -1; in lt7911d_find_best_fit()
850 if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { in lt7911d_find_best_fit()
859 static int lt7911d_set_fmt(struct v4l2_subdev *sd, in lt7911d_set_fmt() argument
863 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_set_fmt()
867 u32 code = format->format.code; in lt7911d_set_fmt()
868 int ret = lt7911d_get_fmt(sd, cfg, format); in lt7911d_set_fmt()
870 format->format.code = code; in lt7911d_set_fmt()
880 return -EINVAL; in lt7911d_set_fmt()
883 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in lt7911d_set_fmt()
886 lt7911d->mbus_fmt_code = format->format.code; in lt7911d_set_fmt()
888 lt7911d->cur_mode = mode; in lt7911d_set_fmt()
889 enable_stream(sd, false); in lt7911d_set_fmt()
894 static int lt7911d_g_frame_interval(struct v4l2_subdev *sd, in lt7911d_g_frame_interval() argument
897 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_g_frame_interval()
898 const struct lt7911d_mode *mode = lt7911d->cur_mode; in lt7911d_g_frame_interval()
900 mutex_lock(<7911d->confctl_mutex); in lt7911d_g_frame_interval()
901 fi->interval = mode->max_fps; in lt7911d_g_frame_interval()
902 mutex_unlock(<7911d->confctl_mutex); in lt7911d_g_frame_interval()
911 strscpy(inf->base.sensor, LT7911D_NAME, sizeof(inf->base.sensor)); in lt7911d_get_module_inf()
912 strscpy(inf->base.module, lt7911d->module_name, sizeof(inf->base.module)); in lt7911d_get_module_inf()
913 strscpy(inf->base.lens, lt7911d->len_name, sizeof(inf->base.lens)); in lt7911d_get_module_inf()
916 static long lt7911d_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) in lt7911d_ioctl() argument
918 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_ioctl()
929 ret = -ENOIOCTLCMD; in lt7911d_ioctl()
937 static long lt7911d_compat_ioctl32(struct v4l2_subdev *sd, in lt7911d_compat_ioctl32() argument
949 ret = -ENOMEM; in lt7911d_compat_ioctl32()
953 ret = lt7911d_ioctl(sd, cmd, inf); in lt7911d_compat_ioctl32()
957 ret = -EFAULT; in lt7911d_compat_ioctl32()
964 ret = -ENOMEM; in lt7911d_compat_ioctl32()
968 ret = lt7911d_ioctl(sd, cmd, seq); in lt7911d_compat_ioctl32()
972 ret = -EFAULT; in lt7911d_compat_ioctl32()
977 ret = -ENOIOCTLCMD; in lt7911d_compat_ioctl32()
1045 struct v4l2_subdev *sd; in lt7911d_init_v4l2_ctrls() local
1048 sd = <7911d->sd; in lt7911d_init_v4l2_ctrls()
1049 ret = v4l2_ctrl_handler_init(<7911d->hdl, 5); in lt7911d_init_v4l2_ctrls()
1053 lt7911d->link_freq = v4l2_ctrl_new_int_menu(<7911d->hdl, NULL, in lt7911d_init_v4l2_ctrls()
1055 ARRAY_SIZE(link_freq_menu_items) - 1, 0, in lt7911d_init_v4l2_ctrls()
1057 lt7911d->pixel_rate = v4l2_ctrl_new_std(<7911d->hdl, NULL, in lt7911d_init_v4l2_ctrls()
1061 lt7911d->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<7911d->hdl, in lt7911d_init_v4l2_ctrls()
1065 lt7911d->audio_sampling_rate_ctrl = in lt7911d_init_v4l2_ctrls()
1066 v4l2_ctrl_new_custom(<7911d->hdl, in lt7911d_init_v4l2_ctrls()
1068 lt7911d->audio_present_ctrl = v4l2_ctrl_new_custom(<7911d->hdl, in lt7911d_init_v4l2_ctrls()
1071 sd->ctrl_handler = <7911d->hdl; in lt7911d_init_v4l2_ctrls()
1072 if (lt7911d->hdl.error) { in lt7911d_init_v4l2_ctrls()
1073 ret = lt7911d->hdl.error; in lt7911d_init_v4l2_ctrls()
1074 v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret); in lt7911d_init_v4l2_ctrls()
1078 __v4l2_ctrl_s_ctrl(lt7911d->link_freq, link_freq_menu_items[0]); in lt7911d_init_v4l2_ctrls()
1079 __v4l2_ctrl_s_ctrl_int64(lt7911d->pixel_rate, LT7911D_PIXEL_RATE); in lt7911d_init_v4l2_ctrls()
1081 if (lt7911d_update_controls(sd)) { in lt7911d_init_v4l2_ctrls()
1082 ret = -ENODEV; in lt7911d_init_v4l2_ctrls()
1083 v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret); in lt7911d_init_v4l2_ctrls()
1093 struct device *dev = <7911d->i2c_client->dev; in lt7911d_probe_of()
1094 struct device_node *node = dev->of_node; in lt7911d_probe_of()
1100 <7911d->module_index); in lt7911d_probe_of()
1102 <7911d->module_facing); in lt7911d_probe_of()
1104 <7911d->module_name); in lt7911d_probe_of()
1106 <7911d->len_name); in lt7911d_probe_of()
1109 return -EINVAL; in lt7911d_probe_of()
1112 lt7911d->power_gpio = devm_gpiod_get_optional(dev, "power", in lt7911d_probe_of()
1114 if (IS_ERR(lt7911d->power_gpio)) { in lt7911d_probe_of()
1116 ret = PTR_ERR(lt7911d->power_gpio); in lt7911d_probe_of()
1120 lt7911d->reset_gpio = devm_gpiod_get_optional(dev, "reset", in lt7911d_probe_of()
1122 if (IS_ERR(lt7911d->reset_gpio)) { in lt7911d_probe_of()
1124 ret = PTR_ERR(lt7911d->reset_gpio); in lt7911d_probe_of()
1128 lt7911d->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", in lt7911d_probe_of()
1130 if (IS_ERR(lt7911d->plugin_det_gpio)) { in lt7911d_probe_of()
1132 ret = PTR_ERR(lt7911d->plugin_det_gpio); in lt7911d_probe_of()
1136 ep = of_graph_get_next_endpoint(dev->of_node, NULL); in lt7911d_probe_of()
1139 return -EINVAL; in lt7911d_probe_of()
1150 dev_err(dev, "missing CSI-2 properties in endpoint\n"); in lt7911d_probe_of()
1151 ret = -EINVAL; in lt7911d_probe_of()
1155 lt7911d->xvclk = devm_clk_get(dev, "xvclk"); in lt7911d_probe_of()
1156 if (IS_ERR(lt7911d->xvclk)) { in lt7911d_probe_of()
1158 ret = -EINVAL; in lt7911d_probe_of()
1162 ret = clk_prepare_enable(lt7911d->xvclk); in lt7911d_probe_of()
1168 lt7911d->csi_lanes_in_use = endpoint.bus.mipi_csi2.num_data_lanes; in lt7911d_probe_of()
1169 lt7911d->bus = endpoint.bus.mipi_csi2; in lt7911d_probe_of()
1170 lt7911d->enable_hdcp = false; in lt7911d_probe_of()
1172 gpiod_set_value(lt7911d->power_gpio, 1); in lt7911d_probe_of()
1174 gpiod_set_value(lt7911d->reset_gpio, 0); in lt7911d_probe_of()
1187 return -ENODEV; in lt7911d_probe_of()
1192 struct device *dev = <7911d->i2c_client->dev; in lt7911d_check_chip_id()
1193 struct v4l2_subdev *sd = <7911d->sd; in lt7911d_check_chip_id() local
1198 lt7911d_i2c_enable(sd); in lt7911d_check_chip_id()
1199 id_l = i2c_rd8(sd, CHIPID_REGL); in lt7911d_check_chip_id()
1200 id_h = i2c_rd8(sd, CHIPID_REGH); in lt7911d_check_chip_id()
1201 lt7911d_i2c_disable(sd); in lt7911d_check_chip_id()
1207 return -EINVAL; in lt7911d_check_chip_id()
1218 struct v4l2_subdev *sd; in lt7911d_probe() local
1219 struct device *dev = &client->dev; in lt7911d_probe()
1230 return -ENOMEM; in lt7911d_probe()
1232 sd = <7911d->sd; in lt7911d_probe()
1233 lt7911d->i2c_client = client; in lt7911d_probe()
1234 lt7911d->cur_mode = &supported_modes[0]; in lt7911d_probe()
1235 lt7911d->mbus_fmt_code = LT7911D_MEDIA_BUS_FMT; in lt7911d_probe()
1239 v4l2_err(sd, "lt7911d_parse_of failed! err:%d\n", err); in lt7911d_probe()
1247 mutex_init(<7911d->confctl_mutex); in lt7911d_probe()
1252 client->flags |= I2C_CLIENT_SCCB; in lt7911d_probe()
1254 v4l2_i2c_subdev_init(sd, client, <7911d_ops); in lt7911d_probe()
1255 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; in lt7911d_probe()
1259 lt7911d->pad.flags = MEDIA_PAD_FL_SOURCE; in lt7911d_probe()
1260 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; in lt7911d_probe()
1261 err = media_entity_pads_init(&sd->entity, 1, <7911d->pad); in lt7911d_probe()
1263 v4l2_err(sd, "media entity init failed! err:%d\n", err); in lt7911d_probe()
1268 if (strcmp(lt7911d->module_facing, "back") == 0) in lt7911d_probe()
1273 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", in lt7911d_probe()
1274 lt7911d->module_index, facing, in lt7911d_probe()
1275 LT7911D_NAME, dev_name(sd->dev)); in lt7911d_probe()
1276 err = v4l2_async_register_subdev_sensor_common(sd); in lt7911d_probe()
1278 v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err); in lt7911d_probe()
1282 INIT_DELAYED_WORK(<7911d->delayed_work_enable_hotplug, in lt7911d_probe()
1284 INIT_DELAYED_WORK(<7911d->delayed_work_res_change, in lt7911d_probe()
1287 if (lt7911d->i2c_client->irq) { in lt7911d_probe()
1288 v4l2_dbg(1, debug, sd, "cfg lt7911d irq!\n"); in lt7911d_probe()
1290 lt7911d->i2c_client->irq, in lt7911d_probe()
1295 v4l2_err(sd, "request irq failed! err:%d\n", err); in lt7911d_probe()
1299 v4l2_dbg(1, debug, sd, "no irq, cfg poll!\n"); in lt7911d_probe()
1300 INIT_WORK(<7911d->work_i2c_poll, lt7911d_work_i2c_poll); in lt7911d_probe()
1301 timer_setup(<7911d->timer, lt7911d_irq_poll_timer, 0); in lt7911d_probe()
1302 lt7911d->timer.expires = jiffies + in lt7911d_probe()
1304 add_timer(<7911d->timer); in lt7911d_probe()
1307 lt7911d->plugin_irq = gpiod_to_irq(lt7911d->plugin_det_gpio); in lt7911d_probe()
1308 if (lt7911d->plugin_irq < 0) in lt7911d_probe()
1311 err = devm_request_threaded_irq(dev, lt7911d->plugin_irq, NULL, in lt7911d_probe()
1318 err = v4l2_ctrl_handler_setup(sd->ctrl_handler); in lt7911d_probe()
1320 v4l2_err(sd, "v4l2 ctrl handler setup failed! err:%d\n", err); in lt7911d_probe()
1324 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, in lt7911d_probe()
1325 client->addr << 1, client->adapter->name); in lt7911d_probe()
1330 if (!lt7911d->i2c_client->irq) in lt7911d_probe()
1331 flush_work(<7911d->work_i2c_poll); in lt7911d_probe()
1332 cancel_delayed_work(<7911d->delayed_work_enable_hotplug); in lt7911d_probe()
1333 cancel_delayed_work(<7911d->delayed_work_res_change); in lt7911d_probe()
1336 media_entity_cleanup(&sd->entity); in lt7911d_probe()
1339 v4l2_ctrl_handler_free(<7911d->hdl); in lt7911d_probe()
1340 mutex_destroy(<7911d->confctl_mutex); in lt7911d_probe()
1346 struct v4l2_subdev *sd = i2c_get_clientdata(client); in lt7911d_remove() local
1347 struct lt7911d_state *lt7911d = to_state(sd); in lt7911d_remove()
1349 if (!lt7911d->i2c_client->irq) { in lt7911d_remove()
1350 del_timer_sync(<7911d->timer); in lt7911d_remove()
1351 flush_work(<7911d->work_i2c_poll); in lt7911d_remove()
1353 cancel_delayed_work_sync(<7911d->delayed_work_enable_hotplug); in lt7911d_remove()
1354 cancel_delayed_work_sync(<7911d->delayed_work_res_change); in lt7911d_remove()
1355 v4l2_async_unregister_subdev(sd); in lt7911d_remove()
1356 v4l2_device_unregister_subdev(sd); in lt7911d_remove()
1358 media_entity_cleanup(&sd->entity); in lt7911d_remove()
1360 v4l2_ctrl_handler_free(<7911d->hdl); in lt7911d_remove()
1361 mutex_destroy(<7911d->confctl_mutex); in lt7911d_remove()
1362 clk_disable_unprepare(lt7911d->xvclk); in lt7911d_remove()
1397 MODULE_DESCRIPTION("Lontium lt7911d HDMI to CSI-2 bridge driver");
1398 MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");