Lines Matching +full:gpio +full:- +full:out +full:- +full:pol

1 // SPDX-License-Identifier: GPL-2.0
5 * Author: Dingxian Wen <shawn.wen@rock-chips.com>
21 #include <linux/gpio/consumer.h>
27 #include <linux/v4l2-dv-timings.h>
31 #include <linux/rk-camera-module.h>
32 #include <media/v4l2-dv-timings.h>
33 #include <media/v4l2-device.h>
34 #include <media/v4l2-ctrls.h>
35 #include <media/v4l2-event.h>
36 #include <media/v4l2-fwnode.h>
45 MODULE_PARM_DESC(debug, "debug level (0-2)");
47 #define RK_CAMERA_MODULE_DUAL_EDGE "rockchip,dual-edge"
49 #define RK_CAMERA_MODULE_DVP_MODE "rockchip,dvp-mode"
259 val = gpiod_get_value(lt8619c->plugin_det_gpio); in tx_5v_power_present()
268 v4l2_dbg(1, debug, sd, "no signal:%d\n", lt8619c->nosignal); in no_signal()
269 return lt8619c->nosignal; in no_signal()
287 struct v4l2_bt_timings *bt = &timings->bt; in lt8619c_get_detected_timings()
294 timings->type = V4L2_DV_BT_656_1120; in lt8619c_get_detected_timings()
296 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_get_detected_timings()
297 regmap_read(lt8619c->reg_map, 0x22, &val); in lt8619c_get_detected_timings()
299 regmap_read(lt8619c->reg_map, 0x23, &val); in lt8619c_get_detected_timings()
302 regmap_read(lt8619c->reg_map, 0x20, &val); in lt8619c_get_detected_timings()
304 regmap_read(lt8619c->reg_map, 0x21, &val); in lt8619c_get_detected_timings()
307 regmap_read(lt8619c->reg_map, 0x1e, &val); in lt8619c_get_detected_timings()
309 regmap_read(lt8619c->reg_map, 0x1f, &val); in lt8619c_get_detected_timings()
312 regmap_read(lt8619c->reg_map, 0x1c, &val); in lt8619c_get_detected_timings()
314 regmap_read(lt8619c->reg_map, 0x1d, &val); in lt8619c_get_detected_timings()
317 regmap_read(lt8619c->reg_map, 0x1a, &val); in lt8619c_get_detected_timings()
319 regmap_read(lt8619c->reg_map, 0x1b, &val); in lt8619c_get_detected_timings()
322 regmap_read(lt8619c->reg_map, 0x18, &val); in lt8619c_get_detected_timings()
324 regmap_read(lt8619c->reg_map, 0x19, &val); in lt8619c_get_detected_timings()
327 regmap_read(lt8619c->reg_map, 0x14, &val); in lt8619c_get_detected_timings()
329 regmap_read(lt8619c->reg_map, 0x15, &val); in lt8619c_get_detected_timings()
332 regmap_read(lt8619c->reg_map, 0x17, &vfp); in lt8619c_get_detected_timings()
333 regmap_read(lt8619c->reg_map, 0x16, &vbp); in lt8619c_get_detected_timings()
334 regmap_read(lt8619c->reg_map, 0x13, &vs); in lt8619c_get_detected_timings()
336 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_get_detected_timings()
337 regmap_read(lt8619c->reg_map, 0x44, &val); in lt8619c_get_detected_timings()
339 regmap_read(lt8619c->reg_map, 0x45, &val); in lt8619c_get_detected_timings()
341 regmap_read(lt8619c->reg_map, 0x46, &val); in lt8619c_get_detected_timings()
344 bt->width = hact; in lt8619c_get_detected_timings()
345 bt->height = vact; in lt8619c_get_detected_timings()
346 bt->hfrontporch = hfp; in lt8619c_get_detected_timings()
347 bt->hsync = hs; in lt8619c_get_detected_timings()
348 bt->hbackporch = hbp; in lt8619c_get_detected_timings()
349 bt->vfrontporch = vfp; in lt8619c_get_detected_timings()
350 bt->vsync = vs; in lt8619c_get_detected_timings()
351 bt->vbackporch = vbp; in lt8619c_get_detected_timings()
353 bt->pixelclock = pix_clk; in lt8619c_get_detected_timings()
361 bt->interlaced = V4L2_DV_INTERLACED; in lt8619c_get_detected_timings()
362 bt->height *= 2; in lt8619c_get_detected_timings()
363 bt->il_vsync = bt->vsync + 1; in lt8619c_get_detected_timings()
365 bt->interlaced = V4L2_DV_PROGRESSIVE; in lt8619c_get_detected_timings()
370 __func__, hact, vact, htotal, vtotal, fps, bt->pixelclock, in lt8619c_get_detected_timings()
371 (bt->interlaced == V4L2_DV_INTERLACED) ? "I" : "P"); in lt8619c_get_detected_timings()
374 __func__, bt->hfrontporch, bt->hsync, bt->hbackporch, in lt8619c_get_detected_timings()
375 bt->vfrontporch, bt->vsync, bt->vbackporch); in lt8619c_get_detected_timings()
394 struct v4l2_subdev *sd = &lt8619c->sd; in lt8619c_delayed_work_enable_hotplug()
397 mutex_lock(&lt8619c->confctl_mutex); in lt8619c_delayed_work_enable_hotplug()
401 lt8619c->nosignal = false; in lt8619c_delayed_work_enable_hotplug()
403 schedule_delayed_work(&lt8619c->delayed_work_monitor_resolution, in lt8619c_delayed_work_enable_hotplug()
406 cancel_delayed_work(&lt8619c->delayed_work_monitor_resolution); in lt8619c_delayed_work_enable_hotplug()
409 lt8619c->nosignal = true; in lt8619c_delayed_work_enable_hotplug()
411 mutex_unlock(&lt8619c->confctl_mutex); in lt8619c_delayed_work_enable_hotplug()
419 struct v4l2_subdev *sd = &lt8619c->sd; in lt8619c_delayed_work_monitor_resolution()
425 v4l2_dbg(2, debug, sd, "%s: HDMI pull out, return!\n", __func__); in lt8619c_delayed_work_monitor_resolution()
426 lt8619c->nosignal = true; in lt8619c_delayed_work_monitor_resolution()
430 mutex_lock(&lt8619c->confctl_mutex); in lt8619c_delayed_work_monitor_resolution()
439 lt8619c->nosignal = true; in lt8619c_delayed_work_monitor_resolution()
446 lt8619c->nosignal = false; in lt8619c_delayed_work_monitor_resolution()
448 mutex_unlock(&lt8619c->confctl_mutex); in lt8619c_delayed_work_monitor_resolution()
450 schedule_delayed_work(&lt8619c->delayed_work_monitor_resolution, HZ); in lt8619c_delayed_work_monitor_resolution()
459 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_load_hdcpkey()
460 regmap_write(lt8619c->reg_map, 0xb2, 0x50); in lt8619c_load_hdcpkey()
461 regmap_write(lt8619c->reg_map, 0xa3, 0x77); in lt8619c_load_hdcpkey()
464 regmap_read(lt8619c->reg_map, 0xc0, &val); in lt8619c_load_hdcpkey()
467 wait_cnt--; in lt8619c_load_hdcpkey()
470 regmap_write(lt8619c->reg_map, 0xb2, 0xd0); in lt8619c_load_hdcpkey()
471 regmap_write(lt8619c->reg_map, 0xa3, 0x57); in lt8619c_load_hdcpkey()
492 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_mode_config()
493 regmap_update_bits(lt8619c->reg_map, 0x2c, BIT(5) | BIT(4), BIT(5) | BIT(4)); in lt8619c_mode_config()
495 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_mode_config()
496 regmap_write(lt8619c->reg_map, 0x80, CLK_SRC); in lt8619c_mode_config()
497 regmap_write(lt8619c->reg_map, 0x89, REF_RESISTANCE); in lt8619c_mode_config()
498 regmap_write(lt8619c->reg_map, 0x8b, 0x90); in lt8619c_mode_config()
500 regmap_write(lt8619c->reg_map, 0xa8, 0x07); in lt8619c_mode_config()
502 regmap_write(lt8619c->reg_map, 0x04, 0xf2); in lt8619c_mode_config()
504 if (lt8619c->BT656_double_clk_en) { in lt8619c_mode_config()
505 regmap_write(lt8619c->reg_map, 0x96, 0x71); in lt8619c_mode_config()
506 regmap_write(lt8619c->reg_map, 0xa0, 0x51); in lt8619c_mode_config()
507 regmap_write(lt8619c->reg_map, 0xa3, 0x44); in lt8619c_mode_config()
508 regmap_write(lt8619c->reg_map, 0xa2, 0x20); in lt8619c_mode_config()
510 regmap_write(lt8619c->reg_map, 0x96, 0x71); in lt8619c_mode_config()
511 regmap_write(lt8619c->reg_map, 0xa0, 0x50); in lt8619c_mode_config()
512 regmap_write(lt8619c->reg_map, 0xa3, 0x44); in lt8619c_mode_config()
513 regmap_write(lt8619c->reg_map, 0xa2, 0x20); in lt8619c_mode_config()
515 regmap_update_bits(lt8619c->reg_map, 0x60, OUTPUT_MODE_MASK, in lt8619c_mode_config()
516 lt8619c->yuv_output_mode); in lt8619c_mode_config()
518 if (lt8619c->clk_ddrmode_en == 1) in lt8619c_mode_config()
519 regmap_write(lt8619c->reg_map, 0xa4, 0x14); in lt8619c_mode_config()
521 regmap_write(lt8619c->reg_map, 0xa4, 0x10); in lt8619c_mode_config()
524 regmap_write(lt8619c->reg_map, 0x6f, 0x04); in lt8619c_mode_config()
527 __func__, (lt8619c->yuv_output_mode == BT656_OUTPUT) ? "BT656" : in lt8619c_mode_config()
528 "BT1120", lt8619c->clk_ddrmode_en); in lt8619c_mode_config()
538 level = lt8619c->hpd_output_inverted ? !en : en; in lt8619c_set_hpd()
539 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_set_hpd()
541 regmap_update_bits(lt8619c->reg_map, 0x06, BIT(3), BIT(3)); in lt8619c_set_hpd()
543 regmap_update_bits(lt8619c->reg_map, 0x06, BIT(3), 0); in lt8619c_set_hpd()
551 u32 edid_len = edid->blocks * EDID_BLOCK_SIZE; in lt8619c_write_edid()
553 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_write_edid()
555 regmap_write(lt8619c->reg_map, 0x8e, 0x07); in lt8619c_write_edid()
557 regmap_write(lt8619c->reg_map, 0x8f, 0x00); in lt8619c_write_edid()
560 regmap_write(lt8619c->reg_map, 0x90, edid->edid[i]); in lt8619c_write_edid()
562 regmap_write(lt8619c->reg_map, 0x8e, 0x02); in lt8619c_write_edid()
571 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_read_edid()
573 regmap_write(lt8619c->reg_map, 0x8e, 0x07); in lt8619c_read_edid()
575 regmap_write(lt8619c->reg_map, 0x8f, 0x00); in lt8619c_read_edid()
577 regmap_read(lt8619c->reg_map, 0x90, &val); in lt8619c_read_edid()
580 regmap_write(lt8619c->reg_map, 0x8e, 0x02); in lt8619c_read_edid()
587 return v4l2_ctrl_s_ctrl(lt8619c->detect_tx_5v_ctrl, in lt8619c_s_ctrl_detect_tx_5v()
620 hact = bt->width; in lt8619c_set_bt_tx_timing()
621 vact = bt->height; in lt8619c_set_bt_tx_timing()
622 hfp = bt->hfrontporch; in lt8619c_set_bt_tx_timing()
623 hs = bt->hsync; in lt8619c_set_bt_tx_timing()
624 hbp = bt->hbackporch; in lt8619c_set_bt_tx_timing()
625 vfp = bt->vfrontporch; in lt8619c_set_bt_tx_timing()
626 vs = bt->vsync; in lt8619c_set_bt_tx_timing()
627 vbp = bt->vbackporch; in lt8619c_set_bt_tx_timing()
632 v_blank = vtotal - vact; in lt8619c_set_bt_tx_timing()
634 if (bt->interlaced == V4L2_DV_INTERLACED) { in lt8619c_set_bt_tx_timing()
638 regmap_update_bits(lt8619c->reg_map, 0x60, IP_SEL_MASK, in lt8619c_set_bt_tx_timing()
653 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_set_bt_tx_timing()
654 regmap_write(lt8619c->reg_map, 0x61, (h_offset >> 8) & 0xff); in lt8619c_set_bt_tx_timing()
655 regmap_write(lt8619c->reg_map, 0x62, h_offset & 0xff); in lt8619c_set_bt_tx_timing()
656 regmap_write(lt8619c->reg_map, 0x63, (hact >> 8) & 0xff); in lt8619c_set_bt_tx_timing()
657 regmap_write(lt8619c->reg_map, 0x64, hact & 0xff); in lt8619c_set_bt_tx_timing()
658 regmap_write(lt8619c->reg_map, 0x65, (htotal >> 8) & 0xff); in lt8619c_set_bt_tx_timing()
659 regmap_write(lt8619c->reg_map, 0x66, htotal & 0xff); in lt8619c_set_bt_tx_timing()
660 regmap_write(lt8619c->reg_map, 0x67, v_offset & 0xff); in lt8619c_set_bt_tx_timing()
661 regmap_write(lt8619c->reg_map, 0x68, v_blank & 0xff); in lt8619c_set_bt_tx_timing()
662 regmap_write(lt8619c->reg_map, 0x69, (vact >> 8) & 0xff); in lt8619c_set_bt_tx_timing()
663 regmap_write(lt8619c->reg_map, 0x6a, vact & 0xff); in lt8619c_set_bt_tx_timing()
664 regmap_write(lt8619c->reg_map, 0x6b, (vtotal >> 8) & 0xff); in lt8619c_set_bt_tx_timing()
665 regmap_write(lt8619c->reg_map, 0x6c, vtotal & 0xff); in lt8619c_set_bt_tx_timing()
670 if (lt8619c->power_gpio) { in lt8619c_power_on()
671 gpiod_set_value(lt8619c->power_gpio, 1); in lt8619c_power_on()
675 if (lt8619c->reset_gpio) { in lt8619c_power_on()
676 gpiod_set_value(lt8619c->reset_gpio, 1); in lt8619c_power_on()
678 gpiod_set_value(lt8619c->reset_gpio, 0); in lt8619c_power_on()
689 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_wait_for_signal_stable()
692 regmap_read(lt8619c->reg_map, 0x43, &val); in lt8619c_wait_for_signal_stable()
704 regmap_read(lt8619c->reg_map, 0x13, &val); in lt8619c_wait_for_signal_stable()
715 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_wait_for_signal_stable()
716 regmap_write(lt8619c->reg_map, 0x09, 0x7f); in lt8619c_wait_for_signal_stable()
718 regmap_write(lt8619c->reg_map, 0x09, 0xff); in lt8619c_wait_for_signal_stable()
722 regmap_write(lt8619c->reg_map, 0x0c, 0xfb); in lt8619c_wait_for_signal_stable()
724 regmap_write(lt8619c->reg_map, 0x0c, 0xff); in lt8619c_wait_for_signal_stable()
734 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in LVDSPLL_Lock_Det()
735 regmap_write(lt8619c->reg_map, 0x0e, 0xfd); in LVDSPLL_Lock_Det()
737 regmap_write(lt8619c->reg_map, 0x0e, 0xff); in LVDSPLL_Lock_Det()
740 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in LVDSPLL_Lock_Det()
741 regmap_read(lt8619c->reg_map, 0x87, &val); in LVDSPLL_Lock_Det()
743 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in LVDSPLL_Lock_Det()
744 regmap_write(lt8619c->reg_map, 0x0e, 0xfd); in LVDSPLL_Lock_Det()
746 regmap_write(lt8619c->reg_map, 0x0e, 0xff); in LVDSPLL_Lock_Det()
748 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in LVDSPLL_Lock_Det()
749 regmap_read(lt8619c->reg_map, 0x87, &val); in LVDSPLL_Lock_Det()
762 int start = -1; in LT8619C_phase_config()
763 int end = -1; in LT8619C_phase_config()
767 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in LT8619C_phase_config()
768 regmap_read(lt8619c->reg_map, 0x87, &val); in LT8619C_phase_config()
770 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in LT8619C_phase_config()
771 regmap_write(lt8619c->reg_map, 0x0e, 0xfd); in LT8619C_phase_config()
773 regmap_write(lt8619c->reg_map, 0x0e, 0xff); in LT8619C_phase_config()
775 regmap_write(lt8619c->reg_map, 0x0a, 0x3f); in LT8619C_phase_config()
777 regmap_write(lt8619c->reg_map, 0x0a, 0x7f); in LT8619C_phase_config()
780 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in LT8619C_phase_config()
781 regmap_read(lt8619c->reg_map, 0x87, &val); in LT8619C_phase_config()
785 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in LT8619C_phase_config()
786 regmap_write(lt8619c->reg_map, 0xa2, phase_num[i]); in LT8619C_phase_config()
788 regmap_read(lt8619c->reg_map, 0x91, &val); in LT8619C_phase_config()
794 if (start == -1) in LT8619C_phase_config()
804 regmap_write(lt8619c->reg_map, 0xa2, phase_num[i]); in LT8619C_phase_config()
806 if ((start != -1) && (end != -1) && (end >= start)) in LT8619C_phase_config()
807 regmap_write(lt8619c->reg_map, 0xa2, in LT8619C_phase_config()
808 phase_num[start + (end - start) / 2]); in LT8619C_phase_config()
810 regmap_write(lt8619c->reg_map, 0xa2, in LT8619C_phase_config()
811 phase_num[ARRAY_SIZE(phase_num) - 1]); in LT8619C_phase_config()
815 regmap_write(lt8619c->reg_map, 0xa8, 0x0f); in LT8619C_phase_config()
823 if (lt8619c->bt_tx_sync_pol == BT_TX_SYNC_POSITIVE) { in sync_polarity_config()
824 v4l2_info(sd, "%s: cfg h_vsync pol: POSITIVE\n", __func__); in sync_polarity_config()
825 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in sync_polarity_config()
826 regmap_update_bits(lt8619c->reg_map, 0x60, SYNC_POL_MASK, in sync_polarity_config()
828 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in sync_polarity_config()
829 regmap_read(lt8619c->reg_map, 0x17, &val); in sync_polarity_config()
830 regmap_read(lt8619c->reg_map, 0x05, &adj); in sync_polarity_config()
833 regmap_update_bits(lt8619c->reg_map, 0x05, in sync_polarity_config()
839 regmap_update_bits(lt8619c->reg_map, 0x05, in sync_polarity_config()
843 v4l2_info(sd, "%s: cfg h_vsync pol: NEGATIVE\n", __func__); in sync_polarity_config()
844 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in sync_polarity_config()
845 regmap_update_bits(lt8619c->reg_map, 0x60, SYNC_POL_MASK, in sync_polarity_config()
847 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in sync_polarity_config()
848 regmap_read(lt8619c->reg_map, 0x17, &val); in sync_polarity_config()
849 regmap_read(lt8619c->reg_map, 0x05, &adj); in sync_polarity_config()
852 regmap_update_bits(lt8619c->reg_map, 0x05, in sync_polarity_config()
858 regmap_update_bits(lt8619c->reg_map, 0x05, in sync_polarity_config()
872 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_yuv_config()
873 regmap_update_bits(lt8619c->reg_map, 0x0d, BIT(1) | BIT(0), 0); in lt8619c_yuv_config()
875 regmap_update_bits(lt8619c->reg_map, 0x0d, BIT(1) | BIT(0), BIT(1) | BIT(0)); in lt8619c_yuv_config()
878 regmap_write(lt8619c->reg_map, BANK_REG, BANK_80); in lt8619c_yuv_config()
879 regmap_read(lt8619c->reg_map, 0x71, &val); in lt8619c_yuv_config()
883 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_yuv_config()
884 regmap_write(lt8619c->reg_map, 0x07, 0xf0); in lt8619c_yuv_config()
885 regmap_write(lt8619c->reg_map, 0x52, 0x02 + in lt8619c_yuv_config()
886 lt8619c->cp_convert_mode); in lt8619c_yuv_config()
890 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_yuv_config()
891 regmap_write(lt8619c->reg_map, 0x07, 0x80); in lt8619c_yuv_config()
892 regmap_write(lt8619c->reg_map, 0x52, 0x00); in lt8619c_yuv_config()
896 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_yuv_config()
897 regmap_write(lt8619c->reg_map, 0x07, 0xf0); in lt8619c_yuv_config()
898 regmap_write(lt8619c->reg_map, 0x52, 0x0a + in lt8619c_yuv_config()
899 lt8619c->cp_convert_mode); in lt8619c_yuv_config()
904 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_yuv_config()
905 regmap_write(lt8619c->reg_map, 0x6d, lt8619c->yc_swap); in lt8619c_yuv_config()
906 regmap_write(lt8619c->reg_map, 0x6e, lt8619c->yuv_colordepth); in lt8619c_yuv_config()
909 regmap_update_bits(lt8619c->reg_map, 0x0e, BIT(1), 0); in lt8619c_yuv_config()
911 regmap_update_bits(lt8619c->reg_map, 0x0e, BIT(1), BIT(1)); in lt8619c_yuv_config()
914 regmap_update_bits(lt8619c->reg_map, 0x0d, BIT(1) | BIT(0), 0); in lt8619c_yuv_config()
916 regmap_update_bits(lt8619c->reg_map, 0x0d, BIT(1) | BIT(0), BIT(1) | BIT(0)); in lt8619c_yuv_config()
930 lt8619c->enable_hdcp = false; in lt8619c_initial_setup()
931 lt8619c->cp_convert_mode = CP_CONVERT_MODE; in lt8619c_initial_setup()
932 lt8619c->yuv_colordepth = YUV_COLORDEPTH; in lt8619c_initial_setup()
933 lt8619c->bt_tx_sync_pol = BT_TX_SYNC_POL; in lt8619c_initial_setup()
935 if (lt8619c->yuv_output_mode == BT656_OUTPUT) { in lt8619c_initial_setup()
936 lt8619c->yc_swap = YC_SWAP_DIS; in lt8619c_initial_setup()
937 lt8619c->BT656_double_clk_en = true; in lt8619c_initial_setup()
939 lt8619c->yc_swap = YC_SWAP_EN; in lt8619c_initial_setup()
940 lt8619c->BT656_double_clk_en = false; in lt8619c_initial_setup()
945 lt8619c->edid_blocks_written = def_edid.blocks; in lt8619c_initial_setup()
946 lt8619c_set_hdmi_hdcp(sd, lt8619c->enable_hdcp); in lt8619c_initial_setup()
953 schedule_delayed_work(&lt8619c->delayed_work_monitor_resolution, in lt8619c_initial_setup()
972 if (!v4l2_match_dv_timings(&lt8619c->timings, &timings, 0, false)) { in lt8619c_format_change()
975 v4l2_print_dv_timings(sd->name, in lt8619c_format_change()
980 if (sd->devnode) in lt8619c_format_change()
988 struct v4l2_bt_timings *new_bt = &timings->bt; in lt8619c_timing_changed()
989 struct v4l2_bt_timings *bt = &lt8619c->timings.bt; in lt8619c_timing_changed()
991 if ((bt->width != new_bt->width) | in lt8619c_timing_changed()
992 (bt->height != new_bt->height) | in lt8619c_timing_changed()
993 (abs(bt->hfrontporch - new_bt->hfrontporch) > 1) | in lt8619c_timing_changed()
994 (abs(bt->hsync - new_bt->hsync) > 1) | in lt8619c_timing_changed()
995 (abs(bt->hbackporch - new_bt->hbackporch) > 1) | in lt8619c_timing_changed()
996 (abs(bt->vfrontporch - new_bt->vfrontporch) > 1) | in lt8619c_timing_changed()
997 (abs(bt->vsync - new_bt->vsync) > 1) | in lt8619c_timing_changed()
998 (abs(bt->vbackporch - new_bt->vbackporch) > 1) | in lt8619c_timing_changed()
999 (abs(bt->pixelclock - new_bt->pixelclock) > 5000)) { in lt8619c_timing_changed()
1012 struct v4l2_bt_timings *bt = &timings->bt; in lt8619c_rcv_supported_res()
1014 hact = bt->width; in lt8619c_rcv_supported_res()
1015 vact = bt->height; in lt8619c_rcv_supported_res()
1016 htotal = bt->hsync + bt->hbackporch + hact + bt->hfrontporch; in lt8619c_rcv_supported_res()
1017 vtotal = bt->vsync + bt->vbackporch + vact + bt->vfrontporch; in lt8619c_rcv_supported_res()
1032 if (bt->pixelclock < 25000000) { in lt8619c_rcv_supported_res()
1033 v4l2_err(sd, "%s pixclk: %llu, err!\n", __func__, bt->pixelclock); in lt8619c_rcv_supported_res()
1043 switch (sub->type) { in lt8619c_subscribe_event()
1049 return -EINVAL; in lt8619c_subscribe_event()
1069 return -EINVAL; in lt8619c_s_dv_timings()
1072 v4l2_print_dv_timings(sd->name, "lt8619c_s_dv_timings: ", in lt8619c_s_dv_timings()
1075 if (v4l2_match_dv_timings(&lt8619c->timings, timings, 0, false)) { in lt8619c_s_dv_timings()
1081 v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); in lt8619c_s_dv_timings()
1082 return -ERANGE; in lt8619c_s_dv_timings()
1085 lt8619c->timings = *timings; in lt8619c_s_dv_timings()
1096 *timings = lt8619c->timings; in lt8619c_g_dv_timings()
1104 if (timings->pad != 0) in lt8619c_enum_dv_timings()
1105 return -EINVAL; in lt8619c_enum_dv_timings()
1116 mutex_lock(&lt8619c->confctl_mutex); in lt8619c_query_dv_timings()
1118 mutex_unlock(&lt8619c->confctl_mutex); in lt8619c_query_dv_timings()
1123 v4l2_print_dv_timings(sd->name, "lt8619c_query_dv_timings: ", in lt8619c_query_dv_timings()
1127 v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); in lt8619c_query_dv_timings()
1128 return -ERANGE; in lt8619c_query_dv_timings()
1137 if (cap->pad != 0) in lt8619c_dv_timings_cap()
1138 return -EINVAL; in lt8619c_dv_timings_cap()
1150 cfg->type = V4L2_MBUS_BT656; in lt8619c_g_mbus_config()
1151 if (lt8619c->clk_ddrmode_en) { in lt8619c_g_mbus_config()
1152 cfg->flags = RKMODULE_CAMERA_BT656_CHANNELS | in lt8619c_g_mbus_config()
1156 cfg->flags = RKMODULE_CAMERA_BT656_CHANNELS | in lt8619c_g_mbus_config()
1174 switch (code->index) { in lt8619c_enum_mbus_code()
1176 code->code = MEDIA_BUS_FMT_UYVY8_2X8; in lt8619c_enum_mbus_code()
1180 return -EINVAL; in lt8619c_enum_mbus_code()
1187 int ret = -1; in lt8619c_get_ctrl()
1188 struct lt8619c *lt8619c = container_of(ctrl->handler, struct lt8619c, hdl); in lt8619c_get_ctrl()
1189 struct v4l2_subdev *sd = &(lt8619c->sd); in lt8619c_get_ctrl()
1191 if (ctrl->id == V4L2_CID_DV_RX_POWER_PRESENT) { in lt8619c_get_ctrl()
1193 *ctrl->p_new.p_s32 = ret; in lt8619c_get_ctrl()
1205 if (fse->index >= ARRAY_SIZE(supported_modes)) in lt8619c_enum_frame_sizes()
1206 return -EINVAL; in lt8619c_enum_frame_sizes()
1208 if (fse->code != MEDIA_BUS_FMT_UYVY8_2X8) in lt8619c_enum_frame_sizes()
1209 return -EINVAL; in lt8619c_enum_frame_sizes()
1211 fse->min_width = supported_modes[fse->index].width; in lt8619c_enum_frame_sizes()
1212 fse->max_width = supported_modes[fse->index].width; in lt8619c_enum_frame_sizes()
1213 fse->max_height = supported_modes[fse->index].height; in lt8619c_enum_frame_sizes()
1214 fse->min_height = supported_modes[fse->index].height; in lt8619c_enum_frame_sizes()
1223 if (fie->index >= ARRAY_SIZE(supported_modes)) in lt8619c_enum_frame_interval()
1224 return -EINVAL; in lt8619c_enum_frame_interval()
1226 fie->code = MEDIA_BUS_FMT_UYVY8_2X8; in lt8619c_enum_frame_interval()
1228 fie->width = supported_modes[fie->index].width; in lt8619c_enum_frame_interval()
1229 fie->height = supported_modes[fie->index].height; in lt8619c_enum_frame_interval()
1230 fie->interval = supported_modes[fie->index].max_fps; in lt8619c_enum_frame_interval()
1239 struct v4l2_bt_timings *bt = &(lt8619c->timings.bt); in lt8619c_get_fmt()
1241 mutex_lock(&lt8619c->confctl_mutex); in lt8619c_get_fmt()
1242 format->format.code = lt8619c->mbus_fmt_code; in lt8619c_get_fmt()
1243 format->format.width = lt8619c->timings.bt.width; in lt8619c_get_fmt()
1244 format->format.height = lt8619c->timings.bt.height; in lt8619c_get_fmt()
1245 format->format.colorspace = V4L2_COLORSPACE_SRGB; in lt8619c_get_fmt()
1246 if (bt->interlaced == V4L2_DV_INTERLACED) in lt8619c_get_fmt()
1247 format->format.field = V4L2_FIELD_INTERLACED; in lt8619c_get_fmt()
1249 format->format.field = V4L2_FIELD_NONE; in lt8619c_get_fmt()
1250 mutex_unlock(&lt8619c->confctl_mutex); in lt8619c_get_fmt()
1253 format->format.code, in lt8619c_get_fmt()
1254 format->format.width, in lt8619c_get_fmt()
1255 format->format.height, in lt8619c_get_fmt()
1256 (format->format.field == V4L2_FIELD_INTERLACED) ? in lt8619c_get_fmt()
1258 format->format.colorspace); in lt8619c_get_fmt()
1266 return abs(mode->width - framefmt->width) + in lt8619c_get_reso_dist()
1267 abs(mode->height - framefmt->height); in lt8619c_get_reso_dist()
1273 struct v4l2_mbus_framefmt *framefmt = &fmt->format; in lt8619c_find_best_fit()
1276 int cur_best_fit_dist = -1; in lt8619c_find_best_fit()
1281 if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) { in lt8619c_find_best_fit()
1298 u32 code = format->format.code; in lt8619c_set_fmt()
1301 format->format.code = code; in lt8619c_set_fmt()
1310 return -EINVAL; in lt8619c_set_fmt()
1313 if (format->which == V4L2_SUBDEV_FORMAT_TRY) in lt8619c_set_fmt()
1316 lt8619c->mbus_fmt_code = format->format.code; in lt8619c_set_fmt()
1318 lt8619c->cur_mode = mode; in lt8619c_set_fmt()
1330 memset(edid->reserved, 0, sizeof(edid->reserved)); in lt8619c_g_edid()
1332 if (edid->pad != 0) in lt8619c_g_edid()
1333 return -EINVAL; in lt8619c_g_edid()
1335 if (edid->start_block == 0 && edid->blocks == 0) { in lt8619c_g_edid()
1336 edid->blocks = lt8619c->edid_blocks_written; in lt8619c_g_edid()
1340 if (lt8619c->edid_blocks_written == 0) in lt8619c_g_edid()
1341 return -ENODATA; in lt8619c_g_edid()
1343 if (edid->start_block >= lt8619c->edid_blocks_written || in lt8619c_g_edid()
1344 edid->blocks == 0) in lt8619c_g_edid()
1345 return -EINVAL; in lt8619c_g_edid()
1347 if (edid->start_block + edid->blocks > lt8619c->edid_blocks_written) in lt8619c_g_edid()
1348 edid->blocks = lt8619c->edid_blocks_written - edid->start_block; in lt8619c_g_edid()
1350 lt8619c_read_edid(sd, edid->edid, edid->blocks * EDID_BLOCK_SIZE); in lt8619c_g_edid()
1361 __func__, edid->pad, edid->start_block, edid->blocks); in lt8619c_s_edid()
1363 memset(edid->reserved, 0, sizeof(edid->reserved)); in lt8619c_s_edid()
1365 if (edid->pad != 0) in lt8619c_s_edid()
1366 return -EINVAL; in lt8619c_s_edid()
1368 if (edid->start_block != 0) in lt8619c_s_edid()
1369 return -EINVAL; in lt8619c_s_edid()
1371 if (edid->blocks > EDID_NUM_BLOCKS_MAX) { in lt8619c_s_edid()
1372 edid->blocks = EDID_NUM_BLOCKS_MAX; in lt8619c_s_edid()
1373 return -E2BIG; in lt8619c_s_edid()
1378 if (edid->blocks == 0) { in lt8619c_s_edid()
1379 lt8619c->edid_blocks_written = 0; in lt8619c_s_edid()
1384 lt8619c->edid_blocks_written = edid->blocks; in lt8619c_s_edid()
1396 const struct lt8619c_mode *mode = lt8619c->cur_mode; in lt8619c_g_frame_interval()
1398 mutex_lock(&lt8619c->confctl_mutex); in lt8619c_g_frame_interval()
1399 fi->interval = mode->max_fps; in lt8619c_g_frame_interval()
1400 mutex_unlock(&lt8619c->confctl_mutex); in lt8619c_g_frame_interval()
1409 if (lt8619c->yuv_output_mode == BT656_OUTPUT) in lt8619c_querystd()
1421 strscpy(inf->base.sensor, LT8619C_NAME, sizeof(inf->base.sensor)); in lt8619c_get_module_inf()
1422 strscpy(inf->base.module, lt8619c->module_name, in lt8619c_get_module_inf()
1423 sizeof(inf->base.module)); in lt8619c_get_module_inf()
1424 strscpy(inf->base.lens, lt8619c->len_name, sizeof(inf->base.lens)); in lt8619c_get_module_inf()
1431 struct v4l2_bt_timings *bt = &(lt8619c->timings.bt); in lt8619c_open()
1433 v4l2_subdev_get_try_format(sd, fh->pad, 0); in lt8619c_open()
1436 mutex_lock(&lt8619c->confctl_mutex); in lt8619c_open()
1437 try_fmt->width = def_mode->width; in lt8619c_open()
1438 try_fmt->height = def_mode->height; in lt8619c_open()
1439 try_fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; in lt8619c_open()
1440 if (bt->interlaced == V4L2_DV_INTERLACED) in lt8619c_open()
1441 try_fmt->field = V4L2_FIELD_INTERLACED; in lt8619c_open()
1443 try_fmt->field = V4L2_FIELD_NONE; in lt8619c_open()
1444 mutex_unlock(&lt8619c->confctl_mutex); in lt8619c_open()
1460 ret = -ENOIOCTLCMD; in lt8619c_ioctl()
1479 ret = -ENOMEM; in lt8619c_compat_ioctl32()
1487 ret = -EFAULT; in lt8619c_compat_ioctl32()
1493 ret = -ENOIOCTLCMD; in lt8619c_compat_ioctl32()
1552 struct v4l2_subdev *sd = &lt8619c->sd; in plugin_detect_irq()
1555 schedule_delayed_work(&lt8619c->delayed_work_enable_hotplug, HZ / 10); in plugin_detect_irq()
1564 struct device *dev = &lt8619c->i2c_client->dev; in lt8619c_parse_of()
1565 struct device_node *node = dev->of_node; in lt8619c_parse_of()
1568 lt8619c->hpd_output_inverted = of_property_read_bool(node, in lt8619c_parse_of()
1569 "hpd-output-inverted"); in lt8619c_parse_of()
1571 &lt8619c->module_index); in lt8619c_parse_of()
1573 &lt8619c->module_facing); in lt8619c_parse_of()
1575 &lt8619c->module_name); in lt8619c_parse_of()
1577 &lt8619c->len_name); in lt8619c_parse_of()
1580 return -EINVAL; in lt8619c_parse_of()
1583 lt8619c->xvclk = devm_clk_get(dev, "xvclk"); in lt8619c_parse_of()
1584 if (IS_ERR(lt8619c->xvclk)) { in lt8619c_parse_of()
1586 return -EINVAL; in lt8619c_parse_of()
1589 err = clk_prepare_enable(lt8619c->xvclk); in lt8619c_parse_of()
1595 lt8619c->power_gpio = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); in lt8619c_parse_of()
1596 if (IS_ERR(lt8619c->power_gpio)) { in lt8619c_parse_of()
1597 dev_err(dev, "failed to get power gpio\n"); in lt8619c_parse_of()
1598 err = PTR_ERR(lt8619c->power_gpio); in lt8619c_parse_of()
1601 lt8619c->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); in lt8619c_parse_of()
1602 if (IS_ERR(lt8619c->reset_gpio)) { in lt8619c_parse_of()
1603 dev_err(dev, "failed to get reset gpio\n"); in lt8619c_parse_of()
1604 err = PTR_ERR(lt8619c->reset_gpio); in lt8619c_parse_of()
1608 lt8619c->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", in lt8619c_parse_of()
1610 if (IS_ERR(lt8619c->plugin_det_gpio)) { in lt8619c_parse_of()
1611 dev_err(dev, "failed to get plugin_det gpio\n"); in lt8619c_parse_of()
1612 err = PTR_ERR(lt8619c->plugin_det_gpio); in lt8619c_parse_of()
1617 &lt8619c->clk_ddrmode_en)) { in lt8619c_parse_of()
1618 lt8619c->clk_ddrmode_en = LT8619C_DEFAULT_DUAL_EDGE; in lt8619c_parse_of()
1623 RK_CAMERA_MODULE_DUAL_EDGE, lt8619c->clk_ddrmode_en); in lt8619c_parse_of()
1627 &lt8619c->yuv_output_mode)) { in lt8619c_parse_of()
1628 lt8619c->yuv_output_mode = LT8619C_DEFAULT_DVP_MODE; in lt8619c_parse_of()
1634 (lt8619c->yuv_output_mode == BT656_OUTPUT) ? "BT656" : "BT1120"); in lt8619c_parse_of()
1640 clk_disable_unprepare(lt8619c->xvclk); in lt8619c_parse_of()
1649 sd = &lt8619c->sd; in lt8619c_init_v4l2_ctrls()
1650 ret = v4l2_ctrl_handler_init(&lt8619c->hdl, 2); in lt8619c_init_v4l2_ctrls()
1654 v4l2_ctrl_new_std(&lt8619c->hdl, NULL, V4L2_CID_PIXEL_RATE, in lt8619c_init_v4l2_ctrls()
1656 lt8619c->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&lt8619c->hdl, in lt8619c_init_v4l2_ctrls()
1659 if (lt8619c->detect_tx_5v_ctrl) in lt8619c_init_v4l2_ctrls()
1660 lt8619c->detect_tx_5v_ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; in lt8619c_init_v4l2_ctrls()
1662 if (lt8619c->hdl.error) { in lt8619c_init_v4l2_ctrls()
1663 ret = lt8619c->hdl.error; in lt8619c_init_v4l2_ctrls()
1667 sd->ctrl_handler = &lt8619c->hdl; in lt8619c_init_v4l2_ctrls()
1670 ret = -ENODEV; in lt8619c_init_v4l2_ctrls()
1680 struct device *dev = &lt8619c->i2c_client->dev; in lt8619c_check_chip_id()
1685 regmap_write(lt8619c->reg_map, BANK_REG, BANK_60); in lt8619c_check_chip_id()
1686 ret = regmap_read(lt8619c->reg_map, CHIPID_REG_H, &id_h); in lt8619c_check_chip_id()
1687 ret |= regmap_read(lt8619c->reg_map, CHIPID_REG_M, &id_m); in lt8619c_check_chip_id()
1688 ret |= regmap_read(lt8619c->reg_map, CHIPID_REG_L, &id_l); in lt8619c_check_chip_id()
1696 ret = -1; in lt8619c_check_chip_id()
1700 ret = -1; in lt8619c_check_chip_id()
1729 struct device *dev = &client->dev; in lt8619c_probe()
1742 return -ENOMEM; in lt8619c_probe()
1744 sd = &lt8619c->sd; in lt8619c_probe()
1745 lt8619c->i2c_client = client; in lt8619c_probe()
1746 lt8619c->cur_mode = &supported_modes[0]; in lt8619c_probe()
1747 lt8619c->mbus_fmt_code = MEDIA_BUS_FMT_UYVY8_2X8; in lt8619c_probe()
1753 mutex_init(&lt8619c->confctl_mutex); in lt8619c_probe()
1758 client->flags |= I2C_CLIENT_SCCB; in lt8619c_probe()
1761 sd->internal_ops = &lt8619c_subdev_internal_ops; in lt8619c_probe()
1762 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; in lt8619c_probe()
1766 lt8619c->pad.flags = MEDIA_PAD_FL_SOURCE; in lt8619c_probe()
1767 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; in lt8619c_probe()
1768 err = media_entity_pads_init(&sd->entity, 1, &lt8619c->pad); in lt8619c_probe()
1775 lt8619c->reg_map = devm_regmap_init_i2c(client, &lt8619c_hdmirx_regmap_cfg); in lt8619c_probe()
1782 if (strcmp(lt8619c->module_facing, "back") == 0) in lt8619c_probe()
1787 snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", in lt8619c_probe()
1788 lt8619c->module_index, facing, in lt8619c_probe()
1789 LT8619C_NAME, dev_name(sd->dev)); in lt8619c_probe()
1796 INIT_DELAYED_WORK(&lt8619c->delayed_work_enable_hotplug, in lt8619c_probe()
1798 INIT_DELAYED_WORK(&lt8619c->delayed_work_monitor_resolution, in lt8619c_probe()
1802 lt8619c->plugin_irq = gpiod_to_irq(lt8619c->plugin_det_gpio); in lt8619c_probe()
1803 if (lt8619c->plugin_irq < 0) { in lt8619c_probe()
1805 err = lt8619c->plugin_irq; in lt8619c_probe()
1809 err = devm_request_threaded_irq(dev, lt8619c->plugin_irq, NULL, in lt8619c_probe()
1817 err = v4l2_ctrl_handler_setup(sd->ctrl_handler); in lt8619c_probe()
1823 v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, in lt8619c_probe()
1824 client->addr << 1, client->adapter->name); in lt8619c_probe()
1829 cancel_delayed_work(&lt8619c->delayed_work_enable_hotplug); in lt8619c_probe()
1830 cancel_delayed_work(&lt8619c->delayed_work_monitor_resolution); in lt8619c_probe()
1833 media_entity_cleanup(&sd->entity); in lt8619c_probe()
1836 v4l2_ctrl_handler_free(&lt8619c->hdl); in lt8619c_probe()
1837 mutex_destroy(&lt8619c->confctl_mutex); in lt8619c_probe()
1838 clk_disable_unprepare(lt8619c->xvclk); in lt8619c_probe()
1847 cancel_delayed_work(&lt8619c->delayed_work_enable_hotplug); in lt8619c_remove()
1848 cancel_delayed_work(&lt8619c->delayed_work_monitor_resolution); in lt8619c_remove()
1852 media_entity_cleanup(&sd->entity); in lt8619c_remove()
1854 v4l2_ctrl_handler_free(&lt8619c->hdl); in lt8619c_remove()
1855 mutex_destroy(&lt8619c->confctl_mutex); in lt8619c_remove()
1856 clk_disable_unprepare(lt8619c->xvclk); in lt8619c_remove()
1892 MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");