RK3588 HDMIIN 디버깅(HDMI에서 MIPI-CSI로)

이 문서는 MIPI-CSI에 대한 RK3588 플랫폼 HDMI의 디버깅 및 구성 단계를 소개합니다. 이전 기사에서는 RK356X HDMIIN의 디버깅을 소개했으며 이 기사에서는 RK3588 플랫폼의 디버깅을 소개합니다. 자체 HDMIIN 외에도 RK3588은 어댑터 칩을 통해 HDMI를 MIPI-CSI 신호로 변환하고 이를 카메라와 같은 장치로 수신 및 처리할 수 있습니다.

목차

(1) MIPICSI에 일반적으로 사용되는 HDMI용 어댑터 칩 도입

1. LT6911UXC/LT6911UXE 사양

2.IT6616

3.RK628D

(2) 어댑터 칩 드라이버 디버깅

1. 드라이버 관련 인터페이스 구성

①lt6911uxe_get_detected_timings

②lt6911uxe_query_dv_timings

③lt6911uxe_g_mbus_config

④lt6911uxe_get_fmt

⑤해상도 변경 이벤트

⑥언플러그 이벤트 신고

2. dts 구성

(3) 안드로이드 HAL 적응

(4) 개요


(1) MIPICSI에 일반적으로 사용되는 HDMI용 어댑터 칩 도입

이전 기사에서는 RK3588 MIPI-CSI의 사양을 소개했습니다.총 4개의 레인 MIPI 인터페이스가 있으며 DPHY 속도는 2.5Gbps에 도달할 수 있고 총 대역폭은 10Gbps에 도달할 수 있으므로 4K60 YUV422 입력을 지원할 수 있습니다. HDMI 4K60을 지원할 수 있는지 여부는 주로 어댑터 칩의 MIPI TX DPHY 사양에 따라 다릅니다. 다음은 몇 가지 일반적인 어댑터 칩입니다.

1. LT6911UXC/LT6911UXE 사양

LT6911UXC 및 LT6911UXE는 HDMI에서 MIPI-CSI로 지원하는 Longxun에서 설계한 브리지 칩입니다.

LT6911UXC: MIPI TX DPHY의 사양은 DPHY1.2 버전이고 최대 속도는 2.0Gbps이며 단일 MIPI PORT(4lane)는 4K60 출력을 지원할 수 없으며 4K30 사양에만 도달할 수 있습니다. 2개의 MIPI PORT가 총 8레인인 시나리오에서는 4K60을 출력할 수 있습니다(RK3588은 이미 이 방식을 지원하는 것 같습니다).

LT6911UXE: MIPI TX DPHY 사양은 DPHY1.2 버전, 최대 속도는 2.5Gbps, 단일 MIPI 포트(4lane)는 4K60 출력을 지원하고 RK3588에 적응하면 주 제어를 위해 MIPI DPHY 포트를 저장할 수 있습니다.

2.IT6616

IT6616은 ITE에서 설계한 HDMI to MIPI-CSI 브리지 칩으로 DPHY 속도는 최대 2.0Gbps이고 HDMI1.4를 지원하며 4K30 YUV422MIPI 출력을 지원할 수 있지만 4K60 YUV422는 지원할 수 없습니다.

3.RK628D

RK628D는 RK 자체에서 설계한 브리지 칩으로 HDMI1.4를 지원하고 MIPI TX DPHY 속도는 1.2Gbps이며 MIPI TX 출력 YUV422 4K30을 지원합니다.

(2) 어댑터 칩 드라이버 디버깅

HDMI to MIPI-CSI 어댑터 칩은 V4L2 프레임워크를 기반으로 구현되고 RK3588의 VICAP 컨트롤러에 연결되는 카메라와 같은 장치로 취급될 수 있습니다. 여기서는 LT6911UXE를 예로 들어 보겠습니다.

1. 드라이버 관련 인터페이스 구성

드라이버의 관련 인터페이스는 카메라의 인터페이스와 대략 동일하며 주요 인터페이스 구성은 다음과 같습니다.

①lt6911uxe_get_detected_timings

어댑터 칩이 인식하는 입력 소스의 타이밍을 얻습니다.일반적으로 인터럽트 기능이 이 기능을 호출합니다.

②lt6911uxe_query_dv_timings

