Lines Matching +full:sd +full:- +full:hs
1 // SPDX-License-Identifier: GPL-2.0
5 * lt6911uxe HDMI to MIPI CSI-2 bridge driver.
7 * Author: Jianwei Fan <jianwei.fan@rock-chips.com>
28 #include <linux/rk-camera-module.h>
31 #include <linux/v4l2-dv-timings.h>
36 #include <media/v4l2-controls_rockchip.h>
37 #include <media/v4l2-ctrls.h>
38 #include <media/v4l2-device.h>
39 #include <media/v4l2-dv-timings.h>
40 #include <media/v4l2-event.h>
41 #include <media/v4l2-fwnode.h>
47 MODULE_PARM_DESC(debug, "debug level (0-3)");
115 //bit[2:0] mipi hs delay
164 struct v4l2_subdev sd; member
544 static void lt6911uxe_format_change(struct v4l2_subdev *sd);
545 static int lt6911uxe_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd);
546 static int lt6911uxe_s_dv_timings(struct v4l2_subdev *sd,
549 static inline struct lt6911uxe *to_lt6911uxe(struct v4l2_subdev *sd) in to_lt6911uxe() argument
551 return container_of(sd, struct lt6911uxe, sd); in to_lt6911uxe()
554 static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) in i2c_rd() argument
556 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in i2c_rd()
557 struct i2c_client *client = lt6911uxe->i2c_client; in i2c_rd()
563 msgs[0].addr = client->addr; in i2c_rd()
568 msgs[1].addr = client->addr; in i2c_rd()
573 msgs[2].addr = client->addr; in i2c_rd()
578 err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in i2c_rd()
580 v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n", in i2c_rd()
581 __func__, reg, client->addr); in i2c_rd()
589 v4l2_info(sd, "I2C read 0x%04x = 0x%02x\n", in i2c_rd()
593 v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x\n", in i2c_rd()
597 v4l2_info(sd, "I2C read 0x%04x = 0x%02x%02x%02x%02x\n", in i2c_rd()
601 v4l2_info(sd, "I2C read %d bytes from address 0x%04x\n", in i2c_rd()
606 static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) in i2c_wr() argument
608 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in i2c_wr()
609 struct i2c_client *client = lt6911uxe->i2c_client; in i2c_wr()
616 n = I2C_MAX_XFER_SIZE - 1; in i2c_wr()
617 v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", in i2c_wr()
621 msgs[0].addr = client->addr; in i2c_wr()
626 msgs[1].addr = client->addr; in i2c_wr()
635 err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); in i2c_wr()
637 v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n", in i2c_wr()
638 __func__, reg, client->addr); in i2c_wr()
647 v4l2_info(sd, "I2C write 0x%04x = 0x%02x\n", in i2c_wr()
651 v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x\n", in i2c_wr()
655 v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x%02x%02x\n", in i2c_wr()
659 v4l2_info(sd, "I2C write %d bytes from address 0x%04x\n", in i2c_wr()
664 static u8 i2c_rd8(struct v4l2_subdev *sd, u16 reg) in i2c_rd8() argument
668 i2c_rd(sd, reg, (u8 __force *)&val, 1); in i2c_rd8()
672 static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val) in i2c_wr8() argument
674 i2c_wr(sd, reg, &val, 1); in i2c_wr8()
677 static __maybe_unused void i2c_wr8_and_or(struct v4l2_subdev *sd, u16 reg, u32 mask, in i2c_wr8_and_or() argument
682 val_p = i2c_rd8(sd, reg); in i2c_wr8_and_or()
683 i2c_wr8(sd, reg, (val_p & mask) | val); in i2c_wr8_and_or()
686 static void lt6911uxe_i2c_enable(struct v4l2_subdev *sd) in lt6911uxe_i2c_enable() argument
688 i2c_wr8(sd, I2C_EN_REG, I2C_ENABLE); in lt6911uxe_i2c_enable()
691 static void lt6911uxe_i2c_disable(struct v4l2_subdev *sd) in lt6911uxe_i2c_disable() argument
693 i2c_wr8(sd, I2C_EN_REG, I2C_DISABLE); in lt6911uxe_i2c_disable()
696 static inline bool tx_5v_power_present(struct v4l2_subdev *sd) in tx_5v_power_present() argument
700 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in tx_5v_power_present()
703 if (!lt6911uxe->plugin_det_gpio) in tx_5v_power_present()
708 val = gpiod_get_value(lt6911uxe->plugin_det_gpio); in tx_5v_power_present()
715 v4l2_dbg(1, debug, sd, "%s: %d\n", __func__, ret); in tx_5v_power_present()
720 static inline bool no_signal(struct v4l2_subdev *sd) in no_signal() argument
722 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in no_signal()
724 v4l2_dbg(1, debug, sd, "%s no signal:%d\n", __func__, in no_signal()
725 lt6911uxe->nosignal); in no_signal()
727 return lt6911uxe->nosignal; in no_signal()
730 static inline bool audio_present(struct v4l2_subdev *sd) in audio_present() argument
732 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in audio_present()
734 return lt6911uxe->is_audio_present; in audio_present()
737 static int get_audio_sampling_rate(struct v4l2_subdev *sd) in get_audio_sampling_rate() argument
744 if (no_signal(sd)) in get_audio_sampling_rate()
755 return DIV_ROUND_CLOSEST((unsigned int)t->pixelclock, in fps_calc()
759 static bool lt6911uxe_rcv_supported_res(struct v4l2_subdev *sd, u32 width, in lt6911uxe_rcv_supported_res() argument
762 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_rcv_supported_res()
765 for (i = 0; i < lt6911uxe->cfg_num; i++) { in lt6911uxe_rcv_supported_res()
766 if ((lt6911uxe->support_modes[i].width == width) && in lt6911uxe_rcv_supported_res()
767 (lt6911uxe->support_modes[i].height == height)) { in lt6911uxe_rcv_supported_res()
772 if (i == lt6911uxe->cfg_num) { in lt6911uxe_rcv_supported_res()
773 v4l2_err(sd, "%s do not support res wxh: %dx%d\n", __func__, in lt6911uxe_rcv_supported_res()
781 static int lt6911uxe_get_detected_timings(struct v4l2_subdev *sd, in lt6911uxe_get_detected_timings() argument
784 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_get_detected_timings()
785 struct v4l2_bt_timings *bt = &timings->bt; in lt6911uxe_get_detected_timings()
786 u32 hact, vact, htotal, vtotal, hs, vs, hbp, vbp, hfp, vfp; in lt6911uxe_get_detected_timings() local
793 lt6911uxe_i2c_enable(sd); in lt6911uxe_get_detected_timings()
795 clk_h = i2c_rd8(sd, PCLK_H); in lt6911uxe_get_detected_timings()
796 clk_m = i2c_rd8(sd, PCLK_M); in lt6911uxe_get_detected_timings()
797 clk_l = i2c_rd8(sd, PCLK_L); in lt6911uxe_get_detected_timings()
801 clk_h = i2c_rd8(sd, BYTE_PCLK_H); in lt6911uxe_get_detected_timings()
802 clk_m = i2c_rd8(sd, BYTE_PCLK_M); in lt6911uxe_get_detected_timings()
803 clk_l = i2c_rd8(sd, BYTE_PCLK_L); in lt6911uxe_get_detected_timings()
808 val_h = i2c_rd8(sd, HTOTAL_H); in lt6911uxe_get_detected_timings()
809 val_l = i2c_rd8(sd, HTOTAL_L); in lt6911uxe_get_detected_timings()
812 val_h = i2c_rd8(sd, VTOTAL_H); in lt6911uxe_get_detected_timings()
813 val_l = i2c_rd8(sd, VTOTAL_L); in lt6911uxe_get_detected_timings()
816 val_h = i2c_rd8(sd, HACT_H); in lt6911uxe_get_detected_timings()
817 val_l = i2c_rd8(sd, HACT_L); in lt6911uxe_get_detected_timings()
820 val_h = i2c_rd8(sd, VACT_H); in lt6911uxe_get_detected_timings()
821 val_l = i2c_rd8(sd, VACT_L); in lt6911uxe_get_detected_timings()
824 hs = i2c_rd8(sd, HS_HALF) * 2; in lt6911uxe_get_detected_timings()
826 val_h = i2c_rd8(sd, HFP_HALF_H); in lt6911uxe_get_detected_timings()
827 val_l = i2c_rd8(sd, HFP_HALF_L); in lt6911uxe_get_detected_timings()
830 hbp = htotal - hact - hs - hfp; in lt6911uxe_get_detected_timings()
832 vs = i2c_rd8(sd, VS); in lt6911uxe_get_detected_timings()
833 val_h = i2c_rd8(sd, VFP_H); in lt6911uxe_get_detected_timings()
834 val_l = i2c_rd8(sd, VFP_L); in lt6911uxe_get_detected_timings()
837 vbp = vtotal - vact - vs - vfp; in lt6911uxe_get_detected_timings()
838 lt6911uxe_i2c_disable(sd); in lt6911uxe_get_detected_timings()
840 lt6911uxe->nosignal = false; in lt6911uxe_get_detected_timings()
841 lt6911uxe->is_audio_present = true; in lt6911uxe_get_detected_timings()
842 timings->type = V4L2_DV_BT_656_1120; in lt6911uxe_get_detected_timings()
843 bt->interlaced = V4L2_DV_PROGRESSIVE; in lt6911uxe_get_detected_timings()
844 bt->width = hact; in lt6911uxe_get_detected_timings()
845 bt->height = vact; in lt6911uxe_get_detected_timings()
846 bt->vsync = vs; in lt6911uxe_get_detected_timings()
847 bt->hsync = hs; in lt6911uxe_get_detected_timings()
848 bt->hfrontporch = hfp; in lt6911uxe_get_detected_timings()
849 bt->vfrontporch = vfp; in lt6911uxe_get_detected_timings()
850 bt->hbackporch = hbp; in lt6911uxe_get_detected_timings()
851 bt->vbackporch = vbp; in lt6911uxe_get_detected_timings()
852 bt->pixelclock = pixel_clock; in lt6911uxe_get_detected_timings()
858 bt->interlaced = V4L2_DV_INTERLACED; in lt6911uxe_get_detected_timings()
859 bt->height *= 2; in lt6911uxe_get_detected_timings()
860 bt->il_vsync = bt->vsync + 1; in lt6911uxe_get_detected_timings()
862 bt->interlaced = V4L2_DV_PROGRESSIVE; in lt6911uxe_get_detected_timings()
865 if (!lt6911uxe_rcv_supported_res(sd, hact, bt->height)) { in lt6911uxe_get_detected_timings()
866 lt6911uxe->nosignal = true; in lt6911uxe_get_detected_timings()
867 v4l2_err(sd, "%s: rcv err res, return no signal!\n", __func__); in lt6911uxe_get_detected_timings()
868 return -EINVAL; in lt6911uxe_get_detected_timings()
871 v4l2_info(sd, "act:%dx%d, total:%dx%d, pixclk:%d, fps:%d\n", in lt6911uxe_get_detected_timings()
873 v4l2_info(sd, "byte_clk:%u, mipi_clk:%u, mipi_data_rate:%u\n", in lt6911uxe_get_detected_timings()
875 v4l2_info(sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d, inerlaced:%d\n", in lt6911uxe_get_detected_timings()
876 bt->hfrontporch, bt->hsync, bt->hbackporch, bt->vfrontporch, in lt6911uxe_get_detected_timings()
877 bt->vsync, bt->vbackporch, bt->interlaced); in lt6911uxe_get_detected_timings()
887 struct v4l2_subdev *sd = <6911uxe->sd; in lt6911uxe_delayed_work_hotplug() local
889 lt6911uxe_s_ctrl_detect_tx_5v(sd); in lt6911uxe_delayed_work_hotplug()
897 struct v4l2_subdev *sd = <6911uxe->sd; in lt6911uxe_delayed_work_res_change() local
899 lt6911uxe_format_change(sd); in lt6911uxe_delayed_work_res_change()
902 static int lt6911uxe_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd) in lt6911uxe_s_ctrl_detect_tx_5v() argument
904 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_s_ctrl_detect_tx_5v()
906 return v4l2_ctrl_s_ctrl(lt6911uxe->detect_tx_5v_ctrl, in lt6911uxe_s_ctrl_detect_tx_5v()
907 tx_5v_power_present(sd)); in lt6911uxe_s_ctrl_detect_tx_5v()
910 static int lt6911uxe_s_ctrl_audio_sampling_rate(struct v4l2_subdev *sd) in lt6911uxe_s_ctrl_audio_sampling_rate() argument
912 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_s_ctrl_audio_sampling_rate()
914 return v4l2_ctrl_s_ctrl(lt6911uxe->audio_sampling_rate_ctrl, in lt6911uxe_s_ctrl_audio_sampling_rate()
915 get_audio_sampling_rate(sd)); in lt6911uxe_s_ctrl_audio_sampling_rate()
918 static int lt6911uxe_s_ctrl_audio_present(struct v4l2_subdev *sd) in lt6911uxe_s_ctrl_audio_present() argument
920 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_s_ctrl_audio_present()
922 return v4l2_ctrl_s_ctrl(lt6911uxe->audio_present_ctrl, in lt6911uxe_s_ctrl_audio_present()
923 audio_present(sd)); in lt6911uxe_s_ctrl_audio_present()
926 static int lt6911uxe_update_controls(struct v4l2_subdev *sd) in lt6911uxe_update_controls() argument
930 ret |= lt6911uxe_s_ctrl_detect_tx_5v(sd); in lt6911uxe_update_controls()
931 ret |= lt6911uxe_s_ctrl_audio_sampling_rate(sd); in lt6911uxe_update_controls()
932 ret |= lt6911uxe_s_ctrl_audio_present(sd); in lt6911uxe_update_controls()
937 static void lt6911uxe_config_dphy_timing(struct v4l2_subdev *sd) in lt6911uxe_config_dphy_timing() argument
941 val = i2c_rd8(sd, CLK_ZERO_REG); in lt6911uxe_config_dphy_timing()
942 i2c_wr8(sd, CLK_ZERO_REG, val); in lt6911uxe_config_dphy_timing()
944 val = i2c_rd8(sd, HS_PREPARE_REG); in lt6911uxe_config_dphy_timing()
945 i2c_wr8(sd, HS_PREPARE_REG, val); in lt6911uxe_config_dphy_timing()
947 val = i2c_rd8(sd, HS_TRAIL); in lt6911uxe_config_dphy_timing()
948 i2c_wr8(sd, HS_TRAIL, val); in lt6911uxe_config_dphy_timing()
949 v4l2_info(sd, "%s: dphy timing: hs trail = %x\n", __func__, val); in lt6911uxe_config_dphy_timing()
951 val = i2c_rd8(sd, MIPI_TX_PT0_TX0_DLY); in lt6911uxe_config_dphy_timing()
952 i2c_wr8_and_or(sd, MIPI_TX_PT0_TX0_DLY, ~MIPI_TIMING_MASK, val); in lt6911uxe_config_dphy_timing()
953 v4l2_info(sd, "%s: dphy timing: port0 tx0 delay = %x\n", __func__, val); in lt6911uxe_config_dphy_timing()
955 val = i2c_rd8(sd, MIPI_TX_PT0_LPTX); in lt6911uxe_config_dphy_timing()
956 i2c_wr8(sd, MIPI_TX_PT0_LPTX, val); in lt6911uxe_config_dphy_timing()
957 v4l2_info(sd, "%s: dphy timing: port0 lptx = %x\n", __func__, val); in lt6911uxe_config_dphy_timing()
959 v4l2_info(sd, "%s: dphy timing config done.\n", __func__); in lt6911uxe_config_dphy_timing()
962 static inline void enable_stream(struct v4l2_subdev *sd, bool enable) in enable_stream() argument
964 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in enable_stream()
966 lt6911uxe_i2c_enable(sd); in enable_stream()
968 lt6911uxe_config_dphy_timing(sd); in enable_stream()
970 i2c_wr8(<6911uxe->sd, STREAM_CTL, ENABLE_STREAM); in enable_stream()
972 i2c_wr8(<6911uxe->sd, STREAM_CTL, DISABLE_STREAM); in enable_stream()
974 lt6911uxe_i2c_disable(sd); in enable_stream()
977 v4l2_dbg(2, debug, sd, "%s: %sable\n", in enable_stream()
981 static void lt6911uxe_format_change(struct v4l2_subdev *sd) in lt6911uxe_format_change() argument
983 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_format_change()
990 if (lt6911uxe_get_detected_timings(sd, &timings)) { in lt6911uxe_format_change()
991 enable_stream(sd, false); in lt6911uxe_format_change()
992 v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); in lt6911uxe_format_change()
995 if (!v4l2_match_dv_timings(<6911uxe->timings, &timings, 0, false)) { in lt6911uxe_format_change()
996 enable_stream(sd, false); in lt6911uxe_format_change()
998 lt6911uxe_s_dv_timings(sd, &timings); in lt6911uxe_format_change()
999 v4l2_print_dv_timings(sd->name, in lt6911uxe_format_change()
1002 if (sd->devnode && !lt6911uxe->i2c_client->irq) in lt6911uxe_format_change()
1003 v4l2_subdev_notify_event(sd, <6911uxe_ev_fmt); in lt6911uxe_format_change()
1005 if (sd->devnode && lt6911uxe->i2c_client->irq) in lt6911uxe_format_change()
1006 v4l2_subdev_notify_event(sd, <6911uxe_ev_fmt); in lt6911uxe_format_change()
1009 static int lt6911uxe_isr(struct v4l2_subdev *sd, u32 status, bool *handled) in lt6911uxe_isr() argument
1011 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_isr()
1013 schedule_delayed_work(<6911uxe->delayed_work_res_change, HZ / 20); in lt6911uxe_isr()
1024 lt6911uxe_isr(<6911uxe->sd, 0, &handled); in lt6911uxe_res_change_irq_handler()
1034 schedule_delayed_work(<6911uxe->delayed_work_hotplug, in plugin_detect_irq_handler()
1044 schedule_work(<6911uxe->work_i2c_poll); in lt6911uxe_irq_poll_timer()
1045 mod_timer(<6911uxe->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS)); in lt6911uxe_irq_poll_timer()
1052 struct v4l2_subdev *sd = <6911uxe->sd; in lt6911uxe_work_i2c_poll() local
1054 lt6911uxe_format_change(sd); in lt6911uxe_work_i2c_poll()
1057 static int lt6911uxe_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, in lt6911uxe_subscribe_event() argument
1060 switch (sub->type) { in lt6911uxe_subscribe_event()
1062 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); in lt6911uxe_subscribe_event()
1064 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); in lt6911uxe_subscribe_event()
1066 return -EINVAL; in lt6911uxe_subscribe_event()
1070 static int lt6911uxe_g_input_status(struct v4l2_subdev *sd, u32 *status) in lt6911uxe_g_input_status() argument
1073 *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0; in lt6911uxe_g_input_status()
1075 v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status); in lt6911uxe_g_input_status()
1080 static int lt6911uxe_s_dv_timings(struct v4l2_subdev *sd, in lt6911uxe_s_dv_timings() argument
1083 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_s_dv_timings()
1086 return -EINVAL; in lt6911uxe_s_dv_timings()
1089 v4l2_print_dv_timings(sd->name, "s_dv_timings: ", in lt6911uxe_s_dv_timings()
1092 if (v4l2_match_dv_timings(<6911uxe->timings, timings, 0, false)) { in lt6911uxe_s_dv_timings()
1093 v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); in lt6911uxe_s_dv_timings()
1099 v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); in lt6911uxe_s_dv_timings()
1100 return -ERANGE; in lt6911uxe_s_dv_timings()
1103 lt6911uxe->timings = *timings; in lt6911uxe_s_dv_timings()
1105 enable_stream(sd, false); in lt6911uxe_s_dv_timings()
1110 static int lt6911uxe_g_dv_timings(struct v4l2_subdev *sd, in lt6911uxe_g_dv_timings() argument
1113 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_g_dv_timings()
1115 *timings = lt6911uxe->timings; in lt6911uxe_g_dv_timings()
1120 static int lt6911uxe_enum_dv_timings(struct v4l2_subdev *sd, in lt6911uxe_enum_dv_timings() argument
1123 if (timings->pad != 0) in lt6911uxe_enum_dv_timings()
1124 return -EINVAL; in lt6911uxe_enum_dv_timings()
1130 static int lt6911uxe_query_dv_timings(struct v4l2_subdev *sd, in lt6911uxe_query_dv_timings() argument
1133 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_query_dv_timings()
1135 *timings = lt6911uxe->timings; in lt6911uxe_query_dv_timings()
1137 v4l2_print_dv_timings(sd->name, in lt6911uxe_query_dv_timings()
1142 v4l2_dbg(1, debug, sd, "%s: timings out of range\n", in lt6911uxe_query_dv_timings()
1145 return -ERANGE; in lt6911uxe_query_dv_timings()
1151 static int lt6911uxe_dv_timings_cap(struct v4l2_subdev *sd, in lt6911uxe_dv_timings_cap() argument
1154 if (cap->pad != 0) in lt6911uxe_dv_timings_cap()
1155 return -EINVAL; in lt6911uxe_dv_timings_cap()
1162 static int lt6911uxe_g_mbus_config(struct v4l2_subdev *sd, in lt6911uxe_g_mbus_config() argument
1165 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_g_mbus_config()
1166 u32 lane_num = lt6911uxe->bus_cfg.bus.mipi_csi2.num_data_lanes; in lt6911uxe_g_mbus_config()
1169 val = 1 << (lane_num - 1) | in lt6911uxe_g_mbus_config()
1173 cfg->type = lt6911uxe->bus_cfg.bus_type; in lt6911uxe_g_mbus_config()
1174 cfg->flags = val; in lt6911uxe_g_mbus_config()
1179 static int lt6911uxe_s_stream(struct v4l2_subdev *sd, int on) in lt6911uxe_s_stream() argument
1181 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_s_stream()
1182 struct i2c_client *client = lt6911uxe->i2c_client; in lt6911uxe_s_stream()
1184 dev_info(&client->dev, "%s: on: %d, %dx%d%s%d\n", __func__, on, in lt6911uxe_s_stream()
1185 lt6911uxe->cur_mode->width, in lt6911uxe_s_stream()
1186 lt6911uxe->cur_mode->height, in lt6911uxe_s_stream()
1187 lt6911uxe->cur_mode->interlace ? "I" : "P", in lt6911uxe_s_stream()
1188 DIV_ROUND_CLOSEST(lt6911uxe->cur_mode->max_fps.denominator, in lt6911uxe_s_stream()
1189 lt6911uxe->cur_mode->max_fps.numerator)); in lt6911uxe_s_stream()
1190 enable_stream(sd, on); in lt6911uxe_s_stream()
1195 static int lt6911uxe_enum_mbus_code(struct v4l2_subdev *sd, in lt6911uxe_enum_mbus_code() argument
1199 switch (code->index) { in lt6911uxe_enum_mbus_code()
1201 code->code = LT6911UXE_MEDIA_BUS_FMT; in lt6911uxe_enum_mbus_code()
1205 return -EINVAL; in lt6911uxe_enum_mbus_code()
1211 static int lt6911uxe_enum_frame_sizes(struct v4l2_subdev *sd, in lt6911uxe_enum_frame_sizes() argument
1215 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_enum_frame_sizes()
1217 if (fse->index >= lt6911uxe->cfg_num) in lt6911uxe_enum_frame_sizes()
1218 return -EINVAL; in lt6911uxe_enum_frame_sizes()
1220 if (fse->code != LT6911UXE_MEDIA_BUS_FMT) in lt6911uxe_enum_frame_sizes()
1221 return -EINVAL; in lt6911uxe_enum_frame_sizes()
1223 fse->min_width = lt6911uxe->support_modes[fse->index].width; in lt6911uxe_enum_frame_sizes()
1224 fse->max_width = lt6911uxe->support_modes[fse->index].width; in lt6911uxe_enum_frame_sizes()
1225 fse->max_height = lt6911uxe->support_modes[fse->index].height; in lt6911uxe_enum_frame_sizes()
1226 fse->min_height = lt6911uxe->support_modes[fse->index].height; in lt6911uxe_enum_frame_sizes()
1231 static int lt6911uxe_enum_frame_interval(struct v4l2_subdev *sd, in lt6911uxe_enum_frame_interval() argument
1235 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_enum_frame_interval()
1237 if (fie->index >= lt6911uxe->cfg_num) in lt6911uxe_enum_frame_interval()
1238 return -EINVAL; in lt6911uxe_enum_frame_interval()
1240 fie->code = LT6911UXE_MEDIA_BUS_FMT; in lt6911uxe_enum_frame_interval()
1242 fie->width = lt6911uxe->support_modes[fie->index].width; in lt6911uxe_enum_frame_interval()
1243 fie->height = lt6911uxe->support_modes[fie->index].height; in lt6911uxe_enum_frame_interval()
1244 fie->interval = lt6911uxe->support_modes[fie->index].max_fps; in lt6911uxe_enum_frame_interval()
1252 struct v4l2_bt_timings *bt = &timings->bt; in lt6911uxe_get_reso_dist()
1256 dist_fps = DIV_ROUND_CLOSEST(mode->max_fps.denominator, mode->max_fps.numerator); in lt6911uxe_get_reso_dist()
1258 return abs(mode->width - bt->width) + in lt6911uxe_get_reso_dist()
1259 abs(mode->height - bt->height) + abs(dist_fps - cur_fps); in lt6911uxe_get_reso_dist()
1267 int cur_best_fit_dist = -1; in lt6911uxe_find_best_fit()
1270 for (i = 0; i < lt6911uxe->cfg_num; i++) { in lt6911uxe_find_best_fit()
1271 if (lt6911uxe->support_modes[i].interlace == lt6911uxe->timings.bt.interlaced) { in lt6911uxe_find_best_fit()
1272 dist = lt6911uxe_get_reso_dist(<6911uxe->support_modes[i], in lt6911uxe_find_best_fit()
1273 <6911uxe->timings); in lt6911uxe_find_best_fit()
1274 if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { in lt6911uxe_find_best_fit()
1280 dev_info(<6911uxe->i2c_client->dev, in lt6911uxe_find_best_fit()
1282 cur_best_fit, lt6911uxe->support_modes[cur_best_fit].width, in lt6911uxe_find_best_fit()
1283 lt6911uxe->support_modes[cur_best_fit].height, in lt6911uxe_find_best_fit()
1284 lt6911uxe->support_modes[cur_best_fit].interlace ? "I" : "P", in lt6911uxe_find_best_fit()
1285 DIV_ROUND_CLOSEST(lt6911uxe->support_modes[cur_best_fit].max_fps.denominator, in lt6911uxe_find_best_fit()
1286 lt6911uxe->support_modes[cur_best_fit].max_fps.numerator)); in lt6911uxe_find_best_fit()
1288 return <6911uxe->support_modes[cur_best_fit]; in lt6911uxe_find_best_fit()
1291 static int lt6911uxe_get_fmt(struct v4l2_subdev *sd, in lt6911uxe_get_fmt() argument
1295 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_get_fmt()
1298 mutex_lock(<6911uxe->confctl_mutex); in lt6911uxe_get_fmt()
1299 format->format.code = lt6911uxe->mbus_fmt_code; in lt6911uxe_get_fmt()
1300 format->format.width = lt6911uxe->timings.bt.width; in lt6911uxe_get_fmt()
1301 format->format.height = lt6911uxe->timings.bt.height; in lt6911uxe_get_fmt()
1302 format->format.field = in lt6911uxe_get_fmt()
1303 lt6911uxe->timings.bt.interlaced ? in lt6911uxe_get_fmt()
1305 format->format.colorspace = V4L2_COLORSPACE_SRGB; in lt6911uxe_get_fmt()
1306 mutex_unlock(<6911uxe->confctl_mutex); in lt6911uxe_get_fmt()
1309 lt6911uxe->cur_mode = mode; in lt6911uxe_get_fmt()
1311 __v4l2_ctrl_s_ctrl_int64(lt6911uxe->pixel_rate, in lt6911uxe_get_fmt()
1313 __v4l2_ctrl_s_ctrl(lt6911uxe->link_freq, in lt6911uxe_get_fmt()
1314 mode->mipi_freq_idx); in lt6911uxe_get_fmt()
1316 v4l2_dbg(1, debug, sd, "%s: mode->mipi_freq_idx(%d)", __func__, mode->mipi_freq_idx); in lt6911uxe_get_fmt()
1318 v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n", in lt6911uxe_get_fmt()
1319 __func__, format->format.code, format->format.width, in lt6911uxe_get_fmt()
1320 format->format.height, format->format.field); in lt6911uxe_get_fmt()
1325 static int lt6911uxe_set_fmt(struct v4l2_subdev *sd, in lt6911uxe_set_fmt() argument
1329 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_set_fmt()
1333 u32 code = format->format.code; in lt6911uxe_set_fmt()
1334 int ret = lt6911uxe_get_fmt(sd, cfg, format); in lt6911uxe_set_fmt()
1336 format->format.code = code; in lt6911uxe_set_fmt()
1346 return -EINVAL; in lt6911uxe_set_fmt()
1349 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in lt6911uxe_set_fmt()
1352 lt6911uxe->mbus_fmt_code = format->format.code; in lt6911uxe_set_fmt()
1354 lt6911uxe->cur_mode = mode; in lt6911uxe_set_fmt()
1356 enable_stream(sd, false); in lt6911uxe_set_fmt()
1361 static int lt6911uxe_g_frame_interval(struct v4l2_subdev *sd, in lt6911uxe_g_frame_interval() argument
1364 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_g_frame_interval()
1365 const struct lt6911uxe_mode *mode = lt6911uxe->cur_mode; in lt6911uxe_g_frame_interval()
1367 mutex_lock(<6911uxe->confctl_mutex); in lt6911uxe_g_frame_interval()
1368 fi->interval = mode->max_fps; in lt6911uxe_g_frame_interval()
1369 mutex_unlock(<6911uxe->confctl_mutex); in lt6911uxe_g_frame_interval()
1378 strscpy(inf->base.sensor, LT6911UXE_NAME, sizeof(inf->base.sensor)); in lt6911uxe_get_module_inf()
1379 strscpy(inf->base.module, lt6911uxe->module_name, sizeof(inf->base.module)); in lt6911uxe_get_module_inf()
1380 strscpy(inf->base.lens, lt6911uxe->len_name, sizeof(inf->base.lens)); in lt6911uxe_get_module_inf()
1383 static long lt6911uxe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) in lt6911uxe_ioctl() argument
1385 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_ioctl()
1398 if (dphy_param->vendor == rk3588_dcphy_param.vendor) in lt6911uxe_ioctl()
1400 dev_dbg(<6911uxe->i2c_client->dev, in lt6911uxe_ioctl()
1405 if (dphy_param->vendor == rk3588_dcphy_param.vendor) in lt6911uxe_ioctl()
1407 dev_dbg(<6911uxe->i2c_client->dev, in lt6911uxe_ioctl()
1411 ret = -ENOIOCTLCMD; in lt6911uxe_ioctl()
1418 static int lt6911uxe_s_power(struct v4l2_subdev *sd, int on) in lt6911uxe_s_power() argument
1420 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_s_power()
1423 mutex_lock(<6911uxe->confctl_mutex); in lt6911uxe_s_power()
1425 if (lt6911uxe->power_on == !!on) in lt6911uxe_s_power()
1429 lt6911uxe->power_on = true; in lt6911uxe_s_power()
1431 lt6911uxe->power_on = false; in lt6911uxe_s_power()
1434 mutex_unlock(<6911uxe->confctl_mutex); in lt6911uxe_s_power()
1440 static long lt6911uxe_compat_ioctl32(struct v4l2_subdev *sd, in lt6911uxe_compat_ioctl32() argument
1453 ret = -ENOMEM; in lt6911uxe_compat_ioctl32()
1457 ret = lt6911uxe_ioctl(sd, cmd, inf); in lt6911uxe_compat_ioctl32()
1461 ret = -EFAULT; in lt6911uxe_compat_ioctl32()
1468 ret = -ENOMEM; in lt6911uxe_compat_ioctl32()
1472 ret = lt6911uxe_ioctl(sd, cmd, seq); in lt6911uxe_compat_ioctl32()
1476 ret = -EFAULT; in lt6911uxe_compat_ioctl32()
1483 ret = -ENOMEM; in lt6911uxe_compat_ioctl32()
1489 ret = lt6911uxe_ioctl(sd, cmd, dphy_param); in lt6911uxe_compat_ioctl32()
1491 ret = -EFAULT; in lt6911uxe_compat_ioctl32()
1497 ret = -ENOMEM; in lt6911uxe_compat_ioctl32()
1501 ret = lt6911uxe_ioctl(sd, cmd, dphy_param); in lt6911uxe_compat_ioctl32()
1505 ret = -EFAULT; in lt6911uxe_compat_ioctl32()
1510 ret = -ENOIOCTLCMD; in lt6911uxe_compat_ioctl32()
1519 static int lt6911uxe_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) in lt6911uxe_open() argument
1521 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_open()
1523 v4l2_subdev_get_try_format(sd, fh->pad, 0); in lt6911uxe_open()
1524 const struct lt6911uxe_mode *def_mode = <6911uxe->support_modes[0]; in lt6911uxe_open()
1526 mutex_lock(<6911uxe->confctl_mutex); in lt6911uxe_open()
1528 try_fmt->width = def_mode->width; in lt6911uxe_open()
1529 try_fmt->height = def_mode->height; in lt6911uxe_open()
1530 try_fmt->code = LT6911UXE_MEDIA_BUS_FMT; in lt6911uxe_open()
1531 try_fmt->field = V4L2_FIELD_NONE; in lt6911uxe_open()
1532 mutex_unlock(<6911uxe->confctl_mutex); in lt6911uxe_open()
1605 gpiod_set_value(lt6911uxe->reset_gpio, 0); in lt6911uxe_reset()
1607 gpiod_set_value(lt6911uxe->reset_gpio, 1); in lt6911uxe_reset()
1609 gpiod_set_value(lt6911uxe->reset_gpio, 0); in lt6911uxe_reset()
1616 struct v4l2_subdev *sd; in lt6911uxe_init_v4l2_ctrls() local
1619 mode = lt6911uxe->cur_mode; in lt6911uxe_init_v4l2_ctrls()
1620 sd = <6911uxe->sd; in lt6911uxe_init_v4l2_ctrls()
1621 ret = v4l2_ctrl_handler_init(<6911uxe->hdl, 5); in lt6911uxe_init_v4l2_ctrls()
1625 lt6911uxe->link_freq = v4l2_ctrl_new_int_menu(<6911uxe->hdl, NULL, in lt6911uxe_init_v4l2_ctrls()
1627 ARRAY_SIZE(link_freq_menu_items) - 1, 0, in lt6911uxe_init_v4l2_ctrls()
1629 lt6911uxe->pixel_rate = v4l2_ctrl_new_std(<6911uxe->hdl, NULL, in lt6911uxe_init_v4l2_ctrls()
1633 lt6911uxe->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<6911uxe->hdl, in lt6911uxe_init_v4l2_ctrls()
1637 lt6911uxe->audio_sampling_rate_ctrl = in lt6911uxe_init_v4l2_ctrls()
1638 v4l2_ctrl_new_custom(<6911uxe->hdl, in lt6911uxe_init_v4l2_ctrls()
1640 lt6911uxe->audio_present_ctrl = v4l2_ctrl_new_custom(<6911uxe->hdl, in lt6911uxe_init_v4l2_ctrls()
1643 sd->ctrl_handler = <6911uxe->hdl; in lt6911uxe_init_v4l2_ctrls()
1644 if (lt6911uxe->hdl.error) { in lt6911uxe_init_v4l2_ctrls()
1645 ret = lt6911uxe->hdl.error; in lt6911uxe_init_v4l2_ctrls()
1646 v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret); in lt6911uxe_init_v4l2_ctrls()
1650 __v4l2_ctrl_s_ctrl(lt6911uxe->link_freq, mode->mipi_freq_idx); in lt6911uxe_init_v4l2_ctrls()
1651 __v4l2_ctrl_s_ctrl_int64(lt6911uxe->pixel_rate, LT6911UXE_PIXEL_RATE); in lt6911uxe_init_v4l2_ctrls()
1653 if (lt6911uxe_update_controls(sd)) { in lt6911uxe_init_v4l2_ctrls()
1654 ret = -ENODEV; in lt6911uxe_init_v4l2_ctrls()
1655 v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret); in lt6911uxe_init_v4l2_ctrls()
1665 struct device *dev = <6911uxe->i2c_client->dev; in lt6911uxe_probe_of()
1666 struct device_node *node = dev->of_node; in lt6911uxe_probe_of()
1671 <6911uxe->module_index); in lt6911uxe_probe_of()
1673 <6911uxe->module_facing); in lt6911uxe_probe_of()
1675 <6911uxe->module_name); in lt6911uxe_probe_of()
1677 <6911uxe->len_name); in lt6911uxe_probe_of()
1680 return -EINVAL; in lt6911uxe_probe_of()
1683 lt6911uxe->power_gpio = devm_gpiod_get_optional(dev, "power", in lt6911uxe_probe_of()
1685 if (IS_ERR(lt6911uxe->power_gpio)) { in lt6911uxe_probe_of()
1687 ret = PTR_ERR(lt6911uxe->power_gpio); in lt6911uxe_probe_of()
1691 lt6911uxe->reset_gpio = devm_gpiod_get_optional(dev, "reset", in lt6911uxe_probe_of()
1693 if (IS_ERR(lt6911uxe->reset_gpio)) { in lt6911uxe_probe_of()
1695 ret = PTR_ERR(lt6911uxe->reset_gpio); in lt6911uxe_probe_of()
1699 lt6911uxe->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", in lt6911uxe_probe_of()
1701 if (IS_ERR(lt6911uxe->plugin_det_gpio)) { in lt6911uxe_probe_of()
1703 ret = PTR_ERR(lt6911uxe->plugin_det_gpio); in lt6911uxe_probe_of()
1707 ep = of_graph_get_next_endpoint(dev->of_node, NULL); in lt6911uxe_probe_of()
1710 return -EINVAL; in lt6911uxe_probe_of()
1714 <6911uxe->bus_cfg); in lt6911uxe_probe_of()
1720 lt6911uxe->support_modes = supported_modes_dphy; in lt6911uxe_probe_of()
1721 lt6911uxe->cfg_num = ARRAY_SIZE(supported_modes_dphy); in lt6911uxe_probe_of()
1723 lt6911uxe->xvclk = devm_clk_get(dev, "xvclk"); in lt6911uxe_probe_of()
1724 if (IS_ERR(lt6911uxe->xvclk)) { in lt6911uxe_probe_of()
1726 ret = -EINVAL; in lt6911uxe_probe_of()
1730 ret = clk_prepare_enable(lt6911uxe->xvclk); in lt6911uxe_probe_of()
1736 lt6911uxe->enable_hdcp = false; in lt6911uxe_probe_of()
1738 gpiod_set_value(lt6911uxe->power_gpio, 1); in lt6911uxe_probe_of()
1750 return -ENODEV; in lt6911uxe_probe_of()
1755 struct device *dev = <6911uxe->i2c_client->dev; in lt6911uxe_check_chip_id()
1756 struct v4l2_subdev *sd = <6911uxe->sd; in lt6911uxe_check_chip_id() local
1761 lt6911uxe_i2c_enable(sd); in lt6911uxe_check_chip_id()
1762 id_l = i2c_rd8(sd, CHIPID_REGL); in lt6911uxe_check_chip_id()
1763 id_h = i2c_rd8(sd, CHIPID_REGH); in lt6911uxe_check_chip_id()
1764 lt6911uxe_i2c_disable(sd); in lt6911uxe_check_chip_id()
1770 return -EINVAL; in lt6911uxe_check_chip_id()
1783 struct v4l2_subdev *sd; in lt6911uxe_probe() local
1784 struct device *dev = &client->dev; in lt6911uxe_probe()
1795 return -ENOMEM; in lt6911uxe_probe()
1797 sd = <6911uxe->sd; in lt6911uxe_probe()
1798 lt6911uxe->i2c_client = client; in lt6911uxe_probe()
1799 lt6911uxe->mbus_fmt_code = LT6911UXE_MEDIA_BUS_FMT; in lt6911uxe_probe()
1803 v4l2_err(sd, "lt6911uxe_parse_of failed! err:%d\n", err); in lt6911uxe_probe()
1807 lt6911uxe->timings = default_timing; in lt6911uxe_probe()
1808 lt6911uxe->cur_mode = <6911uxe->support_modes[0]; in lt6911uxe_probe()
1813 mutex_init(<6911uxe->confctl_mutex); in lt6911uxe_probe()
1818 client->flags |= I2C_CLIENT_SCCB; in lt6911uxe_probe()
1820 v4l2_i2c_subdev_init(sd, client, <6911uxe_ops); in lt6911uxe_probe()
1821 sd->internal_ops = <6911uxe_internal_ops; in lt6911uxe_probe()
1822 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; in lt6911uxe_probe()
1826 lt6911uxe->pad.flags = MEDIA_PAD_FL_SOURCE; in lt6911uxe_probe()
1827 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; in lt6911uxe_probe()
1828 err = media_entity_pads_init(&sd->entity, 1, <6911uxe->pad); in lt6911uxe_probe()
1830 v4l2_err(sd, "media entity init failed! err:%d\n", err); in lt6911uxe_probe()
1835 if (strcmp(lt6911uxe->module_facing, "back") == 0) in lt6911uxe_probe()
1840 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", in lt6911uxe_probe()
1841 lt6911uxe->module_index, facing, in lt6911uxe_probe()
1842 LT6911UXE_NAME, dev_name(sd->dev)); in lt6911uxe_probe()
1843 err = v4l2_async_register_subdev_sensor_common(sd); in lt6911uxe_probe()
1845 v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err); in lt6911uxe_probe()
1849 INIT_DELAYED_WORK(<6911uxe->delayed_work_hotplug, in lt6911uxe_probe()
1851 INIT_DELAYED_WORK(<6911uxe->delayed_work_res_change, in lt6911uxe_probe()
1854 if (lt6911uxe->i2c_client->irq) { in lt6911uxe_probe()
1855 v4l2_dbg(1, debug, sd, "cfg lt6911uxe irq!\n"); in lt6911uxe_probe()
1857 lt6911uxe->i2c_client->irq, in lt6911uxe_probe()
1862 v4l2_err(sd, "request irq failed! err:%d\n", err); in lt6911uxe_probe()
1866 v4l2_dbg(1, debug, sd, "no irq, cfg poll!\n"); in lt6911uxe_probe()
1867 INIT_WORK(<6911uxe->work_i2c_poll, lt6911uxe_work_i2c_poll); in lt6911uxe_probe()
1868 timer_setup(<6911uxe->timer, lt6911uxe_irq_poll_timer, 0); in lt6911uxe_probe()
1869 lt6911uxe->timer.expires = jiffies + in lt6911uxe_probe()
1871 add_timer(<6911uxe->timer); in lt6911uxe_probe()
1874 lt6911uxe->plugin_irq = gpiod_to_irq(lt6911uxe->plugin_det_gpio); in lt6911uxe_probe()
1875 if (lt6911uxe->plugin_irq < 0) in lt6911uxe_probe()
1878 err = devm_request_threaded_irq(dev, lt6911uxe->plugin_irq, NULL, in lt6911uxe_probe()
1885 err = v4l2_ctrl_handler_setup(sd->ctrl_handler); in lt6911uxe_probe()
1887 v4l2_err(sd, "v4l2 ctrl handler setup failed! err:%d\n", err); in lt6911uxe_probe()
1890 enable_stream(sd, false); in lt6911uxe_probe()
1891 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, in lt6911uxe_probe()
1892 client->addr << 1, client->adapter->name); in lt6911uxe_probe()
1897 if (!lt6911uxe->i2c_client->irq) in lt6911uxe_probe()
1898 flush_work(<6911uxe->work_i2c_poll); in lt6911uxe_probe()
1899 cancel_delayed_work(<6911uxe->delayed_work_hotplug); in lt6911uxe_probe()
1900 cancel_delayed_work(<6911uxe->delayed_work_res_change); in lt6911uxe_probe()
1903 media_entity_cleanup(&sd->entity); in lt6911uxe_probe()
1906 v4l2_ctrl_handler_free(<6911uxe->hdl); in lt6911uxe_probe()
1907 mutex_destroy(<6911uxe->confctl_mutex); in lt6911uxe_probe()
1913 struct v4l2_subdev *sd = i2c_get_clientdata(client); in lt6911uxe_remove() local
1914 struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd); in lt6911uxe_remove()
1916 if (!lt6911uxe->i2c_client->irq) { in lt6911uxe_remove()
1917 del_timer_sync(<6911uxe->timer); in lt6911uxe_remove()
1918 flush_work(<6911uxe->work_i2c_poll); in lt6911uxe_remove()
1920 cancel_delayed_work_sync(<6911uxe->delayed_work_hotplug); in lt6911uxe_remove()
1921 cancel_delayed_work_sync(<6911uxe->delayed_work_res_change); in lt6911uxe_remove()
1922 v4l2_async_unregister_subdev(sd); in lt6911uxe_remove()
1923 v4l2_device_unregister_subdev(sd); in lt6911uxe_remove()
1925 media_entity_cleanup(&sd->entity); in lt6911uxe_remove()
1927 v4l2_ctrl_handler_free(<6911uxe->hdl); in lt6911uxe_remove()
1928 mutex_destroy(<6911uxe->confctl_mutex); in lt6911uxe_remove()
1929 clk_disable_unprepare(lt6911uxe->xvclk); in lt6911uxe_remove()
1964 MODULE_DESCRIPTION("Lontium lt6911uxe HDMI to CSI-2 bridge driver");
1965 MODULE_AUTHOR("Jianwei Fan <jianwei.fan@rock-chips.com>");