Lines Matching +full:sd +full:- +full:hs
1 // SPDX-License-Identifier: GPL-2.0
5 * Author: Dingxian Wen <shawn.wen@rock-chips.com>
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"
63 struct v4l2_subdev sd; member
235 static void lt8619c_set_hpd(struct v4l2_subdev *sd, int en);
236 static void lt8619c_wait_for_signal_stable(struct v4l2_subdev *sd);
237 static void lt8619c_yuv_config(struct v4l2_subdev *sd);
238 static void lt8619c_format_change(struct v4l2_subdev *sd);
239 static void enable_stream(struct v4l2_subdev *sd, bool enable);
240 static int lt8619c_s_dv_timings(struct v4l2_subdev *sd,
242 static void LVDSPLL_Lock_Det(struct v4l2_subdev *sd);
243 static void LT8619C_phase_config(struct v4l2_subdev *sd);
244 static bool lt8619c_rcv_supported_res(struct v4l2_subdev *sd,
246 static bool lt8619c_timing_changed(struct v4l2_subdev *sd,
249 static inline struct lt8619c *to_lt8619c(struct v4l2_subdev *sd) in to_lt8619c() argument
251 return container_of(sd, struct lt8619c, sd); in to_lt8619c()
254 static inline bool tx_5v_power_present(struct v4l2_subdev *sd) in tx_5v_power_present() argument
257 struct lt8619c *lt8619c = to_lt8619c(sd); in tx_5v_power_present()
259 val = gpiod_get_value(lt8619c->plugin_det_gpio); in tx_5v_power_present()
260 v4l2_dbg(1, debug, sd, "%s 5v_present: %d!\n", __func__, val); in tx_5v_power_present()
264 static inline bool no_signal(struct v4l2_subdev *sd) in no_signal() argument
266 struct lt8619c *lt8619c = to_lt8619c(sd); in no_signal()
268 v4l2_dbg(1, debug, sd, "no signal:%d\n", lt8619c->nosignal); in no_signal()
269 return lt8619c->nosignal; in no_signal()
272 static bool lt8619c_is_supported_interlaced_res(struct v4l2_subdev *sd, in lt8619c_is_supported_interlaced_res() argument
283 static int lt8619c_get_detected_timings(struct v4l2_subdev *sd, in lt8619c_get_detected_timings() argument
286 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_get_detected_timings()
287 struct v4l2_bt_timings *bt = &timings->bt; in lt8619c_get_detected_timings()
288 u32 hact, vact, htotal, vtotal, hbp, hfp, hs; in lt8619c_get_detected_timings() local
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()
328 hs = val << 8; in lt8619c_get_detected_timings()
329 regmap_read(lt8619c->reg_map, 0x15, &val); in lt8619c_get_detected_timings()
330 hs |= 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()
360 if (lt8619c_is_supported_interlaced_res(sd, hact, vact)) { 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()
368 v4l2_dbg(1, debug, sd, 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()
372 v4l2_dbg(1, debug, sd, in lt8619c_get_detected_timings()
373 "%s: hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d\n", 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()
380 static void lt8619c_config_all(struct v4l2_subdev *sd) in lt8619c_config_all() argument
382 lt8619c_wait_for_signal_stable(sd); in lt8619c_config_all()
383 LVDSPLL_Lock_Det(sd); in lt8619c_config_all()
384 lt8619c_yuv_config(sd); in lt8619c_config_all()
385 LT8619C_phase_config(sd); in lt8619c_config_all()
386 lt8619c_format_change(sd); in lt8619c_config_all()
394 struct v4l2_subdev *sd = <8619c->sd; in lt8619c_delayed_work_enable_hotplug() local
396 v4l2_dbg(2, debug, sd, "%s: in\n", __func__); in lt8619c_delayed_work_enable_hotplug()
397 mutex_lock(<8619c->confctl_mutex); in lt8619c_delayed_work_enable_hotplug()
398 if (tx_5v_power_present(sd)) { in lt8619c_delayed_work_enable_hotplug()
399 lt8619c_set_hpd(sd, 1); in lt8619c_delayed_work_enable_hotplug()
400 lt8619c_config_all(sd); in lt8619c_delayed_work_enable_hotplug()
401 lt8619c->nosignal = false; in lt8619c_delayed_work_enable_hotplug()
403 schedule_delayed_work(<8619c->delayed_work_monitor_resolution, in lt8619c_delayed_work_enable_hotplug()
406 cancel_delayed_work(<8619c->delayed_work_monitor_resolution); in lt8619c_delayed_work_enable_hotplug()
407 enable_stream(sd, false); in lt8619c_delayed_work_enable_hotplug()
408 lt8619c_set_hpd(sd, 0); in lt8619c_delayed_work_enable_hotplug()
409 lt8619c->nosignal = true; in lt8619c_delayed_work_enable_hotplug()
411 mutex_unlock(<8619c->confctl_mutex); in lt8619c_delayed_work_enable_hotplug()
419 struct v4l2_subdev *sd = <8619c->sd; in lt8619c_delayed_work_monitor_resolution() local
423 v4l2_dbg(1, debug, sd, "%s: in\n", __func__); in lt8619c_delayed_work_monitor_resolution()
424 if (!tx_5v_power_present(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(<8619c->confctl_mutex); in lt8619c_delayed_work_monitor_resolution()
431 lt8619c_get_detected_timings(sd, &timings); in lt8619c_delayed_work_monitor_resolution()
432 is_supported_res = lt8619c_rcv_supported_res(sd, &timings); in lt8619c_delayed_work_monitor_resolution()
433 is_timing_changed = lt8619c_timing_changed(sd, &timings); in lt8619c_delayed_work_monitor_resolution()
434 v4l2_dbg(2, debug, sd, in lt8619c_delayed_work_monitor_resolution()
439 lt8619c->nosignal = true; in lt8619c_delayed_work_monitor_resolution()
440 v4l2_dbg(1, debug, sd, "%s: no supported res, cfg as nosignal!\n", in lt8619c_delayed_work_monitor_resolution()
445 lt8619c_config_all(sd); in lt8619c_delayed_work_monitor_resolution()
446 lt8619c->nosignal = false; in lt8619c_delayed_work_monitor_resolution()
448 mutex_unlock(<8619c->confctl_mutex); in lt8619c_delayed_work_monitor_resolution()
450 schedule_delayed_work(<8619c->delayed_work_monitor_resolution, HZ); in lt8619c_delayed_work_monitor_resolution()
453 static void lt8619c_load_hdcpkey(struct v4l2_subdev *sd) in lt8619c_load_hdcpkey() argument
455 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_load_hdcpkey()
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()
473 v4l2_info(sd, "load hdcp key success!\n"); in lt8619c_load_hdcpkey()
475 v4l2_err(sd, "load hdcp key failed!\n"); in lt8619c_load_hdcpkey()
478 static void lt8619c_set_hdmi_hdcp(struct v4l2_subdev *sd, bool enable) in lt8619c_set_hdmi_hdcp() argument
480 v4l2_dbg(2, debug, sd, "%s: %sable\n", __func__, enable ? "en" : "dis"); in lt8619c_set_hdmi_hdcp()
483 lt8619c_load_hdcpkey(sd); in lt8619c_set_hdmi_hdcp()
485 v4l2_info(sd, "disable hdcp function!\n"); in lt8619c_set_hdmi_hdcp()
488 static void lt8619c_mode_config(struct v4l2_subdev *sd) in lt8619c_mode_config() argument
490 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_mode_config()
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()
526 v4l2_dbg(1, debug, sd, "%s: output mode:%s, clk ddrmode en:%d\n", 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()
531 static void lt8619c_set_hpd(struct v4l2_subdev *sd, int en) in lt8619c_set_hpd() argument
533 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_set_hpd()
536 v4l2_dbg(2, debug, sd, "%s: %d\n", __func__, en); in lt8619c_set_hpd()
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()
546 static void lt8619c_write_edid(struct v4l2_subdev *sd, in lt8619c_write_edid() argument
550 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_write_edid()
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()
565 static void lt8619c_read_edid(struct v4l2_subdev *sd, u8 *edid, u32 len) in lt8619c_read_edid() argument
567 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_read_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()
583 static int lt8619c_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd) in lt8619c_s_ctrl_detect_tx_5v() argument
585 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_s_ctrl_detect_tx_5v()
587 return v4l2_ctrl_s_ctrl(lt8619c->detect_tx_5v_ctrl, in lt8619c_s_ctrl_detect_tx_5v()
588 tx_5v_power_present(sd)); in lt8619c_s_ctrl_detect_tx_5v()
591 static int lt8619c_update_controls(struct v4l2_subdev *sd) in lt8619c_update_controls() argument
595 ret = lt8619c_s_ctrl_detect_tx_5v(sd); in lt8619c_update_controls()
600 static void enable_stream(struct v4l2_subdev *sd, bool enable) in enable_stream() argument
603 v4l2_info(sd, "%s: stream on!\n", __func__); in enable_stream()
605 v4l2_info(sd, "%s: stream off!\n", __func__); in enable_stream()
608 static void lt8619c_set_bt_tx_timing(struct v4l2_subdev *sd) in lt8619c_set_bt_tx_timing() argument
610 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_set_bt_tx_timing()
614 u32 hact, hfp, hbp, hs, vact, vfp, vbp, vs; in lt8619c_set_bt_tx_timing() local
618 lt8619c_get_detected_timings(sd, &timings); in lt8619c_set_bt_tx_timing()
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()
628 htotal = hs + hbp + hact + hfp; in lt8619c_set_bt_tx_timing()
630 h_offset = hbp + hs; 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()
645 v4l2_dbg(2, debug, sd, in lt8619c_set_bt_tx_timing()
648 v4l2_dbg(2, debug, sd, in lt8619c_set_bt_tx_timing()
649 "%s: hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d\n", in lt8619c_set_bt_tx_timing()
650 __func__, hfp, hs, hbp, vfp, vs, vbp); 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()
683 static void lt8619c_wait_for_signal_stable(struct v4l2_subdev *sd) in lt8619c_wait_for_signal_stable() argument
685 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_wait_for_signal_stable()
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()
698 v4l2_info(sd, "tmds clk det success, wait cnt:%d!\n", i); in lt8619c_wait_for_signal_stable()
700 v4l2_err(sd, "tmds clk det failed!\n"); in lt8619c_wait_for_signal_stable()
704 regmap_read(lt8619c->reg_map, 0x13, &val); in lt8619c_wait_for_signal_stable()
710 v4l2_info(sd, "Hsync stable, wait cnt:%d!\n", i); in lt8619c_wait_for_signal_stable()
712 v4l2_err(sd, "Hsync unstable!\n"); 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()
728 static void LVDSPLL_Lock_Det(struct v4l2_subdev *sd) in LVDSPLL_Lock_Det() argument
732 struct lt8619c *lt8619c = to_lt8619c(sd); in LVDSPLL_Lock_Det()
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()
753 v4l2_err(sd, "lvds pll lock det failed!\n"); in LVDSPLL_Lock_Det()
759 static void LT8619C_phase_config(struct v4l2_subdev *sd) in LT8619C_phase_config() argument
762 int start = -1; in LT8619C_phase_config()
763 int end = -1; in LT8619C_phase_config()
765 struct lt8619c *lt8619c = to_lt8619c(sd); 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()
801 v4l2_info(sd, "%s: BT_clk_lag:%d, start:%d, end:%d!\n", __func__, 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()
818 static void sync_polarity_config(struct v4l2_subdev *sd) in sync_polarity_config() argument
820 struct lt8619c *lt8619c = to_lt8619c(sd); in sync_polarity_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()
864 static void lt8619c_yuv_config(struct v4l2_subdev *sd) in lt8619c_yuv_config() argument
866 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_yuv_config()
869 sync_polarity_config(sd); in lt8619c_yuv_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()
887 v4l2_info(sd, "%s: colorspace: yuv444\n", __func__); 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()
893 v4l2_info(sd, "%s: colorspace: yuv222\n", __func__); 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()
900 v4l2_info(sd, "%s: colorspace: RGB\n", __func__); in lt8619c_yuv_config()
903 lt8619c_set_bt_tx_timing(sd); 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()
919 static void lt8619c_initial_setup(struct v4l2_subdev *sd) in lt8619c_initial_setup() argument
923 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_initial_setup()
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()
943 lt8619c_set_hpd(sd, 0); in lt8619c_initial_setup()
944 lt8619c_write_edid(sd, &def_edid); 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()
947 lt8619c_mode_config(sd); in lt8619c_initial_setup()
949 if (tx_5v_power_present(sd)) { in lt8619c_initial_setup()
950 lt8619c_set_hpd(sd, 1); in lt8619c_initial_setup()
951 lt8619c_config_all(sd); in lt8619c_initial_setup()
953 schedule_delayed_work(<8619c->delayed_work_monitor_resolution, in lt8619c_initial_setup()
956 lt8619c_s_dv_timings(sd, &default_timing); in lt8619c_initial_setup()
959 v4l2_dbg(1, debug, sd, "%s: init ok\n", __func__); in lt8619c_initial_setup()
962 static void lt8619c_format_change(struct v4l2_subdev *sd) in lt8619c_format_change() argument
964 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_format_change()
971 lt8619c_get_detected_timings(sd, &timings); in lt8619c_format_change()
972 if (!v4l2_match_dv_timings(<8619c->timings, &timings, 0, false)) { in lt8619c_format_change()
974 lt8619c_s_dv_timings(sd, &timings); in lt8619c_format_change()
975 v4l2_print_dv_timings(sd->name, in lt8619c_format_change()
980 if (sd->devnode) in lt8619c_format_change()
981 v4l2_subdev_notify_event(sd, <8619c_ev_fmt); in lt8619c_format_change()
984 static bool lt8619c_timing_changed(struct v4l2_subdev *sd, in lt8619c_timing_changed() argument
987 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_timing_changed()
988 struct v4l2_bt_timings *new_bt = &timings->bt; in lt8619c_timing_changed()
989 struct v4l2_bt_timings *bt = <8619c->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()
1000 v4l2_info(sd, "%s: timing changed!\n", __func__); in lt8619c_timing_changed()
1007 static bool lt8619c_rcv_supported_res(struct v4l2_subdev *sd, in lt8619c_rcv_supported_res() argument
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()
1027 v4l2_err(sd, "%s do not support res act: %dx%d, total: %dx%d\n", 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()
1040 static int lt8619c_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, in lt8619c_subscribe_event() argument
1043 switch (sub->type) { in lt8619c_subscribe_event()
1045 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub); in lt8619c_subscribe_event()
1047 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub); in lt8619c_subscribe_event()
1049 return -EINVAL; in lt8619c_subscribe_event()
1053 static int lt8619c_g_input_status(struct v4l2_subdev *sd, u32 *status) in lt8619c_g_input_status() argument
1056 *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0; in lt8619c_g_input_status()
1058 v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status); in lt8619c_g_input_status()
1063 static int lt8619c_s_dv_timings(struct v4l2_subdev *sd, in lt8619c_s_dv_timings() argument
1066 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_s_dv_timings()
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(<8619c->timings, timings, 0, false)) { in lt8619c_s_dv_timings()
1076 v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); 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()
1086 enable_stream(sd, false); in lt8619c_s_dv_timings()
1091 static int lt8619c_g_dv_timings(struct v4l2_subdev *sd, in lt8619c_g_dv_timings() argument
1094 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_g_dv_timings()
1096 *timings = lt8619c->timings; in lt8619c_g_dv_timings()
1101 static int lt8619c_enum_dv_timings(struct v4l2_subdev *sd, in lt8619c_enum_dv_timings() argument
1104 if (timings->pad != 0) in lt8619c_enum_dv_timings()
1105 return -EINVAL; in lt8619c_enum_dv_timings()
1110 static int lt8619c_query_dv_timings(struct v4l2_subdev *sd, in lt8619c_query_dv_timings() argument
1114 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_query_dv_timings()
1116 mutex_lock(<8619c->confctl_mutex); in lt8619c_query_dv_timings()
1117 ret = lt8619c_get_detected_timings(sd, timings); in lt8619c_query_dv_timings()
1118 mutex_unlock(<8619c->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()
1134 static int lt8619c_dv_timings_cap(struct v4l2_subdev *sd, in lt8619c_dv_timings_cap() argument
1137 if (cap->pad != 0) in lt8619c_dv_timings_cap()
1138 return -EINVAL; in lt8619c_dv_timings_cap()
1145 static int lt8619c_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad, in lt8619c_g_mbus_config() argument
1148 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_g_mbus_config()
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()
1163 static int lt8619c_s_stream(struct v4l2_subdev *sd, int enable) in lt8619c_s_stream() argument
1165 enable_stream(sd, enable); in lt8619c_s_stream()
1170 static int lt8619c_enum_mbus_code(struct v4l2_subdev *sd, in lt8619c_enum_mbus_code() argument
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() local
1191 if (ctrl->id == V4L2_CID_DV_RX_POWER_PRESENT) { in lt8619c_get_ctrl()
1192 ret = tx_5v_power_present(sd); in lt8619c_get_ctrl()
1193 *ctrl->p_new.p_s32 = ret; in lt8619c_get_ctrl()
1199 static int lt8619c_enum_frame_sizes(struct v4l2_subdev *sd, in lt8619c_enum_frame_sizes() argument
1203 v4l2_dbg(1, debug, sd, "%s:\n", __func__); in lt8619c_enum_frame_sizes()
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()
1219 static int lt8619c_enum_frame_interval(struct v4l2_subdev *sd, in lt8619c_enum_frame_interval() argument
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()
1234 static int lt8619c_get_fmt(struct v4l2_subdev *sd, in lt8619c_get_fmt() argument
1238 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_get_fmt()
1239 struct v4l2_bt_timings *bt = &(lt8619c->timings.bt); in lt8619c_get_fmt()
1241 mutex_lock(<8619c->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(<8619c->confctl_mutex); in lt8619c_get_fmt()
1252 v4l2_dbg(2, debug, sd, "fmt code:%d, w:%d, h:%d, field:%s, cosp:%d\n", 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()
1290 static int lt8619c_set_fmt(struct v4l2_subdev *sd, in lt8619c_set_fmt() argument
1294 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_set_fmt()
1298 u32 code = format->format.code; in lt8619c_set_fmt()
1299 int ret = lt8619c_get_fmt(sd, cfg, format); 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()
1320 enable_stream(sd, false); in lt8619c_set_fmt()
1325 static int lt8619c_g_edid(struct v4l2_subdev *sd, in lt8619c_g_edid() argument
1328 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_g_edid()
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()
1355 static int lt8619c_s_edid(struct v4l2_subdev *sd, in lt8619c_s_edid() argument
1358 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_s_edid()
1360 v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", in lt8619c_s_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()
1376 lt8619c_set_hpd(sd, 0); in lt8619c_s_edid()
1378 if (edid->blocks == 0) { in lt8619c_s_edid()
1379 lt8619c->edid_blocks_written = 0; in lt8619c_s_edid()
1383 lt8619c_write_edid(sd, edid); in lt8619c_s_edid()
1384 lt8619c->edid_blocks_written = edid->blocks; in lt8619c_s_edid()
1386 if (tx_5v_power_present(sd)) in lt8619c_s_edid()
1387 lt8619c_set_hpd(sd, 1); in lt8619c_s_edid()
1392 static int lt8619c_g_frame_interval(struct v4l2_subdev *sd, in lt8619c_g_frame_interval() argument
1395 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_g_frame_interval()
1396 const struct lt8619c_mode *mode = lt8619c->cur_mode; in lt8619c_g_frame_interval()
1398 mutex_lock(<8619c->confctl_mutex); in lt8619c_g_frame_interval()
1399 fi->interval = mode->max_fps; in lt8619c_g_frame_interval()
1400 mutex_unlock(<8619c->confctl_mutex); in lt8619c_g_frame_interval()
1405 static int lt8619c_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) in lt8619c_querystd() argument
1407 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_querystd()
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()
1428 static int lt8619c_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) in lt8619c_open() argument
1430 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_open()
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(<8619c->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(<8619c->confctl_mutex); in lt8619c_open()
1450 static long lt8619c_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) in lt8619c_ioctl() argument
1452 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_ioctl()
1460 ret = -ENOIOCTLCMD; in lt8619c_ioctl()
1468 static long lt8619c_compat_ioctl32(struct v4l2_subdev *sd, in lt8619c_compat_ioctl32() argument
1479 ret = -ENOMEM; in lt8619c_compat_ioctl32()
1483 ret = lt8619c_ioctl(sd, cmd, inf); in lt8619c_compat_ioctl32()
1487 ret = -EFAULT; in lt8619c_compat_ioctl32()
1493 ret = -ENOIOCTLCMD; in lt8619c_compat_ioctl32()
1552 struct v4l2_subdev *sd = <8619c->sd; in plugin_detect_irq() local
1555 schedule_delayed_work(<8619c->delayed_work_enable_hotplug, HZ / 10); in plugin_detect_irq()
1556 v4l2_dbg(2, debug, sd, "%s: plug change!\n", __func__); in plugin_detect_irq()
1557 tx_5v_power_present(sd); in plugin_detect_irq()
1564 struct device *dev = <8619c->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 <8619c->module_index); in lt8619c_parse_of()
1573 <8619c->module_facing); in lt8619c_parse_of()
1575 <8619c->module_name); in lt8619c_parse_of()
1577 <8619c->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()
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()
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()
1612 err = PTR_ERR(lt8619c->plugin_det_gpio); in lt8619c_parse_of()
1617 <8619c->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 <8619c->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()
1646 struct v4l2_subdev *sd; in lt8619c_init_v4l2_ctrls() local
1649 sd = <8619c->sd; in lt8619c_init_v4l2_ctrls()
1650 ret = v4l2_ctrl_handler_init(<8619c->hdl, 2); in lt8619c_init_v4l2_ctrls()
1654 v4l2_ctrl_new_std(<8619c->hdl, NULL, V4L2_CID_PIXEL_RATE, in lt8619c_init_v4l2_ctrls()
1656 lt8619c->detect_tx_5v_ctrl = v4l2_ctrl_new_std(<8619c->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()
1664 v4l2_err(sd, "cfg v4l2 ctrls failed! ret:%d\n", ret); in lt8619c_init_v4l2_ctrls()
1667 sd->ctrl_handler = <8619c->hdl; in lt8619c_init_v4l2_ctrls()
1669 if (lt8619c_update_controls(sd)) { in lt8619c_init_v4l2_ctrls()
1670 ret = -ENODEV; in lt8619c_init_v4l2_ctrls()
1671 v4l2_err(sd, "update v4l2 ctrls failed! ret:%d\n", ret); in lt8619c_init_v4l2_ctrls()
1680 struct device *dev = <8619c->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()
1731 struct v4l2_subdev *sd; in lt8619c_probe() local
1742 return -ENOMEM; in lt8619c_probe()
1744 sd = <8619c->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(<8619c->confctl_mutex); in lt8619c_probe()
1758 client->flags |= I2C_CLIENT_SCCB; in lt8619c_probe()
1760 v4l2_i2c_subdev_init(sd, client, <8619c_ops); in lt8619c_probe()
1761 sd->internal_ops = <8619c_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, <8619c->pad); in lt8619c_probe()
1770 v4l2_err(sd, "media entity init failed! err:%d\n", err); in lt8619c_probe()
1775 lt8619c->reg_map = devm_regmap_init_i2c(client, <8619c_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()
1790 err = v4l2_async_register_subdev_sensor_common(sd); in lt8619c_probe()
1792 v4l2_err(sd, "v4l2 register subdev failed! err:%d\n", err); in lt8619c_probe()
1796 INIT_DELAYED_WORK(<8619c->delayed_work_enable_hotplug, in lt8619c_probe()
1798 INIT_DELAYED_WORK(<8619c->delayed_work_monitor_resolution, in lt8619c_probe()
1800 lt8619c_initial_setup(sd); 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()
1819 v4l2_err(sd, "v4l2 ctrl handler setup failed! err:%d\n", err); 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(<8619c->delayed_work_enable_hotplug); in lt8619c_probe()
1830 cancel_delayed_work(<8619c->delayed_work_monitor_resolution); in lt8619c_probe()
1833 media_entity_cleanup(&sd->entity); in lt8619c_probe()
1836 v4l2_ctrl_handler_free(<8619c->hdl); in lt8619c_probe()
1837 mutex_destroy(<8619c->confctl_mutex); in lt8619c_probe()
1838 clk_disable_unprepare(lt8619c->xvclk); in lt8619c_probe()
1844 struct v4l2_subdev *sd = i2c_get_clientdata(client); in lt8619c_remove() local
1845 struct lt8619c *lt8619c = to_lt8619c(sd); in lt8619c_remove()
1847 cancel_delayed_work(<8619c->delayed_work_enable_hotplug); in lt8619c_remove()
1848 cancel_delayed_work(<8619c->delayed_work_monitor_resolution); in lt8619c_remove()
1849 v4l2_async_unregister_subdev(sd); in lt8619c_remove()
1850 v4l2_device_unregister_subdev(sd); in lt8619c_remove()
1852 media_entity_cleanup(&sd->entity); in lt8619c_remove()
1854 v4l2_ctrl_handler_free(<8619c->hdl); in lt8619c_remove()
1855 mutex_destroy(<8619c->confctl_mutex); in lt8619c_remove()
1856 clk_disable_unprepare(lt8619c->xvclk); in lt8619c_remove()
1892 MODULE_AUTHOR("Dingxian Wen <shawn.wen@rock-chips.com>");