해당 타이밍을 쿼리하고 쿼리 해결과 같은 정보를 상위 계층 응용 프로그램에 제공합니다.

static int lt6911uxe_query_dv_timings(struct v4l2_subdev *sd,
				struct v4l2_dv_timings *timings)
{
	struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd);

	*timings = lt6911uxe->timings;
	if (debug)
		v4l2_print_dv_timings(sd->name,
				"query_dv_timings: ", timings, false);

	if (!v4l2_valid_dv_timings(timings, &lt6911uxe_timings_cap, NULL,
				NULL)) {
		v4l2_dbg(1, debug, sd, "%s: timings out of range\n",
				__func__);

		return -ERANGE;
	}

	return 0;
}

③lt6911uxe_g_mbus_config

버스 관련 정보, 차선수, 채널수 등의 설정

static int lt6911uxe_g_mbus_config(struct v4l2_subdev *sd,
			unsigned int pad, struct v4l2_mbus_config *cfg)
{
	struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd);
	u32 lane_num = lt6911uxe->bus_cfg.bus.mipi_csi2.num_data_lanes;
	u32 val = 0;

	val = 1 << (lane_num - 1) |
		V4L2_MBUS_CSI2_CHANNEL_0 |
		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;

	cfg->type = lt6911uxe->bus_cfg.bus_type;
	cfg->flags = val;

	return 0;
}

④lt6911uxe_get_fmt

관련 해결 정보 등을 얻습니다.

static int lt6911uxe_get_fmt(struct v4l2_subdev *sd,
			struct v4l2_subdev_pad_config *cfg,
			struct v4l2_subdev_format *format)
{
	struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd);
	const struct lt6911uxe_mode *mode;

	mutex_lock(&lt6911uxe->confctl_mutex);
	format->format.code = lt6911uxe->mbus_fmt_code;
	format->format.width = lt6911uxe->timings.bt.width;
	format->format.height = lt6911uxe->timings.bt.height;
	format->format.field =
		lt6911uxe->timings.bt.interlaced ?
		V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
	format->format.colorspace = V4L2_COLORSPACE_SRGB;
	mutex_unlock(&lt6911uxe->confctl_mutex);

	mode = lt6911uxe_find_best_fit(lt6911uxe);
	lt6911uxe->cur_mode = mode;

	__v4l2_ctrl_s_ctrl_int64(lt6911uxe->pixel_rate,
				LT6911UXE_PIXEL_RATE);
	__v4l2_ctrl_s_ctrl(lt6911uxe->link_freq,
				mode->mipi_freq_idx);

	v4l2_dbg(1, debug, sd, "%s: mode->mipi_freq_idx(%d)", __func__, mode->mipi_freq_idx);

	v4l2_dbg(1, debug, sd, "%s: fmt code:%d, w:%d, h:%d, field code:%d\n",
			__func__, format->format.code, format->format.width,
			format->format.height, format->format.field);

	return 0;
}

⑤해상도 변경 이벤트

HDMI-to-MIPI-CSI 방식의 드라이버와 일반 카메라 드라이버의 가장 큰 차이점은 드라이버가 입력 소스 해상도의 변화와 Plugging과 Unplugging의 변화를 감지하여 이벤트 형태로 보고해야 한다는 점이다. . 애플리케이션이 이벤트를 수신한 후 Rate 릴리스 미리 보기를 다시 식별해야 합니다.

이벤트 구독: 해상도 변경 및 언플러그 이벤트를 각각 등록합니다.

static int lt6911uxe_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
				    struct v4l2_event_subscription *sub)
{
	switch (sub->type) {
	case V4L2_EVENT_SOURCE_CHANGE:
		return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
	case V4L2_EVENT_CTRL:
		return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
	default:
		return -EINVAL;
	}
}

해상도 변경 이벤트는 일반적으로 해상도 변경 인터럽트에서 보고되며 v4l2_subdev_notify_event 인터페이스에서 이벤트를 보고합니다.

static void lt6911uxe_format_change(struct v4l2_subdev *sd)
{
	struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd);
	struct v4l2_dv_timings timings;
	const struct v4l2_event lt6911uxe_ev_fmt = {
		.type = V4L2_EVENT_SOURCE_CHANGE,
		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
	};

	if (lt6911uxe_get_detected_timings(sd, &timings)) {
		enable_stream(sd, false);
		v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__);
	}

	if (!v4l2_match_dv_timings(&lt6911uxe->timings, &timings, 0, false)) {
		enable_stream(sd, false);
		/* automatically set timing rather than set by user */
		lt6911uxe_s_dv_timings(sd, &timings);
		v4l2_print_dv_timings(sd->name,
				"Format_change: New format: ",
				&timings, false);
		if (sd->devnode && !lt6911uxe->i2c_client->irq)
			v4l2_subdev_notify_event(sd, &lt6911uxe_ev_fmt);
	}
	if (sd->devnode && lt6911uxe->i2c_client->irq)
		v4l2_subdev_notify_event(sd, &lt6911uxe_ev_fmt);
}

⑥언플러그 이벤트 신고

언플러그 이벤트는 다음 인터페이스를 통해 설정됩니다. 변수가 변경되면 이벤트가 보고됩니다. 일반적으로 드라이버는 언플러그 감지를 구현해야 합니다. 현재 방법은 HDMI의 5V를 RK3588의 io에 연결하고 사용하는 것입니다. 분리 작업을 감지하는 io 상태.

static int lt6911uxe_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd)
{
	struct lt6911uxe *lt6911uxe = to_lt6911uxe(sd);

	return v4l2_ctrl_s_ctrl(lt6911uxe->detect_tx_5v_ctrl,
			tx_5v_power_present(sd));
}

2. dts 구성

주요 dts 링크 l 구성은 다음과 같습니다: lt6911uxe-> csi2_dphy -> mipi2_csi2 -> rkcif_mipi_lvds2.

&csi2_dphy0 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;
		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			hdmi_mipi2_in: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&lt6911uxe_out1>;
				data-lanes = <1 2 3 4>;
			};
		};
		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			csidphy0_out: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&mipi2_csi2_input>;
			};
		};
	};
};

&csi2_dphy0_hw {
	status = "okay";
};

&i2c3 {
	status = "okay";

	lt6911uxe_1: lt6911uxe_1@2b {
		compatible = "lontium,lt6911uxe";
		status = "okay";
		reg = <0x2b>;
		clocks = <&ext_cam_clk>;
		clock-names = "xvclk";
		power-domains = <&power RK3588_PD_VI>;
		pinctrl-names = "default";
		pinctrl-0 = <&lt6911uxe_pin_1>;
		interrupt-parent = <&gpio1>;
		interrupts = <RK_PB3 IRQ_TYPE_LEVEL_LOW>;
		// reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_LOW>;
		// power-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_HIGH>;
		plugin-det-gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_HIGH>;
		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "HDMI-MIPI2";
		rockchip,camera-module-lens-name = "LT6911UXE-2";
		port {
			lt6911uxe_out1: endpoint {
				remote-endpoint = <&hdmi_mipi2_in>;
				data-lanes = <1 2 3 4>;
			};
		};
	};
};

&mipi2_csi2 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			mipi2_csi2_input: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&csidphy0_out>;
			};
		};

		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			mipi2_csi2_output: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&cif_mipi_in2>;
			};
		};
	};
};

&rkcif {
	status = "okay";
};

&rkcif_mipi_lvds2 {
	status = "okay";

	port {
		cif_mipi_in2: endpoint {
			remote-endpoint = <&mipi2_csi2_output>;
		};
	};
};

&rkcif_mmu {
	status = "okay";
};

&pinctrl {
	hdmiin {

		lt6911uxe_pin_1: lt6911uxe-pin-1 {
			rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>,
					<1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

(3) 안드로이드 HAL 적응

cameraHAL의 적응은 camera3_profiles.xml에 관련 구성을 추가해야 합니다.

이름은 드라이버에 해당하는 이름과 일치해야 합니다. moduleid는 dts에서 구성한 색인과 일치해야 합니다.

지원되는 해상도 및 프레임 속도를 추가해야 합니다.

 SOC 모드로 구성되어 ISP를 통해 효과를 디버깅할 필요가 없습니다.

(4) 개요

RK3588 플랫폼에서 HDMI to MIPI CSI 디버깅은 카메라 디버깅과 유사하며 드라이버는 HDMI 소스 해상도 변경 또는 연결 및 연결 해제에 대한 이벤트 보고 메커니즘을 추가한 다음 애플리케이션이 해당 이벤트를 처리합니다.

추천

출처blog.csdn.net/qq_34341546/article/details/129009091