mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
Merge commit 'e3f7d79af1b514a182765d6d95e65d88aba6f94f'
* commit 'e3f7d79af1b514a182765d6d95e65d88aba6f94f': (84 commits) media: i2c: rk628: Compatible with both kernel-5.10 and kernel-6.1 media: i2c: rk628: fix audio fs in large offset media: i2c: rk628: check for overflow when i2c operation media: i2c: rk628: add register debugfs node media: i2c: rk628: Auto derepeat media: i2c: rk628: allows the PHY to lock to a low control period media: i2c: rk628: update driver for dsi mode media: i2c: rk628: fix hdmi1.4 change format not recognized media: i2c: rk628: fix i2c timeout media: i2c: rk628: fix display error media: i2c: rk628: fix combtxphy mipi lp-tx output slew-rate media: i2c: rk628: set default timing when driver probe media: i2c: rk628: add support for rk628f hdmirx audio media: i2c: rk628: cru: add hdmirx aud apll support media: i2c: rk628: add apll regmap_range media: i2c: rk628: cru: Add rk628f APLL media: i2c: rk628: read raw state must delay some time when clear interrupt media: i2c: rk628: move some function to rk628_mipi_dphy.c media: i2c: rk628: add csc matrix support media: i2c: rk628: add csi1 support and dual mipi mode for rk628f ... Change-Id: If91f3e03071c93d46cdff8afbf9e45da420bb9f2 Conflicts: drivers/media/i2c/rk628/rk628_bt1120_v4l2.c drivers/media/i2c/rk628/rk628_csi_v4l2.c
This commit is contained in:
@@ -159,6 +159,17 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-dual-channel-lvds.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-one-vp-two-single-channel-lvds.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-single-channel-lvds.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3567-evb2-lp4x-v10-two-vp-two-separate-single-channel-lvds.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-hdmi2bt1120-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-rgb2dsi-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-rgb2gvi-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-rgb2lvds-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-dual-camera.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-ddr4-v10-one-vp-two-single-channel-lvds.dtb
|
||||
@@ -257,6 +268,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-lp4-v10-rk1608-ipc-8x-linux.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-lp4-v11-linux-ipc.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-v11.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-v11-linux.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb7-v11-rk628-hdmi2csi.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nvr-demo-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nvr-demo-v10-android.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-nvr-demo-v10-ipc-4x-linux.dtb
|
||||
|
||||
169
arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-ddr4-v10.dtsi
Normal file
169
arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-ddr4-v10.dtsi
Normal file
@@ -0,0 +1,169 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/pinctrl/rockchip.h>
|
||||
#include "rk3568.dtsi"
|
||||
#include "rk3568-evb.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RK3568 EVB RK628 DDR4 V10 Board";
|
||||
compatible = "rockchip,rk3568-evb-rk628-ddr4-v10", "rockchip,rk3568";
|
||||
|
||||
rk628_sound: rk628-sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,mclk-fs = <128>;
|
||||
simple-audio-card,name = "rockchip,hdmi-rk628";
|
||||
status = "disabled";
|
||||
|
||||
simple-audio-card,cpu {
|
||||
sound-dai = <&i2s2_2ch>;
|
||||
};
|
||||
simple-audio-card,codec {
|
||||
sound-dai = <&i2c2_rk628>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c2 {
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
i2c2_rk628: rk628@50 {
|
||||
compatible = "rockchip,rk628";
|
||||
reg = <0x50>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
enable-gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
|
||||
#sound-dai-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rk628_reset>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
i2c3_rk628: rk628@51 {
|
||||
compatible = "rockchip,rk628";
|
||||
reg = <0x51>;
|
||||
|
||||
/* external test board
|
||||
* rk628_int1: gpio1_a5
|
||||
* rk628_reset1: gpio1_a6
|
||||
* rk628_int2: gpio1_a7
|
||||
* rk628_reset2: gpio1_b0
|
||||
*/
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reset-gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c4m1_xfer>;
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
i2c4_rk628: rk628@50 {
|
||||
compatible = "rockchip,rk628";
|
||||
reg = <0x50>;
|
||||
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
enable-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2s1_8ch {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
rk628 {
|
||||
rk628_reset: rk628-reset {
|
||||
rockchip,pins = <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pwm5 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pwm7 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&pmu_io_domains {
|
||||
status = "okay";
|
||||
pmuio1-supply = <&vcc3v3_pmu>;
|
||||
pmuio2-supply = <&vcc3v3_pmu>;
|
||||
vccio1-supply = <&vcc_3v3>;
|
||||
vccio3-supply = <&vcc_3v3>;
|
||||
vccio4-supply = <&vcc_3v3>;
|
||||
vccio5-supply = <&vcc_3v3>;
|
||||
vccio6-supply = <&vcc_3v3>;
|
||||
vccio7-supply = <&vcc_3v3>;
|
||||
};
|
||||
|
||||
&sdmmc0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&spdif_8ch {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&spdif_out {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&u2phy0_otg {
|
||||
/delete-property/ vbus-supply;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbdrd_dwc3 {
|
||||
dr_mode = "otg";
|
||||
phys = <&u2phy0_otg>;
|
||||
phy-names = "usb2-phy";
|
||||
extcon = <&usb2phy0>;
|
||||
maximum-speed = "high-speed";
|
||||
snps,dis_u2_susphy_quirk;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vcc3v3_lcd0_n {
|
||||
gpio = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
&vcc3v3_lcd1_n {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wireless_wlan {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&wireless_bluetooth {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
&i2c4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c4m1_xfer>;
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
rk628_bt1120: rk628_bt1120@50 {
|
||||
compatible = "rockchip,rk628-bt1120-v4l2";
|
||||
reg = <0x50>;
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&cif_dvp_clk &cif_dvp_bus16 &cif_dvp_bus8>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
enable-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio2 RK_PB0 GPIO_ACTIVE_LOW>;
|
||||
plugin-det-gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>;
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "RK628-BT1120";
|
||||
rockchip,camera-module-lens-name = "NC";
|
||||
dual-edge = <1>;
|
||||
|
||||
port {
|
||||
lt8619c_out: endpoint {
|
||||
remote-endpoint = <&cif_para_in>;
|
||||
bus-width = <16>;
|
||||
pclk-sample = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&rkcif_dvp {
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
/* Parallel bus endpoint */
|
||||
cif_para_in: endpoint {
|
||||
remote-endpoint = <<8619c_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&rkcif {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rkcif_mmu {
|
||||
status = "okay";
|
||||
};
|
||||
@@ -0,0 +1,397 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
#include <dt-bindings/display/media-bus-format.h>
|
||||
|
||||
>1x {
|
||||
status = "okay";
|
||||
power-supply = <&vcc3v3_lcd0_n>;
|
||||
goodix,rst-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
goodix,irq-gpio = <&gpio0 RK_PA4 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <10>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
|
||||
rk628,hdmi-in;
|
||||
rk628-dsi {
|
||||
//rockchip,dual-channel;
|
||||
dsi,eotp;
|
||||
dsi,video-mode;
|
||||
dsi,format = "rgb888";
|
||||
dsi,lanes = <4>;
|
||||
status = "okay";
|
||||
|
||||
rk628-panel {
|
||||
panel-init-sequence = [
|
||||
23 00 02 FE 21
|
||||
23 00 02 04 00
|
||||
23 00 02 00 64
|
||||
23 00 02 2A 00
|
||||
23 00 02 26 64
|
||||
23 00 02 54 00
|
||||
23 00 02 50 64
|
||||
23 00 02 7B 00
|
||||
23 00 02 77 64
|
||||
23 00 02 A2 00
|
||||
23 00 02 9D 64
|
||||
23 00 02 C9 00
|
||||
23 00 02 C5 64
|
||||
23 00 02 01 71
|
||||
23 00 02 27 71
|
||||
23 00 02 51 71
|
||||
23 00 02 78 71
|
||||
23 00 02 9E 71
|
||||
23 00 02 C6 71
|
||||
23 00 02 02 89
|
||||
23 00 02 28 89
|
||||
23 00 02 52 89
|
||||
23 00 02 79 89
|
||||
23 00 02 9F 89
|
||||
23 00 02 C7 89
|
||||
23 00 02 03 9E
|
||||
23 00 02 29 9E
|
||||
23 00 02 53 9E
|
||||
23 00 02 7A 9E
|
||||
23 00 02 A0 9E
|
||||
23 00 02 C8 9E
|
||||
23 00 02 09 00
|
||||
23 00 02 05 B0
|
||||
23 00 02 31 00
|
||||
23 00 02 2B B0
|
||||
23 00 02 5A 00
|
||||
23 00 02 55 B0
|
||||
23 00 02 80 00
|
||||
23 00 02 7C B0
|
||||
23 00 02 A7 00
|
||||
23 00 02 A3 B0
|
||||
23 00 02 CE 00
|
||||
23 00 02 CA B0
|
||||
23 00 02 06 C0
|
||||
23 00 02 2D C0
|
||||
23 00 02 56 C0
|
||||
23 00 02 7D C0
|
||||
23 00 02 A4 C0
|
||||
23 00 02 CB C0
|
||||
23 00 02 07 CF
|
||||
23 00 02 2F CF
|
||||
23 00 02 58 CF
|
||||
23 00 02 7E CF
|
||||
23 00 02 A5 CF
|
||||
23 00 02 CC CF
|
||||
23 00 02 08 DD
|
||||
23 00 02 30 DD
|
||||
23 00 02 59 DD
|
||||
23 00 02 7F DD
|
||||
23 00 02 A6 DD
|
||||
23 00 02 CD DD
|
||||
23 00 02 0E 15
|
||||
23 00 02 0A E9
|
||||
23 00 02 36 15
|
||||
23 00 02 32 E9
|
||||
23 00 02 5F 15
|
||||
23 00 02 5B E9
|
||||
23 00 02 85 15
|
||||
23 00 02 81 E9
|
||||
23 00 02 AD 15
|
||||
23 00 02 A9 E9
|
||||
23 00 02 D3 15
|
||||
23 00 02 CF E9
|
||||
23 00 02 0B 14
|
||||
23 00 02 33 14
|
||||
23 00 02 5C 14
|
||||
23 00 02 82 14
|
||||
23 00 02 AA 14
|
||||
23 00 02 D0 14
|
||||
23 00 02 0C 36
|
||||
23 00 02 34 36
|
||||
23 00 02 5D 36
|
||||
23 00 02 83 36
|
||||
23 00 02 AB 36
|
||||
23 00 02 D1 36
|
||||
23 00 02 0D 6B
|
||||
23 00 02 35 6B
|
||||
23 00 02 5E 6B
|
||||
23 00 02 84 6B
|
||||
23 00 02 AC 6B
|
||||
23 00 02 D2 6B
|
||||
23 00 02 13 5A
|
||||
23 00 02 0F 94
|
||||
23 00 02 3B 5A
|
||||
23 00 02 37 94
|
||||
23 00 02 64 5A
|
||||
23 00 02 60 94
|
||||
23 00 02 8A 5A
|
||||
23 00 02 86 94
|
||||
23 00 02 B2 5A
|
||||
23 00 02 AE 94
|
||||
23 00 02 D8 5A
|
||||
23 00 02 D4 94
|
||||
23 00 02 10 D1
|
||||
23 00 02 38 D1
|
||||
23 00 02 61 D1
|
||||
23 00 02 87 D1
|
||||
23 00 02 AF D1
|
||||
23 00 02 D5 D1
|
||||
23 00 02 11 04
|
||||
23 00 02 39 04
|
||||
23 00 02 62 04
|
||||
23 00 02 88 04
|
||||
23 00 02 B0 04
|
||||
23 00 02 D6 04
|
||||
23 00 02 12 05
|
||||
23 00 02 3A 05
|
||||
23 00 02 63 05
|
||||
23 00 02 89 05
|
||||
23 00 02 B1 05
|
||||
23 00 02 D7 05
|
||||
23 00 02 18 AA
|
||||
23 00 02 14 36
|
||||
23 00 02 42 AA
|
||||
23 00 02 3D 36
|
||||
23 00 02 69 AA
|
||||
23 00 02 65 36
|
||||
23 00 02 8F AA
|
||||
23 00 02 8B 36
|
||||
23 00 02 B7 AA
|
||||
23 00 02 B3 36
|
||||
23 00 02 DD AA
|
||||
23 00 02 D9 36
|
||||
23 00 02 15 74
|
||||
23 00 02 3F 74
|
||||
23 00 02 66 74
|
||||
23 00 02 8C 74
|
||||
23 00 02 B4 74
|
||||
23 00 02 DA 74
|
||||
23 00 02 16 9F
|
||||
23 00 02 40 9F
|
||||
23 00 02 67 9F
|
||||
23 00 02 8D 9F
|
||||
23 00 02 B5 9F
|
||||
23 00 02 DB 9F
|
||||
23 00 02 17 DC
|
||||
23 00 02 41 DC
|
||||
23 00 02 68 DC
|
||||
23 00 02 8E DC
|
||||
23 00 02 B6 DC
|
||||
23 00 02 DC DC
|
||||
23 00 02 1D FF
|
||||
23 00 02 19 03
|
||||
23 00 02 47 FF
|
||||
23 00 02 43 03
|
||||
23 00 02 6E FF
|
||||
23 00 02 6A 03
|
||||
23 00 02 94 FF
|
||||
23 00 02 90 03
|
||||
23 00 02 BC FF
|
||||
23 00 02 B8 03
|
||||
23 00 02 E2 FF
|
||||
23 00 02 DE 03
|
||||
23 00 02 1A 35
|
||||
23 00 02 44 35
|
||||
23 00 02 6B 35
|
||||
23 00 02 91 35
|
||||
23 00 02 B9 35
|
||||
23 00 02 DF 35
|
||||
23 00 02 1B 45
|
||||
23 00 02 45 45
|
||||
23 00 02 6C 45
|
||||
23 00 02 92 45
|
||||
23 00 02 BA 45
|
||||
23 00 02 E0 45
|
||||
23 00 02 1C 55
|
||||
23 00 02 46 55
|
||||
23 00 02 6D 55
|
||||
23 00 02 93 55
|
||||
23 00 02 BB 55
|
||||
23 00 02 E1 55
|
||||
23 00 02 22 FF
|
||||
23 00 02 1E 68
|
||||
23 00 02 4C FF
|
||||
23 00 02 48 68
|
||||
23 00 02 73 FF
|
||||
23 00 02 6F 68
|
||||
23 00 02 99 FF
|
||||
23 00 02 95 68
|
||||
23 00 02 C1 FF
|
||||
23 00 02 BD 68
|
||||
23 00 02 E7 FF
|
||||
23 00 02 E3 68
|
||||
23 00 02 1F 7E
|
||||
23 00 02 49 7E
|
||||
23 00 02 70 7E
|
||||
23 00 02 96 7E
|
||||
23 00 02 BE 7E
|
||||
23 00 02 E4 7E
|
||||
23 00 02 20 97
|
||||
23 00 02 4A 97
|
||||
23 00 02 71 97
|
||||
23 00 02 97 97
|
||||
23 00 02 BF 97
|
||||
23 00 02 E5 97
|
||||
23 00 02 21 B5
|
||||
23 00 02 4B B5
|
||||
23 00 02 72 B5
|
||||
23 00 02 98 B5
|
||||
23 00 02 C0 B5
|
||||
23 00 02 E6 B5
|
||||
23 00 02 25 F0
|
||||
23 00 02 23 E8
|
||||
23 00 02 4F F0
|
||||
23 00 02 4D E8
|
||||
23 00 02 76 F0
|
||||
23 00 02 74 E8
|
||||
23 00 02 9C F0
|
||||
23 00 02 9A E8
|
||||
23 00 02 C4 F0
|
||||
23 00 02 C2 E8
|
||||
23 00 02 EA F0
|
||||
23 00 02 E8 E8
|
||||
23 00 02 24 FF
|
||||
23 00 02 4E FF
|
||||
23 00 02 75 FF
|
||||
23 00 02 9B FF
|
||||
23 00 02 C3 FF
|
||||
23 00 02 E9 FF
|
||||
23 00 02 FE 3D
|
||||
23 00 02 00 04
|
||||
23 00 02 FE 23
|
||||
23 00 02 08 82
|
||||
23 00 02 0A 00
|
||||
23 00 02 0B 00
|
||||
23 00 02 0C 01
|
||||
23 00 02 16 00
|
||||
23 00 02 18 02
|
||||
23 00 02 1B 04
|
||||
23 00 02 19 04
|
||||
23 00 02 1C 81
|
||||
23 00 02 1F 00
|
||||
23 00 02 20 03
|
||||
23 00 02 23 04
|
||||
23 00 02 21 01
|
||||
23 00 02 54 63
|
||||
23 00 02 55 54
|
||||
23 00 02 6E 45
|
||||
23 00 02 6D 36
|
||||
23 00 02 FE 3D
|
||||
23 00 02 55 78
|
||||
23 00 02 FE 20
|
||||
23 00 02 26 30
|
||||
23 00 02 FE 3D
|
||||
23 00 02 20 71
|
||||
23 00 02 50 8F
|
||||
23 00 02 51 8F
|
||||
23 00 02 FE 00
|
||||
23 00 02 35 00
|
||||
05 78 01 11
|
||||
05 00 01 29
|
||||
];
|
||||
|
||||
panel-exit-sequence = [
|
||||
05 00 01 28
|
||||
05 00 01 10
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <60>;
|
||||
vback-porch = <10>;
|
||||
vfront-porch = <10>;
|
||||
hsync-len = <40>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <60>;
|
||||
vback-porch = <10>;
|
||||
vfront-porch = <10>;
|
||||
hsync-len = <40>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <60>;
|
||||
vback-porch = <10>;
|
||||
vfront-porch = <10>;
|
||||
hsync-len = <40>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi_in_vp0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_in_vp1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "okay";
|
||||
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <60>;
|
||||
vback-porch = <10>;
|
||||
vfront-porch = <10>;
|
||||
hsync-len = <40>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&touch_gpio {
|
||||
rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
|
||||
<0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
@@ -0,0 +1,239 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
#include <dt-bindings/display/media-bus-format.h>
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <240>;
|
||||
panel-enable-delay-ms = <240>;
|
||||
panel-prepare-delay-ms = <240>;
|
||||
panel-unprepare-delay-ms = <240>;
|
||||
panel-disable-delay-ms = <240>;
|
||||
panel-init-delay-ms = <240>;
|
||||
|
||||
rk628,hdmi-in;
|
||||
rk628-dsi {
|
||||
rockchip,lane-mbps = <1100>;
|
||||
rockchip,dual-channel;
|
||||
dsi,eotp;
|
||||
dsi,video-mode;
|
||||
dsi,format = "rgb888";
|
||||
dsi,lanes = <4>;
|
||||
status = "okay";
|
||||
|
||||
rk628-panel {
|
||||
panel-init-sequence = [
|
||||
29 00 05 ff aa 55 a5 80
|
||||
23 00 02 6f 31
|
||||
23 00 02 fa 00
|
||||
23 00 02 6f 13
|
||||
23 00 02 f4 00
|
||||
23 00 02 fa 00
|
||||
29 00 05 ff aa 55 a5 00
|
||||
29 00 06 f0 55 aa 52 08 00
|
||||
23 00 02 b1 21
|
||||
29 00 03 b2 10 82
|
||||
29 00 03 b2 87 22
|
||||
29 00 04 b4 25 02 8c
|
||||
29 00 03 b5 0a 00
|
||||
29 00 04 b8 00 04 02
|
||||
29 00 0a b9 03 00 18 11 31 44 03 51 00
|
||||
29 00 03 ba 00 32
|
||||
29 00 03 bc 4f 00
|
||||
29 00 05 bd 00 b6 10 10
|
||||
29 00 03 c6 11 10
|
||||
29 00 06 f0 55 aa 52 08 01
|
||||
29 00 03 b1 11 11
|
||||
29 00 07 b2 08 08 08 08 08 08
|
||||
29 00 07 b3 0f 19 0f 19 0f 19
|
||||
29 00 07 b6 15 14 15 14 15 14
|
||||
29 00 03 bc 5f 00
|
||||
29 00 03 bd 5f 00
|
||||
29 00 03 be 00 db
|
||||
23 00 02 ca 0f
|
||||
29 00 06 f0 55 aa 52 08 02
|
||||
29 00 0f b0 00 0e 29 36 3f 48 51 3b 37
|
||||
3c 3c 51 61 60
|
||||
29 00 0f b1 59 6a 81 81 94 9b a8 a8 af
|
||||
b6 bd c4 cc ff
|
||||
29 00 0f b2 00 0e 29 36 3f 48 51 3b 37
|
||||
3c 3c 51 61 60
|
||||
29 00 10 b3 59 6a 81 81 94 9b a8 a8 af
|
||||
b6 bd c4 ca cc ff
|
||||
29 00 0f b4 00 0e 29 36 3f 48 51 3b 37
|
||||
3c 3c 51 61 60
|
||||
29 00 10 b5 59 6a 81 81 94 9b a8 a8 af
|
||||
b6 bd c4 ca cc ff
|
||||
29 00 0f b6 00 0e 29 36 3f 48 51 3b 37
|
||||
3c 3c 51 61 60
|
||||
29 00 10 b7 59 6a 81 81 94 9b a8 a8 af
|
||||
b6 bd c4 ca cc ff
|
||||
29 00 0f b8 00 0e 29 36 3f 48 51 3b 37
|
||||
3c 3c 51 61 60
|
||||
29 00 10 b9 59 6a 81 81 94 9b a8 a8 af
|
||||
b6 bd c4 ca cc ff
|
||||
29 00 0f ba 00 0e 29 36 3f 48 51 3b 37
|
||||
3c 3c 51 61 60
|
||||
29 00 10 bb 59 6a 81 81 94 9b a8 a8 af
|
||||
b6 bd c4 ca cc ff
|
||||
29 00 06 f0 55 aa 52 08 03
|
||||
29 00 05 b0 00 00 00 00
|
||||
29 00 05 b1 03 00 00 03
|
||||
29 00 08 b2 00 00 64 00 64 05 02
|
||||
29 00 03 b4 00 08
|
||||
29 00 05 b5 12 28 06 06
|
||||
29 00 06 ba 31 00 01 00 09
|
||||
29 00 06 bb 31 00 01 00 09
|
||||
29 00 06 f0 55 aa 52 08 05
|
||||
29 00 04 b0 03 11 3f
|
||||
29 00 03 b2 06 60
|
||||
29 00 03 b3 10 33
|
||||
23 00 02 b4 26
|
||||
29 00 04 b5 06 20 00
|
||||
29 00 04 b6 86 e0 00
|
||||
29 00 06 ba 8e 00 00 a4 00
|
||||
29 00 06 bb 06 00 00 20 00
|
||||
29 00 06 bc 8e 00 00 a4 00
|
||||
29 00 06 bd 2e 00 00 a4 00
|
||||
29 00 06 be 8e 00 00 a0 00
|
||||
29 00 06 bf 06 00 00 24 00
|
||||
23 00 02 c1 00
|
||||
29 00 03 c8 05 10
|
||||
29 00 03 c9 03 10
|
||||
29 00 04 d0 00 0a 02
|
||||
29 00 04 d1 00 0a 04
|
||||
23 00 02 ec 12
|
||||
23 00 02 ed 00
|
||||
29 00 03 ee 03 00
|
||||
29 00 06 f0 55 aa 52 08 06
|
||||
29 00 06 b0 00 04 08 11 12
|
||||
29 00 06 b1 1f 15 16 1f 1f
|
||||
29 00 06 b2 1f 13 1f 1f 1f
|
||||
29 00 06 b3 1f 19 19 19 19
|
||||
29 00 06 b4 1b 1b 1b 1b 1d
|
||||
29 00 04 b5 1d 1d 1d
|
||||
29 00 06 b6 00 05 09 11 12
|
||||
29 00 06 b7 1f 15 16 1f 1f
|
||||
29 00 06 b8 1f 13 1f 1f 1f
|
||||
29 00 06 b9 1f 19 19 19 19
|
||||
29 00 06 ba 1b 1b 1b 1b 1d
|
||||
29 00 04 bb 1d 1d 1d
|
||||
29 00 06 c0 00 09 05 12 11
|
||||
29 00 06 c1 1f 15 16 1f 1f
|
||||
29 00 06 c2 1f 13 1f 1f 1f
|
||||
29 00 06 c3 1f 19 19 19 19
|
||||
29 00 06 c4 1b 1b 1b 1b 1d
|
||||
29 00 04 c5 1d 1d 1d
|
||||
29 00 06 c6 00 08 04 12 11
|
||||
29 00 06 c7 1f 15 16 1f 1f
|
||||
29 00 06 c8 1f 13 1f 1f 1f
|
||||
29 00 06 c9 1f 19 19 19 19
|
||||
29 00 06 ca 1b 1b 1b 1b 1d
|
||||
29 00 04 cb 1d 1d 1d
|
||||
29 78 04 d0 00 aa 0a
|
||||
05 78 01 11
|
||||
05 78 01 29
|
||||
];
|
||||
|
||||
panel-exit-sequence = [
|
||||
05 00 01 28
|
||||
05 00 01 10
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <264000000>;
|
||||
hactive = <1440>;
|
||||
vactive = <2560>;
|
||||
hfront-porch = <150>;
|
||||
hsync-len = <30>;
|
||||
hback-porch = <60>;
|
||||
vfront-porch = <20>;
|
||||
vsync-len = <20>;
|
||||
vback-porch = <20>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <264000000>;
|
||||
hactive = <1440>;
|
||||
vactive = <2560>;
|
||||
hfront-porch = <150>;
|
||||
hsync-len = <30>;
|
||||
hback-porch = <60>;
|
||||
vfront-porch = <20>;
|
||||
vsync-len = <20>;
|
||||
vback-porch = <20>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <264000000>;
|
||||
hactive = <1440>;
|
||||
vactive = <2560>;
|
||||
hfront-porch = <150>;
|
||||
hsync-len = <30>;
|
||||
hback-porch = <60>;
|
||||
vfront-porch = <20>;
|
||||
vsync-len = <20>;
|
||||
vback-porch = <20>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi_in_vp0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_in_vp1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing {
|
||||
clock-frequency = <264000000>;
|
||||
hactive = <1440>;
|
||||
vactive = <2560>;
|
||||
hfront-porch = <150>;
|
||||
hsync-len = <30>;
|
||||
hback-porch = <60>;
|
||||
vfront-porch = <20>;
|
||||
vsync-len = <20>;
|
||||
vback-porch = <20>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,137 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dt-bindings/display/media-bus-format.h>
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
&backlight {
|
||||
enable-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <150>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rk628_reset &refclk_pins>;
|
||||
assigned-clocks = <&pmucru CLK_WIFI>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
clocks = <&pmucru CLK_WIFI>;
|
||||
clock-names = "soc_24M";
|
||||
|
||||
rk628,hdmi-in;
|
||||
rk628-gvi {
|
||||
/* "rgb666"
|
||||
* "rgb888"
|
||||
* "rgb101010"
|
||||
* "yuyv8"
|
||||
* "yuyv10"
|
||||
*/
|
||||
bus-format = "rgb888";
|
||||
gvi,lanes = <8>;
|
||||
//"rockchip,division-mode";
|
||||
//"rockchip, gvi-frm-rst";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <594000000>;
|
||||
hactive = <3840>;
|
||||
vactive = <2160>;
|
||||
hback-porch = <296>;
|
||||
hfront-porch = <176>;
|
||||
vback-porch = <72>;
|
||||
vfront-porch = <8>;
|
||||
hsync-len = <88>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <594000000>;
|
||||
hactive = <3840>;
|
||||
vactive = <2160>;
|
||||
hback-porch = <296>;
|
||||
hfront-porch = <176>;
|
||||
vback-porch = <72>;
|
||||
vfront-porch = <8>;
|
||||
hsync-len = <88>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing {
|
||||
clock-frequency = <594000000>;
|
||||
hactive = <3840>;
|
||||
vactive = <2160>;
|
||||
hback-porch = <296>;
|
||||
hfront-porch = <176>;
|
||||
vback-porch = <72>;
|
||||
vfront-porch = <8>;
|
||||
hsync-len = <88>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi_in_vp0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_in_vp1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing {
|
||||
clock-frequency = <594000000>;
|
||||
hactive = <3840>;
|
||||
vactive = <2160>;
|
||||
hback-porch = <296>;
|
||||
hfront-porch = <176>;
|
||||
vback-porch = <72>;
|
||||
vfront-porch = <8>;
|
||||
hsync-len = <88>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&vcc3v3_lcd0_n {
|
||||
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
@@ -0,0 +1,122 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
#include <dt-bindings/display/media-bus-format.h>
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-enable-gpios = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <10>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
|
||||
rk628,hdmi-in;
|
||||
rk628-lvds {
|
||||
/* "jeida_18","vesa_24","vesa_18" */
|
||||
bus-format = "jeida_24";
|
||||
|
||||
/* "dual_link_odd_even_pixels"
|
||||
* "dual_link_even_odd_pixels"
|
||||
* "dual_link_left_right_pixels"
|
||||
* "dual_link_right_left_pixels"
|
||||
*/
|
||||
link-type = "single_link";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <10>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <10>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <10>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi_in_vp0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_in_vp1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <10>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dt-bindings/display/media-bus-format.h>
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
&backlight {
|
||||
enable-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <10>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
|
||||
rk628,hdmi-in;
|
||||
rk628-lvds {
|
||||
/* "jeida_18","vesa_24","vesa_18" */
|
||||
bus-format = "vesa_24";
|
||||
|
||||
/* "dual_link_odd_even_pixels"
|
||||
* "dual_link_even_odd_pixels"
|
||||
* "dual_link_left_right_pixels"
|
||||
* "dual_link_right_left_pixels"
|
||||
*/
|
||||
link-type = "dual_link_even_odd_pixels";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <148>;
|
||||
hfront-porch = <88>;
|
||||
vback-porch = <36>;
|
||||
vfront-porch = <4>;
|
||||
hsync-len = <44>;
|
||||
vsync-len = <5>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <148>;
|
||||
hfront-porch = <88>;
|
||||
vback-porch = <36>;
|
||||
vfront-porch = <4>;
|
||||
hsync-len = <44>;
|
||||
vsync-len = <5>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <148>;
|
||||
hfront-porch = <88>;
|
||||
vback-porch = <36>;
|
||||
vfront-porch = <4>;
|
||||
hsync-len = <44>;
|
||||
vsync-len = <5>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&hdmi_in_vp0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_in_vp1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&route_hdmi {
|
||||
status = "okay";
|
||||
force-bus-format = <MEDIA_BUS_FMT_RGB888_1X24>;
|
||||
force-output;
|
||||
force_timing{
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <148>;
|
||||
hfront-porch = <88>;
|
||||
vback-porch = <36>;
|
||||
vfront-porch = <4>;
|
||||
hsync-len = <44>;
|
||||
vsync-len = <5>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&vcc3v3_lcd0_n {
|
||||
gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
@@ -0,0 +1,399 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
/ {
|
||||
panel@0 {
|
||||
compatible = "simple-panel";
|
||||
|
||||
disp_timings3: display-timings {
|
||||
native-mode = <&rgb2dsi_timing>;
|
||||
rgb2dsi_timing: timing0 {
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hfront-porch = <15>;
|
||||
hsync-len = <2>;
|
||||
hback-porch = <30>;
|
||||
vfront-porch = <15>;
|
||||
vsync-len = <2>;
|
||||
vback-porch = <15>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&rgb_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "okay";
|
||||
power-supply = <&vcc3v3_lcd0_n>;
|
||||
goodix,rst-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
goodix,irq-gpio = <&gpio0 RK_PA4 IRQ_TYPE_LEVEL_LOW>;
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <10>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
|
||||
rk628,rgb-in;
|
||||
rk628-dsi {
|
||||
//rockchip,dual-channel;
|
||||
dsi,eotp;
|
||||
dsi,video-mode;
|
||||
dsi,format = "rgb888";
|
||||
dsi,lanes = <4>;
|
||||
status = "okay";
|
||||
|
||||
rk628-panel {
|
||||
panel-init-sequence = [
|
||||
23 00 02 FE 21
|
||||
23 00 02 04 00
|
||||
23 00 02 00 64
|
||||
23 00 02 2A 00
|
||||
23 00 02 26 64
|
||||
23 00 02 54 00
|
||||
23 00 02 50 64
|
||||
23 00 02 7B 00
|
||||
23 00 02 77 64
|
||||
23 00 02 A2 00
|
||||
23 00 02 9D 64
|
||||
23 00 02 C9 00
|
||||
23 00 02 C5 64
|
||||
23 00 02 01 71
|
||||
23 00 02 27 71
|
||||
23 00 02 51 71
|
||||
23 00 02 78 71
|
||||
23 00 02 9E 71
|
||||
23 00 02 C6 71
|
||||
23 00 02 02 89
|
||||
23 00 02 28 89
|
||||
23 00 02 52 89
|
||||
23 00 02 79 89
|
||||
23 00 02 9F 89
|
||||
23 00 02 C7 89
|
||||
23 00 02 03 9E
|
||||
23 00 02 29 9E
|
||||
23 00 02 53 9E
|
||||
23 00 02 7A 9E
|
||||
23 00 02 A0 9E
|
||||
23 00 02 C8 9E
|
||||
23 00 02 09 00
|
||||
23 00 02 05 B0
|
||||
23 00 02 31 00
|
||||
23 00 02 2B B0
|
||||
23 00 02 5A 00
|
||||
23 00 02 55 B0
|
||||
23 00 02 80 00
|
||||
23 00 02 7C B0
|
||||
23 00 02 A7 00
|
||||
23 00 02 A3 B0
|
||||
23 00 02 CE 00
|
||||
23 00 02 CA B0
|
||||
23 00 02 06 C0
|
||||
23 00 02 2D C0
|
||||
23 00 02 56 C0
|
||||
23 00 02 7D C0
|
||||
23 00 02 A4 C0
|
||||
23 00 02 CB C0
|
||||
23 00 02 07 CF
|
||||
23 00 02 2F CF
|
||||
23 00 02 58 CF
|
||||
23 00 02 7E CF
|
||||
23 00 02 A5 CF
|
||||
23 00 02 CC CF
|
||||
23 00 02 08 DD
|
||||
23 00 02 30 DD
|
||||
23 00 02 59 DD
|
||||
23 00 02 7F DD
|
||||
23 00 02 A6 DD
|
||||
23 00 02 CD DD
|
||||
23 00 02 0E 15
|
||||
23 00 02 0A E9
|
||||
23 00 02 36 15
|
||||
23 00 02 32 E9
|
||||
23 00 02 5F 15
|
||||
23 00 02 5B E9
|
||||
23 00 02 85 15
|
||||
23 00 02 81 E9
|
||||
23 00 02 AD 15
|
||||
23 00 02 A9 E9
|
||||
23 00 02 D3 15
|
||||
23 00 02 CF E9
|
||||
23 00 02 0B 14
|
||||
23 00 02 33 14
|
||||
23 00 02 5C 14
|
||||
23 00 02 82 14
|
||||
23 00 02 AA 14
|
||||
23 00 02 D0 14
|
||||
23 00 02 0C 36
|
||||
23 00 02 34 36
|
||||
23 00 02 5D 36
|
||||
23 00 02 83 36
|
||||
23 00 02 AB 36
|
||||
23 00 02 D1 36
|
||||
23 00 02 0D 6B
|
||||
23 00 02 35 6B
|
||||
23 00 02 5E 6B
|
||||
23 00 02 84 6B
|
||||
23 00 02 AC 6B
|
||||
23 00 02 D2 6B
|
||||
23 00 02 13 5A
|
||||
23 00 02 0F 94
|
||||
23 00 02 3B 5A
|
||||
23 00 02 37 94
|
||||
23 00 02 64 5A
|
||||
23 00 02 60 94
|
||||
23 00 02 8A 5A
|
||||
23 00 02 86 94
|
||||
23 00 02 B2 5A
|
||||
23 00 02 AE 94
|
||||
23 00 02 D8 5A
|
||||
23 00 02 D4 94
|
||||
23 00 02 10 D1
|
||||
23 00 02 38 D1
|
||||
23 00 02 61 D1
|
||||
23 00 02 87 D1
|
||||
23 00 02 AF D1
|
||||
23 00 02 D5 D1
|
||||
23 00 02 11 04
|
||||
23 00 02 39 04
|
||||
23 00 02 62 04
|
||||
23 00 02 88 04
|
||||
23 00 02 B0 04
|
||||
23 00 02 D6 04
|
||||
23 00 02 12 05
|
||||
23 00 02 3A 05
|
||||
23 00 02 63 05
|
||||
23 00 02 89 05
|
||||
23 00 02 B1 05
|
||||
23 00 02 D7 05
|
||||
23 00 02 18 AA
|
||||
23 00 02 14 36
|
||||
23 00 02 42 AA
|
||||
23 00 02 3D 36
|
||||
23 00 02 69 AA
|
||||
23 00 02 65 36
|
||||
23 00 02 8F AA
|
||||
23 00 02 8B 36
|
||||
23 00 02 B7 AA
|
||||
23 00 02 B3 36
|
||||
23 00 02 DD AA
|
||||
23 00 02 D9 36
|
||||
23 00 02 15 74
|
||||
23 00 02 3F 74
|
||||
23 00 02 66 74
|
||||
23 00 02 8C 74
|
||||
23 00 02 B4 74
|
||||
23 00 02 DA 74
|
||||
23 00 02 16 9F
|
||||
23 00 02 40 9F
|
||||
23 00 02 67 9F
|
||||
23 00 02 8D 9F
|
||||
23 00 02 B5 9F
|
||||
23 00 02 DB 9F
|
||||
23 00 02 17 DC
|
||||
23 00 02 41 DC
|
||||
23 00 02 68 DC
|
||||
23 00 02 8E DC
|
||||
23 00 02 B6 DC
|
||||
23 00 02 DC DC
|
||||
23 00 02 1D FF
|
||||
23 00 02 19 03
|
||||
23 00 02 47 FF
|
||||
23 00 02 43 03
|
||||
23 00 02 6E FF
|
||||
23 00 02 6A 03
|
||||
23 00 02 94 FF
|
||||
23 00 02 90 03
|
||||
23 00 02 BC FF
|
||||
23 00 02 B8 03
|
||||
23 00 02 E2 FF
|
||||
23 00 02 DE 03
|
||||
23 00 02 1A 35
|
||||
23 00 02 44 35
|
||||
23 00 02 6B 35
|
||||
23 00 02 91 35
|
||||
23 00 02 B9 35
|
||||
23 00 02 DF 35
|
||||
23 00 02 1B 45
|
||||
23 00 02 45 45
|
||||
23 00 02 6C 45
|
||||
23 00 02 92 45
|
||||
23 00 02 BA 45
|
||||
23 00 02 E0 45
|
||||
23 00 02 1C 55
|
||||
23 00 02 46 55
|
||||
23 00 02 6D 55
|
||||
23 00 02 93 55
|
||||
23 00 02 BB 55
|
||||
23 00 02 E1 55
|
||||
23 00 02 22 FF
|
||||
23 00 02 1E 68
|
||||
23 00 02 4C FF
|
||||
23 00 02 48 68
|
||||
23 00 02 73 FF
|
||||
23 00 02 6F 68
|
||||
23 00 02 99 FF
|
||||
23 00 02 95 68
|
||||
23 00 02 C1 FF
|
||||
23 00 02 BD 68
|
||||
23 00 02 E7 FF
|
||||
23 00 02 E3 68
|
||||
23 00 02 1F 7E
|
||||
23 00 02 49 7E
|
||||
23 00 02 70 7E
|
||||
23 00 02 96 7E
|
||||
23 00 02 BE 7E
|
||||
23 00 02 E4 7E
|
||||
23 00 02 20 97
|
||||
23 00 02 4A 97
|
||||
23 00 02 71 97
|
||||
23 00 02 97 97
|
||||
23 00 02 BF 97
|
||||
23 00 02 E5 97
|
||||
23 00 02 21 B5
|
||||
23 00 02 4B B5
|
||||
23 00 02 72 B5
|
||||
23 00 02 98 B5
|
||||
23 00 02 C0 B5
|
||||
23 00 02 E6 B5
|
||||
23 00 02 25 F0
|
||||
23 00 02 23 E8
|
||||
23 00 02 4F F0
|
||||
23 00 02 4D E8
|
||||
23 00 02 76 F0
|
||||
23 00 02 74 E8
|
||||
23 00 02 9C F0
|
||||
23 00 02 9A E8
|
||||
23 00 02 C4 F0
|
||||
23 00 02 C2 E8
|
||||
23 00 02 EA F0
|
||||
23 00 02 E8 E8
|
||||
23 00 02 24 FF
|
||||
23 00 02 4E FF
|
||||
23 00 02 75 FF
|
||||
23 00 02 9B FF
|
||||
23 00 02 C3 FF
|
||||
23 00 02 E9 FF
|
||||
23 00 02 FE 3D
|
||||
23 00 02 00 04
|
||||
23 00 02 FE 23
|
||||
23 00 02 08 82
|
||||
23 00 02 0A 00
|
||||
23 00 02 0B 00
|
||||
23 00 02 0C 01
|
||||
23 00 02 16 00
|
||||
23 00 02 18 02
|
||||
23 00 02 1B 04
|
||||
23 00 02 19 04
|
||||
23 00 02 1C 81
|
||||
23 00 02 1F 00
|
||||
23 00 02 20 03
|
||||
23 00 02 23 04
|
||||
23 00 02 21 01
|
||||
23 00 02 54 63
|
||||
23 00 02 55 54
|
||||
23 00 02 6E 45
|
||||
23 00 02 6D 36
|
||||
23 00 02 FE 3D
|
||||
23 00 02 55 78
|
||||
23 00 02 FE 20
|
||||
23 00 02 26 30
|
||||
23 00 02 FE 3D
|
||||
23 00 02 20 71
|
||||
23 00 02 50 8F
|
||||
23 00 02 51 8F
|
||||
23 00 02 FE 00
|
||||
23 00 02 35 00
|
||||
05 78 01 11
|
||||
05 00 01 29
|
||||
];
|
||||
|
||||
panel-exit-sequence = [
|
||||
05 00 01 28
|
||||
05 00 01 10
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <15>;
|
||||
vback-porch = <15>;
|
||||
vfront-porch = <15>;
|
||||
hsync-len = <2>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <132000000>;
|
||||
hactive = <1080>;
|
||||
vactive = <1920>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <15>;
|
||||
vback-porch = <15>;
|
||||
vfront-porch = <15>;
|
||||
hsync-len = <2>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb_in_vp2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
rgb_out_panel: endpoint {
|
||||
remote-endpoint = <&panel_in_rgb>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&touch_gpio {
|
||||
rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
|
||||
<0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
@@ -0,0 +1,140 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
/ {
|
||||
panel@0 {
|
||||
compatible = "simple-panel";
|
||||
|
||||
disp_timings3: display-timings {
|
||||
native-mode = <&rgb2lvds_timing>;
|
||||
rgb2lvds_timing: timing0 {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <148>;
|
||||
hfront-porch = <88>;
|
||||
vback-porch = <36>;
|
||||
vfront-porch = <4>;
|
||||
hsync-len = <44>;
|
||||
vsync-len = <5>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&rgb_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&backlight {
|
||||
enable-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <100>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rk628_reset &refclk_pins>;
|
||||
assigned-clocks = <&pmucru CLK_WIFI>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
clocks = <&pmucru CLK_WIFI>;
|
||||
clock-names = "soc_24M";
|
||||
|
||||
rk628,rgb-in;
|
||||
rk628-gvi {
|
||||
/* "rgb666"
|
||||
* "rgb888"
|
||||
* "rgb101010"
|
||||
* "yuyv8"
|
||||
* "yuyv10"
|
||||
*/
|
||||
bus-format = "rgb888";
|
||||
gvi,lanes = <8>;
|
||||
//"rockchip,division-mode";
|
||||
//"rockchip, gvi-frm-rst";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <148>;
|
||||
hfront-porch = <88>;
|
||||
vback-porch = <36>;
|
||||
vfront-porch = <4>;
|
||||
hsync-len = <44>;
|
||||
vsync-len = <5>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <594000000>;
|
||||
hactive = <3840>;
|
||||
vactive = <2160>;
|
||||
hback-porch = <296>;
|
||||
hfront-porch = <176>;
|
||||
vback-porch = <72>;
|
||||
vfront-porch = <8>;
|
||||
hsync-len = <88>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb_in_vp2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
rgb_out_panel: endpoint {
|
||||
remote-endpoint = <&panel_in_rgb>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&vcc3v3_lcd0_n {
|
||||
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
&backlight {
|
||||
enable-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
assigned-clocks = <&pmucru CLK_WIFI>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
clocks = <&pmucru CLK_WIFI>;
|
||||
clock-names = "soc_24M";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rk628_reset &refclk_pins>;
|
||||
|
||||
rk628,rgb-in;
|
||||
rk628,hdmi-out;
|
||||
status = "okay";
|
||||
|
||||
port {
|
||||
rgb_in_hdmi: endpoint {
|
||||
remote-endpoint = <&rgb_out_hdmi>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2s2_2ch {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&rgb_in_vp2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
rgb_out_hdmi: endpoint {
|
||||
remote-endpoint = <&rgb_in_hdmi>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&rk628_sound {
|
||||
status = "okay";
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
/ {
|
||||
panel@0 {
|
||||
compatible = "simple-panel";
|
||||
|
||||
disp_timings3: display-timings {
|
||||
native-mode = <&rgb2lvds_timing>;
|
||||
rgb2lvds_timing: timing0 {
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <4>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&rgb_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&backlight {
|
||||
pwms = <&pwm4 0 25000 PWM_POLARITY_INVERTED>;
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <10>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
|
||||
rk628,rgb-in;
|
||||
rk628-lvds {
|
||||
/* "jeida_18","vesa_24","vesa_18" */
|
||||
bus-format = "jeida_24";
|
||||
|
||||
/* "dual_link_odd_even_pixels"
|
||||
* "dual_link_even_odd_pixels"
|
||||
* "dual_link_left_right_pixels"
|
||||
* "dual_link_right_left_pixels"
|
||||
*/
|
||||
link-type = "single_link";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <4>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <66000000>;
|
||||
hactive = <800>;
|
||||
vactive = <1280>;
|
||||
hback-porch = <30>;
|
||||
hfront-porch = <30>;
|
||||
vback-porch = <3>;
|
||||
vfront-porch = <3>;
|
||||
hsync-len = <4>;
|
||||
vsync-len = <2>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb_in_vp2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
rgb_out_panel: endpoint {
|
||||
remote-endpoint = <&panel_in_rgb>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb-rk628-ddr4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
/ {
|
||||
panel@0 {
|
||||
compatible = "simple-panel";
|
||||
|
||||
disp_timings3: display-timings {
|
||||
native-mode = <&rgb2lvds_timing>;
|
||||
rgb2lvds_timing: timing0 {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <96>;
|
||||
hfront-porch = <120>;
|
||||
vback-porch = <8>;
|
||||
vfront-porch = <33>;
|
||||
hsync-len = <64>;
|
||||
vsync-len = <4>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&rgb_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&backlight {
|
||||
enable-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
pwms = <&pwm4 0 25000 PWM_POLARITY_INVERTED>;
|
||||
};
|
||||
|
||||
>1x {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c2_rk628 {
|
||||
panel-backlight = <&backlight>;
|
||||
panel-power-supply = <&vcc3v3_lcd0_n>;
|
||||
panel-reset-delay-ms = <10>;
|
||||
panel-enable-delay-ms = <10>;
|
||||
panel-prepare-delay-ms = <60>;
|
||||
panel-unprepare-delay-ms = <10>;
|
||||
panel-disable-delay-ms = <60>;
|
||||
|
||||
rk628,rgb-in;
|
||||
rk628-lvds {
|
||||
/* "jeida_18","vesa_24","vesa_18" */
|
||||
bus-format = "vesa_24";
|
||||
|
||||
/* "dual_link_odd_even_pixels"
|
||||
* "dual_link_even_odd_pixels"
|
||||
* "dual_link_left_right_pixels"
|
||||
* "dual_link_right_left_pixels"
|
||||
*/
|
||||
link-type = "dual_link_even_odd_pixels";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
display-timings {
|
||||
src-timing {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <96>;
|
||||
hfront-porch = <120>;
|
||||
vback-porch = <8>;
|
||||
vfront-porch = <33>;
|
||||
hsync-len = <64>;
|
||||
vsync-len = <4>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
|
||||
dst-timing {
|
||||
clock-frequency = <148500000>;
|
||||
hactive = <1920>;
|
||||
vactive = <1080>;
|
||||
hback-porch = <96>;
|
||||
hfront-porch = <120>;
|
||||
vback-porch = <8>;
|
||||
vfront-porch = <33>;
|
||||
hsync-len = <64>;
|
||||
vsync-len = <4>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb_in_vp2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
rgb_out_panel: endpoint {
|
||||
remote-endpoint = <&panel_in_rgb>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&vcc3v3_lcd0_n {
|
||||
gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
|
||||
enable-active-high;
|
||||
};
|
||||
@@ -31,40 +31,6 @@
|
||||
&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 = <&hdmiin_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";
|
||||
};
|
||||
|
||||
&csi2_dcphy0 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@@ -92,7 +58,46 @@
|
||||
};
|
||||
};
|
||||
|
||||
&csi2_dphy0_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&csi2_dphy1 {
|
||||
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 = <&hdmiin_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_dphy1_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
rk628_csi_1: rk628_csi_1@50 {
|
||||
@@ -113,6 +118,15 @@
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "HDMI-MIPI2";
|
||||
rockchip,camera-module-lens-name = "RK628-CSI";
|
||||
|
||||
multi-dev-info {
|
||||
dev-idx-l = <2>;
|
||||
dev-idx-r = <4>;
|
||||
combine-idx = <2>;
|
||||
pixel-offset = <0>;
|
||||
dev-num = <2>;
|
||||
};
|
||||
|
||||
port {
|
||||
hdmiin_out1: endpoint {
|
||||
remote-endpoint = <&hdmi_mipi2_in>;
|
||||
@@ -123,6 +137,7 @@
|
||||
};
|
||||
|
||||
&i2c5 {
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
rk628_csi: rk628_csi@50 {
|
||||
@@ -143,6 +158,15 @@
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "HDMI-MIPI";
|
||||
rockchip,camera-module-lens-name = "RK628-CSI";
|
||||
|
||||
multi-dev-info {
|
||||
dev-idx-l = <0>;
|
||||
dev-idx-r = <1>;
|
||||
combine-idx = <0>;
|
||||
pixel-offset = <0>;
|
||||
dev-num = <2>;
|
||||
};
|
||||
|
||||
port {
|
||||
hdmiin_out0: endpoint {
|
||||
remote-endpoint = <&hdmi_mipi0_in>;
|
||||
@@ -156,6 +180,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi_dcphy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi0_csi2 {
|
||||
status = "okay";
|
||||
|
||||
|
||||
175
arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-rk628-hdmi2csi.dts
Normal file
175
arch/arm64/boot/dts/rockchip/rk3588-evb7-v11-rk628-hdmi2csi.dts
Normal file
@@ -0,0 +1,175 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
/dts-v1/;
|
||||
|
||||
#include "rk3588-evb7-v11.dtsi"
|
||||
#include "rk3588-android.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RK3588 EVB7 V11 Board + Rockchip RK628 HDMI to MIPI Extboard";
|
||||
compatible = "rockchip,rk3588-evb7-v11", "rockchip,rk3588";
|
||||
|
||||
vcc_mipicsi0: vcc-mipicsi0-regulator {
|
||||
/delete-property/ gpio;
|
||||
/delete-property/ pinctrl-0;
|
||||
};
|
||||
|
||||
vcc_mipicsi1: vcc-mipicsi1-regulator {
|
||||
/delete-property/ gpio;
|
||||
/delete-property/ pinctrl-0;
|
||||
};
|
||||
|
||||
vcc_mipidcphy0: vcc-mipidcphy0-regulator {
|
||||
/delete-property/ gpio;
|
||||
/delete-property/ pinctrl-0;
|
||||
};
|
||||
};
|
||||
|
||||
&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 = <&hdmiin_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";
|
||||
};
|
||||
|
||||
&csi2_dphy1_hw {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
status = "okay";
|
||||
clock-frequency = <400000>;
|
||||
|
||||
rk628_csi: rk628_csi@50 {
|
||||
reg = <0x50>;
|
||||
compatible = "rockchip,rk628-csi-v4l2";
|
||||
status = "okay";
|
||||
power-domains = <&power RK3588_PD_VI>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rk628_pin>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <RK_PB2 IRQ_TYPE_LEVEL_HIGH>;
|
||||
enable-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
plugin-det-gpios = <&gpio2 RK_PB6 GPIO_ACTIVE_LOW>;
|
||||
continues-clk = <1>;
|
||||
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "HDMI-MIPI2";
|
||||
rockchip,camera-module-lens-name = "RK628-CSI";
|
||||
|
||||
multi-dev-info {
|
||||
dev-idx-l = <2>;
|
||||
dev-idx-r = <4>;
|
||||
combine-idx = <2>;
|
||||
pixel-offset = <0>;
|
||||
dev-num = <2>;
|
||||
};
|
||||
|
||||
port {
|
||||
hdmiin_out1: endpoint {
|
||||
remote-endpoint = <&hdmi_mipi2_in>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&mipi_dcphy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&mipi_dcphy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&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 {
|
||||
rk628_pin: rk628-pin {
|
||||
rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
<1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
<1 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
<2 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -293,6 +293,8 @@ CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
CONFIG_BLK_DEV_RAM_SIZE=8192
|
||||
CONFIG_BLK_DEV_NVME=y
|
||||
CONFIG_RK628_MISC=y
|
||||
CONFIG_RK628_MISC_HDMITX=y
|
||||
CONFIG_LT7911D_FB_NOTIFIER=y
|
||||
CONFIG_SRAM=y
|
||||
CONFIG_UID_SYS_STATS=y
|
||||
@@ -556,7 +558,6 @@ CONFIG_ROCKCHIP_THERMAL=y
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_DW_WATCHDOG=y
|
||||
CONFIG_MFD_RK618=y
|
||||
CONFIG_MFD_RK628=y
|
||||
CONFIG_MFD_RK630_I2C=y
|
||||
CONFIG_MFD_RK806_I2C=y
|
||||
CONFIG_MFD_RK806_SPI=y
|
||||
@@ -639,7 +640,6 @@ CONFIG_ROCKCHIP_LVDS=y
|
||||
CONFIG_ROCKCHIP_RGB=y
|
||||
CONFIG_ROCKCHIP_DW_HDCP2=y
|
||||
CONFIG_DRM_ROCKCHIP_RK618=y
|
||||
CONFIG_DRM_ROCKCHIP_RK628=y
|
||||
CONFIG_DRM_PANEL_SIMPLE=y
|
||||
CONFIG_DRM_PANEL_MAXIM_MAX96752F=y
|
||||
CONFIG_DRM_PANEL_MAXIM_MAX96772=y
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#
|
||||
# Makefile for the Rockchip RK628 display bridge driver.
|
||||
#
|
||||
video-rk628-objs := rk628.o rk628_cru.o rk628_hdmirx.o rk628_dsi.o rk628_combrxphy.o rk628_combtxphy.o
|
||||
video-rk628-objs := rk628.o rk628_cru.o rk628_hdmirx.o rk628_dsi.o rk628_combrxphy.o \
|
||||
rk628_combtxphy.o rk628_mipi_dphy.o rk628_post_process.o
|
||||
obj-$(CONFIG_VIDEO_RK628) += video-rk628.o
|
||||
|
||||
rk628-csi-objs := rk628_csi_v4l2.o
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
static const struct regmap_range rk628_cru_readable_ranges[] = {
|
||||
regmap_reg_range(CRU_CPLL_CON0, CRU_CPLL_CON4),
|
||||
regmap_reg_range(CRU_GPLL_CON0, CRU_GPLL_CON4),
|
||||
regmap_reg_range(CRU_APLL_CON0, CRU_APLL_CON4),
|
||||
regmap_reg_range(CRU_MODE_CON00, CRU_MODE_CON00),
|
||||
regmap_reg_range(CRU_CLKSEL_CON00, CRU_CLKSEL_CON21),
|
||||
regmap_reg_range(CRU_GATE_CON00, CRU_GATE_CON05),
|
||||
@@ -46,12 +47,12 @@ static const struct regmap_access_table rk628_combrxphy_readable_table = {
|
||||
};
|
||||
|
||||
static const struct regmap_range rk628_hdmirx_readable_ranges[] = {
|
||||
regmap_reg_range(HDMI_RX_HDMI_SETUP_CTRL, HDMI_RX_HDMI_SETUP_CTRL),
|
||||
regmap_reg_range(HDMI_RX_HDMI_SETUP_CTRL, HDMI_RX_HDMI_TIMER_CTRL),
|
||||
regmap_reg_range(HDMI_RX_HDMI_PCB_CTRL, HDMI_RX_HDMI_PCB_CTRL),
|
||||
regmap_reg_range(HDMI_RX_HDMI_MODE_RECOVER, HDMI_RX_HDMI_ERROR_PROTECT),
|
||||
regmap_reg_range(HDMI_RX_HDMI_SYNC_CTRL, HDMI_RX_HDMI_CKM_RESULT),
|
||||
regmap_reg_range(HDMI_RX_HDMI_RESMPL_CTRL, HDMI_RX_HDMI_RESMPL_CTRL),
|
||||
regmap_reg_range(HDMI_VM_CFG_CH2, HDMI_VM_CFG_CH2),
|
||||
regmap_reg_range(HDMI_VM_CFG_CH0_1, HDMI_VM_CFG_CH2),
|
||||
regmap_reg_range(HDMI_RX_HDCP_CTRL, HDMI_RX_HDCP_SETTINGS),
|
||||
regmap_reg_range(HDMI_RX_HDCP_KIDX, HDMI_RX_HDCP_KIDX),
|
||||
regmap_reg_range(HDMI_RX_HDCP_DBG, HDMI_RX_HDCP_AN0),
|
||||
@@ -67,6 +68,7 @@ static const struct regmap_range rk628_hdmirx_readable_ranges[] = {
|
||||
regmap_reg_range(HDMI_RX_AUD_CHEXTR_CTRL, HDMI_RX_AUD_PAO_CTRL),
|
||||
regmap_reg_range(HDMI_RX_AUD_FIFO_STS, HDMI_RX_AUD_FIFO_STS),
|
||||
regmap_reg_range(HDMI_RX_AUDPLL_GEN_CTS, HDMI_RX_AUDPLL_GEN_N),
|
||||
regmap_reg_range(HDMI_RX_I2CM_PHYG3_DATAI, HDMI_RX_I2CM_PHYG3_DATAI),
|
||||
regmap_reg_range(HDMI_RX_PDEC_CTRL, HDMI_RX_PDEC_CTRL),
|
||||
regmap_reg_range(HDMI_RX_PDEC_AUDIODET_CTRL, HDMI_RX_PDEC_AUDIODET_CTRL),
|
||||
regmap_reg_range(HDMI_RX_PDEC_ERR_FILTER, HDMI_RX_PDEC_ASP_CTRL),
|
||||
@@ -76,8 +78,9 @@ static const struct regmap_range rk628_hdmirx_readable_ranges[] = {
|
||||
regmap_reg_range(HDMI_RX_PDEC_AIF_CTRL, HDMI_RX_PDEC_AIF_PB0),
|
||||
regmap_reg_range(HDMI_RX_PDEC_AVI_PB, HDMI_RX_PDEC_AVI_PB),
|
||||
regmap_reg_range(HDMI_RX_HDMI20_CONTROL, HDMI_RX_CHLOCK_CONFIG),
|
||||
regmap_reg_range(HDMI_RX_SCDC_REGS1, HDMI_RX_SCDC_REGS2),
|
||||
regmap_reg_range(HDMI_RX_SCDC_REGS0, HDMI_RX_SCDC_REGS2),
|
||||
regmap_reg_range(HDMI_RX_SCDC_WRDATA0, HDMI_RX_SCDC_WRDATA0),
|
||||
regmap_reg_range(HDMI_RX_HDMI20_STATUS, HDMI_RX_HDMI20_STATUS),
|
||||
regmap_reg_range(HDMI_RX_PDEC_ISTS, HDMI_RX_PDEC_IEN),
|
||||
regmap_reg_range(HDMI_RX_AUD_FIFO_ISTS, HDMI_RX_AUD_FIFO_IEN),
|
||||
regmap_reg_range(HDMI_RX_MD_ISTS, HDMI_RX_MD_IEN),
|
||||
@@ -112,6 +115,7 @@ static const struct regmap_range rk628_csi_readable_ranges[] = {
|
||||
regmap_reg_range(CSITX_CONFIG_DONE, CSITX_CSITX_VERSION),
|
||||
regmap_reg_range(CSITX_SYS_CTRL0_IMD, CSITX_TIMING_HPW_PADDING_NUM),
|
||||
regmap_reg_range(CSITX_VOP_PATH_CTRL, CSITX_VOP_PATH_CTRL),
|
||||
regmap_reg_range(CSITX_VOP_FILTER_CTRL, CSITX_VOP_FILTER_CTRL),
|
||||
regmap_reg_range(CSITX_VOP_PATH_PKT_CTRL, CSITX_VOP_PATH_PKT_CTRL),
|
||||
regmap_reg_range(CSITX_CSITX_STATUS0, CSITX_LPDT_DATA_IMD),
|
||||
regmap_reg_range(CSITX_DPHY_CTRL, CSITX_DPHY_CTRL),
|
||||
@@ -122,6 +126,21 @@ static const struct regmap_access_table rk628_csi_readable_table = {
|
||||
.n_yes_ranges = ARRAY_SIZE(rk628_csi_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range rk628_csi1_readable_ranges[] = {
|
||||
regmap_reg_range(CSITX1_CONFIG_DONE, CSITX1_CSITX_VERSION),
|
||||
regmap_reg_range(CSITX1_SYS_CTRL0_IMD, CSITX1_TIMING_HPW_PADDING_NUM),
|
||||
regmap_reg_range(CSITX1_VOP_PATH_CTRL, CSITX1_VOP_PATH_CTRL),
|
||||
regmap_reg_range(CSITX1_VOP_FILTER_CTRL, CSITX1_VOP_FILTER_CTRL),
|
||||
regmap_reg_range(CSITX1_VOP_PATH_PKT_CTRL, CSITX1_VOP_PATH_PKT_CTRL),
|
||||
regmap_reg_range(CSITX1_CSITX_STATUS0, CSITX1_LPDT_DATA_IMD),
|
||||
regmap_reg_range(CSITX1_DPHY_CTRL, CSITX1_DPHY_CTRL),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table rk628_csi1_readable_table = {
|
||||
.yes_ranges = rk628_csi1_readable_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(rk628_csi1_readable_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_range rk628_dsi0_readable_ranges[] = {
|
||||
regmap_reg_range(DSI0_BASE, DSI0_BASE + DSI_MAX_REGISTER),
|
||||
};
|
||||
@@ -231,8 +250,192 @@ static const struct regmap_config rk628_regmap_config[RK628_DEV_MAX] = {
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
.rd_table = &rk628_csi_readable_table,
|
||||
},
|
||||
[RK628_DEV_CSI1] = {
|
||||
.name = "csi1",
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = CSI1_MAX_REGISTER,
|
||||
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
.rd_table = &rk628_csi1_readable_table,
|
||||
},
|
||||
};
|
||||
|
||||
int rk628_media_i2c_write(struct rk628 *rk628, u32 reg, u32 val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
int ret = 0;
|
||||
|
||||
if (region >= RK628_DEV_MAX) {
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err: invalid arguments, out of register range\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_write(rk628->regmap[region], reg, val);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err reg=0x%x, val=0x%x, ret=%d\n", __func__, reg, val, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_media_i2c_write);
|
||||
|
||||
int rk628_media_i2c_read(struct rk628 *rk628, u32 reg, u32 *val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
int ret = 0;
|
||||
|
||||
if (region >= RK628_DEV_MAX) {
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err: invalid arguments, out of register range\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_read(rk628->regmap[region], reg, val);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err reg=0x%x, val=0x%x ret=%d\n", __func__, reg, *val, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_media_i2c_read);
|
||||
|
||||
int rk628_media_i2c_update_bits(struct rk628 *rk628, u32 reg, u32 mask,
|
||||
u32 val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
|
||||
if (region >= RK628_DEV_MAX) {
|
||||
dev_err(rk628->dev,
|
||||
"%s: i2c err: invalid arguments, out of register range\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rk628->regmap[region], reg, mask, val);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_media_i2c_update_bits);
|
||||
|
||||
static int rk628_reg_show(struct seq_file *s, void *v)
|
||||
{
|
||||
const struct regmap_config *reg;
|
||||
struct rk628 *rk628 = s->private;
|
||||
unsigned int i, j;
|
||||
u32 val;
|
||||
|
||||
seq_printf(s, "rk628_%s:\n", file_dentry(s->file)->d_iname);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk628_regmap_config); i++) {
|
||||
reg = &rk628_regmap_config[i];
|
||||
if (!reg->name)
|
||||
continue;
|
||||
if (!strcmp(reg->name, file_dentry(s->file)->d_iname))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(rk628_regmap_config))
|
||||
return -ENODEV;
|
||||
|
||||
/* grf */
|
||||
if (!reg->rd_table) {
|
||||
for (i = 0; i <= reg->max_register; i += 4) {
|
||||
rk628_i2c_read(rk628, i, &val);
|
||||
if (i % 16 == 0)
|
||||
seq_printf(s, "\n0x%04x:", i);
|
||||
seq_printf(s, " %08x", val);
|
||||
}
|
||||
} else {
|
||||
const struct regmap_range *range_list = reg->rd_table->yes_ranges;
|
||||
const struct regmap_range *range;
|
||||
int range_list_len = reg->rd_table->n_yes_ranges;
|
||||
|
||||
for (i = 0; i < range_list_len; i++) {
|
||||
range = &range_list[i];
|
||||
for (j = range->range_min; j <= range->range_max; j += 4) {
|
||||
rk628_i2c_read(rk628, j, &val);
|
||||
if (j % 16 == 0 || j == range->range_min)
|
||||
seq_printf(s, "\n0x%04x:", j);
|
||||
seq_printf(s, " %08x", val);
|
||||
}
|
||||
}
|
||||
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rk628_reg_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rk628 *rk628 = file->f_path.dentry->d_inode->i_private;
|
||||
u32 addr;
|
||||
u32 val;
|
||||
char kbuf[25];
|
||||
int ret;
|
||||
|
||||
if (count >= sizeof(kbuf))
|
||||
return -ENOSPC;
|
||||
|
||||
if (copy_from_user(kbuf, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
kbuf[count] = '\0';
|
||||
|
||||
ret = sscanf(kbuf, "%x%x", &addr, &val);
|
||||
if (ret != 2)
|
||||
return -EINVAL;
|
||||
|
||||
rk628_i2c_write(rk628, addr, val);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int rk628_reg_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct rk628 *rk628 = inode->i_private;
|
||||
|
||||
return single_open(file, rk628_reg_show, rk628);
|
||||
}
|
||||
|
||||
static const struct file_operations rk628_reg_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk628_reg_open,
|
||||
.read = seq_read,
|
||||
.write = rk628_reg_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static void rk628_debugfs_register_create(struct rk628 *rk628)
|
||||
{
|
||||
const struct regmap_config *reg;
|
||||
struct dentry *dir;
|
||||
int i;
|
||||
|
||||
dir = debugfs_create_dir("registers", rk628->debug_dir);
|
||||
if (IS_ERR(dir))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(rk628_regmap_config); i++) {
|
||||
reg = &rk628_regmap_config[i];
|
||||
if (!reg->name)
|
||||
continue;
|
||||
debugfs_create_file(reg->name, 0600, dir, rk628, &rk628_reg_fops);
|
||||
}
|
||||
}
|
||||
|
||||
void rk628_debugfs_create(struct rk628 *rk628)
|
||||
{
|
||||
rk628->debug_dir = debugfs_create_dir(dev_name(rk628->dev), debugfs_lookup("rk628", NULL));
|
||||
if (IS_ERR(rk628->debug_dir))
|
||||
return;
|
||||
|
||||
rk628_debugfs_register_create(rk628);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_debugfs_create);
|
||||
|
||||
struct rk628 *rk628_i2c_register(struct i2c_client *client)
|
||||
{
|
||||
struct rk628 *rk628;
|
||||
@@ -259,6 +462,7 @@ struct rk628 *rk628_i2c_register(struct i2c_client *client)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
mutex_init(&rk628->rst_lock);
|
||||
|
||||
return rk628;
|
||||
}
|
||||
@@ -475,6 +679,29 @@ void rk628_post_process_en(struct rk628 *rk628,
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_post_process_en);
|
||||
|
||||
static const char * const rk628_version[] = {
|
||||
"UNKNOWN",
|
||||
"RK628D",
|
||||
"RK628F/H",
|
||||
};
|
||||
|
||||
void rk628_version_parse(struct rk628 *rk628)
|
||||
{
|
||||
u32 version;
|
||||
|
||||
rk628_i2c_read(rk628, GRF_SOC_VERSION, &version);
|
||||
if (version == 0x20200326)
|
||||
rk628->version = RK628D_VERSION;
|
||||
else if (version == 0x20230321)
|
||||
rk628->version = RK628F_VERSION;
|
||||
else
|
||||
rk628->version = RK628_UNKNOWN;
|
||||
|
||||
dev_info(rk628->dev, "rk628 version is: %s (%x)\n",
|
||||
rk628_version[rk628->version], version);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_version_parse);
|
||||
|
||||
MODULE_AUTHOR("Shunqing Chen <csq@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Rockchip RK628 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#define SW_EFUSE_HDCP_EN(x) UPDATE(x, 8, 8)
|
||||
#define SW_OUTPUT_MODE_MASK GENMASK(7, 3)
|
||||
#define SW_OUTPUT_MODE(x) UPDATE(x, 7, 3)
|
||||
#define SW_OUTPUT_COMBTX_MODE_MASK GENMASK(4, 3)
|
||||
#define SW_OUTPUT_COMBTX_MODE(x) UPDATE(x, 4, 3)
|
||||
#define SW_INPUT_MODE_MASK GENMASK(2, 0)
|
||||
#define SW_INPUT_MODE(x) UPDATE(x, 2, 0)
|
||||
#define GRF_SYSTEM_CON1 0x0004
|
||||
@@ -45,6 +47,10 @@
|
||||
#define GRF_GPIO_RXDDC_SDA_SEL(x) UPDATE(x, 6, 6)
|
||||
#define GRF_GPIO_RXDDC_SCL_SEL_MASK BIT(5)
|
||||
#define GRF_GPIO_RXDDC_SCL_SEL(x) UPDATE(x, 5, 5)
|
||||
#define GRF_DPHY_CH1_EN_MASK BIT(1)
|
||||
#define GRF_DPHY_CH1_EN(x) UPDATE(x, 1, 1)
|
||||
#define GRF_AS_DSIPHY_MASK BIT(0)
|
||||
#define GRF_AS_DSIPHY(x) UPDATE(x, 0, 0)
|
||||
#define GRF_SCALER_CON0 0x0010
|
||||
#define SCL_VER_DOWN_MODE(x) HIWORD_UPDATE(x, 8, 8)
|
||||
#define SCL_HOR_DOWN_MODE(x) HIWORD_UPDATE(x, 7, 7)
|
||||
@@ -87,9 +93,13 @@
|
||||
#define SW_SPLIT_MODE(x) UPDATE(x, 1, 1)
|
||||
#define SW_SPLIT_EN BIT(0)
|
||||
#define GRF_CSC_CTRL_CON 0x0038
|
||||
#define SW_Y2R_MODE(x) HIWORD_UPDATE(x, 13, 12)
|
||||
#define SW_FROM_CSC_MATRIX_EN(x) HIWORD_UPDATE(x, 11, 11)
|
||||
#define SW_YUV2VYU_SWP(x) HIWORD_UPDATE(x, 8, 8)
|
||||
#define SW_R2Y_EN(x) HIWORD_UPDATE(x, 4, 4)
|
||||
#define SW_Y2R_EN(x) HIWORD_UPDATE(x, 0, 0)
|
||||
#define SW_R2Y_CSC_MODE(x) HIWORD_UPDATE(x, 7, 6)
|
||||
#define SW_Y2R_CSC_MODE(x) HIWORD_UPDATE(x, 3, 2)
|
||||
#define GRF_LVDS_TX_CON 0x003c
|
||||
#define SW_LVDS_CON_DUAL_SEL(x) HIWORD_UPDATE(x, 12, 12)
|
||||
#define SW_LVDS_CON_DEN_POLARITY(x) HIWORD_UPDATE(x, 11, 11)
|
||||
@@ -173,6 +183,17 @@
|
||||
#define GRF_GPIO3A_D1_CON 0x00e4
|
||||
#define GRF_GPIO3B_D_CON 0x00e8
|
||||
#define GRF_GPIO_SR_CON 0x00ec
|
||||
#define GRF_BG_CTRL 0x00f0
|
||||
#define BG_ENABLE_MASK GENMASK(31, 31)
|
||||
#define BG_ENABLE(x) UPDATE(x, 31, 31)
|
||||
#define BG_R_OR_V_MASK GENMASK(29, 20)
|
||||
#define BG_R_OR_V(x) UPDATE(x, 29, 20)
|
||||
#define BG_G_OR_Y_MASK GENMASK(19, 10)
|
||||
#define BG_G_OR_Y(x) UPDATE(x, 19, 10)
|
||||
#define BG_B_OR_U_MASK GENMASK(9, 0)
|
||||
#define BG_B_OR_U(x) UPDATE(x, 9, 0)
|
||||
|
||||
#define GRF_SW_HDMIRXPHY_CRTL 0x00f4
|
||||
#define GRF_INTR0_EN 0x0100
|
||||
#define GRF_INTR0_CLR_EN 0x0104
|
||||
#define GRF_INTR0_STATUS 0x0108
|
||||
@@ -190,7 +211,15 @@
|
||||
#define GRF_OS_REG1 0x0144
|
||||
#define GRF_OS_REG2 0x0148
|
||||
#define GRF_OS_REG3 0x014c
|
||||
#define GRF_SOC_VERSION 0x0150
|
||||
#define GRF_CSC_MATRIX_COE01_COE00 0x01a0
|
||||
#define GRF_CSC_MATRIX_COE10_COE02 0x01a4
|
||||
#define GRF_CSC_MATRIX_COE12_COE11 0x01a8
|
||||
#define GRF_CSC_MATRIX_COE21_COE20 0x01ac
|
||||
#define GRF_CSC_MATRIX_COE22 0x01b0
|
||||
#define GRF_CSC_MATRIX_OFFSET0 0x01b4
|
||||
#define GRF_CSC_MATRIX_OFFSET1 0x01b8
|
||||
#define GRF_CSC_MATRIX_OFFSET2 0x01bc
|
||||
#define GRF_SOC_VERSION 0x0200
|
||||
#define GRF_MAX_REGISTER GRF_SOC_VERSION
|
||||
|
||||
enum {
|
||||
@@ -233,46 +262,58 @@ enum {
|
||||
RK628_DEV_GPIO1,
|
||||
RK628_DEV_GPIO2,
|
||||
RK628_DEV_GPIO3,
|
||||
RK628_DEV_CSI1 = 0x14,
|
||||
RK628_DEV_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
RK628_UNKNOWN,
|
||||
RK628D_VERSION,
|
||||
RK628F_VERSION,
|
||||
};
|
||||
|
||||
struct mipi_timing {
|
||||
u8 data_prepare;
|
||||
u8 data_zero;
|
||||
u8 data_trail;
|
||||
u8 clk_prepare;
|
||||
u8 clk_zero;
|
||||
u8 clk_trail;
|
||||
u8 clk_post;
|
||||
};
|
||||
|
||||
struct rk628 {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap[RK628_DEV_MAX];
|
||||
u8 version;
|
||||
void *txphy;
|
||||
u8 dphy_lane_en;
|
||||
bool dual_mipi;
|
||||
struct mipi_timing mipi_timing[2];
|
||||
struct mutex rst_lock;
|
||||
int tx_mode;
|
||||
struct dentry *debug_dir;
|
||||
};
|
||||
|
||||
int rk628_media_i2c_write(struct rk628 *rk628, u32 reg, u32 val);
|
||||
int rk628_media_i2c_read(struct rk628 *rk628, u32 reg, u32 *val);
|
||||
int rk628_media_i2c_update_bits(struct rk628 *rk628, u32 reg, u32 mask, u32 val);
|
||||
|
||||
static inline int rk628_i2c_write(struct rk628 *rk628, u32 reg, u32 val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
int ret = 0;
|
||||
|
||||
ret = regmap_write(rk628->regmap[region], reg, val);
|
||||
if (ret < 0)
|
||||
pr_info("%s: i2c err reg=0x%x, val=0x%x, ret=%d\n", __func__, reg, val, ret);
|
||||
|
||||
return ret;
|
||||
return rk628_media_i2c_write(rk628, reg, val);
|
||||
}
|
||||
|
||||
static inline int rk628_i2c_read(struct rk628 *rk628, u32 reg, u32 *val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
int ret = 0;
|
||||
|
||||
ret = regmap_read(rk628->regmap[region], reg, val);
|
||||
if (ret < 0)
|
||||
pr_info("%s: i2c err reg=0x%x, val=0x%x ret=%d\n", __func__, reg, *val, ret);
|
||||
|
||||
return ret;
|
||||
return rk628_media_i2c_read(rk628, reg, val);
|
||||
}
|
||||
|
||||
static inline int rk628_i2c_update_bits(struct rk628 *rk628, u32 reg, u32 mask,
|
||||
u32 val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
|
||||
return regmap_update_bits(rk628->regmap[region], reg, mask, val);
|
||||
return rk628_media_i2c_update_bits(rk628, reg, mask, val);
|
||||
}
|
||||
|
||||
struct rk628 *rk628_i2c_register(struct i2c_client *client);
|
||||
@@ -280,5 +321,7 @@ void rk628_post_process_en(struct rk628 *rk628,
|
||||
struct videomode *src,
|
||||
struct videomode *dst,
|
||||
u64 *dst_pclk);
|
||||
void rk628_version_parse(struct rk628 *rk628);
|
||||
void rk628_debugfs_create(struct rk628 *rk628);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,27 +44,9 @@ static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "debug level (0-3)");
|
||||
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x0, 0x1)
|
||||
#define DRIVER_VERSION KERNEL_VERSION(0, 0x1, 0x0)
|
||||
#define RK628_BT1120_NAME "rk628-bt1120"
|
||||
|
||||
#define EDID_NUM_BLOCKS_MAX 2
|
||||
#define EDID_BLOCK_SIZE 128
|
||||
|
||||
#define RK628_CSI_LINK_FREQ_LOW 350000000
|
||||
#define RK628_CSI_LINK_FREQ_HIGH 400000000
|
||||
#define RK628_CSI_PIXEL_RATE_LOW 400000000
|
||||
#define RK628_CSI_PIXEL_RATE_HIGH 600000000
|
||||
#define MIPI_DATARATE_MBPS_LOW 750
|
||||
#define MIPI_DATARATE_MBPS_HIGH 1250
|
||||
|
||||
#define POLL_INTERVAL_MS 1000
|
||||
#define MODETCLK_CNT_NUM 1000
|
||||
#define MODETCLK_HZ 49500000
|
||||
#define RXPHY_CFG_MAX_TIMES 15
|
||||
#define CSITX_ERR_RETRY_TIMES 3
|
||||
|
||||
#define USE_4_LANES 4
|
||||
#define YUV422_8BIT 0x1e
|
||||
/* Test Code: 0x44 (HS RX Control of Lane 0) */
|
||||
#define HSFREQRANGE(x) UPDATE(x, 6, 1)
|
||||
|
||||
@@ -92,6 +74,7 @@ struct rk628_bt1120 {
|
||||
struct clk *clk_rx_read;
|
||||
struct delayed_work delayed_work_enable_hotplug;
|
||||
struct delayed_work delayed_work_res_change;
|
||||
struct work_struct work_isr;
|
||||
struct timer_list timer;
|
||||
struct work_struct work_i2c_poll;
|
||||
struct mutex confctl_mutex;
|
||||
@@ -246,14 +229,13 @@ static int rk628_bt1120_s_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *timings);
|
||||
static int rk628_bt1120_s_edid(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_edid *edid);
|
||||
static int rk628_hdmirx_phy_power_on(struct v4l2_subdev *sd);
|
||||
static int rk628_hdmirx_phy_power_off(struct v4l2_subdev *sd);
|
||||
static int rk628_hdmirx_inno_phy_power_on(struct v4l2_subdev *sd);
|
||||
static int rk628_hdmirx_inno_phy_power_off(struct v4l2_subdev *sd);
|
||||
static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd);
|
||||
static void rk628_bt1120_format_change(struct v4l2_subdev *sd);
|
||||
static void enable_stream(struct v4l2_subdev *sd, bool enable);
|
||||
static void rk628_hdmirx_vid_enable(struct v4l2_subdev *sd, bool en);
|
||||
static void rk628_hdmirx_hpd_ctrl(struct v4l2_subdev *sd, bool en);
|
||||
static void rk628_hdmirx_controller_reset(struct v4l2_subdev *sd);
|
||||
static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd);
|
||||
|
||||
static inline struct rk628_bt1120 *to_bt1120(struct v4l2_subdev *sd)
|
||||
@@ -333,95 +315,12 @@ static int rk628_bt1120_get_detected_timings(struct v4l2_subdev *sd,
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
struct v4l2_bt_timings *bt = &timings->bt;
|
||||
u32 hact, vact, htotal, vtotal, fps, status;
|
||||
u32 val;
|
||||
u32 modetclk_cnt_hs, modetclk_cnt_vs, hs, vs;
|
||||
u32 hofs_pix, hbp, hfp, vbp, vfp;
|
||||
u32 tmds_clk, tmdsclk_cnt;
|
||||
u64 tmp_data;
|
||||
int retry = 0;
|
||||
int ret;
|
||||
|
||||
__retry:
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
timings->type = V4L2_DV_BT_656_1120;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_SCDC_REGS1, &val);
|
||||
status = val;
|
||||
ret = rk628_hdmirx_get_timings(bt1120->rk628, timings);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_STS, &val);
|
||||
bt->interlaced = val & ILACE_STS ?
|
||||
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HACT_PX, &val);
|
||||
hact = val & 0xffff;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VAL, &val);
|
||||
vact = val & 0xffff;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HT1, &val);
|
||||
htotal = (val >> 16) & 0xffff;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VTL, &val);
|
||||
vtotal = val & 0xffff;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HT1, &val);
|
||||
hofs_pix = val & 0xffff;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VOL, &val);
|
||||
vbp = (val & 0xffff) + 1;
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_HDMI_CKM_RESULT, &val);
|
||||
tmdsclk_cnt = val & 0xffff;
|
||||
tmp_data = tmdsclk_cnt;
|
||||
tmp_data = ((tmp_data * MODETCLK_HZ) + MODETCLK_CNT_NUM / 2);
|
||||
do_div(tmp_data, MODETCLK_CNT_NUM);
|
||||
tmds_clk = tmp_data;
|
||||
if (!htotal || !vtotal) {
|
||||
v4l2_err(&bt1120->sd, "timing err, htotal:%d, vtotal:%d\n",
|
||||
htotal, vtotal);
|
||||
if (retry++ < 5)
|
||||
goto __retry;
|
||||
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
fps = (tmds_clk + (htotal * vtotal) / 2) / (htotal * vtotal);
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HT0, &val);
|
||||
modetclk_cnt_hs = val & 0xffff;
|
||||
hs = (tmdsclk_cnt * modetclk_cnt_hs + MODETCLK_CNT_NUM / 2) /
|
||||
MODETCLK_CNT_NUM;
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VSC, &val);
|
||||
modetclk_cnt_vs = val & 0xffff;
|
||||
vs = (tmdsclk_cnt * modetclk_cnt_vs + MODETCLK_CNT_NUM / 2) /
|
||||
MODETCLK_CNT_NUM;
|
||||
vs = (vs + htotal / 2) / htotal;
|
||||
|
||||
if ((hofs_pix < hs) || (htotal < (hact + hofs_pix)) ||
|
||||
(vtotal < (vact + vs + vbp))) {
|
||||
v4l2_err(sd, "timing err, total:%dx%d, act:%dx%d, hofs:%d, hs:%d, vs:%d, vbp:%d\n",
|
||||
htotal, vtotal, hact, vact, hofs_pix, hs, vs, vbp);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
hbp = hofs_pix - hs;
|
||||
hfp = htotal - hact - hofs_pix;
|
||||
vfp = vtotal - vact - vs - vbp;
|
||||
|
||||
v4l2_dbg(2, debug, sd, "cnt_num:%d, tmds_cnt:%d, hs_cnt:%d, vs_cnt:%d, hofs:%d\n",
|
||||
MODETCLK_CNT_NUM, tmdsclk_cnt, modetclk_cnt_hs, modetclk_cnt_vs, hofs_pix);
|
||||
|
||||
bt->width = hact;
|
||||
bt->height = vact;
|
||||
bt->hfrontporch = hfp;
|
||||
bt->hsync = hs;
|
||||
bt->hbackporch = hbp;
|
||||
bt->vfrontporch = vfp;
|
||||
bt->vsync = vs;
|
||||
bt->vbackporch = vbp;
|
||||
bt->pixelclock = htotal * vtotal * fps;
|
||||
|
||||
if (bt->interlaced == V4L2_DV_INTERLACED) {
|
||||
bt->height *= 2;
|
||||
bt->il_vsync = bt->vsync + 1;
|
||||
bt->pixelclock /= 2;
|
||||
}
|
||||
|
||||
v4l2_dbg(1, debug, sd, "SCDC_REGS1:%#x, act:%dx%d, total:%dx%d, fps:%d, pixclk:%llu\n",
|
||||
status, hact, vact, htotal, vtotal, fps, bt->pixelclock);
|
||||
v4l2_dbg(1, debug, sd, "hfp:%d, hs:%d, hbp:%d, vfp:%d, vs:%d, vbp:%d, interlace:%d\n",
|
||||
bt->hfrontporch, bt->hsync, bt->hbackporch, bt->vfrontporch,
|
||||
bt->vsync, bt->vbackporch, bt->interlaced);
|
||||
@@ -430,10 +329,21 @@ __retry:
|
||||
if (bt1120->scaler_en)
|
||||
*timings = bt1120->timings;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
TIMING_ERR:
|
||||
return -ENOLCK;
|
||||
static void rk628_hdmirx_plugout(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
enable_stream(sd, false);
|
||||
bt1120->nosignal = true;
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_inno_phy_power_off(sd);
|
||||
rk628_hdmirx_controller_reset(bt1120->rk628);
|
||||
}
|
||||
|
||||
static void rk628_hdmirx_config_all(struct v4l2_subdev *sd)
|
||||
@@ -441,12 +351,18 @@ static void rk628_hdmirx_config_all(struct v4l2_subdev *sd)
|
||||
int ret;
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
rk628_hdmirx_controller_setup(bt1120->rk628);
|
||||
ret = rk628_hdmirx_phy_setup(sd);
|
||||
if (ret >= 0) {
|
||||
if (ret >= 0 && !rk628_hdmirx_scdc_ced_err(bt1120->rk628)) {
|
||||
rk628_bt1120_format_change(sd);
|
||||
bt1120->nosignal = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret < 0 || rk628_hdmirx_scdc_ced_err(bt1120->rk628)) {
|
||||
rk628_hdmirx_plugout(sd);
|
||||
schedule_delayed_work(&bt1120->delayed_work_enable_hotplug,
|
||||
msecs_to_jiffies(800));
|
||||
}
|
||||
}
|
||||
|
||||
static void rk628_hdmirx_reset_regfile(struct v4l2_subdev *sd)
|
||||
@@ -489,6 +405,7 @@ static void rk628_bt1120_delayed_work_enable_hotplug(struct work_struct *work)
|
||||
bool plugin;
|
||||
|
||||
mutex_lock(&bt1120->confctl_mutex);
|
||||
rk628_set_bg_enable(bt1120->rk628, false);
|
||||
bt1120->avi_rcv_rdy = false;
|
||||
plugin = tx_5v_power_present(sd);
|
||||
v4l2_ctrl_s_ctrl(bt1120->detect_tx_5v_ctrl, plugin);
|
||||
@@ -498,20 +415,15 @@ static void rk628_bt1120_delayed_work_enable_hotplug(struct work_struct *work)
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
rk628_hdmirx_audio_setup(bt1120->audio_info);
|
||||
rk628_hdmirx_set_hdcp(bt1120->rk628, &bt1120->hdcp, bt1120->enable_hdcp);
|
||||
rk628_hdmirx_controller_setup(bt1120->rk628);
|
||||
rk628_hdmirx_hpd_ctrl(sd, true);
|
||||
rk628_hdmirx_config_all(sd);
|
||||
rk628_bt1120_enable_interrupts(sd, true);
|
||||
rk628_i2c_update_bits(bt1120->rk628, GRF_SYSTEM_CON0,
|
||||
SW_I2S_DATA_OEN_MASK, SW_I2S_DATA_OEN(0));
|
||||
} else {
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
enable_stream(sd, false);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_phy_power_off(sd);
|
||||
rk628_hdmirx_controller_reset(sd);
|
||||
bt1120->nosignal = true;
|
||||
rk628_hdmirx_plugout(sd);
|
||||
rk628_set_io_func_to_gpio(bt1120->rk628);
|
||||
}
|
||||
mutex_unlock(&bt1120->confctl_mutex);
|
||||
@@ -525,6 +437,9 @@ static int rk628_check_resulotion_change(struct v4l2_subdev *sd)
|
||||
u32 old_htotal, old_vtotal;
|
||||
struct v4l2_bt_timings *bt = &bt1120->src_timings.bt;
|
||||
|
||||
if (bt1120->rk628->version >= RK628F_VERSION)
|
||||
return 1;
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HT1, &val);
|
||||
htotal = (val >> 16) & 0xffff;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VTL, &val);
|
||||
@@ -551,6 +466,8 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
|
||||
bool plugin;
|
||||
|
||||
mutex_lock(&bt1120->confctl_mutex);
|
||||
enable_stream(sd, false);
|
||||
bt1120->nosignal = true;
|
||||
bt1120->avi_rcv_rdy = false;
|
||||
plugin = tx_5v_power_present(sd);
|
||||
v4l2_dbg(1, debug, sd, "%s: 5v_det:%d\n", __func__, plugin);
|
||||
@@ -558,18 +475,28 @@ static void rk628_delayed_work_res_change(struct work_struct *work)
|
||||
if (rk628_check_resulotion_change(sd)) {
|
||||
v4l2_dbg(1, debug, sd, "res change, recfg ctrler and phy!\n");
|
||||
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
enable_stream(sd, false);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_phy_power_off(sd);
|
||||
rk628_hdmirx_controller_reset(sd);
|
||||
bt1120->nosignal = true;
|
||||
rk628_hdmirx_reset_regfile(sd);
|
||||
if (bt1120->rk628->version >= RK628F_VERSION) {
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_inno_phy_power_off(sd);
|
||||
rk628_hdmirx_controller_reset(bt1120->rk628);
|
||||
schedule_delayed_work(&bt1120->delayed_work_enable_hotplug,
|
||||
msecs_to_jiffies(800));
|
||||
} else {
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
enable_stream(sd, false);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_hdmirx_controller_setup(bt1120->rk628);
|
||||
rk628_hdmirx_hpd_ctrl(sd, false);
|
||||
rk628_hdmirx_inno_phy_power_off(sd);
|
||||
rk628_hdmirx_controller_reset(bt1120->rk628);
|
||||
bt1120->nosignal = true;
|
||||
rk628_hdmirx_reset_regfile(sd);
|
||||
}
|
||||
} else {
|
||||
rk628_bt1120_format_change(sd);
|
||||
bt1120->nosignal = false;
|
||||
rk628_bt1120_enable_interrupts(sd, true);
|
||||
}
|
||||
}
|
||||
@@ -661,7 +588,7 @@ static void enable_bt1120tx(struct v4l2_subdev *sd)
|
||||
/* rgb data: cfg SW_R2Y_EN */
|
||||
rk628_i2c_write(bt1120->rk628, GRF_CSC_CTRL_CON,
|
||||
SW_YUV2VYU_SWP(0) |
|
||||
SW_R2Y_EN(1));
|
||||
SW_R2Y_EN(1) | SW_R2Y_CSC_MODE(2));
|
||||
}
|
||||
|
||||
/* if avi packet is not stable, reset ctrl*/
|
||||
@@ -672,9 +599,19 @@ static void enable_bt1120tx(struct v4l2_subdev *sd)
|
||||
static void enable_stream(struct v4l2_subdev *sd, bool en)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
u32 val;
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, en ? "en" : "dis");
|
||||
if (en) {
|
||||
if (bt1120->rk628->version >= RK628F_VERSION) {
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_SCDC_REGS2, &val);
|
||||
if (rk628_hdmirx_scdc_ced_err(bt1120->rk628)) {
|
||||
rk628_hdmirx_plugout(sd);
|
||||
schedule_delayed_work(&bt1120->delayed_work_enable_hotplug,
|
||||
msecs_to_jiffies(800));
|
||||
return;
|
||||
}
|
||||
}
|
||||
rk628_hdmirx_vid_enable(sd, true);
|
||||
enable_bt1120tx(sd);
|
||||
} else {
|
||||
@@ -724,7 +661,7 @@ static void rk628_post_process_setup(struct v4l2_subdev *sd)
|
||||
dst_bt->pixelclock = dst_pclk;
|
||||
}
|
||||
|
||||
static int rk628_hdmirx_phy_power_on(struct v4l2_subdev *sd)
|
||||
static int rk628_hdmirx_inno_phy_power_on(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
int ret, f;
|
||||
@@ -765,10 +702,13 @@ static int rk628_hdmirx_phy_power_on(struct v4l2_subdev *sd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk628_hdmirx_phy_power_off(struct v4l2_subdev *sd)
|
||||
static int rk628_hdmirx_inno_phy_power_off(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
if (bt1120->rk628->version >= RK628F_VERSION)
|
||||
return 0;
|
||||
|
||||
if (bt1120->rxphy_pwron) {
|
||||
v4l2_dbg(1, debug, sd, "rxphy power off!\n");
|
||||
rk628_rxphy_power_off(bt1120->rk628);
|
||||
@@ -797,24 +737,14 @@ static void rk628_hdmirx_vid_enable(struct v4l2_subdev *sd, bool en)
|
||||
}
|
||||
}
|
||||
|
||||
static void rk628_hdmirx_controller_reset(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
rk628_control_assert(bt1120->rk628, RGU_HDMIRX_PON);
|
||||
udelay(10);
|
||||
rk628_control_deassert(bt1120->rk628, RGU_HDMIRX_PON);
|
||||
udelay(10);
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_DMI_SW_RST, 0x000101ff);
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_DMI_DISABLE_IF, 0x00000000);
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_DMI_DISABLE_IF, 0x0000017f);
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_DMI_DISABLE_IF, 0x0001017f);
|
||||
}
|
||||
|
||||
static bool rk628_rcv_supported_res(struct v4l2_subdev *sd, u32 width,
|
||||
u32 height)
|
||||
{
|
||||
u32 i;
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
if (bt1120->rk628->version >= RK628F_VERSION)
|
||||
return true;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
if ((supported_modes[i].width == width) &&
|
||||
@@ -836,10 +766,13 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd)
|
||||
u32 i, cnt, val;
|
||||
u32 width, height, frame_width, frame_height, status;
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < RXPHY_CFG_MAX_TIMES; i++) {
|
||||
ret = rk628_hdmirx_phy_power_on(sd);
|
||||
if (bt1120->rk628->version < RK628F_VERSION)
|
||||
ret = rk628_hdmirx_inno_phy_power_on(sd);
|
||||
else
|
||||
rk628_hdmirx_verisyno_phy_power_on(bt1120->rk628);
|
||||
if (ret < 0) {
|
||||
msleep(50);
|
||||
continue;
|
||||
@@ -847,6 +780,7 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd)
|
||||
cnt = 0;
|
||||
|
||||
do {
|
||||
msleep(20);
|
||||
cnt++;
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HACT_PX, &val);
|
||||
width = val & 0xffff;
|
||||
@@ -862,7 +796,7 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd)
|
||||
__func__, width, height, frame_width, frame_height, status, cnt);
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_PDEC_STS, &val);
|
||||
if (val & DVI_DET)
|
||||
if (bt1120->rk628->version < RK628F_VERSION && (val & DVI_DET))
|
||||
dev_info(bt1120->dev, "DVI mode detected\n");
|
||||
|
||||
if (!tx_5v_power_present(sd)) {
|
||||
@@ -872,15 +806,17 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd)
|
||||
|
||||
if (cnt >= 15)
|
||||
break;
|
||||
} while (((status & 0xfff) != 0xf00) ||
|
||||
} while (((status & 0xfff) < 0xf00) ||
|
||||
(!rk628_rcv_supported_res(sd, width, height)));
|
||||
|
||||
if (((status & 0xfff) != 0xf00) ||
|
||||
if (((status & 0xfff) < 0xf00) ||
|
||||
(!rk628_rcv_supported_res(sd, width, height))) {
|
||||
v4l2_err(sd, "%s hdmi rxphy lock failed, retry:%d\n",
|
||||
__func__, i);
|
||||
continue;
|
||||
} else {
|
||||
if (bt1120->rk628->version >= RK628F_VERSION)
|
||||
rk628_hdmirx_phy_prepclk_cfg(bt1120->rk628);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -906,7 +842,10 @@ static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd)
|
||||
/* I2SM0D0 */
|
||||
rk628_i2c_write(bt1120->rk628, GRF_GPIO0AB_SEL_CON, HIWORD_UPDATE(0x1, 5, 4));
|
||||
/* hdmirx int en */
|
||||
rk628_i2c_write(bt1120->rk628, GRF_INTR0_EN, 0x01000100);
|
||||
if (bt1120->rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(bt1120->rk628, GRF_INTR0_EN, 0x02000200);
|
||||
else
|
||||
rk628_i2c_write(bt1120->rk628, GRF_INTR0_EN, 0x01000100);
|
||||
|
||||
udelay(10);
|
||||
rk628_control_assert(bt1120->rk628, RGU_HDMIRX);
|
||||
@@ -930,7 +869,7 @@ static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd)
|
||||
SW_EFUSE_HDCP_EN(0) |
|
||||
SW_HSYNC_POL(1) |
|
||||
SW_VSYNC_POL(1));
|
||||
rk628_hdmirx_controller_reset(sd);
|
||||
rk628_hdmirx_controller_reset(bt1120->rk628);
|
||||
|
||||
def_edid.pad = 0;
|
||||
def_edid.start_block = 0;
|
||||
@@ -940,7 +879,7 @@ static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd)
|
||||
rk628_hdmirx_set_hdcp(bt1120->rk628, &bt1120->hdcp, false);
|
||||
|
||||
if (tx_5v_power_present(sd))
|
||||
schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, 1000);
|
||||
schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, 4000);
|
||||
}
|
||||
|
||||
static void rk628_bt1120_format_change(struct v4l2_subdev *sd)
|
||||
@@ -971,7 +910,7 @@ static void rk628_bt1120_enable_interrupts(struct v4l2_subdev *sd, bool en)
|
||||
u32 pdec_mask = 0, md_mask = 0;
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
pdec_mask |= AVI_RCV_ENSET;
|
||||
pdec_mask = AVI_RCV_ENSET | AVI_CKS_CHG_ICLR;
|
||||
md_mask = VACT_LIN_ENSET | HACT_PIX_ENSET | HS_CLK_ENSET |
|
||||
DE_ACTIVITY_ENSET | VS_ACT_ENSET | HS_ACT_ENSET;
|
||||
v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, en ? "en" : "dis");
|
||||
@@ -994,42 +933,56 @@ static void rk628_bt1120_enable_interrupts(struct v4l2_subdev *sd, bool en)
|
||||
v4l2_dbg(1, debug, sd, "%s MD_IEN:%#x, PDEC_IEN:%#x\n", __func__, md_ien, pdec_ien);
|
||||
}
|
||||
|
||||
static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
static void rk628_work_isr(struct work_struct *work)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = container_of(work, struct rk628_bt1120, work_isr);
|
||||
struct v4l2_subdev *sd = &bt1120->sd;
|
||||
u32 md_ints, pdec_ints, fifo_ints, hact, vact;
|
||||
bool plugin;
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
void *audio_info = bt1120->audio_info;
|
||||
bool handled = false;
|
||||
|
||||
if (handled == NULL) {
|
||||
v4l2_err(sd, "handled NULL, err return!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock(&bt1120->rk628->rst_lock);
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_ISTS, &md_ints);
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_PDEC_ISTS, &pdec_ints);
|
||||
if (rk628_audio_ctsnints_enabled(audio_info)) {
|
||||
if (pdec_ints & (ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR)) {
|
||||
rk628_csi_isr_ctsn(audio_info, pdec_ints);
|
||||
pdec_ints &= ~(ACR_CTS_CHG_ICLR | ACR_CTS_CHG_ICLR);
|
||||
*handled = true;
|
||||
}
|
||||
if (bt1120->rk628->version >= RK628F_VERSION &&
|
||||
(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS |
|
||||
HS_CLK_ISTS | DE_ACTIVITY_ISTS |
|
||||
VS_ACT_ISTS | HS_ACT_ISTS) ||
|
||||
pdec_ints & AVI_CKS_CHG_ISTS))
|
||||
rk628_set_bg_enable(bt1120->rk628, true);
|
||||
|
||||
plugin = tx_5v_power_present(sd);
|
||||
if (!plugin) {
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
goto __clear_int;
|
||||
}
|
||||
if (rk628_audio_fifoints_enabled(audio_info)) {
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints);
|
||||
if (fifo_ints & 0x18) {
|
||||
rk628_csi_isr_fifoints(audio_info, fifo_ints);
|
||||
*handled = true;
|
||||
|
||||
if (bt1120->rk628->version < RK628F_VERSION) {
|
||||
if (rk628_audio_ctsnints_enabled(audio_info)) {
|
||||
if (pdec_ints & (ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR)) {
|
||||
rk628_csi_isr_ctsn(audio_info, pdec_ints);
|
||||
pdec_ints &= ~(ACR_CTS_CHG_ICLR | ACR_CTS_CHG_ICLR);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
if (rk628_audio_fifoints_enabled(audio_info)) {
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints);
|
||||
if (fifo_ints & 0x18) {
|
||||
rk628_csi_isr_fifoints(audio_info, fifo_ints);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bt1120->vid_ints_en) {
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_ISTS, &md_ints);
|
||||
plugin = tx_5v_power_present(sd);
|
||||
v4l2_dbg(1, debug, sd, "%s: md_ints: %#x, pdec_ints:%#x, plugin: %d\n",
|
||||
__func__, md_ints, pdec_ints, plugin);
|
||||
|
||||
if ((md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS |
|
||||
HS_CLK_ISTS | DE_ACTIVITY_ISTS |
|
||||
VS_ACT_ISTS | HS_ACT_ISTS))
|
||||
&& plugin) {
|
||||
VS_ACT_ISTS | HS_ACT_ISTS) ||
|
||||
pdec_ints & AVI_CKS_CHG_ISTS)) {
|
||||
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_HACT_PX, &hact);
|
||||
rk628_i2c_read(bt1120->rk628, HDMI_RX_MD_VAL, &vact);
|
||||
@@ -1037,13 +990,15 @@ static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
__func__, hact, vact);
|
||||
|
||||
rk628_bt1120_enable_interrupts(sd, false);
|
||||
enable_stream(sd, false);
|
||||
bt1120->nosignal = true;
|
||||
if (bt1120->rk628->version < RK628F_VERSION) {
|
||||
enable_stream(sd, false);
|
||||
bt1120->nosignal = true;
|
||||
}
|
||||
schedule_delayed_work(&bt1120->delayed_work_res_change, HZ / 2);
|
||||
|
||||
v4l2_dbg(1, debug, sd, "%s: hact/vact change, md_ints: %#x\n",
|
||||
__func__, (u32)(md_ints & (VACT_LIN_ISTS | HACT_PIX_ISTS)));
|
||||
*handled = true;
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if ((pdec_ints & AVI_RCV_ISTS) && plugin && !bt1120->avi_rcv_rdy) {
|
||||
@@ -1052,16 +1007,34 @@ static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
/* After get the AVI_RCV interrupt state, disable interrupt. */
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_IEN_CLR, AVI_RCV_ISTS);
|
||||
|
||||
*handled = true;
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
if (*handled != true)
|
||||
if (!handled)
|
||||
v4l2_dbg(1, debug, sd, "%s: unhandled interrupt!\n", __func__);
|
||||
|
||||
__clear_int:
|
||||
/* clear interrupts */
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_MD_ICLR, 0xffffffff);
|
||||
rk628_i2c_write(bt1120->rk628, HDMI_RX_PDEC_ICLR, 0xffffffff);
|
||||
rk628_i2c_write(bt1120->rk628, GRF_INTR0_CLR_EN, 0x01000100);
|
||||
if (bt1120->rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(bt1120->rk628, GRF_INTR0_CLR_EN, 0x02000200);
|
||||
else
|
||||
rk628_i2c_write(bt1120->rk628, GRF_INTR0_CLR_EN, 0x01000100);
|
||||
|
||||
mutex_unlock(&bt1120->rk628->rst_lock);
|
||||
}
|
||||
|
||||
static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
if (handled == NULL) {
|
||||
v4l2_err(sd, "handled NULL, err return!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
schedule_work(&bt1120->work_isr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1069,7 +1042,7 @@ static int rk628_bt1120_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
|
||||
static irqreturn_t rk628_bt1120_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = dev_id;
|
||||
bool handled = false;
|
||||
bool handled = true;
|
||||
|
||||
rk628_bt1120_isr(&bt1120->sd, 0, &handled);
|
||||
|
||||
@@ -1216,10 +1189,22 @@ static int rk628_bt1120_g_mbus_config(struct v4l2_subdev *sd,
|
||||
unsigned int pad,
|
||||
struct v4l2_mbus_config *cfg)
|
||||
{
|
||||
struct rk628_bt1120 *bt1120 = to_bt1120(sd);
|
||||
|
||||
cfg->type = V4L2_MBUS_BT656;
|
||||
#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
|
||||
cfg->bus.parallel.flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
|
||||
V4L2_MBUS_VSYNC_ACTIVE_HIGH |
|
||||
V4L2_MBUS_PCLK_SAMPLE_RISING;
|
||||
if (bt1120->dual_edge)
|
||||
cfg->bus.parallel.flags |= V4L2_MBUS_PCLK_SAMPLE_FALLING;
|
||||
#else
|
||||
cfg->flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |
|
||||
V4L2_MBUS_VSYNC_ACTIVE_HIGH |
|
||||
V4L2_MBUS_PCLK_SAMPLE_RISING;
|
||||
if (bt1120->dual_edge)
|
||||
cfg->flags |= V4L2_MBUS_PCLK_SAMPLE_FALLING;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1483,7 +1468,7 @@ static int rk628_bt1120_s_edid(struct v4l2_subdev *sd,
|
||||
bt1120->edid_blocks_written = edid->blocks;
|
||||
udelay(100);
|
||||
|
||||
if (tx_5v_power_present(sd))
|
||||
if (tx_5v_power_present(sd) && bt1120->rk628->version < RK628F_VERSION)
|
||||
rk628_hdmirx_hpd_ctrl(sd, true);
|
||||
|
||||
return 0;
|
||||
@@ -1857,6 +1842,8 @@ static int rk628_bt1120_probe(struct i2c_client *client,
|
||||
|
||||
rk628_cru_initialize(rk628);
|
||||
|
||||
rk628_version_parse(rk628);
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
|
||||
v4l2_i2c_subdev_init(sd, client, &rk628_bt1120_ops);
|
||||
sd->internal_ops = &bt1120_subdev_internal_ops;
|
||||
@@ -1931,6 +1918,7 @@ static int rk628_bt1120_probe(struct i2c_client *client,
|
||||
rk628_bt1120_delayed_work_enable_hotplug);
|
||||
INIT_DELAYED_WORK(&bt1120->delayed_work_res_change,
|
||||
rk628_delayed_work_res_change);
|
||||
INIT_WORK(&bt1120->work_isr, rk628_work_isr);
|
||||
bt1120->audio_info = rk628_hdmirx_audioinfo_alloc(dev,
|
||||
&bt1120->confctl_mutex,
|
||||
rk628,
|
||||
@@ -1995,6 +1983,7 @@ err_work_queues:
|
||||
flush_work(&bt1120->work_i2c_poll);
|
||||
cancel_delayed_work(&bt1120->delayed_work_enable_hotplug);
|
||||
cancel_delayed_work(&bt1120->delayed_work_res_change);
|
||||
cancel_work_sync(&bt1120->work_isr);
|
||||
rk628_hdmirx_audio_destroy(bt1120->audio_info);
|
||||
err_hdl:
|
||||
mutex_destroy(&bt1120->confctl_mutex);
|
||||
@@ -2013,6 +2002,7 @@ static void rk628_bt1120_remove(struct i2c_client *client)
|
||||
}
|
||||
cancel_delayed_work_sync(&bt1120->delayed_work_enable_hotplug);
|
||||
cancel_delayed_work_sync(&bt1120->delayed_work_res_change);
|
||||
cancel_work_sync(&bt1120->work_isr);
|
||||
rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true);
|
||||
rk628_hdmirx_audio_cancel_work_rate_change(bt1120->audio_info, true);
|
||||
|
||||
|
||||
@@ -49,8 +49,11 @@ static void rk628_combtxphy_dsi_power_on(struct rk628 *rk628)
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON0, SW_PD_PLL, 0);
|
||||
usleep_range(100, 200);
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON9, SW_DSI_FSET_EN_MASK |
|
||||
SW_DSI_RCAL_EN_MASK, SW_DSI_FSET_EN |
|
||||
SW_DSI_RCAL_EN);
|
||||
SW_DSI_RCAL_EN_MASK | SW_LPTX_SR_TRIM_MASK, SW_DSI_FSET_EN |
|
||||
SW_DSI_RCAL_EN | SW_LPTX_SR_TRIM(7));
|
||||
if (rk628->tx_mode && rk628->dual_mipi)
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON6, SW_PLL_CTRL0_MASK, SW_PLL_CTRL0(1));
|
||||
|
||||
usleep_range(100, 200);
|
||||
}
|
||||
|
||||
@@ -111,7 +114,7 @@ void rk628_txphy_set_mode(struct rk628 *rk628, enum phy_mode mode)
|
||||
unsigned int flags = bus_width & 0xff;
|
||||
|
||||
fhsc = fin * (fhsc / fin);
|
||||
if (fhsc < 80 || fhsc > 1500)
|
||||
if (fhsc < 80 || fhsc > 1800)
|
||||
return;
|
||||
else if (fhsc < 375)
|
||||
txphy->rate_div = 4;
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#define SW_PLL_FB_DIV(x) UPDATE(x, 14, 10)
|
||||
#define SW_PLL_FRAC_DIV(x) UPDATE(x, 9, 0)
|
||||
#define COMBTXPHY_CON6 COMBTXPHY_REG(0x0018)
|
||||
#define SW_PLL_CTRL0_MASK GENMASK(2, 0)
|
||||
#define SW_PLL_CTRL0(x) UPDATE(x, 2, 0)
|
||||
#define COMBTXPHY_CON7 COMBTXPHY_REG(0x001c)
|
||||
#define SW_TX_RTERM_MASK GENMASK(22, 20)
|
||||
#define SW_TX_RTERM(x) UPDATE(x, 22, 20)
|
||||
@@ -52,6 +54,14 @@
|
||||
#define SW_TX_CTL_CON4(x) UPDATE(x, 9, 8)
|
||||
#define COMBTXPHY_CON8 COMBTXPHY_REG(0x0020)
|
||||
#define COMBTXPHY_CON9 COMBTXPHY_REG(0x0024)
|
||||
#define SW_HSTX_AMP_TRIM_MASK GENMASK(2, 0)
|
||||
#define SW_HSTX_AMP_TRIM(x) UPDATE(x, 2, 0)
|
||||
#define SW_LPTX_SR_TRIM_MASK GENMASK(6, 4)
|
||||
#define SW_LPTX_SR_TRIM(x) UPDATE(x, 6, 4)
|
||||
#define SW_DSI_RCAL_CTRL_MASK GENMASK(23, 16)
|
||||
#define SW_DSI_RCAL_CTRL(x) UPDATE(x, 23, 16)
|
||||
#define SW_DSI_RCAL_TRIM_MASK GENMASK(27, 24)
|
||||
#define SW_DSI_RCAL_TRIM(x) UPDATE(x, 27, 24)
|
||||
#define SW_DSI_FSET_EN_MASK BIT(29)
|
||||
#define SW_DSI_FSET_EN BIT(29)
|
||||
#define SW_DSI_RCAL_EN_MASK BIT(28)
|
||||
|
||||
@@ -66,6 +66,9 @@ static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628,
|
||||
u64 foutvco, foutpostdiv;
|
||||
u32 offset, val;
|
||||
|
||||
if (id == CGU_CLK_APLL && rk628->version == RK628D_VERSION)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_MODE_CON00, &val);
|
||||
if (id == CGU_CLK_CPLL) {
|
||||
val &= CLK_CPLL_MODE_MASK;
|
||||
@@ -74,15 +77,22 @@ static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628,
|
||||
return parent_rate;
|
||||
|
||||
offset = 0x00;
|
||||
} else {
|
||||
} else if (id == CGU_CLK_GPLL) {
|
||||
val &= CLK_GPLL_MODE_MASK;
|
||||
val >>= CLK_GPLL_MODE_SHIFT;
|
||||
if (val == CLK_GPLL_MODE_OSC)
|
||||
return parent_rate;
|
||||
|
||||
offset = 0x20;
|
||||
} else {
|
||||
val &= CLK_APLL_MODE_MASK;
|
||||
val >>= CLK_APLL_MODE_SHIFT;
|
||||
if (val == CLK_APLL_MODE_OSC)
|
||||
return parent_rate;
|
||||
offset = 0x40;
|
||||
}
|
||||
|
||||
|
||||
rk628_i2c_read(rk628, offset + CRU_CPLL_CON0, &con0);
|
||||
rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &con1);
|
||||
rk628_i2c_read(rk628, offset + CRU_CPLL_CON2, &con2);
|
||||
@@ -127,6 +137,9 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
u64 foutvco, foutpostdiv;
|
||||
u32 offset, val;
|
||||
|
||||
if (id == CGU_CLK_APLL && rk628->version == RK628D_VERSION)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* FREF : 10MHz ~ 800MHz
|
||||
* FREFDIV : 1MHz ~ 40MHz
|
||||
@@ -141,8 +154,10 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
|
||||
if (id == CGU_CLK_CPLL)
|
||||
offset = 0x00;
|
||||
else
|
||||
else if (id == CGU_CLK_GPLL)
|
||||
offset = 0x20;
|
||||
else
|
||||
offset = 0x40;
|
||||
|
||||
if (fin == fout) {
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON0, PLL_BYPASS(1));
|
||||
@@ -282,17 +297,24 @@ static unsigned long rk628_cru_clk_set_rate_sclk_vop(struct rk628 *rk628,
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_set_rate_sclk_hdmirx_aud(struct rk628 *rk628,
|
||||
unsigned long rate)
|
||||
unsigned long rate)
|
||||
{
|
||||
u64 parent_rate;
|
||||
u8 div;
|
||||
|
||||
parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_GPLL, rate*4);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_APLL, rate*4);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_GPLL, rate*4);
|
||||
div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate);
|
||||
do_div(parent_rate, div);
|
||||
rate = parent_rate;
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON05, 0x3fc0 << 16 | ((div - 1) << 6) |
|
||||
CLK_HDMIRX_AUD_SEL << 16 | CLK_HDMIRX_AUD_SEL);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON05, CLK_HDMIRX_AUD_DIV(div - 1) |
|
||||
CLK_HDMIRX_AUD_SEL_V2(2));
|
||||
else
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON05, CLK_HDMIRX_AUD_DIV(div - 1) |
|
||||
CLK_HDMIRX_AUD_SEL_V1(1));
|
||||
return rate;
|
||||
}
|
||||
|
||||
@@ -304,11 +326,17 @@ static unsigned long rk628_cru_clk_get_rate_sclk_hdmirx_aud(struct rk628 *rk628)
|
||||
u32 val;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val);
|
||||
if (val & CLK_HDMIRX_AUD_SEL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
div = ((val & CLK_HDMIRX_AUD_DIV_MASK) >> 6) + 1;
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V2) >> 14;
|
||||
else
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V1) >> 15;
|
||||
if (!val)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
div = ((val&0x3fc0) >> 6) + 1;
|
||||
else if (val == 2)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_APLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
do_div(parent_rate, div);
|
||||
rate = parent_rate;
|
||||
return rate;
|
||||
@@ -424,7 +452,11 @@ EXPORT_SYMBOL(rk628_clk_mux_testout);
|
||||
int rk628_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
unsigned long rate)
|
||||
{
|
||||
if (id == CGU_CLK_APLL && rk628->version == RK628D_VERSION)
|
||||
return -EINVAL;
|
||||
|
||||
switch (id) {
|
||||
case CGU_CLK_APLL:
|
||||
case CGU_CLK_CPLL:
|
||||
case CGU_CLK_GPLL:
|
||||
rk628_cru_clk_set_rate_pll(rk628, id, rate);
|
||||
@@ -442,7 +474,7 @@ int rk628_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
rk628_cru_clk_set_rate_sclk_hdmirx_aud(rk628, rate);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -453,7 +485,11 @@ unsigned long rk628_clk_get_rate(struct rk628 *rk628, unsigned int id)
|
||||
{
|
||||
unsigned long rate;
|
||||
|
||||
if (id == CGU_CLK_APLL && rk628->version == RK628D_VERSION)
|
||||
return 0;
|
||||
|
||||
switch (id) {
|
||||
case CGU_CLK_APLL:
|
||||
case CGU_CLK_CPLL:
|
||||
case CGU_CLK_GPLL:
|
||||
rate = rk628_cru_clk_get_rate_pll(rk628, id);
|
||||
@@ -519,6 +555,7 @@ static const struct rk628_rgu_data rk628_rgu_data[] = {
|
||||
RSTGEN(RGU_HDMIRX_PON, CRU_SOFTRST_CON02, 12),
|
||||
RSTGEN(RGU_TXBYTEHS, CRU_SOFTRST_CON02, 13),
|
||||
RSTGEN(RGU_TXESC, CRU_SOFTRST_CON02, 14),
|
||||
RSTGEN(RGU_CSI1, CRU_SOFTRST_CON02, 15),
|
||||
};
|
||||
|
||||
static int rk628_rgu_update(struct rk628 *rk628, unsigned long id, int assert)
|
||||
|
||||
@@ -46,7 +46,16 @@
|
||||
#define CRU_GPLL_CON2 CRU_REG(0x0028)
|
||||
#define CRU_GPLL_CON3 CRU_REG(0x002c)
|
||||
#define CRU_GPLL_CON4 CRU_REG(0x0030)
|
||||
#define CRU_APLL_CON0 CRU_REG(0x0040)
|
||||
#define CRU_APLL_CON1 CRU_REG(0x0044)
|
||||
#define CRU_APLL_CON2 CRU_REG(0x0048)
|
||||
#define CRU_APLL_CON3 CRU_REG(0x004c)
|
||||
#define CRU_APLL_CON4 CRU_REG(0x0050)
|
||||
#define CRU_MODE_CON00 CRU_REG(0x0060)
|
||||
#define CLK_APLL_MODE_MASK BIT(4)
|
||||
#define CLK_APLL_MODE_SHIFT 4
|
||||
#define CLK_APLL_MODE_APLL 1
|
||||
#define CLK_APLL_MODE_OSC 0
|
||||
#define CLK_GPLL_MODE_MASK BIT(2)
|
||||
#define CLK_GPLL_MODE_SHIFT 2
|
||||
#define CLK_GPLL_MODE_GPLL 1
|
||||
@@ -69,7 +78,12 @@
|
||||
#define CRU_CLKSEL_CON03 CRU_REG(0x008c)
|
||||
#define CRU_CLKSEL_CON04 CRU_REG(0x0090)
|
||||
#define CRU_CLKSEL_CON05 CRU_REG(0x0094)
|
||||
#define CLK_HDMIRX_AUD_SEL BIT(15)
|
||||
#define CLK_HDMIRX_AUD_DIV_MASK GENMASK(13, 6)
|
||||
#define CLK_HDMIRX_AUD_DIV(x) HIWORD_UPDATE(x, 13, 6)
|
||||
#define CLK_HDMIRX_AUD_SEL_V1(x) HIWORD_UPDATE(x, 15, 15)
|
||||
#define CLK_HDMIRX_AUD_SEL_MASK_V1 GENMASK(15, 15)
|
||||
#define CLK_HDMIRX_AUD_SEL_V2(x) HIWORD_UPDATE(x, 15, 14)
|
||||
#define CLK_HDMIRX_AUD_SEL_MASK_V2 GENMASK(15, 14)
|
||||
#define CRU_CLKSEL_CON06 CRU_REG(0x0098)
|
||||
#define SCLK_UART_SEL(x) HIWORD_UPDATE(x, 15, 14)
|
||||
#define SCLK_UART_SEL_MASK GENMASK(15, 14)
|
||||
@@ -146,6 +160,7 @@
|
||||
#define CGU_I2S_MCLKOUT 36
|
||||
#define CGU_BT1120DEC 37
|
||||
#define CGU_SCLK_UART 38
|
||||
#define CGU_CLK_APLL 39
|
||||
|
||||
#define RGU_LOGIC 0
|
||||
#define RGU_CRU 1
|
||||
@@ -178,6 +193,7 @@
|
||||
#define RGU_HDMIRX_PON 28
|
||||
#define RGU_TXBYTEHS 29
|
||||
#define RGU_TXESC 30
|
||||
#define RGU_CSI1 31
|
||||
|
||||
unsigned long rk628_clk_get_rate(struct rk628 *rk628, unsigned int id);
|
||||
int rk628_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#define VOP_YU_SWAP(x) UPDATE(x, 14, 14)
|
||||
#define VOP_UV_SWAP_MASK BIT(13)
|
||||
#define VOP_UV_SWAP(x) UPDATE(x, 13, 13)
|
||||
#define VOP_YUV422_MODE_MASK GENMASK(11, 10)
|
||||
#define VOP_YUV422_MODE(x) UPDATE(x, 11, 10)
|
||||
#define VOP_YUV422_EN_MASK BIT(12)
|
||||
#define VOP_YUV422_EN(x) UPDATE(x, 12, 12)
|
||||
#define VOP_P2_EN_MASK BIT(8)
|
||||
@@ -58,6 +60,11 @@
|
||||
#define VOP_DT_USERDEFINE_EN(x) UPDATE(x, 1, 1)
|
||||
#define VOP_PATH_EN_MASK BIT(0)
|
||||
#define VOP_PATH_EN(x) UPDATE(x, 0, 0)
|
||||
#define CSITX_VOP_FILTER_CTRL (CSITX_BASE + 0x0044)
|
||||
#define VOP_FILTER_EN_MASK BIT(0)
|
||||
#define VOP_FILTER_EN(x) UPDATE(x, 0, 0)
|
||||
#define VOP_FILTER_MASK GENMASK(15, 8)
|
||||
#define VOP_FILTER(x) UPDATE(x, 15, 8)
|
||||
#define CSITX_VOP_PATH_PKT_CTRL (CSITX_BASE + 0x0050)
|
||||
#define CSITX_CSITX_STATUS0 (CSITX_BASE + 0x0070)
|
||||
#define CSITX_CSITX_STATUS1 (CSITX_BASE + 0x0074)
|
||||
@@ -77,5 +84,27 @@
|
||||
#define CSI_DPHY_EN(x) UPDATE(x, 7, 3)
|
||||
#define DPHY_ENABLECLK BIT(3)
|
||||
#define CSI_MAX_REGISTER CSITX_DPHY_CTRL
|
||||
//for rk628f csi1
|
||||
#define CSITX1_BASE 0x00140000
|
||||
#define CSITX1_CONFIG_DONE (CSITX1_BASE + 0x0000)
|
||||
#define CSITX1_CSITX_EN (CSITX1_BASE + 0x0004)
|
||||
#define CSITX1_CSITX_VERSION (CSITX1_BASE + 0x0008)
|
||||
#define CSITX1_SYS_CTRL0_IMD (CSITX1_BASE + 0x0010)
|
||||
#define CSITX1_SYS_CTRL1 (CSITX1_BASE + 0x0014)
|
||||
#define CSITX1_SYS_CTRL2 (CSITX1_BASE + 0x0018)
|
||||
#define CSITX1_SYS_CTRL3_IMD (CSITX1_BASE + 0x001c)
|
||||
#define CSITX1_TIMING_HPW_PADDING_NUM (CSITX1_BASE + 0x0030)
|
||||
#define CSITX1_VOP_PATH_CTRL (CSITX1_BASE + 0x0040)
|
||||
#define CSITX1_VOP_FILTER_CTRL (CSITX1_BASE + 0x0044)
|
||||
#define CSITX1_VOP_PATH_PKT_CTRL (CSITX1_BASE + 0x0050)
|
||||
#define CSITX1_CSITX_STATUS0 (CSITX1_BASE + 0x0070)
|
||||
#define CSITX1_CSITX_STATUS1 (CSITX1_BASE + 0x0074)
|
||||
#define CSITX1_ERR_INTR_EN_IMD (CSITX1_BASE + 0x0090)
|
||||
#define CSITX1_ERR_INTR_CLR_IMD (CSITX1_BASE + 0x0094)
|
||||
#define CSITX1_ERR_INTR_STATUS_IMD (CSITX1_BASE + 0x0098)
|
||||
#define CSITX1_ERR_INTR_RAW_STATUS_IMD (CSITX1_BASE + 0x009c)
|
||||
#define CSITX1_LPDT_DATA_IMD (CSITX1_BASE + 0x00a8)
|
||||
#define CSITX1_DPHY_CTRL (CSITX1_BASE + 0x00b0)
|
||||
#define CSI1_MAX_REGISTER CSITX1_DPHY_CTRL
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -58,7 +58,7 @@ static inline int dsi_update_bits(struct rk628 *rk628, int id,
|
||||
return rk628_i2c_update_bits(rk628, dsi_base + reg, mask, val);
|
||||
}
|
||||
|
||||
static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi)
|
||||
static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi, uint8_t mipi_id)
|
||||
{
|
||||
int dev_id;
|
||||
unsigned int dsi_base;
|
||||
@@ -66,29 +66,38 @@ static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi)
|
||||
int ret;
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
|
||||
dev_id = RK628_DEV_DSI0;
|
||||
dsi_base = DSI0_BASE;
|
||||
dev_id = mipi_id ? RK628_DEV_DSI1 : RK628_DEV_DSI0;
|
||||
dsi_base = mipi_id ? DSI1_BASE : DSI0_BASE;
|
||||
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_ENABLECLK, 0);
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_SHUTDOWNZ, 0);
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_RSTZ, 0);
|
||||
testif_testclr_assert(dsi->rk628);
|
||||
dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, PHY_ENABLECLK, 0);
|
||||
dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, PHY_SHUTDOWNZ, 0);
|
||||
dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, PHY_RSTZ, 0);
|
||||
rk628_testif_testclr_assert(dsi->rk628, mipi_id);
|
||||
|
||||
/* Set all REQUEST inputs to zero */
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
FORCERXMODE_MASK | FORCETXSTOPMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
if (mipi_id)
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX1_CON,
|
||||
FORCERXMODE_MASK | FORCETXSTOPMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
else
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
FORCERXMODE_MASK | FORCETXSTOPMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
udelay(1);
|
||||
|
||||
testif_testclr_deassert(dsi->rk628);
|
||||
rk628_testif_testclr_deassert(dsi->rk628, mipi_id);
|
||||
rk628_mipi_dphy_init_hsfreqrange(dsi->rk628, dsi->lane_mbps, mipi_id);
|
||||
|
||||
mipi_dphy_init_hsfreqrange(dsi->rk628, dsi->lane_mbps);
|
||||
if (dsi->lane_mbps > 1100)
|
||||
rk628_mipi_dphy_init_hsmanual(dsi->rk628, true, mipi_id);
|
||||
else
|
||||
rk628_mipi_dphy_init_hsmanual(dsi->rk628, false, mipi_id);
|
||||
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ,
|
||||
dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ,
|
||||
PHY_ENABLECLK, PHY_ENABLECLK);
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ,
|
||||
dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ,
|
||||
PHY_SHUTDOWNZ, PHY_SHUTDOWNZ);
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_RSTZ, PHY_RSTZ);
|
||||
dsi_update_bits(rk628, mipi_id, DSI_PHY_RSTZ, PHY_RSTZ, PHY_RSTZ);
|
||||
usleep_range(1500, 2000);
|
||||
|
||||
rk628_txphy_power_on(rk628);
|
||||
@@ -112,42 +121,42 @@ static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void rk628_dsi_pre_enable(struct rk628_dsi *dsi)
|
||||
static void rk628_dsi_pre_enable(struct rk628_dsi *dsi, uint8_t mipi_id)
|
||||
{
|
||||
u32 val;
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
u32 lane_mbps = dsi->lane_mbps;
|
||||
|
||||
dsi_write(rk628, 0, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, 0, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
dsi_write(rk628, mipi_id, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, mipi_id, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
|
||||
val = DIV_ROUND_UP(lane_mbps >> 3, 20);
|
||||
dsi_write(rk628, 0, DSI_CLKMGR_CFG,
|
||||
dsi_write(rk628, mipi_id, DSI_CLKMGR_CFG,
|
||||
TO_CLK_DIVISION(10) | TX_ESC_CLK_DIVISION(val));
|
||||
|
||||
val = CRC_RX_EN | ECC_RX_EN | BTA_EN | EOTP_TX_EN;
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET)
|
||||
val &= ~EOTP_TX_EN;
|
||||
|
||||
dsi_write(rk628, 0, DSI_PCKHDL_CFG, val);
|
||||
dsi_write(rk628, mipi_id, DSI_PCKHDL_CFG, val);
|
||||
|
||||
dsi_write(rk628, 0, DSI_TO_CNT_CFG,
|
||||
dsi_write(rk628, mipi_id, DSI_TO_CNT_CFG,
|
||||
HSTX_TO_CNT(1000) | LPRX_TO_CNT(1000));
|
||||
dsi_write(rk628, 0, DSI_BTA_TO_CNT, 0xd00);
|
||||
dsi_write(rk628, 0, DSI_PHY_TMR_CFG,
|
||||
dsi_write(rk628, mipi_id, DSI_BTA_TO_CNT, 0xd00);
|
||||
dsi_write(rk628, mipi_id, DSI_PHY_TMR_CFG,
|
||||
PHY_HS2LP_TIME(0x14) | PHY_LP2HS_TIME(0x10) |
|
||||
MAX_RD_TIME(10000));
|
||||
dsi_write(rk628, 0, DSI_PHY_TMR_LPCLK_CFG,
|
||||
dsi_write(rk628, mipi_id, DSI_PHY_TMR_LPCLK_CFG,
|
||||
PHY_CLKHS2LP_TIME(0x40) | PHY_CLKLP2HS_TIME(0x40));
|
||||
dsi_write(rk628, 0, DSI_PHY_IF_CFG,
|
||||
dsi_write(rk628, mipi_id, DSI_PHY_IF_CFG,
|
||||
PHY_STOP_WAIT_TIME(0x20) | N_LANES(4 - 1));
|
||||
|
||||
mipi_dphy_power_on_dsi(dsi);
|
||||
mipi_dphy_power_on_dsi(dsi, mipi_id);
|
||||
|
||||
dsi_write(rk628, 0, DSI_PWR_UP, POWER_UP);
|
||||
dsi_write(rk628, mipi_id, DSI_PWR_UP, POWER_UP);
|
||||
}
|
||||
|
||||
static void rk628_dsi_set_vid_mode(struct rk628_dsi *dsi)
|
||||
static void rk628_dsi_set_vid_mode(struct rk628_dsi *dsi, uint8_t mipi_id)
|
||||
{
|
||||
unsigned int lanebyteclk = (dsi->lane_mbps * 1000L) >> 3;
|
||||
u64 dpipclk;
|
||||
@@ -176,16 +185,16 @@ static void rk628_dsi_set_vid_mode(struct rk628_dsi *dsi)
|
||||
else
|
||||
val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS;
|
||||
|
||||
dsi_write(rk628, 0, DSI_VID_MODE_CFG, val);
|
||||
dsi_write(rk628, mipi_id, DSI_VID_MODE_CFG, val);
|
||||
|
||||
if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
|
||||
dsi_update_bits(rk628, 0, DSI_LPCLK_CTRL,
|
||||
dsi_update_bits(rk628, mipi_id, DSI_LPCLK_CTRL,
|
||||
AUTO_CLKLANE_CTRL, AUTO_CLKLANE_CTRL);
|
||||
|
||||
|
||||
pkt_size = VID_PKT_SIZE(bt->width);
|
||||
pkt_size = rk628->dual_mipi ? VID_PKT_SIZE(bt->width) / 2 : VID_PKT_SIZE(bt->width);
|
||||
|
||||
dsi_write(rk628, 0, DSI_VID_PKT_SIZE, pkt_size);
|
||||
dsi_write(rk628, mipi_id, DSI_VID_PKT_SIZE, pkt_size);
|
||||
|
||||
vactive = bt->height;
|
||||
vs = bt->vsync;
|
||||
@@ -202,43 +211,47 @@ static void rk628_dsi_set_vid_mode(struct rk628_dsi *dsi)
|
||||
|
||||
//hline_time = hline * lanebyteclk / dpipclk;
|
||||
hline_time = DIV_ROUND_CLOSEST_ULL(hline * lanebyteclk, dpipclk);
|
||||
dsi_write(rk628, 0, DSI_VID_HLINE_TIME,
|
||||
dsi_write(rk628, mipi_id, DSI_VID_HLINE_TIME,
|
||||
VID_HLINE_TIME(hline_time));
|
||||
//hs_time = hs * lanebyteclk / dpipclk;
|
||||
hs_time = DIV_ROUND_CLOSEST_ULL(hs * lanebyteclk, dpipclk);
|
||||
dsi_write(rk628, 0, DSI_VID_HSA_TIME, VID_HSA_TIME(hs_time));
|
||||
dsi_write(rk628, mipi_id, DSI_VID_HSA_TIME, VID_HSA_TIME(hs_time));
|
||||
//hbp_time = hbp * lanebyteclk / dpipclk;
|
||||
hbp_time = DIV_ROUND_CLOSEST_ULL(hbp * lanebyteclk, dpipclk);
|
||||
dsi_write(rk628, 0, DSI_VID_HBP_TIME, VID_HBP_TIME(hbp_time));
|
||||
dsi_write(rk628, mipi_id, DSI_VID_HBP_TIME, VID_HBP_TIME(hbp_time));
|
||||
|
||||
dsi_write(rk628, 0, DSI_VID_VACTIVE_LINES, vactive);
|
||||
dsi_write(rk628, 0, DSI_VID_VSA_LINES, vs);
|
||||
dsi_write(rk628, 0, DSI_VID_VFP_LINES, vfp);
|
||||
dsi_write(rk628, 0, DSI_VID_VBP_LINES, vbp);
|
||||
dsi_write(rk628, mipi_id, DSI_VID_VACTIVE_LINES, vactive);
|
||||
dsi_write(rk628, mipi_id, DSI_VID_VSA_LINES, vs);
|
||||
dsi_write(rk628, mipi_id, DSI_VID_VFP_LINES, vfp);
|
||||
dsi_write(rk628, mipi_id, DSI_VID_VBP_LINES, vbp);
|
||||
|
||||
dsi_write(rk628, 0, DSI_MODE_CFG, CMD_VIDEO_MODE(VIDEO_MODE));
|
||||
dsi_write(rk628, mipi_id, DSI_MODE_CFG, CMD_VIDEO_MODE(VIDEO_MODE));
|
||||
}
|
||||
|
||||
static void rk628_dsi_set_cmd_mode(struct rk628_dsi *dsi)
|
||||
static void rk628_dsi_set_cmd_mode(struct rk628_dsi *dsi, uint8_t mipi_id)
|
||||
{
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
|
||||
dsi_update_bits(rk628, 0, DSI_CMD_MODE_CFG, DCS_LW_TX, 0);
|
||||
dsi_write(rk628, 0, DSI_EDPI_CMD_SIZE,
|
||||
EDPI_ALLOWED_CMD_SIZE(dsi->timings.bt.width));
|
||||
dsi_write(rk628, 0, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
dsi_update_bits(rk628, mipi_id, DSI_CMD_MODE_CFG, DCS_LW_TX, 0);
|
||||
if (rk628->dual_mipi)
|
||||
dsi_write(rk628, mipi_id, DSI_EDPI_CMD_SIZE,
|
||||
EDPI_ALLOWED_CMD_SIZE(dsi->timings.bt.width / 2));
|
||||
else
|
||||
dsi_write(rk628, mipi_id, DSI_EDPI_CMD_SIZE,
|
||||
EDPI_ALLOWED_CMD_SIZE(dsi->timings.bt.width));
|
||||
dsi_write(rk628, mipi_id, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
}
|
||||
|
||||
static void rk628_dsi_enable(struct rk628_dsi *dsi)
|
||||
static void rk628_dsi_enable(struct rk628_dsi *dsi, uint8_t mipi_id)
|
||||
{
|
||||
u32 val;
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
|
||||
dsi_write(rk628, 0, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, mipi_id, DSI_PWR_UP, RESET);
|
||||
|
||||
val = DPI_COLOR_CODING(5);
|
||||
|
||||
dsi_write(rk628, 0, DSI_DPI_COLOR_CODING, val);
|
||||
dsi_write(rk628, mipi_id, DSI_DPI_COLOR_CODING, val);
|
||||
|
||||
val = 0;
|
||||
|
||||
@@ -249,26 +262,27 @@ static void rk628_dsi_enable(struct rk628_dsi *dsi)
|
||||
* val |= HSYNC_ACTIVE_LOW;
|
||||
*/
|
||||
|
||||
dsi_write(rk628, 0, DSI_DPI_CFG_POL, val);
|
||||
dsi_write(rk628, mipi_id, DSI_DPI_CFG_POL, val);
|
||||
|
||||
dsi_write(rk628, 0, DSI_DPI_VCID, DPI_VID(0));
|
||||
dsi_write(rk628, 0, DSI_DPI_LP_CMD_TIM,
|
||||
dsi_write(rk628, mipi_id, DSI_DPI_VCID, DPI_VID(0));
|
||||
dsi_write(rk628, mipi_id, DSI_DPI_LP_CMD_TIM,
|
||||
OUTVACT_LPCMD_TIME(4) | INVACT_LPCMD_TIME(4));
|
||||
dsi_update_bits(rk628, 0, DSI_LPCLK_CTRL,
|
||||
PHY_TXREQUESTCLKHS | AUTO_CLKLANE_CTRL,
|
||||
PHY_TXREQUESTCLKHS | AUTO_CLKLANE_CTRL);
|
||||
dsi_update_bits(rk628, mipi_id, DSI_LPCLK_CTRL,
|
||||
PHY_TXREQUESTCLKHS,
|
||||
PHY_TXREQUESTCLKHS);
|
||||
if (dsi->vid_mode == VIDEO_MODE)
|
||||
rk628_dsi_set_vid_mode(dsi);
|
||||
rk628_dsi_set_vid_mode(dsi, mipi_id);
|
||||
else
|
||||
rk628_dsi_set_cmd_mode(dsi);
|
||||
rk628_dsi_set_cmd_mode(dsi, mipi_id);
|
||||
|
||||
dsi_write(rk628, 0, DSI_PWR_UP, POWER_UP);
|
||||
dsi_write(rk628, mipi_id, DSI_PWR_UP, POWER_UP);
|
||||
}
|
||||
|
||||
static u32 rk628_dsi_get_lane_rate(struct rk628_dsi *dsi)
|
||||
u32 rk628_dsi_get_lane_rate_mbps(struct rk628_dsi *dsi)
|
||||
{
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
u32 lane_rate;
|
||||
u32 max_lane_rate = 1500;
|
||||
u32 max_lane_rate = 1800;
|
||||
u8 bpp, lanes;
|
||||
u64 pixelclock = dsi->timings.bt.pixelclock;
|
||||
|
||||
@@ -278,33 +292,81 @@ static u32 rk628_dsi_get_lane_rate(struct rk628_dsi *dsi)
|
||||
lane_rate = pixelclock * bpp;
|
||||
lane_rate = div_u64(lane_rate, lanes);
|
||||
lane_rate = DIV_ROUND_UP(lane_rate * 5, 4);
|
||||
if (rk628->dual_mipi)
|
||||
lane_rate /= 2;
|
||||
|
||||
if (lane_rate > max_lane_rate)
|
||||
if (lane_rate > 1300)
|
||||
lane_rate = max_lane_rate;
|
||||
else if (lane_rate > 700 && lane_rate <= 1300)
|
||||
lane_rate = 1300;
|
||||
else
|
||||
lane_rate = 700;
|
||||
|
||||
return lane_rate;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_dsi_get_lane_rate_mbps);
|
||||
|
||||
void rk628_mipi_dsi_power_on(struct rk628_dsi *dsi)
|
||||
{
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
u32 rate = rk628_dsi_get_lane_rate(dsi);
|
||||
u32 rate = rk628_dsi_get_lane_rate_mbps(dsi);
|
||||
int bus_width;
|
||||
u32 mask = SW_OUTPUT_MODE_MASK;
|
||||
u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_DSI);
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_DSI));
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON, SW_SPLIT_EN, 0);
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
mask = SW_OUTPUT_COMBTX_MODE_MASK;
|
||||
val = SW_OUTPUT_COMBTX_MODE(OUTPUT_MODE_DSI - 2);
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON3,
|
||||
GRF_AS_DSIPHY_MASK,
|
||||
GRF_AS_DSIPHY(1));
|
||||
}
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
|
||||
dev_info(dsi->rk628->dev, "%s mipi mode, %sable dphy1 and split en\n",
|
||||
rk628->dual_mipi ? "dual" : "single", rk628->dual_mipi ? "en" : "dis");
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON3, GRF_DPHY_CH1_EN_MASK,
|
||||
rk628->dual_mipi ? GRF_DPHY_CH1_EN(1) : GRF_DPHY_CH1_EN(0));
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON, SW_SPLIT_EN,
|
||||
rk628->dual_mipi ? 1 : 0);
|
||||
|
||||
bus_width = rate << 8;
|
||||
bus_width |= COMBTXPHY_MODULEA_EN;
|
||||
if (rk628->dual_mipi)
|
||||
bus_width |= COMBTXPHY_MODULEB_EN;
|
||||
rk628_txphy_set_bus_width(dsi->rk628, bus_width);
|
||||
rk628_txphy_set_mode(dsi->rk628, PHY_MODE_VIDEO_MIPI);
|
||||
dsi->lane_mbps = rk628_txphy_get_bus_width(dsi->rk628);
|
||||
dev_dbg(dsi->rk628->dev, "%s mipi bitrate:%llu mbps\n", __func__,
|
||||
dev_info(dsi->rk628->dev, "%s mipi bitrate:%llu mbps\n", __func__,
|
||||
dsi->lane_mbps);
|
||||
|
||||
rk628_dsi_pre_enable(dsi);
|
||||
rk628_dsi_pre_enable(dsi, 0);
|
||||
if (rk628->dual_mipi)
|
||||
rk628_dsi_pre_enable(dsi, 1);
|
||||
|
||||
rk628_dsi_enable(dsi);
|
||||
rk628_dsi_enable(dsi, 0);
|
||||
if (rk628->dual_mipi)
|
||||
rk628_dsi_enable(dsi, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dsi_power_on);
|
||||
|
||||
void rk628_dsi_disable_stream(struct rk628_dsi *dsi)
|
||||
{
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
|
||||
dsi_write(rk628, 0, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, 0, DSI_LPCLK_CTRL, 0);
|
||||
dsi_write(rk628, 0, DSI_EDPI_CMD_SIZE, 0);
|
||||
dsi_write(rk628, 0, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
dsi_write(rk628, 0, DSI_PWR_UP, POWER_UP);
|
||||
|
||||
dsi_write(rk628, 1, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, 1, DSI_LPCLK_CTRL, 0);
|
||||
dsi_write(rk628, 1, DSI_EDPI_CMD_SIZE, 0);
|
||||
dsi_write(rk628, 1, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
dsi_write(rk628, 1, DSI_PWR_UP, POWER_UP);
|
||||
|
||||
rk628_txphy_power_off(rk628);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_dsi_disable_stream);
|
||||
|
||||
@@ -166,8 +166,11 @@ struct rk628_dsi {
|
||||
u64 lane_mbps;
|
||||
int vid_mode;
|
||||
int mode_flags;
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
void rk628_mipi_dsi_power_on(struct rk628_dsi *dsi);
|
||||
void rk628_dsi_disable_stream(struct rk628_dsi *dsi);
|
||||
u32 rk628_dsi_get_lane_rate_mbps(struct rk628_dsi *dsi);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,15 +18,6 @@
|
||||
|
||||
#define INIT_FIFO_STATE 64
|
||||
|
||||
#define is_validfs(x) (x == 32000 || \
|
||||
x == 44100 || \
|
||||
x == 48000 || \
|
||||
x == 88200 || \
|
||||
x == 96000 || \
|
||||
x == 176400 || \
|
||||
x == 192000 || \
|
||||
x == 768000)
|
||||
|
||||
struct rk628_audiostate {
|
||||
u32 hdmirx_aud_clkrate;
|
||||
u32 fs_audio;
|
||||
@@ -53,6 +44,25 @@ struct rk628_audioinfo {
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
struct hdmirx_tmdsclk_cnt {
|
||||
u32 tmds_cnt;
|
||||
u8 cnt;
|
||||
};
|
||||
|
||||
#define HDMIRX_GET_TMDSCLK_TIME 21
|
||||
|
||||
static int supported_fs[] = {
|
||||
32000,
|
||||
44100,
|
||||
48000,
|
||||
88200,
|
||||
96000,
|
||||
176400,
|
||||
192000,
|
||||
768000,
|
||||
-1
|
||||
};
|
||||
|
||||
static int hdcp_load_keys_cb(struct rk628 *rk628, struct rk628_hdcp *hdcp)
|
||||
{
|
||||
int size;
|
||||
@@ -168,11 +178,11 @@ EXPORT_SYMBOL(rk628_hdmirx_set_hdcp);
|
||||
|
||||
void rk628_hdmirx_controller_setup(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI20_CONTROL, 0x10000f10);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI20_CONTROL, 0x10000f11);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_MODE_RECOVER, 0x00000021);
|
||||
rk628_i2c_write(rk628, HDMI_RX_PDEC_CTRL, 0xbfff8011);
|
||||
rk628_i2c_write(rk628, HDMI_RX_PDEC_ASP_CTRL, 0x00000040);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_RESMPL_CTRL, 0x00000001);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_RESMPL_CTRL, 0x00000000);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_SYNC_CTRL, 0x00000014);
|
||||
rk628_i2c_write(rk628, HDMI_RX_PDEC_ERR_FILTER, 0x00000008);
|
||||
rk628_i2c_write(rk628, HDMI_RX_SCDC_I2CCONFIG, 0x01000000);
|
||||
@@ -181,7 +191,7 @@ void rk628_hdmirx_controller_setup(struct rk628 *rk628)
|
||||
rk628_i2c_write(rk628, HDMI_RX_CHLOCK_CONFIG, 0x0030c15c);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_ERROR_PROTECT, 0x000d0c98);
|
||||
rk628_i2c_write(rk628, HDMI_RX_MD_HCTRL1, 0x00000010);
|
||||
rk628_i2c_write(rk628, HDMI_RX_MD_HCTRL2, 0x00001738);
|
||||
rk628_i2c_write(rk628, HDMI_RX_MD_HCTRL2, 0x0000173a);
|
||||
rk628_i2c_write(rk628, HDMI_RX_MD_VCTRL, 0x00000002);
|
||||
rk628_i2c_write(rk628, HDMI_RX_MD_VTH, 0x0000073a);
|
||||
rk628_i2c_write(rk628, HDMI_RX_MD_IL_POL, 0x00000004);
|
||||
@@ -189,7 +199,7 @@ void rk628_hdmirx_controller_setup(struct rk628 *rk628)
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_DCM_CTRL, 0x00040414);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_CKM_EVLTM, 0x00103e70);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_CKM_F, 0x0c1c0b54);
|
||||
rk628_i2c_write(rk628, HDMI_RX_HDMI_RESMPL_CTRL, 0x00000001);
|
||||
rk628_i2c_update_bits(rk628, HDMI_RX_HDMI_TIMER_CTRL, VIDEO_PERIOD_MASK, VIDEO_PERIOD(1));
|
||||
|
||||
rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_SETTINGS,
|
||||
HDMI_RESERVED_MASK |
|
||||
@@ -203,6 +213,39 @@ void rk628_hdmirx_controller_setup(struct rk628 *rk628)
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_controller_setup);
|
||||
|
||||
static bool is_validfs(int fs)
|
||||
{
|
||||
int i = 0;
|
||||
int fs_t;
|
||||
|
||||
fs_t = supported_fs[i++];
|
||||
while (fs_t > 0) {
|
||||
if (fs == fs_t)
|
||||
return true;
|
||||
fs_t = supported_fs[i++];
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
static int rk628_hdmirx_audio_find_closest_fs(struct rk628_audioinfo *aif, int fs)
|
||||
{
|
||||
int i = 0;
|
||||
int fs_t;
|
||||
int difference;
|
||||
|
||||
fs_t = supported_fs[i++];
|
||||
while (fs_t > 0) {
|
||||
difference = abs(fs - fs_t);
|
||||
if (difference <= 2000) {
|
||||
if (fs != fs_t)
|
||||
dev_dbg(aif->dev, "%s fix fs from %u to %u", __func__, fs, fs_t);
|
||||
return fs_t;
|
||||
}
|
||||
fs_t = supported_fs[i++];
|
||||
};
|
||||
return fs_t;
|
||||
}
|
||||
|
||||
static void rk628_hdmirx_audio_fifo_init(struct rk628_audioinfo *aif)
|
||||
{
|
||||
|
||||
@@ -246,8 +289,7 @@ static u32 _rk628_hdmirx_audio_fs(struct rk628_audioinfo *aif)
|
||||
if (cts_decoded != 0) {
|
||||
fs_audio = div_u64((tmdsclk * n_decoded), cts_decoded);
|
||||
fs_audio /= 128;
|
||||
fs_audio = div_u64(fs_audio + 50, 100);
|
||||
fs_audio *= 100;
|
||||
fs_audio = rk628_hdmirx_audio_find_closest_fs(aif, fs_audio);
|
||||
}
|
||||
dev_dbg(aif->dev,
|
||||
"%s: clkrate:%u tmdsclk:%llu, n_decoded:%u, cts_decoded:%u, fs_audio:%u\n",
|
||||
@@ -306,6 +348,85 @@ static void rk628_hdmirx_audio_enable(struct rk628_audioinfo *aif)
|
||||
AFIF_OVERFL_ISTS | AFIF_UNDERFL_ISTS);
|
||||
}
|
||||
|
||||
static const char *audio_fifo_err(u32 fifo_status)
|
||||
{
|
||||
switch (fifo_status & (AFIF_UNDERFL_ISTS | AFIF_OVERFL_ISTS)) {
|
||||
case AFIF_UNDERFL_ISTS:
|
||||
return "underflow";
|
||||
case AFIF_OVERFL_ISTS:
|
||||
return "overflow";
|
||||
case AFIF_UNDERFL_ISTS | AFIF_OVERFL_ISTS:
|
||||
return "underflow and overflow";
|
||||
}
|
||||
return "underflow or overflow";
|
||||
}
|
||||
|
||||
static void rk628_csi_delayed_work_audio_v2(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
struct rk628_audioinfo *aif = container_of(dwork, struct rk628_audioinfo,
|
||||
delayed_work_audio);
|
||||
struct rk628_audiostate *audio_state = &aif->audio_state;
|
||||
struct rk628 *rk628 = aif->rk628;
|
||||
u32 fs_audio;
|
||||
int init_state, pre_state, fifo_status, fifo_ints;
|
||||
unsigned long delay = 500;
|
||||
|
||||
fs_audio = _rk628_hdmirx_audio_fs(aif);
|
||||
/* read fifo init status */
|
||||
rk628_i2c_read(rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints);
|
||||
dev_dbg(rk628->dev, "%s: HDMI_RX_AUD_FIFO_ISTS:%#x\r\n", __func__, fifo_ints);
|
||||
|
||||
if (fifo_ints & (AFIF_UNDERFL_ISTS | AFIF_OVERFL_ISTS)) {
|
||||
dev_warn(rk628->dev, "%s: audio %s %#x, with fs %svalid %d\n",
|
||||
__func__, audio_fifo_err(fifo_ints), fifo_ints,
|
||||
is_validfs(fs_audio) ? "" : "in", fs_audio);
|
||||
if (is_validfs(fs_audio))
|
||||
rk628_hdmirx_audio_set_fs(aif, fs_audio);
|
||||
rk628_hdmirx_audio_fifo_init(aif);
|
||||
audio_state->pre_state = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* read fifo fill status */
|
||||
init_state = audio_state->init_state;
|
||||
pre_state = audio_state->pre_state;
|
||||
rk628_i2c_read(rk628, HDMI_RX_AUD_FIFO_FILLSTS1, &fifo_status);
|
||||
dev_dbg(rk628->dev,
|
||||
"%s: HDMI_RX_AUD_FIFO_FILLSTS1:%#x, single offset:%d, total offset:%d\n",
|
||||
__func__, fifo_status, fifo_status - pre_state, fifo_status - init_state);
|
||||
if (!is_validfs(fs_audio)) {
|
||||
dev_dbg(rk628->dev, "%s: no supported fs(%u), fifo_status %d\n",
|
||||
__func__, fs_audio, fifo_status);
|
||||
delay = 1000;
|
||||
} else if (abs(fs_audio - audio_state->fs_audio) > 1000) {
|
||||
dev_info(rk628->dev, "%s: restart audio fs(%d -> %d)\n",
|
||||
__func__, audio_state->fs_audio, fs_audio);
|
||||
rk628_hdmirx_audio_set_fs(aif, fs_audio);
|
||||
rk628_hdmirx_audio_fifo_init(aif);
|
||||
audio_state->pre_state = 0;
|
||||
goto exit;
|
||||
}
|
||||
if (fifo_status != 0) {
|
||||
if (!aif->audio_present) {
|
||||
dev_info(rk628->dev, "audio on");
|
||||
aif->audio_present = true;
|
||||
}
|
||||
if (fifo_status - init_state > 16 && fifo_status - pre_state > 0)
|
||||
rk628_hdmirx_audio_clk_inc_rate(aif, 10);
|
||||
else if (fifo_status - init_state < -16 && fifo_status - pre_state < 0)
|
||||
rk628_hdmirx_audio_clk_inc_rate(aif, -10);
|
||||
} else {
|
||||
if (aif->audio_present) {
|
||||
dev_info(rk628->dev, "audio off");
|
||||
aif->audio_present = false;
|
||||
}
|
||||
}
|
||||
audio_state->pre_state = fifo_status;
|
||||
exit:
|
||||
schedule_delayed_work(&aif->delayed_work_audio, msecs_to_jiffies(delay));
|
||||
}
|
||||
|
||||
static void rk628_csi_delayed_work_audio(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
@@ -395,10 +516,13 @@ HAUDINFO rk628_hdmirx_audioinfo_alloc(struct device *dev,
|
||||
aif = devm_kzalloc(dev, sizeof(*aif), GFP_KERNEL);
|
||||
if (!aif)
|
||||
return NULL;
|
||||
INIT_DELAYED_WORK(&aif->delayed_work_audio_rate_change,
|
||||
rk628_csi_delayed_work_audio_rate_change);
|
||||
INIT_DELAYED_WORK(&aif->delayed_work_audio,
|
||||
rk628_csi_delayed_work_audio);
|
||||
if (rk628->version >= RK628F_VERSION) {
|
||||
INIT_DELAYED_WORK(&aif->delayed_work_audio, rk628_csi_delayed_work_audio_v2);
|
||||
} else {
|
||||
INIT_DELAYED_WORK(&aif->delayed_work_audio, rk628_csi_delayed_work_audio);
|
||||
INIT_DELAYED_WORK(&aif->delayed_work_audio_rate_change,
|
||||
rk628_csi_delayed_work_audio_rate_change);
|
||||
}
|
||||
aif->confctl_mutex = confctl_mutex;
|
||||
aif->rk628 = rk628;
|
||||
aif->i2s_enabled_default = en;
|
||||
@@ -432,11 +556,14 @@ EXPORT_SYMBOL(rk628_hdmirx_audio_cancel_work_rate_change);
|
||||
void rk628_hdmirx_audio_destroy(HAUDINFO info)
|
||||
{
|
||||
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
|
||||
struct rk628 *rk628;
|
||||
|
||||
if (!aif)
|
||||
return;
|
||||
rk628 = aif->rk628;
|
||||
rk628_hdmirx_audio_cancel_work_audio(aif, true);
|
||||
rk628_hdmirx_audio_cancel_work_rate_change(aif, true);
|
||||
if (rk628->version < RK628F_VERSION)
|
||||
rk628_hdmirx_audio_cancel_work_rate_change(aif, true);
|
||||
aif->confctl_mutex = NULL;
|
||||
aif->rk628 = NULL;
|
||||
}
|
||||
@@ -485,6 +612,7 @@ EXPORT_SYMBOL(rk628_hdmirx_audio_i2s_ctrl);
|
||||
void rk628_hdmirx_audio_setup(HAUDINFO info)
|
||||
{
|
||||
struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
|
||||
struct rk628 *rk628 = aif->rk628;
|
||||
u32 audio_pll_n, audio_pll_cts;
|
||||
|
||||
dev_dbg(aif->dev, "%s: setup audio\n", __func__);
|
||||
@@ -500,6 +628,9 @@ void rk628_hdmirx_audio_setup(HAUDINFO info)
|
||||
aif->ctsn_ints_en = false;
|
||||
aif->i2s_enabled = false;
|
||||
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CRU_MODE_CON00, HIWORD_UPDATE(1, 4, 4));
|
||||
|
||||
rk628_hdmirx_audio_clk_set_rate(aif, 5644800);
|
||||
/* manual aud CTS */
|
||||
rk628_i2c_write(aif->rk628, HDMI_RX_AUDPLL_GEN_CTS, audio_pll_cts);
|
||||
@@ -544,11 +675,17 @@ void rk628_hdmirx_audio_setup(HAUDINFO info)
|
||||
PAO_RATE(0));
|
||||
rk628_i2c_write(aif->rk628, HDMI_RX_AUD_CHEXTR_CTRL,
|
||||
AUD_LAYOUT_CTRL(1));
|
||||
aif->ctsn_ints_en = true;
|
||||
rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_IEN_SET, ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR);
|
||||
/* audio detect */
|
||||
rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_AUDIODET_CTRL,
|
||||
AUDIODET_THRESHOLD(0));
|
||||
if (rk628->version >= RK628F_VERSION) {
|
||||
rk628_i2c_update_bits(aif->rk628, HDMI_RX_DMI_DISABLE_IF,
|
||||
AUD_ENABLE_MASK, AUD_ENABLE(1));
|
||||
schedule_delayed_work(&aif->delayed_work_audio, msecs_to_jiffies(1000));
|
||||
} else {
|
||||
aif->ctsn_ints_en = true;
|
||||
rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_IEN_SET,
|
||||
ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR);
|
||||
/* audio detect */
|
||||
rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_AUDIODET_CTRL, AUDIODET_THRESHOLD(0));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_audio_setup);
|
||||
|
||||
@@ -616,6 +753,9 @@ int rk628_is_avi_ready(struct rk628 *rk628, bool avi_rcv_rdy)
|
||||
u8 cnt = 0, max_cnt = 2;
|
||||
u32 hdcp_ctrl_val = 0;
|
||||
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
return 1;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_HDCP_CTRL, &val);
|
||||
if ((val & HDCP_ENABLE_MASK))
|
||||
max_cnt = 5;
|
||||
@@ -646,3 +786,430 @@ int rk628_is_avi_ready(struct rk628 *rk628, bool avi_rcv_rdy)
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_is_avi_ready);
|
||||
|
||||
static void hdmirxphy_write(struct rk628 *rk628, u32 offset, u32 val)
|
||||
{
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_ADDRESS, offset);
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_DATAO, val);
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_OPERATION, 1);
|
||||
}
|
||||
|
||||
static __maybe_unused u32 hdmirxphy_read(struct rk628 *rk628, u32 offset)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_ADDRESS, offset);
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_OPERATION, 2);
|
||||
rk628_i2c_read(rk628, HDMI_RX_I2CM_PHYG3_DATAI, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void rk628_hdmirxphy_enable(struct rk628 *rk628, bool is_hdmi2, bool scramble_en)
|
||||
{
|
||||
hdmirxphy_write(rk628, 0x02, 0x1860);
|
||||
hdmirxphy_write(rk628, 0x03, 0x0060);
|
||||
if (!is_hdmi2 && scramble_en)
|
||||
hdmirxphy_write(rk628, 0x0d, 0x00c0);
|
||||
else
|
||||
hdmirxphy_write(rk628, 0x0d, 0x0);
|
||||
hdmirxphy_write(rk628, 0x27, 0x1c94);
|
||||
hdmirxphy_write(rk628, 0x28, 0x3713);
|
||||
hdmirxphy_write(rk628, 0x29, 0x24da);
|
||||
hdmirxphy_write(rk628, 0x2a, 0x5492);
|
||||
hdmirxphy_write(rk628, 0x2b, 0x4b0d);
|
||||
hdmirxphy_write(rk628, 0x2d, 0x008c);
|
||||
hdmirxphy_write(rk628, 0x2e, 0x0001);
|
||||
|
||||
if (is_hdmi2)
|
||||
hdmirxphy_write(rk628, 0x0e, 0x0108);
|
||||
else
|
||||
hdmirxphy_write(rk628, 0x0e, 0x0008);
|
||||
|
||||
}
|
||||
|
||||
static void rk628_hdmirxphy_set_clrdpt(struct rk628 *rk628, bool is_8bit)
|
||||
{
|
||||
if (is_8bit)
|
||||
hdmirxphy_write(rk628, 0x03, 0x0000);
|
||||
else
|
||||
hdmirxphy_write(rk628, 0x03, 0x0060);
|
||||
}
|
||||
|
||||
void rk628_hdmirx_verisyno_phy_power_on(struct rk628 *rk628)
|
||||
{
|
||||
bool is_hdmi2 = false;
|
||||
u32 val;
|
||||
int i;
|
||||
bool scramble = false;
|
||||
|
||||
/* wait tx to write scdc tmds ratio */
|
||||
for (i = 0; i < 50; i++) {
|
||||
rk628_i2c_read(rk628, HDMI_RX_SCDC_REGS0, &val);
|
||||
if (val & SCDC_TMDSBITCLKRATIO)
|
||||
break;
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
if (val & SCDC_TMDSBITCLKRATIO)
|
||||
is_hdmi2 = true;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_HDMI20_STATUS, &val);
|
||||
scramble = (val & SCRAMBDET_MASK) ? true : false;
|
||||
|
||||
dev_info(rk628->dev, "%s: %s, %s\n", __func__, is_hdmi2 ? "hdmi2.0" : "hdmi1.4",
|
||||
scramble ? "Scramble" : "Descramble");
|
||||
/* power down phy */
|
||||
rk628_i2c_write(rk628, GRF_SW_HDMIRXPHY_CRTL, 0x17);
|
||||
usleep_range(20, 30);
|
||||
rk628_i2c_write(rk628, GRF_SW_HDMIRXPHY_CRTL, 0x15);
|
||||
/* init phy i2c */
|
||||
rk628_i2c_write(rk628, HDMI_RX_SNPS_PHYG3_CTRL, 0);
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_SS_CNTS, 0x018c01d2);
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_FS_HCNT, 0x003c0081);
|
||||
rk628_i2c_write(rk628, HDMI_RX_I2CM_PHYG3_MODE, 1);
|
||||
rk628_i2c_write(rk628, GRF_SW_HDMIRXPHY_CRTL, 0x11);
|
||||
/* enable rx phy */
|
||||
rk628_hdmirxphy_enable(rk628, is_hdmi2, scramble);
|
||||
rk628_i2c_write(rk628, GRF_SW_HDMIRXPHY_CRTL, 0x14);
|
||||
msleep(20);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_verisyno_phy_power_on);
|
||||
|
||||
void rk628_hdmirx_phy_prepclk_cfg(struct rk628 *rk628)
|
||||
{
|
||||
u32 format;
|
||||
bool is_clrdpt_8bit = false;
|
||||
|
||||
usleep_range(20 * 1000, 30 * 1000);
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &format);
|
||||
format = (format & VIDEO_FORMAT_MASK) >> 5;
|
||||
dev_info(rk628->dev, "%s: format = %d from AVI\n", __func__, format);
|
||||
|
||||
/* yuv420 should set phy color depth 8bit */
|
||||
if (format == 3)
|
||||
is_clrdpt_8bit = true;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_GCP_AVMUTE, &format);
|
||||
format = (format & PKTDEC_GCP_CD_MASK) >> 4;
|
||||
dev_info(rk628->dev, "%s: format = %d from GCP\n", __func__, format);
|
||||
|
||||
/* 10bit color depth should set phy color depth 8bit */
|
||||
if (format == 5)
|
||||
is_clrdpt_8bit = true;
|
||||
|
||||
rk628_hdmirxphy_set_clrdpt(rk628, is_clrdpt_8bit);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_phy_prepclk_cfg);
|
||||
|
||||
static const char * const bus_format_str[] = {
|
||||
"RGB",
|
||||
"YUV422",
|
||||
"YUV444",
|
||||
"YUV420",
|
||||
"UNKNOWN",
|
||||
};
|
||||
|
||||
u8 rk628_hdmirx_get_format(struct rk628 *rk628)
|
||||
{
|
||||
u32 val;
|
||||
u8 video_fmt;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
video_fmt = (val & VIDEO_FORMAT_MASK) >> 5;
|
||||
if (video_fmt > BUS_FMT_UNKNOWN)
|
||||
video_fmt = BUS_FMT_UNKNOWN;
|
||||
dev_info(rk628->dev, "%s: format = %s\n", __func__, bus_format_str[video_fmt]);
|
||||
|
||||
/*
|
||||
* set avmute value to black
|
||||
* RGB: R: CH2[15:0], G:CH0_1[31:16], B: CH0_1[15:0]
|
||||
* YUV: Cr:CH2[15:0], Y:CH0_1[31:16], Cb:CH0_1[15:0]
|
||||
*/
|
||||
if (video_fmt == BUS_FMT_RGB) {
|
||||
rk628_i2c_write(rk628, HDMI_VM_CFG_CH0_1, 0x0);
|
||||
rk628_i2c_write(rk628, HDMI_VM_CFG_CH2, 0x0);
|
||||
} else {
|
||||
rk628_i2c_write(rk628, HDMI_VM_CFG_CH0_1, 0x00008000);
|
||||
rk628_i2c_write(rk628, HDMI_VM_CFG_CH2, 0x8000);
|
||||
}
|
||||
|
||||
return video_fmt;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_format);
|
||||
|
||||
void rk628_set_bg_enable(struct rk628 *rk628, bool en)
|
||||
{
|
||||
if (en) {
|
||||
if (rk628->tx_mode)
|
||||
rk628_i2c_write(rk628, GRF_BG_CTRL,
|
||||
BG_R_OR_V(0) | BG_B_OR_U(0) | BG_G_OR_Y(0) | BG_ENABLE(1));
|
||||
else
|
||||
rk628_i2c_write(rk628, GRF_BG_CTRL,
|
||||
BG_R_OR_V(512) | BG_B_OR_U(512) | BG_G_OR_Y(64) | BG_ENABLE(1));
|
||||
return;
|
||||
}
|
||||
rk628_i2c_write(rk628, GRF_BG_CTRL, BG_ENABLE(0));
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_set_bg_enable);
|
||||
|
||||
u32 rk628_hdmirx_get_tmdsclk_cnt(struct rk628 *rk628)
|
||||
{
|
||||
int i, j;
|
||||
u32 val, tmdsclk_cnt = 0;
|
||||
struct hdmirx_tmdsclk_cnt tmdsclk[HDMIRX_GET_TMDSCLK_TIME] = {0};
|
||||
|
||||
for (i = 0; i < HDMIRX_GET_TMDSCLK_TIME; i++) {
|
||||
rk628_i2c_read(rk628, HDMI_RX_HDMI_CKM_RESULT, &val);
|
||||
tmdsclk_cnt = val & 0xffff;
|
||||
for (j = 0; j < HDMIRX_GET_TMDSCLK_TIME; j++) {
|
||||
if (tmdsclk_cnt == tmdsclk[j].tmds_cnt || !tmdsclk[j].tmds_cnt) {
|
||||
tmdsclk[j].tmds_cnt = tmdsclk_cnt;
|
||||
tmdsclk[j].cnt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < HDMIRX_GET_TMDSCLK_TIME; i++) {
|
||||
if (!tmdsclk[i].tmds_cnt)
|
||||
return tmdsclk_cnt;
|
||||
|
||||
dev_info(rk628->dev, "tmdsclk_cnt: %d, cnt: %d\n",
|
||||
tmdsclk[i].tmds_cnt, tmdsclk[i].cnt);
|
||||
if (!i)
|
||||
tmdsclk_cnt = tmdsclk[i].tmds_cnt;
|
||||
else if (tmdsclk[i].cnt > tmdsclk[i - 1].cnt)
|
||||
tmdsclk_cnt = tmdsclk[i].tmds_cnt;
|
||||
}
|
||||
|
||||
return tmdsclk_cnt;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_tmdsclk_cnt);
|
||||
|
||||
static int rk628_hdmirx_read_timing(struct rk628 *rk628,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
struct v4l2_bt_timings *bt = &timings->bt;
|
||||
u32 hact, vact, htotal, vtotal, fps, status;
|
||||
u32 val;
|
||||
u32 modetclk_cnt_hs, modetclk_cnt_vs, hs, vs;
|
||||
u32 hofs_pix, hbp, hfp, vbp, vfp;
|
||||
u32 tmds_clk, tmdsclk_cnt;
|
||||
u64 tmp_data;
|
||||
u8 video_fmt;
|
||||
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
timings->type = V4L2_DV_BT_656_1120;
|
||||
rk628_i2c_read(rk628, HDMI_RX_SCDC_REGS1, &val);
|
||||
status = val;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_STS, &val);
|
||||
bt->interlaced = val & ILACE_STS ?
|
||||
V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HACT_PX, &val);
|
||||
hact = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VAL, &val);
|
||||
vact = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT1, &val);
|
||||
htotal = (val >> 16) & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VTL, &val);
|
||||
vtotal = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT1, &val);
|
||||
hofs_pix = val & 0xffff;
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VOL, &val);
|
||||
vbp = (val & 0xffff) + 1;
|
||||
|
||||
tmdsclk_cnt = rk628_hdmirx_get_tmdsclk_cnt(rk628);
|
||||
tmp_data = tmdsclk_cnt;
|
||||
tmp_data = ((tmp_data * HDMIRX_MODETCLK_HZ) + HDMIRX_MODETCLK_CNT_NUM / 2);
|
||||
do_div(tmp_data, HDMIRX_MODETCLK_CNT_NUM);
|
||||
tmds_clk = tmp_data;
|
||||
if (!htotal || !vtotal || bt->interlaced || vtotal > 3000) {
|
||||
dev_err(rk628->dev, "timing err, %s htotal:%d, vtotal:%d\n",
|
||||
bt->interlaced ? "interlaced is not supported," : "",
|
||||
htotal, vtotal);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
fps = tmds_clk / (htotal * vtotal);
|
||||
else
|
||||
fps = (tmds_clk + (htotal * vtotal) / 2) / (htotal * vtotal);
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_HT0, &val);
|
||||
modetclk_cnt_hs = val & 0xffff;
|
||||
hs = (tmdsclk_cnt * modetclk_cnt_hs + HDMIRX_MODETCLK_CNT_NUM / 2) /
|
||||
HDMIRX_MODETCLK_CNT_NUM;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_MD_VSC, &val);
|
||||
modetclk_cnt_vs = val & 0xffff;
|
||||
vs = (tmdsclk_cnt * modetclk_cnt_vs + HDMIRX_MODETCLK_CNT_NUM / 2) /
|
||||
HDMIRX_MODETCLK_CNT_NUM;
|
||||
vs = (vs + htotal / 2) / htotal;
|
||||
|
||||
if ((hofs_pix < hs) || (htotal < (hact + hofs_pix)) ||
|
||||
(vtotal < (vact + vs + vbp)) || !vs) {
|
||||
dev_err(rk628->dev, "timing err, total:%dx%d, act:%dx%d, hofs:%d, hs:%d, vs:%d, vbp:%d\n",
|
||||
htotal, vtotal, hact, vact, hofs_pix, hs, vs, vbp);
|
||||
goto TIMING_ERR;
|
||||
}
|
||||
hbp = hofs_pix - hs;
|
||||
hfp = htotal - hact - hofs_pix;
|
||||
vfp = vtotal - vact - vs - vbp;
|
||||
|
||||
video_fmt = rk628_hdmirx_get_format(rk628);
|
||||
if (video_fmt == BUS_FMT_YUV420) {
|
||||
htotal *= 2;
|
||||
hact *= 2;
|
||||
hfp *= 2;
|
||||
hbp *= 2;
|
||||
hs *= 2;
|
||||
}
|
||||
|
||||
dev_info(rk628->dev, "cnt_num:%d, tmds_cnt:%d, hs_cnt:%d, vs_cnt:%d, hofs:%d\n",
|
||||
HDMIRX_MODETCLK_CNT_NUM, tmdsclk_cnt, modetclk_cnt_hs, modetclk_cnt_vs, hofs_pix);
|
||||
|
||||
bt->width = hact;
|
||||
bt->height = vact;
|
||||
bt->hfrontporch = hfp;
|
||||
bt->hsync = hs;
|
||||
bt->hbackporch = hbp;
|
||||
bt->vfrontporch = vfp;
|
||||
bt->vsync = vs;
|
||||
bt->vbackporch = vbp;
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
bt->pixelclock = tmds_clk;
|
||||
else
|
||||
bt->pixelclock = htotal * vtotal * fps;
|
||||
|
||||
if (bt->interlaced == V4L2_DV_INTERLACED) {
|
||||
bt->height *= 2;
|
||||
bt->il_vsync = bt->vsync + 1;
|
||||
bt->pixelclock /= 2;
|
||||
}
|
||||
if (video_fmt == BUS_FMT_YUV420)
|
||||
bt->pixelclock *= 2;
|
||||
|
||||
if (vact == 1080 && vtotal > 1500)
|
||||
goto TIMING_ERR;
|
||||
|
||||
dev_info(rk628->dev, "SCDC_REGS1:%#x, act:%dx%d, total:%dx%d, fps:%d, pixclk:%llu\n",
|
||||
status, hact, vact, htotal, vtotal, fps, bt->pixelclock);
|
||||
|
||||
return 0;
|
||||
|
||||
TIMING_ERR:
|
||||
return -ENOLCK;
|
||||
}
|
||||
|
||||
static int rk628_hdmirx_try_to_get_timing(struct rk628 *rk628,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ret = rk628_hdmirx_read_timing(rk628, timings);
|
||||
if (!ret)
|
||||
return ret;
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rk628_hdmirx_get_timings(struct rk628 *rk628,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
int i, cnt = 0, ret = 0;
|
||||
u32 last_w, last_h;
|
||||
u8 last_fmt;
|
||||
struct v4l2_bt_timings *bt = &timings->bt;
|
||||
|
||||
last_w = 0;
|
||||
last_h = 0;
|
||||
last_fmt = BUS_FMT_RGB;
|
||||
|
||||
for (i = 0; i < HDMIRX_GET_TIMING_CNT; i++) {
|
||||
ret = rk628_hdmirx_try_to_get_timing(rk628, timings);
|
||||
if ((last_w == 0) && (last_h == 0)) {
|
||||
last_w = bt->width;
|
||||
last_h = bt->height;
|
||||
last_fmt = rk628_hdmirx_get_format(rk628);
|
||||
}
|
||||
|
||||
if (ret || (last_w != bt->width) || (last_h != bt->height)
|
||||
|| (last_fmt != rk628_hdmirx_get_format(rk628)))
|
||||
cnt = 0;
|
||||
else
|
||||
cnt++;
|
||||
|
||||
if (cnt >= 8)
|
||||
break;
|
||||
|
||||
last_w = bt->width;
|
||||
last_h = bt->height;
|
||||
last_fmt = rk628_hdmirx_get_format(rk628);
|
||||
usleep_range(10*1000, 10*1100);
|
||||
}
|
||||
|
||||
if (cnt < 8) {
|
||||
dev_info(rk628->dev, "%s: res not stable!\n", __func__);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_timings);
|
||||
|
||||
u8 rk628_hdmirx_get_range(struct rk628 *rk628)
|
||||
{
|
||||
u32 val;
|
||||
u8 color_range;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
|
||||
color_range = (val & RGB_COLORRANGE_MASK) >> 18;
|
||||
if (color_range == 0x1)
|
||||
color_range = CSC_LIMIT_RANGE;
|
||||
else
|
||||
color_range = CSC_FULL_RANGE;
|
||||
|
||||
return color_range;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_get_range);
|
||||
|
||||
void rk628_hdmirx_controller_reset(struct rk628 *rk628)
|
||||
{
|
||||
mutex_lock(&rk628->rst_lock);
|
||||
rk628_control_assert(rk628, RGU_HDMIRX);
|
||||
rk628_control_assert(rk628, RGU_HDMIRX_PON);
|
||||
udelay(10);
|
||||
rk628_control_deassert(rk628, RGU_HDMIRX);
|
||||
rk628_control_deassert(rk628, RGU_HDMIRX_PON);
|
||||
udelay(10);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_SW_RST, 0x000101ff);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x00000000);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0000017f);
|
||||
rk628_i2c_write(rk628, HDMI_RX_DMI_DISABLE_IF, 0x0001017f);
|
||||
mutex_unlock(&rk628->rst_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_controller_reset);
|
||||
|
||||
bool rk628_hdmirx_scdc_ced_err(struct rk628 *rk628)
|
||||
{
|
||||
u32 val, val1;
|
||||
|
||||
if (rk628->version < RK628F_VERSION)
|
||||
return false;
|
||||
|
||||
rk628_i2c_read(rk628, HDMI_RX_SCDC_REGS1, &val);
|
||||
rk628_i2c_read(rk628, HDMI_RX_SCDC_REGS2, &val1);
|
||||
if (((val >> 15) & SCDC_ERRDET_MASK) < SCDC_CED_ERR_CNT &&
|
||||
((val1 >> 15) & SCDC_ERRDET_MASK) < SCDC_CED_ERR_CNT &&
|
||||
(val1 & SCDC_ERRDET_MASK) < SCDC_CED_ERR_CNT)
|
||||
return false;
|
||||
|
||||
dev_info(rk628->dev, "%s: Character Error(0x%x 0x%x)!\n", __func__, val, val1);
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_hdmirx_scdc_ced_err);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef __RK628_HDMIRX_H
|
||||
#define __RK628_HDMIRX_H
|
||||
|
||||
#include <media/v4l2-dv-timings.h>
|
||||
#include "rk628.h"
|
||||
|
||||
/* --------- EDID and HDCP KEY ------- */
|
||||
@@ -32,6 +33,8 @@
|
||||
#define HOT_PLUG_DETECT_MASK BIT(0)
|
||||
#define HOT_PLUG_DETECT(x) UPDATE(x, 0, 0)
|
||||
#define HDMI_RX_HDMI_TIMER_CTRL (HDMI_RX_BASE + 0x0008)
|
||||
#define VIDEO_PERIOD_MASK BIT(11)
|
||||
#define VIDEO_PERIOD(x) UPDATE(x, 11, 11)
|
||||
#define HDMI_RX_HDMI_RES_OVR (HDMI_RX_BASE + 0x0010)
|
||||
#define HDMI_RX_HDMI_PLL_FRQSET2 (HDMI_RX_BASE + 0x0020)
|
||||
#define HDMI_RX_HDMI_PCB_CTRL (HDMI_RX_BASE + 0x0038)
|
||||
@@ -81,6 +84,7 @@
|
||||
#define DCM_COLOUR_DEPTH_SEL(x) UPDATE(x, 12, 12)
|
||||
#define DCM_COLOUR_DEPTH(x) UPDATE(x, 11, 8)
|
||||
#define DCM_GCP_ZERO_FIELDS(x) UPDATE(x, 5, 2)
|
||||
#define HDMI_VM_CFG_CH0_1 (HDMI_RX_BASE + 0x00b0)
|
||||
#define HDMI_VM_CFG_CH2 (HDMI_RX_BASE + 0x00b4)
|
||||
#define HDMI_RX_HDCP_CTRL (HDMI_RX_BASE + 0x00c0)
|
||||
#define HDCP_ENABLE_MASK BIT(24)
|
||||
@@ -189,6 +193,15 @@
|
||||
#define HDMI_RX_AUDPLL_GEN_N (HDMI_RX_BASE + 0x0284)
|
||||
#define HDMI_RX_SNPS_PHYG3_CTRL (HDMI_RX_BASE + 0x02c0)
|
||||
#define PORTSELECT(x) UPDATE(x, 3, 2)
|
||||
#define HDMI_RX_I2CM_PHYG3_SLAVE (HDMI_RX_BASE + 0x02c4)
|
||||
#define HDMI_RX_I2CM_PHYG3_ADDRESS (HDMI_RX_BASE + 0x02c8)
|
||||
#define HDMI_RX_I2CM_PHYG3_DATAO (HDMI_RX_BASE + 0x02cc)
|
||||
#define HDMI_RX_I2CM_PHYG3_DATAI (HDMI_RX_BASE + 0x02d0)
|
||||
#define HDMI_RX_I2CM_PHYG3_OPERATION (HDMI_RX_BASE + 0x02d4)
|
||||
#define HDMI_RX_I2CM_PHYG3_MODE (HDMI_RX_BASE + 0x02d8)
|
||||
#define HDMI_RX_I2CM_PHYG3_SS_CNTS (HDMI_RX_BASE + 0x02e0)
|
||||
#define HDMI_RX_I2CM_PHYG3_FS_HCNT (HDMI_RX_BASE + 0x02e4)
|
||||
|
||||
#define HDMI_RX_PDEC_CTRL (HDMI_RX_BASE + 0x0300)
|
||||
#define PFIFO_STORE_FILTER_EN_MASK BIT(31)
|
||||
#define PFIFO_STORE_FILTER_EN(x) UPDATE(x, 31, 31)
|
||||
@@ -234,9 +247,12 @@
|
||||
#define HDMI_RX_PDEC_STS (HDMI_RX_BASE + 0x0360)
|
||||
#define DVI_DET BIT(28)
|
||||
#define HDMI_RX_PDEC_GCP_AVMUTE (HDMI_RX_BASE + 0x0380)
|
||||
#define PKTDEC_GCP_CD_MASK GENMASK(7, 4)
|
||||
#define HDMI_RX_PDEC_AVI_PB (HDMI_RX_BASE + 0x03a4)
|
||||
#define VIDEO_FORMAT_MASK GENMASK(6, 5)
|
||||
#define VIDEO_FORMAT(x) UPDATE(x, 6, 5)
|
||||
#define RGB_COLORRANGE_MASK GENMASK(19, 18)
|
||||
#define RGB_COLORRANGE(x) UPDATE(x, 19, 18)
|
||||
#define ACT_INFO_PRESENT_MASK BIT(4)
|
||||
#define HDMI_RX_PDEC_ACR_CTS (HDMI_RX_BASE + 0x0390)
|
||||
#define HDMI_RX_PDEC_ACR_N (HDMI_RX_BASE + 0x0394)
|
||||
@@ -248,6 +264,7 @@
|
||||
#define PVO1UNMUTE(x) UPDATE(x, 29, 29)
|
||||
#define PIXELMODE(x) UPDATE(x, 28, 28)
|
||||
#define CTRLCHECKEN(x) UPDATE(x, 8, 8)
|
||||
#define SCDC_ENABLE_MASK BIT(4)
|
||||
#define SCDC_ENABLE(x) UPDATE(x, 4, 4)
|
||||
#define SCRAMBEN_SEL(x) UPDATE(x, 1, 0)
|
||||
#define HDMI_RX_SCDC_I2CCONFIG (HDMI_RX_BASE + 0x0804)
|
||||
@@ -259,16 +276,21 @@
|
||||
#define MILISECTIMERLIMIT(x) UPDATE(x, 15, 0)
|
||||
#define HDMI_RX_HDCP22_CONTROL (HDMI_RX_BASE + 0x081c)
|
||||
#define HDMI_RX_SCDC_REGS0 (HDMI_RX_BASE + 0x0820)
|
||||
#define SCDC_TMDSBITCLKRATIO BIT(17)
|
||||
#define HDMI_RX_SCDC_REGS1 (HDMI_RX_BASE + 0x0824)
|
||||
#define HDMI_RX_SCDC_REGS2 (HDMI_RX_BASE + 0x0828)
|
||||
#define SCDC_ERRDET_MASK GENMASK(14, 0)
|
||||
#define HDMI_RX_SCDC_REGS3 (HDMI_RX_BASE + 0x082c)
|
||||
#define HDMI_RX_SCDC_WRDATA0 (HDMI_RX_BASE + 0x0860)
|
||||
#define MANUFACTUREROUI(x) UPDATE(x, 31, 8)
|
||||
#define SINKVERSION(x) UPDATE(x, 7, 0)
|
||||
#define HDMI_RX_HDMI20_STATUS (HDMI_RX_BASE + 0x08e0)
|
||||
#define SCRAMBDET_MASK BIT(0)
|
||||
|
||||
#define HDMI_RX_HDMI2_IEN_CLR (HDMI_RX_BASE + 0x0f60)
|
||||
#define HDMI_RX_HDMI2_ISTS (HDMI_RX_BASE + 0x0f68)
|
||||
#define HDMI_RX_PDEC_IEN_CLR (HDMI_RX_BASE + 0x0f78)
|
||||
#define AVI_CKS_CHG_ICLR BIT(24)
|
||||
#define ACR_N_CHG_ICLR BIT(23)
|
||||
#define ACR_CTS_CHG_ICLR BIT(22)
|
||||
#define GCP_AV_MUTE_CHG_ENCLR BIT(21)
|
||||
@@ -284,6 +306,7 @@
|
||||
#define GCP_RCV_ENSET BIT(16)
|
||||
#define AMP_RCV_ENSET BIT(14)
|
||||
#define HDMI_RX_PDEC_ISTS (HDMI_RX_BASE + 0x0f80)
|
||||
#define AVI_CKS_CHG_ISTS BIT(24)
|
||||
#define GCP_AV_MUTE_CHG_ISTS BIT(21)
|
||||
#define AIF_RCV_ISTS BIT(19)
|
||||
#define AVI_RCV_ISTS BIT(18)
|
||||
@@ -359,6 +382,43 @@
|
||||
|
||||
#define HDMIRX_HDCP1X_ID 13
|
||||
|
||||
#define HDMIRX_GET_TIMING_CNT 20
|
||||
#define HDMIRX_MODETCLK_CNT_NUM 1000
|
||||
#define HDMIRX_MODETCLK_HZ 49500000
|
||||
|
||||
#define EDID_NUM_BLOCKS_MAX 2
|
||||
#define EDID_BLOCK_SIZE 128
|
||||
|
||||
#define RK628_CSI_LINK_FREQ_LOW 350000000
|
||||
#define RK628_CSI_LINK_FREQ_HIGH 650000000
|
||||
#define RK628_CSI_LINK_FREQ_925M 925000000
|
||||
#define RK628_CSI_PIXEL_RATE_LOW 400000000
|
||||
#define RK628_CSI_PIXEL_RATE_HIGH 600000000
|
||||
#define MIPI_DATARATE_MBPS_LOW 700
|
||||
#define MIPI_DATARATE_MBPS_HIGH 1300
|
||||
|
||||
#define POLL_INTERVAL_MS 1000
|
||||
#define RXPHY_CFG_MAX_TIMES 10
|
||||
#define CSITX_ERR_RETRY_TIMES 3
|
||||
|
||||
#define USE_4_LANES 4
|
||||
#define YUV422_8BIT 0x1e
|
||||
|
||||
#define SCDC_CED_ERR_CNT 0xfff
|
||||
|
||||
enum color_range {
|
||||
CSC_LIMIT_RANGE,
|
||||
CSC_FULL_RANGE,
|
||||
};
|
||||
|
||||
enum bus_format {
|
||||
BUS_FMT_RGB = 0,
|
||||
BUS_FMT_YUV422 = 1,
|
||||
BUS_FMT_YUV444 = 2,
|
||||
BUS_FMT_YUV420 = 3,
|
||||
BUS_FMT_UNKNOWN,
|
||||
};
|
||||
|
||||
struct hdcp_keys {
|
||||
u8 KSV[HDCP_KEY_KSV_SIZE];
|
||||
u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
|
||||
@@ -392,5 +452,16 @@ bool rk628_audio_ctsnints_enabled(HAUDINFO info);
|
||||
void rk628_csi_isr_ctsn(HAUDINFO info, u32 pdec_ints);
|
||||
void rk628_csi_isr_fifoints(HAUDINFO info, u32 fifo_ints);
|
||||
int rk628_is_avi_ready(struct rk628 *rk628, bool avi_rcv_rdy);
|
||||
void rk628_hdmirx_verisyno_phy_power_on(struct rk628 *rk628);
|
||||
void rk628_hdmirx_phy_prepclk_cfg(struct rk628 *rk628);
|
||||
int rk628_hdmirx_verisyno_phy_init(struct rk628 *rk628);
|
||||
u8 rk628_hdmirx_get_format(struct rk628 *rk628);
|
||||
void rk628_set_bg_enable(struct rk628 *rk628, bool en);
|
||||
u32 rk628_hdmirx_get_tmdsclk_cnt(struct rk628 *rk628);
|
||||
int rk628_hdmirx_get_timings(struct rk628 *rk628,
|
||||
struct v4l2_dv_timings *timings);
|
||||
u8 rk628_hdmirx_get_range(struct rk628 *rk628);
|
||||
void rk628_hdmirx_controller_reset(struct rk628 *rk628);
|
||||
bool rk628_hdmirx_scdc_ced_err(struct rk628 *rk628);
|
||||
|
||||
#endif
|
||||
|
||||
279
drivers/media/i2c/rk628/rk628_mipi_dphy.c
Normal file
279
drivers/media/i2c/rk628/rk628_mipi_dphy.c
Normal file
@@ -0,0 +1,279 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "rk628_csi.h"
|
||||
#include "rk628_dsi.h"
|
||||
#include "rk628_mipi_dphy.h"
|
||||
|
||||
static inline void testif_testclk_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, PHY_TESTCLK);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclk_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
void rk628_testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, PHY_TESTCLR);
|
||||
udelay(1);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_testclr_assert);
|
||||
|
||||
void rk628_testif_testclr_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, 0);
|
||||
udelay(1);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_testclr_deassert);
|
||||
|
||||
static inline void testif_testen_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, PHY_TESTEN);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testen_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_set_data(struct rk628 *rk628, u8 data, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTDIN_MASK, PHY_TESTDIN(data));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline u8 testif_get_data(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
rk628_i2c_read(rk628, mipi_id ? GRF_DPHY1_STATUS : GRF_DPHY0_STATUS, &data);
|
||||
|
||||
return data >> PHY_TESTDOUT_SHIFT;
|
||||
}
|
||||
|
||||
static void testif_test_code_write(struct rk628 *rk628, u8 test_code, uint8_t mipi_id)
|
||||
{
|
||||
testif_testclk_assert(rk628, mipi_id);
|
||||
testif_set_data(rk628, test_code, mipi_id);
|
||||
testif_testen_assert(rk628, mipi_id);
|
||||
testif_testclk_deassert(rk628, mipi_id);
|
||||
testif_testen_deassert(rk628, mipi_id);
|
||||
}
|
||||
|
||||
static void testif_test_data_write(struct rk628 *rk628, u8 test_data, uint8_t mipi_id)
|
||||
{
|
||||
testif_testclk_deassert(rk628, mipi_id);
|
||||
testif_set_data(rk628, test_data, mipi_id);
|
||||
testif_testclk_assert(rk628, mipi_id);
|
||||
}
|
||||
|
||||
u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id)
|
||||
{
|
||||
u8 monitor_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code, mipi_id);
|
||||
testif_test_data_write(rk628, test_data, mipi_id);
|
||||
monitor_data = testif_get_data(rk628, mipi_id);
|
||||
|
||||
dev_dbg(rk628->dev, "test_code=0x%02x, mipi dphy%x", test_code, mipi_id);
|
||||
dev_dbg(rk628->dev, "test_data=0x%02x, mipi dphy%x", test_data, mipi_id);
|
||||
dev_dbg(rk628->dev, "monitor_data=0x%02x, mipi dphy%x\n", monitor_data, mipi_id);
|
||||
|
||||
return monitor_data;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_write);
|
||||
|
||||
u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id)
|
||||
{
|
||||
u8 test_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code, mipi_id);
|
||||
test_data = testif_get_data(rk628, mipi_id);
|
||||
testif_test_data_write(rk628, test_data, mipi_id);
|
||||
|
||||
return test_data;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_read);
|
||||
|
||||
static inline void mipi_dphy_enablelane_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
CSI_DPHY_EN_MASK, CSI_DPHY_EN(rk628->dphy_lane_en));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enablelane_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
CSI_DPHY_EN_MASK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ,
|
||||
CSI_PHYSHUTDOWNZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ,
|
||||
CSI_PHYRSTZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id)
|
||||
{
|
||||
const struct {
|
||||
unsigned long max_lane_mbps;
|
||||
u8 hsfreqrange;
|
||||
} hsfreqrange_table[] = {
|
||||
{ 90, 0x00}, { 100, 0x10}, { 110, 0x20}, { 130, 0x01},
|
||||
{ 140, 0x11}, { 150, 0x21}, { 170, 0x02}, { 180, 0x12},
|
||||
{ 200, 0x22}, { 220, 0x03}, { 240, 0x13}, { 250, 0x23},
|
||||
{ 270, 0x04}, { 300, 0x14}, { 330, 0x05}, { 360, 0x15},
|
||||
{ 400, 0x25}, { 450, 0x06}, { 500, 0x16}, { 550, 0x07},
|
||||
{ 600, 0x17}, { 650, 0x08}, { 700, 0x18}, { 750, 0x09},
|
||||
{ 800, 0x19}, { 850, 0x29}, { 900, 0x39}, { 950, 0x0a},
|
||||
{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
|
||||
{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
|
||||
{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
|
||||
};
|
||||
u8 hsfreqrange;
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < ARRAY_SIZE(hsfreqrange_table); index++)
|
||||
if (lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
|
||||
break;
|
||||
|
||||
if (index == ARRAY_SIZE(hsfreqrange_table))
|
||||
--index;
|
||||
|
||||
hsfreqrange = hsfreqrange_table[index].hsfreqrange;
|
||||
rk628_testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange), mipi_id);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dphy_init_hsfreqrange);
|
||||
|
||||
void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id)
|
||||
{
|
||||
dev_info(rk628->dev,
|
||||
"mipi dphy%d hs config, manual: %s\n", mipi_id, manual ? "true" : "false");
|
||||
//config mipi timing when mipi freq is 1250Mbps
|
||||
rk628_testif_write(rk628, 0x71,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].data_prepare) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x72,
|
||||
manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_zero) | BIT(6)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x73,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].data_trail) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x61,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_prepare) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x62,
|
||||
manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_zero) | BIT(6)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x63,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_trail) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x65,
|
||||
manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(5)) : 0, mipi_id);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dphy_init_hsmanual);
|
||||
|
||||
int rk628_mipi_dphy_reset(struct rk628 *rk628)
|
||||
{
|
||||
u32 val, mask;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x1);
|
||||
mipi_dphy_enablelane_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_deassert(rk628, 1);
|
||||
mipi_dphy_shutdownz_assert(rk628);
|
||||
mipi_dphy_rstz_assert(rk628);
|
||||
rk628_testif_testclr_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_testif_testclr_assert(rk628, 1);
|
||||
|
||||
/* Set all REQUEST inputs to zero */
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX1_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
udelay(1);
|
||||
rk628_testif_testclr_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_testif_testclr_deassert(rk628, 1);
|
||||
mipi_dphy_enablelane_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_assert(rk628, 1);
|
||||
mipi_dphy_shutdownz_deassert(rk628);
|
||||
mipi_dphy_rstz_deassert(rk628);
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x0);
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
mask = STOPSTATE_CLK | STOPSTATE_LANE0;
|
||||
|
||||
ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI],
|
||||
CSITX_CSITX_STATUS1,
|
||||
val, (val & mask) == mask,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev, "csi0 lane module is not in stop state, val: 0x%x\n", val);
|
||||
|
||||
if (rk628->version >= RK628F_VERSION) {
|
||||
ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI1],
|
||||
CSITX1_CSITX_STATUS1,
|
||||
val, (val & mask) == mask,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"csi1 lane module is not in stop state, val: 0x%x\n", val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dphy_reset);
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
|
||||
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
* Author: Shunqing Chen <csq@rock-chips.com>
|
||||
*/
|
||||
@@ -8,12 +8,6 @@
|
||||
#ifndef _RK628_MIPI_DPHY_H
|
||||
#define _RK628_MIPI_DPHY_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "rk628_csi.h"
|
||||
#include "rk628_dsi.h"
|
||||
#include "rk628.h"
|
||||
|
||||
/* Test Code: 0x44 (HS RX Control of Lane 0) */
|
||||
@@ -21,239 +15,14 @@
|
||||
#define HSTX(x) UPDATE(x, 6, 0)
|
||||
#define HSZERO(x) UPDATE(x, 5, 0)
|
||||
#define HSPOST(x) UPDATE(x, 4, 0)
|
||||
#define HSEXIT(x) UPDATE(x, 4, 0)
|
||||
|
||||
static inline void testif_testclk_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, PHY_TESTCLK);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclk_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclr_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, PHY_TESTCLR);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclr_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testen_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, PHY_TESTEN);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testen_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_set_data(struct rk628 *rk628, u8 data)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
PHY_TESTDIN_MASK, PHY_TESTDIN(data));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline u8 testif_get_data(struct rk628 *rk628)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
rk628_i2c_read(rk628, GRF_DPHY0_STATUS, &data);
|
||||
|
||||
return data >> PHY_TESTDOUT_SHIFT;
|
||||
}
|
||||
|
||||
static void testif_test_code_write(struct rk628 *rk628, u8 test_code)
|
||||
{
|
||||
testif_testclk_assert(rk628);
|
||||
testif_set_data(rk628, test_code);
|
||||
testif_testen_assert(rk628);
|
||||
testif_testclk_deassert(rk628);
|
||||
testif_testen_deassert(rk628);
|
||||
}
|
||||
|
||||
static void testif_test_data_write(struct rk628 *rk628, u8 test_data)
|
||||
{
|
||||
testif_testclk_deassert(rk628);
|
||||
testif_set_data(rk628, test_data);
|
||||
testif_testclk_assert(rk628);
|
||||
}
|
||||
|
||||
static u8 testif_write(struct rk628 *rk628, u8 test_code, u8 test_data)
|
||||
{
|
||||
u8 monitor_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code);
|
||||
testif_test_data_write(rk628, test_data);
|
||||
monitor_data = testif_get_data(rk628);
|
||||
|
||||
dev_dbg(rk628->dev, "test_code=0x%02x, ", test_code);
|
||||
dev_dbg(rk628->dev, "test_data=0x%02x, ", test_data);
|
||||
dev_dbg(rk628->dev, "monitor_data=0x%02x\n", monitor_data);
|
||||
|
||||
return monitor_data;
|
||||
}
|
||||
|
||||
static inline u8 testif_read(struct rk628 *rk628, u8 test_code)
|
||||
{
|
||||
u8 test_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code);
|
||||
test_data = testif_get_data(rk628);
|
||||
testif_test_data_write(rk628, test_data);
|
||||
|
||||
return test_data;
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enableclk_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, CSITX_DPHY_CTRL, DPHY_ENABLECLK,
|
||||
DPHY_ENABLECLK);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enableclk_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, CSITX_DPHY_CTRL, DPHY_ENABLECLK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ,
|
||||
CSI_PHYSHUTDOWNZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ,
|
||||
CSI_PHYRSTZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps)
|
||||
{
|
||||
const struct {
|
||||
unsigned long max_lane_mbps;
|
||||
u8 hsfreqrange;
|
||||
} hsfreqrange_table[] = {
|
||||
{ 90, 0x00}, { 100, 0x10}, { 110, 0x20}, { 130, 0x01},
|
||||
{ 140, 0x11}, { 150, 0x21}, { 170, 0x02}, { 180, 0x12},
|
||||
{ 200, 0x22}, { 220, 0x03}, { 240, 0x13}, { 250, 0x23},
|
||||
{ 270, 0x04}, { 300, 0x14}, { 330, 0x05}, { 360, 0x15},
|
||||
{ 400, 0x25}, { 450, 0x06}, { 500, 0x16}, { 550, 0x07},
|
||||
{ 600, 0x17}, { 650, 0x08}, { 700, 0x18}, { 750, 0x09},
|
||||
{ 800, 0x19}, { 850, 0x29}, { 900, 0x39}, { 950, 0x0a},
|
||||
{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
|
||||
{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
|
||||
{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
|
||||
};
|
||||
u8 hsfreqrange;
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < ARRAY_SIZE(hsfreqrange_table); index++)
|
||||
if (lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
|
||||
break;
|
||||
|
||||
if (index == ARRAY_SIZE(hsfreqrange_table))
|
||||
--index;
|
||||
|
||||
hsfreqrange = hsfreqrange_table[index].hsfreqrange;
|
||||
testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange));
|
||||
}
|
||||
|
||||
static void __maybe_unused mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual)
|
||||
{
|
||||
if (manual) {
|
||||
//config mipi timing when mipi freq is 1250Mbps
|
||||
testif_write(rk628, 0x71, HSTX(0x4a) | BIT(7));
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x72, HSZERO(0xf) | BIT(6));
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x73, HSTX(0x5d) | BIT(7));
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x61, HSTX(0x3a) | BIT(7));
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x62, HSZERO(0x3a) | BIT(6));
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x63, HSTX(0x5a) | BIT(7));
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x65, HSPOST(0x1f) | BIT(5));
|
||||
} else {
|
||||
testif_write(rk628, 0x71, 0);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x72, 0);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x73, 0);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x61, 0);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x62, 0);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x63, 0);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x65, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int mipi_dphy_reset(struct rk628 *rk628)
|
||||
{
|
||||
u32 val, mask;
|
||||
|
||||
mipi_dphy_enableclk_deassert(rk628);
|
||||
mipi_dphy_shutdownz_assert(rk628);
|
||||
mipi_dphy_rstz_assert(rk628);
|
||||
testif_testclr_assert(rk628);
|
||||
|
||||
/* Set all REQUEST inputs to zero */
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
udelay(1);
|
||||
testif_testclr_deassert(rk628);
|
||||
mipi_dphy_enableclk_assert(rk628);
|
||||
mipi_dphy_shutdownz_deassert(rk628);
|
||||
mipi_dphy_rstz_deassert(rk628);
|
||||
usleep_range(1500, 2000);
|
||||
|
||||
mask = STOPSTATE_CLK | STOPSTATE_LANE0;
|
||||
rk628_i2c_read(rk628, CSITX_CSITX_STATUS1, &val);
|
||||
if ((val & mask) != mask) {
|
||||
dev_err(rk628->dev, "lane module is not in stop state\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void rk628_testif_testclr_deassert(struct rk628 *rk628, uint8_t mipi_id);
|
||||
void rk628_testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id);
|
||||
u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id);
|
||||
u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id);
|
||||
void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id);
|
||||
void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id);
|
||||
int rk628_mipi_dphy_reset(struct rk628 *rk628);
|
||||
|
||||
#endif
|
||||
|
||||
1356
drivers/media/i2c/rk628/rk628_post_process.c
Normal file
1356
drivers/media/i2c/rk628/rk628_post_process.c
Normal file
File diff suppressed because it is too large
Load Diff
13
drivers/media/i2c/rk628/rk628_post_process.h
Normal file
13
drivers/media/i2c/rk628/rk628_post_process.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef POST_PROCESS_H
|
||||
#define POST_PROCESS_H
|
||||
|
||||
void rk628_post_process_csc_en(struct rk628 *rk628);
|
||||
void rk628_post_process_csc_dis(struct rk628 *rk628);
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,7 @@
|
||||
rk628_misc-$(CONFIG_RK628_MISC) += rk628.o rk628_cru.o rk628_config.o rk628_post_process.o \
|
||||
rk628_combrxphy.o rk628_hdmirx.o rk628_combtxphy.o rk628_dsi.o \
|
||||
panel.o rk628_lvds.o rk628_rgb.o rk628_gvi.o rk628_pinctrl.o \
|
||||
rk628_csi.o
|
||||
rk628_csi.o rk628_efuse.o
|
||||
|
||||
rk628_misc-$(CONFIG_RK628_MISC_HDMITX) += rk628_hdmitx.o
|
||||
|
||||
|
||||
@@ -132,16 +132,16 @@ init_err:
|
||||
|
||||
int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np)
|
||||
{
|
||||
struct panel_simple *panel;
|
||||
struct rk628_panel_simple *panel;
|
||||
struct device *dev = rk628->dev;
|
||||
struct device_node *backlight;
|
||||
int ret;
|
||||
|
||||
panel = devm_kzalloc(dev, sizeof(struct panel_simple), GFP_KERNEL);
|
||||
panel = devm_kzalloc(dev, sizeof(struct rk628_panel_simple), GFP_KERNEL);
|
||||
if (!panel)
|
||||
return -ENOMEM;
|
||||
|
||||
panel->supply = devm_regulator_get(dev, "power");
|
||||
panel->supply = devm_regulator_get(dev, "panel-power");
|
||||
if (IS_ERR(panel->supply)) {
|
||||
ret = PTR_ERR(panel->supply);
|
||||
dev_err(dev, "failed to get power regulator: %d\n", ret);
|
||||
@@ -174,9 +174,16 @@ int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np)
|
||||
|
||||
}
|
||||
|
||||
device_property_read_u32(dev, "panel-prepare-delay-ms", &panel->delay.prepare);
|
||||
device_property_read_u32(dev, "panel-enable-delay-ms", &panel->delay.enable);
|
||||
device_property_read_u32(dev, "panel-disable-delay-ms", &panel->delay.disable);
|
||||
device_property_read_u32(dev, "panel-unprepare-delay-ms", &panel->delay.unprepare);
|
||||
device_property_read_u32(dev, "panel-reset-delay-ms", &panel->delay.reset);
|
||||
device_property_read_u32(dev, "panel-init-delay-ms", &panel->delay.init);
|
||||
|
||||
rk628->panel = panel;
|
||||
|
||||
if (rk628->output_mode == OUTPUT_MODE_DSI) {
|
||||
if (rk628_output_is_dsi(rk628)) {
|
||||
ret = dsi_panel_get_cmds(rk628, np);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get cmds\n");
|
||||
@@ -189,57 +196,75 @@ int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np)
|
||||
|
||||
void rk628_panel_prepare(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_panel_simple *p = rk628->panel;
|
||||
int ret;
|
||||
|
||||
if (rk628->panel->supply) {
|
||||
ret = regulator_enable(rk628->panel->supply);
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (p->supply) {
|
||||
ret = regulator_enable(p->supply);
|
||||
if (ret)
|
||||
dev_info(rk628->dev, "failed to enable panel power supply\n");
|
||||
|
||||
}
|
||||
|
||||
if (rk628->panel->enable_gpio) {
|
||||
gpiod_set_value(rk628->panel->enable_gpio, 0);
|
||||
mdelay(120);
|
||||
gpiod_set_value(rk628->panel->enable_gpio, 1);
|
||||
mdelay(120);
|
||||
}
|
||||
gpiod_direction_output(p->enable_gpio, 1);
|
||||
if (p->delay.prepare)
|
||||
msleep(p->delay.prepare);
|
||||
|
||||
if (rk628->panel->reset_gpio) {
|
||||
gpiod_set_value(rk628->panel->reset_gpio, 0);
|
||||
mdelay(120);
|
||||
gpiod_set_value(rk628->panel->reset_gpio, 1);
|
||||
mdelay(120);
|
||||
gpiod_set_value(rk628->panel->reset_gpio, 0);
|
||||
mdelay(120);
|
||||
}
|
||||
gpiod_direction_output(p->reset_gpio, 1);
|
||||
|
||||
if (p->delay.reset)
|
||||
msleep(p->delay.reset);
|
||||
|
||||
gpiod_direction_output(p->reset_gpio, 0);
|
||||
|
||||
if (p->delay.init)
|
||||
msleep(p->delay.init);
|
||||
}
|
||||
|
||||
void rk628_panel_enable(struct rk628 *rk628)
|
||||
{
|
||||
if (rk628->panel->backlight)
|
||||
backlight_enable(rk628->panel->backlight);
|
||||
struct rk628_panel_simple *p = rk628->panel;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (p->delay.enable)
|
||||
msleep(p->delay.enable);
|
||||
|
||||
if (p->backlight)
|
||||
backlight_enable(p->backlight);
|
||||
}
|
||||
|
||||
void rk628_panel_unprepare(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_panel_simple *p = rk628->panel;
|
||||
|
||||
if (rk628->panel->reset_gpio) {
|
||||
gpiod_set_value(rk628->panel->reset_gpio, 1);
|
||||
mdelay(120);
|
||||
}
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (rk628->panel->enable_gpio) {
|
||||
gpiod_set_value(rk628->panel->enable_gpio, 0);
|
||||
mdelay(120);
|
||||
}
|
||||
gpiod_direction_output(p->reset_gpio, 1);
|
||||
gpiod_direction_output(p->enable_gpio, 0);
|
||||
|
||||
if (rk628->panel->supply)
|
||||
regulator_disable(rk628->panel->supply);
|
||||
|
||||
if (p->delay.unprepare)
|
||||
msleep(p->delay.unprepare);
|
||||
}
|
||||
|
||||
void rk628_panel_disable(struct rk628 *rk628)
|
||||
{
|
||||
if (rk628->panel->backlight)
|
||||
backlight_disable(rk628->panel->backlight);
|
||||
struct rk628_panel_simple *p = rk628->panel;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
if (p->backlight)
|
||||
backlight_disable(p->backlight);
|
||||
|
||||
if (p->delay.disable)
|
||||
msleep(p->delay.disable);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/of.h>
|
||||
@@ -18,7 +19,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define DRIVER_VERSION "0.0.1"
|
||||
#define DRIVER_VERSION "0.1.0"
|
||||
#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
|
||||
#define HIWORD_UPDATE(v, h, l) ((((v) << (l)) & GENMASK((h), (l))) | \
|
||||
(GENMASK((h), (l)) << 16))
|
||||
@@ -38,8 +39,16 @@
|
||||
#define SW_BT_DATA_OEN BIT(9)
|
||||
#define SW_EFUSE_HDCP_EN_MASK BIT(8)
|
||||
#define SW_EFUSE_HDCP_EN(x) UPDATE(x, 8, 8)
|
||||
#define SW_OUTPUT_MODE_MASK GENMASK(7, 3)
|
||||
#define SW_OUTPUT_MODE(x) UPDATE(x, 7, 3)
|
||||
#define SW_OUTPUT_MODE_MASK GENMASK(5, 3)
|
||||
#define SW_OUTPUT_MODE(x) UPDATE(x, 5, 3)
|
||||
/* compatible with rk628f */
|
||||
#define SW_OUTPUT_RGB_MODE_MASK GENMASK(7, 6)
|
||||
#define SW_OUTPUT_RGB_MODE(x) UPDATE(x, 7, 6)
|
||||
#define SW_HDMITX_EN_MASK BIT(5)
|
||||
#define SW_HDMITX_EN(x) UPDATE(x, 5, 5)
|
||||
#define SW_OUTPUT_COMBTX_MODE_MASK GENMASK(4, 3)
|
||||
#define SW_OUTPUT_COMBTX_MODE(x) UPDATE(x, 4, 3)
|
||||
|
||||
#define SW_INPUT_MODE_MASK GENMASK(2, 0)
|
||||
#define SW_INPUT_MODE(x) UPDATE(x, 2, 0)
|
||||
#define GRF_SYSTEM_CON1 0x0004
|
||||
@@ -51,7 +60,14 @@
|
||||
#define GRF_GPIO_RXDDC_SDA_SEL(x) UPDATE(x, 6, 6)
|
||||
#define GRF_GPIO_RXDDC_SCL_SEL_MASK BIT(5)
|
||||
#define GRF_GPIO_RXDDC_SCL_SEL(x) UPDATE(x, 5, 5)
|
||||
#define GRF_DPHY_CH1_EN_MASK BIT(1)
|
||||
#define GRF_DPHY_CH1_EN(x) UPDATE(x, 1, 1)
|
||||
#define GRF_AS_DSIPHY_MASK BIT(0)
|
||||
#define GRF_AS_DSIPHY(x) UPDATE(x, 0, 0)
|
||||
#define GRF_SCALER_CON0 0x0010
|
||||
#define SCL_8_PIXEL_ALIGN(x) HIWORD_UPDATE(x, 12, 12)
|
||||
#define SCL_COLOR_VER_EN(x) HIWORD_UPDATE(x, 10, 10)
|
||||
#define SCL_COLOR_BAR_EN(x) HIWORD_UPDATE(x, 9, 9)
|
||||
#define SCL_VER_DOWN_MODE(x) HIWORD_UPDATE(x, 8, 8)
|
||||
#define SCL_HOR_DOWN_MODE(x) HIWORD_UPDATE(x, 7, 7)
|
||||
#define SCL_BIC_COE_SEL(x) HIWORD_UPDATE(x, 6, 5)
|
||||
@@ -83,6 +99,8 @@
|
||||
#define DSP_VBOR_ST(x) UPDATE(x, 28, 16)
|
||||
#define DSP_VBOR_END(x) UPDATE(x, 12, 0)
|
||||
#define GRF_POST_PROC_CON 0x0034
|
||||
#define SW_HDMITX_VSYNC_POL BIT(17)
|
||||
#define SW_HDMITX_HSYNC_POL BIT(16)
|
||||
#define SW_DCLK_OUT_INV_EN BIT(9)
|
||||
#define SW_DCLK_IN_INV_EN BIT(8)
|
||||
#define SW_TXPHY_REFCLK_SEL_MASK GENMASK(6, 5)
|
||||
@@ -93,6 +111,8 @@
|
||||
#define SW_SPLIT_MODE(x) UPDATE(x, 1, 1)
|
||||
#define SW_SPLIT_EN BIT(0)
|
||||
#define GRF_CSC_CTRL_CON 0x0038
|
||||
#define SW_Y2R_MODE(x) HIWORD_UPDATE(x, 13, 12)
|
||||
#define SW_FROM_CSC_MATRIX_EN(x) HIWORD_UPDATE(x, 11, 11)
|
||||
#define SW_YUV2VYU_SWP(x) HIWORD_UPDATE(x, 8, 8)
|
||||
#define SW_R2Y_EN(x) HIWORD_UPDATE(x, 4, 4)
|
||||
#define SW_Y2R_EN(x) HIWORD_UPDATE(x, 0, 0)
|
||||
@@ -179,7 +199,10 @@
|
||||
#define GRF_GPIO3A_D1_CON 0x00e4
|
||||
#define GRF_GPIO3B_D_CON 0x00e8
|
||||
#define GRF_GPIO_SR_CON 0x00ec
|
||||
#define GRF_SW_HDMIRXPHY_CRTL 0x00f4
|
||||
#define GRF_INTR0_EN 0x0100
|
||||
#define RK628F_HDMIRX_IRQ_EN(x) HIWORD_UPDATE(x, 9, 9)
|
||||
#define RK628D_HDMIRX_IRQ_EN(x) HIWORD_UPDATE(x, 8, 8)
|
||||
#define GRF_INTR0_CLR_EN 0x0104
|
||||
#define GRF_INTR0_STATUS 0x0108
|
||||
#define GRF_INTR0_RAW_STATUS 0x010c
|
||||
@@ -191,18 +214,53 @@
|
||||
/* 0: i2c mode and mcu mode; 1: i2c mode only */
|
||||
#define I2C_ONLY_FLAG BIT(6)
|
||||
#define GRF_SYSTEM_STATUS3 0x012c
|
||||
#define DECODER_1120_LAST_LINE_NUM_MASK GENMASK(12, 0)
|
||||
#define GRF_SYSTEM_STATUS4 0x0130
|
||||
#define DECODER_1120_LAST_PIX_NUM_MASK GENMASK(12, 0)
|
||||
#define GRF_OS_REG0 0x0140
|
||||
#define GRF_OS_REG1 0x0144
|
||||
#define GRF_OS_REG2 0x0148
|
||||
#define GRF_OS_REG3 0x014c
|
||||
#define GRF_SOC_VERSION 0x0150
|
||||
#define GRF_MAX_REGISTER GRF_SOC_VERSION
|
||||
#define GRF_RGB_RX_DBG_MEAS0 0x0170
|
||||
#define RGB_RX_EVAL_TIME_MASK GENMASK(27, 16)
|
||||
#define RGB_RX_MODET_EN BIT(1)
|
||||
#define RGB_RX_DCLK_EN BIT(0)
|
||||
#define GRF_RGB_RX_DBG_MEAS2 0x0178
|
||||
#define RGB_RX_CLKRATE_MASK GENMASK(15, 0)
|
||||
#define GRF_RGB_RX_DBG_MEAS3 0x017c
|
||||
#define RGB_RX_CNT_EN_MASK BIT(0)
|
||||
#define RGB_RX_CNT_EN(x) UPDATE(x, 0, 0)
|
||||
#define GRF_RGB_RX_DBG_MEAS4 0x0180
|
||||
#define GRF_BT1120_TIMING_CTRL0 0x0190
|
||||
#define BT1120_DSP_HS_END(x) UPDATE(x, 28, 16)
|
||||
#define BT1120_DSP_HTOTAL(x) UPDATE(x, 12, 0)
|
||||
#define GRF_BT1120_TIMING_CTRL1 0x0194
|
||||
#define BT1120_DSP_HACT_ST(x) UPDATE(x, 28, 16)
|
||||
#define GRF_BT1120_TIMING_CTRL2 0x0198
|
||||
#define BT1120_DSP_VS_END(x) UPDATE(x, 28, 16)
|
||||
#define BT1120_DSP_VTOTAL(x) UPDATE(x, 12, 0)
|
||||
#define GRF_BT1120_TIMING_CTRL3 0x019c
|
||||
#define BT1120_DSP_VACT_ST(x) UPDATE(x, 28, 16)
|
||||
#define GRF_CSC_MATRIX_COE01_COE00 0x01a0
|
||||
#define GRF_CSC_MATRIX_COE10_COE02 0x01a4
|
||||
#define GRF_CSC_MATRIX_COE12_COE11 0x01a8
|
||||
#define GRF_CSC_MATRIX_COE21_COE20 0x01ac
|
||||
#define GRF_CSC_MATRIX_COE22 0x01b0
|
||||
#define GRF_CSC_MATRIX_OFFSET0 0x01b4
|
||||
#define GRF_CSC_MATRIX_OFFSET1 0x01b8
|
||||
#define GRF_CSC_MATRIX_OFFSET2 0x01bc
|
||||
#define GRF_SOC_VERSION 0x0200
|
||||
#define GRF_OBS_REG 0X0300
|
||||
#define GRF_MAX_REGISTER GRF_OBS_REG
|
||||
|
||||
#define DRM_MODE_FLAG_PHSYNC (1<<0)
|
||||
#define DRM_MODE_FLAG_NHSYNC (1<<1)
|
||||
#define DRM_MODE_FLAG_PVSYNC (1<<2)
|
||||
#define DRM_MODE_FLAG_NVSYNC (1<<3)
|
||||
#define DRM_MODE_FLAG_INTERLACE (1<<4)
|
||||
|
||||
#define RK628D_VERSION 0x20200326
|
||||
#define RK628F_VERSION 0x20230321
|
||||
|
||||
enum {
|
||||
COMBTXPHY_MODULEA_EN = BIT(0),
|
||||
@@ -317,7 +375,63 @@ enum rk628_mode_sync_pol {
|
||||
MODE_FLAG_PSYNC,
|
||||
};
|
||||
|
||||
#undef BT1120_DUAL_EDGE
|
||||
/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
|
||||
enum rk628_v4l2_colorspace {
|
||||
/*
|
||||
* Default colorspace, i.e. let the driver figure it out.
|
||||
* Can only be used with video capture.
|
||||
*/
|
||||
V4L2_COLORSPACE_DEFAULT = 0,
|
||||
|
||||
/* SMPTE 170M: used for broadcast NTSC/PAL SDTV */
|
||||
V4L2_COLORSPACE_SMPTE170M = 1,
|
||||
|
||||
/* Obsolete pre-1998 SMPTE 240M HDTV standard, superseded by Rec 709 */
|
||||
V4L2_COLORSPACE_SMPTE240M = 2,
|
||||
|
||||
/* Rec.709: used for HDTV */
|
||||
V4L2_COLORSPACE_REC709 = 3,
|
||||
|
||||
/*
|
||||
* Deprecated, do not use. No driver will ever return this. This was
|
||||
* based on a misunderstanding of the bt878 datasheet.
|
||||
*/
|
||||
V4L2_COLORSPACE_BT878 = 4,
|
||||
|
||||
/*
|
||||
* NTSC 1953 colorspace. This only makes sense when dealing with
|
||||
* really, really old NTSC recordings. Superseded by SMPTE 170M.
|
||||
*/
|
||||
V4L2_COLORSPACE_470_SYSTEM_M = 5,
|
||||
|
||||
/*
|
||||
* EBU Tech 3213 PAL/SECAM colorspace. This only makes sense when
|
||||
* dealing with really old PAL/SECAM recordings. Superseded by
|
||||
* SMPTE 170M.
|
||||
*/
|
||||
V4L2_COLORSPACE_470_SYSTEM_BG = 6,
|
||||
|
||||
/*
|
||||
* Effectively shorthand for V4L2_COLORSPACE_SRGB, V4L2_YCBCR_ENC_601
|
||||
* and V4L2_QUANTIZATION_FULL_RANGE. To be used for (Motion-)JPEG.
|
||||
*/
|
||||
V4L2_COLORSPACE_JPEG = 7,
|
||||
|
||||
/* For RGB colorspaces such as produces by most webcams. */
|
||||
V4L2_COLORSPACE_SRGB = 8,
|
||||
|
||||
/* opRGB colorspace */
|
||||
V4L2_COLORSPACE_OPRGB = 9,
|
||||
|
||||
/* BT.2020 colorspace, used for UHDTV. */
|
||||
V4L2_COLORSPACE_BT2020 = 10,
|
||||
|
||||
/* Raw colorspace: for RAW unprocessed images */
|
||||
V4L2_COLORSPACE_RAW = 11,
|
||||
|
||||
/* DCI-P3 colorspace, used by cinema projectors */
|
||||
V4L2_COLORSPACE_DCI_P3 = 12,
|
||||
};
|
||||
|
||||
struct rk628_videomode {
|
||||
u32 pixelclock; /* pixelclock in Hz */
|
||||
@@ -366,7 +480,7 @@ struct panel_cmds {
|
||||
int cmd_cnt;
|
||||
};
|
||||
|
||||
struct panel_simple {
|
||||
struct rk628_panel_simple {
|
||||
struct backlight_device *backlight;
|
||||
|
||||
struct regulator *supply;
|
||||
@@ -374,6 +488,15 @@ struct panel_simple {
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct panel_cmds *on_cmds;
|
||||
struct panel_cmds *off_cmds;
|
||||
|
||||
struct {
|
||||
unsigned int prepare;
|
||||
unsigned int enable;
|
||||
unsigned int disable;
|
||||
unsigned int unprepare;
|
||||
unsigned int reset;
|
||||
unsigned int init;
|
||||
} delay;
|
||||
};
|
||||
|
||||
struct rk628_dsi {
|
||||
@@ -386,6 +509,7 @@ struct rk628_dsi {
|
||||
uint8_t lanes;
|
||||
uint8_t id; /* 0:dsi0 1:dsi1 */
|
||||
struct rk628 *rk628;
|
||||
unsigned int lane_mbps; /* per lane */
|
||||
};
|
||||
|
||||
struct rk628_lvds {
|
||||
@@ -396,6 +520,7 @@ struct rk628_lvds {
|
||||
struct rk628_gvi {
|
||||
enum gvi_bus_format bus_format;
|
||||
enum gvi_color_depth color_depth;
|
||||
int retry_times;
|
||||
uint8_t lanes;
|
||||
bool division_mode;
|
||||
bool frm_rst;
|
||||
@@ -413,6 +538,11 @@ struct rk628_combtxphy {
|
||||
bool division_mode;
|
||||
};
|
||||
|
||||
struct rk628_rgb {
|
||||
struct regulator *vccio_rgb;
|
||||
bool bt1120_dual_edge;
|
||||
};
|
||||
|
||||
struct rk628 {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
@@ -425,13 +555,15 @@ struct rk628 {
|
||||
struct clk *soc_24M;
|
||||
struct workqueue_struct *monitor_wq;
|
||||
struct delayed_work delay_work;
|
||||
struct dentry *debug_dir;
|
||||
struct workqueue_struct *dsi_wq;
|
||||
struct delayed_work dsi_delay_work;
|
||||
struct panel_simple *panel;
|
||||
struct rk628_panel_simple *panel;
|
||||
void *hdmirx;
|
||||
void *hdmitx;
|
||||
bool display_enabled;
|
||||
enum rk628_input_mode input_mode;
|
||||
enum rk628_output_mode output_mode;
|
||||
u32 input_mode;
|
||||
u32 output_mode;
|
||||
struct rk628_display_mode src_mode;
|
||||
struct rk628_display_mode dst_mode;
|
||||
enum bus_format input_fmt;
|
||||
@@ -443,8 +575,62 @@ struct rk628 {
|
||||
struct rk628_combtxphy combtxphy;
|
||||
int sync_pol;
|
||||
void *csi;
|
||||
struct notifier_block fb_nb;
|
||||
u32 version;
|
||||
struct rk628_rgb rgb;
|
||||
int old_blank;
|
||||
};
|
||||
|
||||
static inline bool rk628_input_is_hdmi(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->input_mode & BIT(INPUT_MODE_HDMI);
|
||||
}
|
||||
|
||||
static inline bool rk628_input_is_rgb(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->input_mode & BIT(INPUT_MODE_RGB);
|
||||
}
|
||||
|
||||
static inline bool rk628_input_is_bt1120(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->input_mode & BIT(INPUT_MODE_BT1120);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_rgb(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_RGB);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_bt1120(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_BT1120);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_gvi(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_GVI);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_lvds(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_LVDS);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_dsi(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_DSI);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_csi(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_CSI);
|
||||
}
|
||||
|
||||
static inline bool rk628_output_is_hdmi(struct rk628 *rk628)
|
||||
{
|
||||
return rk628->output_mode & BIT(OUTPUT_MODE_HDMI);
|
||||
}
|
||||
|
||||
static inline int rk628_i2c_write(struct rk628 *rk628, u32 reg, u32 val)
|
||||
{
|
||||
int region = (reg >> 16) & 0xff;
|
||||
|
||||
@@ -41,10 +41,20 @@ static void rk628_combtxphy_dsi_power_on(struct rk628 *rk628)
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev, "phy is not lock\n");
|
||||
|
||||
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON9,
|
||||
SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK,
|
||||
SW_DSI_FSET_EN | SW_DSI_RCAL_EN);
|
||||
SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK,
|
||||
SW_DSI_FSET_EN | SW_DSI_RCAL_EN(1));
|
||||
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON6,
|
||||
SW_PLL_CTL_CON0_MASK,
|
||||
SW_PLL_CTL_CON0(1));
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON9,
|
||||
SW_DSI_LPTX_SR_TRIM_MASK |
|
||||
SW_DSI_HSTX_AMP_TRIM_MASK,
|
||||
SW_DSI_LPTX_SR_TRIM(0) |
|
||||
SW_DSI_HSTX_AMP_TRIM(4));
|
||||
}
|
||||
|
||||
usleep_range(200, 400);
|
||||
}
|
||||
@@ -57,11 +67,15 @@ static void rk628_combtxphy_lvds_power_on(struct rk628 *rk628)
|
||||
int ret;
|
||||
|
||||
/* Adjust terminal resistance 133 ohm, bypass 0.95v ldo for driver. */
|
||||
if (rk628->version == RK628F_VERSION)
|
||||
val = TX_COM_VOLT_ADJ(3);
|
||||
else
|
||||
val = TX_COM_VOLT_ADJ(0);
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON7,
|
||||
SW_TX_RTERM_MASK | SW_TX_MODE_MASK |
|
||||
BYPASS_095V_LDO_MASK | TX_COM_VOLT_ADJ_MASK,
|
||||
SW_TX_RTERM(6) | SW_TX_MODE(3) |
|
||||
BYPASS_095V_LDO(1) | TX_COM_VOLT_ADJ(0));
|
||||
BYPASS_095V_LDO(1) | val);
|
||||
|
||||
rk628_i2c_write(rk628, COMBTXPHY_CON10, TX7_CKDRV_EN | TX2_CKDRV_EN);
|
||||
rk628_i2c_update_bits(rk628, COMBTXPHY_CON0,
|
||||
@@ -263,7 +277,9 @@ void rk628_combtxphy_set_mode(struct rk628 *rk628, enum phy_mode mode)
|
||||
else
|
||||
combtxphy->rate_div = 1;
|
||||
fvco = bus_width * combtxphy->rate_div;
|
||||
ref_clk = rk628_cru_clk_get_rate(rk628, CGU_SCLK_VOP) / 1000; /* khz */
|
||||
ref_clk = rk628_cru_clk_get_rate(rk628, CGU_SCLK_VOP);
|
||||
ref_clk = DIV_ROUND_CLOSEST_ULL(ref_clk, 1000); /* khz */
|
||||
|
||||
if (combtxphy->division_mode)
|
||||
ref_clk /= 2;
|
||||
/*
|
||||
@@ -284,7 +300,7 @@ void rk628_combtxphy_set_mode(struct rk628 *rk628, enum phy_mode mode)
|
||||
/*
|
||||
* ref_clk / ref_div * 8 * fb_div = FVCO
|
||||
*/
|
||||
pre_clk = (unsigned long long)fvco / 8 * combtxphy->ref_div * 1024;
|
||||
pre_clk = (unsigned long long)fvco * combtxphy->ref_div / 8 * 1024;
|
||||
do_div(pre_clk, ref_clk);
|
||||
fb_div = pre_clk / 1024;
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
#define SW_PLL_FB_DIV(x) UPDATE(x, 14, 10)
|
||||
#define SW_PLL_FRAC_DIV(x) UPDATE(x, 9, 0)
|
||||
#define COMBTXPHY_CON6 REG(0x0018)
|
||||
#define SW_PLL_CTL_CON0_MASK GENMASK(2, 0)
|
||||
#define SW_PLL_CTL_CON0(x) UPDATE(x, 2, 0)
|
||||
#define COMBTXPHY_CON7 REG(0x001c)
|
||||
#define SW_TX_RTERM_MASK GENMASK(22, 20)
|
||||
#define SW_TX_RTERM(x) UPDATE(x, 22, 20)
|
||||
@@ -60,7 +62,13 @@
|
||||
#define SW_DSI_FSET_EN_MASK BIT(29)
|
||||
#define SW_DSI_FSET_EN BIT(29)
|
||||
#define SW_DSI_RCAL_EN_MASK BIT(28)
|
||||
#define SW_DSI_RCAL_EN BIT(28)
|
||||
#define SW_DSI_RCAL_EN(x) UPDATE(x, 28, 28)
|
||||
#define SW_DSI_RCAL_TRIM_MASK GENMASK(27, 24)
|
||||
#define SW_DSI_RCAL_TRIM(x) UPDATE(x, 27, 24)
|
||||
#define SW_DSI_LPTX_SR_TRIM_MASK GENMASK(6, 4)
|
||||
#define SW_DSI_LPTX_SR_TRIM(x) UPDATE(x, 6, 4)
|
||||
#define SW_DSI_HSTX_AMP_TRIM_MASK GENMASK(2, 0)
|
||||
#define SW_DSI_HSTX_AMP_TRIM(x) UPDATE(x, 2, 0)
|
||||
#define COMBTXPHY_CON10 REG(0x0028)
|
||||
#define TX9_CKDRV_EN BIT(9)
|
||||
#define TX8_CKDRV_EN BIT(8)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include "asm-generic/errno-base.h"
|
||||
#include "rk628.h"
|
||||
#include "rk628_cru.h"
|
||||
|
||||
@@ -65,6 +66,9 @@ static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628,
|
||||
u64 foutvco, foutpostdiv;
|
||||
u32 offset, val;
|
||||
|
||||
if (id == CGU_CLK_APLL && rk628->version < RK628F_VERSION)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_MODE_CON00, &val);
|
||||
if (id == CGU_CLK_CPLL) {
|
||||
val &= CLK_CPLL_MODE_MASK;
|
||||
@@ -73,13 +77,20 @@ static unsigned long rk628_cru_clk_get_rate_pll(struct rk628 *rk628,
|
||||
return parent_rate;
|
||||
|
||||
offset = 0x00;
|
||||
} else {
|
||||
} else if (id == CGU_CLK_GPLL) {
|
||||
val &= CLK_GPLL_MODE_MASK;
|
||||
val >>= CLK_GPLL_MODE_SHIFT;
|
||||
if (val == CLK_GPLL_MODE_OSC)
|
||||
return parent_rate;
|
||||
|
||||
offset = 0x20;
|
||||
} else {
|
||||
val &= CLK_APLL_MODE_MASK;
|
||||
val >>= CLK_APLL_MODE_SHIFT;
|
||||
if (val == CLK_APLL_MODE_OSC)
|
||||
return parent_rate;
|
||||
|
||||
offset = 0x40;
|
||||
}
|
||||
|
||||
rk628_i2c_read(rk628, offset + CRU_CPLL_CON0, &con0);
|
||||
@@ -123,7 +134,7 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
u8 dsmpd = 1, postdiv1 = 0, postdiv2 = 0, refdiv = 0;
|
||||
u16 fbdiv = 0;
|
||||
u32 frac = 0;
|
||||
u64 foutvco, foutpostdiv;
|
||||
u64 foutvco, foutpostdiv, div1, div2;
|
||||
u32 offset, val;
|
||||
|
||||
/*
|
||||
@@ -140,10 +151,13 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
|
||||
if (id == CGU_CLK_CPLL)
|
||||
offset = 0x00;
|
||||
else
|
||||
else if (id == CGU_CLK_GPLL)
|
||||
offset = 0x20;
|
||||
else
|
||||
offset = 0x40;
|
||||
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(1));
|
||||
if (id != CGU_CLK_APLL)
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(1));
|
||||
|
||||
if (fin == fout) {
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON0, PLL_BYPASS(1));
|
||||
@@ -162,21 +176,24 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
max_refdiv = 64;
|
||||
|
||||
if (fout < MIN_FVCO_RATE) {
|
||||
postdiv = MIN_FVCO_RATE / fout + 1;
|
||||
|
||||
for (postdiv2 = 1; postdiv2 < 8; postdiv2++) {
|
||||
if (postdiv % postdiv2)
|
||||
div1 = DIV_ROUND_UP(MIN_FVCO_RATE, fout);
|
||||
div2 = DIV_ROUND_UP(MAX_FVCO_RATE, fout);
|
||||
for (postdiv = div1; postdiv <= div2; postdiv++) {
|
||||
/* fix prime number that can not find right div*/
|
||||
for (postdiv2 = 1; postdiv2 < 8; postdiv2++) {
|
||||
if (postdiv % postdiv2)
|
||||
continue;
|
||||
postdiv1 = postdiv / postdiv2;
|
||||
if (postdiv1 > 0 && postdiv1 < 8)
|
||||
break;
|
||||
}
|
||||
if (postdiv2 > 7)
|
||||
continue;
|
||||
|
||||
postdiv1 = postdiv / postdiv2;
|
||||
|
||||
if (postdiv1 > 0 && postdiv1 < 8)
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (postdiv2 > 7)
|
||||
if (postdiv > div2)
|
||||
return 0;
|
||||
|
||||
fout *= postdiv1 * postdiv2;
|
||||
} else {
|
||||
postdiv1 = 1;
|
||||
@@ -244,7 +261,9 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
PLL_REFDIV(refdiv));
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON2, PLL_FRAC(frac));
|
||||
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0));
|
||||
if (id != CGU_CLK_APLL)
|
||||
rk628_i2c_write(rk628, offset + CRU_CPLL_CON1, PLL_PD(0));
|
||||
|
||||
while (1) {
|
||||
rk628_i2c_read(rk628, offset + CRU_CPLL_CON1, &val);
|
||||
if (val & PLL_LOCK)
|
||||
@@ -297,6 +316,26 @@ static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628)
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_get_rate_clk_imodet(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate, parent_rate, n;
|
||||
u32 mux, div;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &mux);
|
||||
mux &= CLK_IMODET_SEL_MASK;
|
||||
mux >>= CLK_IMODET_SEL_SHIFT;
|
||||
if (mux == SCLK_VOP_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &div);
|
||||
n = div & 0x1f;
|
||||
rate = parent_rate / (n + 1);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628,
|
||||
unsigned long rate)
|
||||
{
|
||||
@@ -367,6 +406,51 @@ static unsigned long rk628_cru_clk_set_rate_sclk_uart(struct rk628 *rk628,
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_set_rate_sclk_hdmirx_aud(struct rk628 *rk628, unsigned long rate)
|
||||
{
|
||||
u64 parent_rate;
|
||||
u8 div;
|
||||
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_APLL, rate*4);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_set_rate_pll(rk628, CGU_CLK_GPLL, rate*4);
|
||||
div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate);
|
||||
do_div(parent_rate, div);
|
||||
rate = parent_rate;
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON05, CLK_HDMIRX_AUD_DIV(div - 1) |
|
||||
CLK_HDMIRX_AUD_SEL_V2(2));
|
||||
else
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON05, CLK_HDMIRX_AUD_DIV(div - 1) |
|
||||
CLK_HDMIRX_AUD_SEL_V1(1));
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_get_rate_sclk_hdmirx_aud(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate;
|
||||
u64 parent_rate;
|
||||
u8 div;
|
||||
u32 val;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val);
|
||||
div = ((val & CLK_HDMIRX_AUD_DIV_MASK) >> 6) + 1;
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V2) >> 14;
|
||||
else
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V1) >> 15;
|
||||
if (!val)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
else if (val == 2)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_APLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
do_div(parent_rate, div);
|
||||
rate = parent_rate;
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
rk628_cru_clk_get_rate_bt1120_dec_parent(struct rk628 *rk628)
|
||||
{
|
||||
@@ -399,7 +483,11 @@ static unsigned long rk628_cru_clk_set_rate_bt1120_dec(struct rk628 *rk628,
|
||||
int rk628_cru_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
unsigned long rate)
|
||||
{
|
||||
if (id == CGU_CLK_APLL && rk628->version < RK628F_VERSION)
|
||||
return -EINVAL;
|
||||
|
||||
switch (id) {
|
||||
case CGU_CLK_APLL:
|
||||
case CGU_CLK_CPLL:
|
||||
case CGU_CLK_GPLL:
|
||||
rk628_cru_clk_set_rate_pll(rk628, id, rate);
|
||||
@@ -416,8 +504,11 @@ int rk628_cru_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
case CGU_BT1120DEC:
|
||||
rk628_cru_clk_set_rate_bt1120_dec(rk628, rate);
|
||||
break;
|
||||
case CGU_CLK_HDMIRX_AUD:
|
||||
rk628_cru_clk_set_rate_sclk_hdmirx_aud(rk628, rate);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -427,7 +518,11 @@ unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id)
|
||||
{
|
||||
unsigned long rate;
|
||||
|
||||
if (id == CGU_CLK_APLL && rk628->version < RK628F_VERSION)
|
||||
return 0;
|
||||
|
||||
switch (id) {
|
||||
case CGU_CLK_APLL:
|
||||
case CGU_CLK_CPLL:
|
||||
case CGU_CLK_GPLL:
|
||||
rate = rk628_cru_clk_get_rate_pll(rk628, id);
|
||||
@@ -435,6 +530,12 @@ unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id)
|
||||
case CGU_SCLK_VOP:
|
||||
rate = rk628_cru_clk_get_rate_sclk_vop(rk628);
|
||||
break;
|
||||
case CGU_CLK_IMODET:
|
||||
rate = rk628_cru_clk_get_rate_clk_imodet(rk628);
|
||||
break;
|
||||
case CGU_CLK_HDMIRX_AUD:
|
||||
rate = rk628_cru_clk_get_rate_sclk_hdmirx_aud(rk628);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -449,9 +550,10 @@ void rk628_cru_init(struct rk628 *rk628)
|
||||
|
||||
rk628_i2c_read(rk628, GRF_SYSTEM_STATUS0, &val);
|
||||
mcu_mode = (val & I2C_ONLY_FLAG) ? 0 : 1;
|
||||
if (mcu_mode)
|
||||
if (mcu_mode || rk628->version >= RK628F_VERSION) {
|
||||
rk628_i2c_write(rk628, CRU_MODE_CON00, HIWORD_UPDATE(1, 4, 4));
|
||||
return;
|
||||
|
||||
}
|
||||
rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d);
|
||||
mdelay(1);
|
||||
rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004);
|
||||
|
||||
@@ -46,7 +46,16 @@
|
||||
#define CRU_GPLL_CON2 CRU_REG(0x0028)
|
||||
#define CRU_GPLL_CON3 CRU_REG(0x002c)
|
||||
#define CRU_GPLL_CON4 CRU_REG(0x0030)
|
||||
#define CRU_APLL_CON0 CRU_REG(0x0040)
|
||||
#define CRU_APLL_CON1 CRU_REG(0x0044)
|
||||
#define CRU_APLL_CON2 CRU_REG(0x0048)
|
||||
#define CRU_APLL_CON3 CRU_REG(0x004c)
|
||||
#define CRU_APLL_CON4 CRU_REG(0x0050)
|
||||
#define CRU_MODE_CON00 CRU_REG(0x0060)
|
||||
#define CLK_APLL_MODE_MASK BIT(4)
|
||||
#define CLK_APLL_MODE_SHIFT 4
|
||||
#define CLK_APLL_MODE_GPLL 1
|
||||
#define CLK_APLL_MODE_OSC 0
|
||||
#define CLK_GPLL_MODE_MASK BIT(2)
|
||||
#define CLK_GPLL_MODE_SHIFT 2
|
||||
#define CLK_GPLL_MODE_GPLL 1
|
||||
@@ -73,7 +82,19 @@
|
||||
#define CLK_BT1120DEC_DIV(x) HIWORD_UPDATE(x, 4, 0)
|
||||
#define CRU_CLKSEL_CON03 CRU_REG(0x008c)
|
||||
#define CRU_CLKSEL_CON04 CRU_REG(0x0090)
|
||||
#define CLK_HDMIRX_AUD_DIV_MASK GENMASK(13, 6)
|
||||
#define CLK_HDMIRX_AUD_DIV(x) HIWORD_UPDATE(x, 13, 6)
|
||||
#define CLK_HDMIRX_AUD_SEL_MASK GENMASK(15, 14)
|
||||
#define CLK_HDMIRX_AUD_SEL(x) HIWORD_UPDATE(x, 15, 14)
|
||||
#define CRU_CLKSEL_CON05 CRU_REG(0x0094)
|
||||
#define CLK_HDMIRX_AUD_DIV_MASK GENMASK(13, 6)
|
||||
#define CLK_HDMIRX_AUD_DIV(x) HIWORD_UPDATE(x, 13, 6)
|
||||
#define CLK_HDMIRX_AUD_SEL_V1(x) HIWORD_UPDATE(x, 15, 15)
|
||||
#define CLK_HDMIRX_AUD_SEL_MASK_V1 GENMASK(15, 15)
|
||||
#define CLK_HDMIRX_AUD_SEL_V2(x) HIWORD_UPDATE(x, 15, 14)
|
||||
#define CLK_HDMIRX_AUD_SEL_MASK_V2 GENMASK(15, 14)
|
||||
#define CLK_IMODET_SEL_MASK BIT(5)
|
||||
#define CLK_IMODET_SEL_SHIFT 5
|
||||
#define CRU_CLKSEL_CON06 CRU_REG(0x0098)
|
||||
#define SCLK_UART_SEL(x) HIWORD_UPDATE(x, 15, 14)
|
||||
#define SCLK_UART_SEL_MASK GENMASK(15, 14)
|
||||
@@ -150,6 +171,7 @@
|
||||
#define CGU_I2S_MCLKOUT 36
|
||||
#define CGU_BT1120DEC 37
|
||||
#define CGU_SCLK_UART 38
|
||||
#define CGU_CLK_APLL 39
|
||||
|
||||
unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id);
|
||||
int rk628_cru_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
|
||||
@@ -416,8 +416,15 @@ static void enable_stream(struct rk628 *rk628, bool en)
|
||||
|
||||
void rk628_csi_init(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
|
||||
SW_OUTPUT_MODE_MASK, SW_OUTPUT_MODE(OUTPUT_MODE_CSI));
|
||||
u32 mask = SW_OUTPUT_MODE_MASK;
|
||||
u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_CSI);
|
||||
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
mask = SW_OUTPUT_COMBTX_MODE_MASK;
|
||||
val = SW_OUTPUT_COMBTX_MODE(OUTPUT_MODE_CSI - 1);
|
||||
}
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
rk628_csi_get_detected_timings(rk628);
|
||||
mipi_dphy_reset(rk628);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include "rk628.h"
|
||||
#include "rk628_cru.h"
|
||||
#include "rk628_dsi.h"
|
||||
@@ -21,8 +22,6 @@
|
||||
/* use Low Power Mode to transmit message */
|
||||
#define MIPI_DSI_MSG_USE_LPM BIT(1)
|
||||
|
||||
static u32 lane_mbps;
|
||||
|
||||
enum vid_mode_type {
|
||||
VIDEO_MODE,
|
||||
COMMAND_MODE,
|
||||
@@ -237,7 +236,6 @@ int rk628_dsi_parse(struct rk628 *rk628, struct device_node *dsi_np)
|
||||
if (!of_device_is_available(dsi_np))
|
||||
return -EINVAL;
|
||||
|
||||
rk628->output_mode = OUTPUT_MODE_DSI;
|
||||
rk628->dsi0.id = 0;
|
||||
rk628->dsi0.channel = 0;
|
||||
rk628->dsi0.rk628 = rk628;
|
||||
@@ -254,6 +252,9 @@ int rk628_dsi_parse(struct rk628 *rk628, struct device_node *dsi_np)
|
||||
if (of_property_read_bool(dsi_np, "dsi,eotp"))
|
||||
rk628->dsi0.mode_flags |= MIPI_DSI_MODE_EOT_PACKET;
|
||||
|
||||
if (of_property_read_bool(dsi_np, "dsi,clk-non-continuous"))
|
||||
rk628->dsi0.mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
if (!of_property_read_string(dsi_np, "dsi,format", &string)) {
|
||||
if (!strcmp(string, "rgb666")) {
|
||||
rk628->dsi0.bus_format = MIPI_DSI_FMT_RGB666;
|
||||
@@ -697,8 +698,8 @@ static int rk628_dsi_transfer(struct rk628 *rk628, const struct rk628_dsi *dsi,
|
||||
return msg->tx_len;
|
||||
}
|
||||
|
||||
int rk628_mipi_dsi_generic_write(struct rk628 *rk628,
|
||||
const void *payload, size_t size)
|
||||
static int rk628_mipi_dsi_generic_write(struct rk628 *rk628,
|
||||
const void *payload, size_t size)
|
||||
{
|
||||
const struct rk628_dsi *dsi = &rk628->dsi0;
|
||||
struct mipi_dsi_msg msg;
|
||||
@@ -731,8 +732,8 @@ int rk628_mipi_dsi_generic_write(struct rk628 *rk628,
|
||||
return rk628_dsi_transfer(rk628, dsi, &msg);
|
||||
}
|
||||
|
||||
int rk628_mipi_dsi_dcs_write_buffer(struct rk628 *rk628,
|
||||
const void *data, size_t len)
|
||||
static int rk628_mipi_dsi_dcs_write_buffer(struct rk628 *rk628,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
const struct rk628_dsi *dsi = &rk628->dsi0;
|
||||
struct mipi_dsi_msg msg;
|
||||
@@ -763,7 +764,8 @@ int rk628_mipi_dsi_dcs_write_buffer(struct rk628 *rk628,
|
||||
return rk628_dsi_transfer(rk628, dsi, &msg);
|
||||
}
|
||||
|
||||
int rk628_mipi_dsi_dcs_read(struct rk628 *rk628, u8 cmd, void *data, size_t len)
|
||||
static __maybe_unused int rk628_mipi_dsi_dcs_read(struct rk628 *rk628, u8 cmd,
|
||||
void *data, size_t len)
|
||||
{
|
||||
const struct rk628_dsi *dsi = &rk628->dsi0;
|
||||
struct mipi_dsi_msg msg;
|
||||
@@ -823,14 +825,20 @@ panel_simple_xfer_dsi_cmd_seq(struct rk628 *rk628, struct panel_cmds *cmds)
|
||||
static u32 rk628_dsi_get_lane_rate(const struct rk628_dsi *dsi)
|
||||
{
|
||||
const struct rk628_display_mode *mode = &dsi->rk628->dst_mode;
|
||||
u32 lane_rate;
|
||||
struct device_node *dsi_np;
|
||||
u32 lane_rate, value;
|
||||
u32 max_lane_rate = 1500;
|
||||
u8 bpp, lanes;
|
||||
|
||||
bpp = dsi->bpp;
|
||||
lanes = dsi->slave ? dsi->lanes * 2 : dsi->lanes;
|
||||
lane_rate = mode->clock / 1000 * bpp / lanes;
|
||||
lane_rate = DIV_ROUND_UP(lane_rate * 5, 4);
|
||||
dsi_np = of_find_node_by_name(dsi->rk628->dev->of_node, "rk628-dsi");
|
||||
if (dsi_np && !of_property_read_u32(dsi_np, "rockchip,lane-mbps", &value)) {
|
||||
lane_rate = value;
|
||||
} else {
|
||||
bpp = dsi->bpp;
|
||||
lanes = dsi->slave ? dsi->lanes * 2 : dsi->lanes;
|
||||
lane_rate = mode->clock / 1000 * bpp / lanes;
|
||||
lane_rate = DIV_ROUND_UP(lane_rate * 5, 4);
|
||||
}
|
||||
|
||||
if (lane_rate > max_lane_rate)
|
||||
lane_rate = max_lane_rate;
|
||||
@@ -939,6 +947,65 @@ static void testif_write(struct rk628 *rk628, const struct rk628_dsi *dsi,
|
||||
dev_info(rk628->dev, "monitor_data: 0x%x\n", monitor_data);
|
||||
}
|
||||
|
||||
static void testif_set_timing(const struct rk628_dsi *dsi, u8 addr,
|
||||
u8 max, u8 val)
|
||||
{
|
||||
struct rk628 *rk628 = dsi->rk628;
|
||||
|
||||
if (val > max)
|
||||
return;
|
||||
|
||||
testif_write(rk628, dsi, addr, (max + 1) | val);
|
||||
}
|
||||
|
||||
static void mipi_dphy_set_timing(const struct rk628_dsi *dsi)
|
||||
{
|
||||
const struct {
|
||||
unsigned int min_lane_mbps;
|
||||
unsigned int max_lane_mbps;
|
||||
u8 clk_lp;
|
||||
u8 clk_hs_prepare;
|
||||
u8 clk_hs_zero;
|
||||
u8 clk_hs_trail;
|
||||
u8 clk_post;
|
||||
u8 data_lp;
|
||||
u8 data_hs_prepare;
|
||||
u8 data_hs_zero;
|
||||
u8 data_hs_trail;
|
||||
} timing_table[] = {
|
||||
{800, 899, 0x07, 0x30, 0x25, 0x3c, 0x0f, 0x07, 0x40, 0x09, 0x40},
|
||||
{1100, 1249, 0x0a, 0x43, 0x2c, 0x50, 0x0f, 0x0a, 0x43, 0x10, 0x55},
|
||||
{1250, 1349, 0x0b, 0x43, 0x2c, 0x50, 0x0f, 0x0b, 0x53, 0x10, 0x5b},
|
||||
{1350, 1449, 0x0c, 0x43, 0x36, 0x60, 0x0f, 0x0c, 0x53, 0x10, 0x65},
|
||||
{1450, 1500, 0x0f, 0x60, 0x31, 0x60, 0x0f, 0x0e, 0x60, 0x11, 0x6a}
|
||||
};
|
||||
unsigned int index;
|
||||
|
||||
if (dsi->lane_mbps < timing_table[0].min_lane_mbps)
|
||||
return;
|
||||
|
||||
for (index = 0; index < ARRAY_SIZE(timing_table); index++)
|
||||
if (dsi->lane_mbps >= timing_table[index].min_lane_mbps &&
|
||||
dsi->lane_mbps < timing_table[index].max_lane_mbps)
|
||||
break;
|
||||
|
||||
if (index == ARRAY_SIZE(timing_table))
|
||||
--index;
|
||||
|
||||
if (dsi->lane_mbps < timing_table[index].max_lane_mbps)
|
||||
return;
|
||||
|
||||
testif_set_timing(dsi, 0x60, 0x3f, timing_table[index].clk_lp);
|
||||
testif_set_timing(dsi, 0x61, 0x7f, timing_table[index].clk_hs_prepare);
|
||||
testif_set_timing(dsi, 0x62, 0x3f, timing_table[index].clk_hs_zero);
|
||||
testif_set_timing(dsi, 0x63, 0x7f, timing_table[index].clk_hs_trail);
|
||||
testif_set_timing(dsi, 0x65, 0x0f, timing_table[index].clk_post);
|
||||
testif_set_timing(dsi, 0x70, 0x3f, timing_table[index].data_lp);
|
||||
testif_set_timing(dsi, 0x71, 0x7f, timing_table[index].data_hs_prepare);
|
||||
testif_set_timing(dsi, 0x72, 0x3f, timing_table[index].data_hs_zero);
|
||||
testif_set_timing(dsi, 0x73, 0x7f, timing_table[index].data_hs_trail);
|
||||
}
|
||||
|
||||
static void mipi_dphy_init(struct rk628 *rk628, const struct rk628_dsi *dsi)
|
||||
{
|
||||
const struct {
|
||||
@@ -960,7 +1027,7 @@ static void mipi_dphy_init(struct rk628 *rk628, const struct rk628_dsi *dsi)
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < ARRAY_SIZE(hsfreqrange_table); index++)
|
||||
if (lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
|
||||
if (dsi->lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
|
||||
break;
|
||||
|
||||
if (index == ARRAY_SIZE(hsfreqrange_table))
|
||||
@@ -968,6 +1035,9 @@ static void mipi_dphy_init(struct rk628 *rk628, const struct rk628_dsi *dsi)
|
||||
|
||||
hsfreqrange = hsfreqrange_table[index].hsfreqrange;
|
||||
testif_write(rk628, dsi, 0x44, HSFREQRANGE(hsfreqrange));
|
||||
|
||||
if (rk628->version == RK628F_VERSION)
|
||||
mipi_dphy_set_timing(dsi);
|
||||
}
|
||||
|
||||
static void mipi_dphy_power_on(struct rk628 *rk628, const struct rk628_dsi *dsi)
|
||||
@@ -1024,35 +1094,35 @@ static void mipi_dphy_power_on(struct rk628 *rk628, const struct rk628_dsi *dsi)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
void rk628_dsi0_reset_control_assert(struct rk628 *rk628)
|
||||
static void rk628_dsi0_reset_control_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON02, 0x400040);
|
||||
}
|
||||
|
||||
void rk628_dsi0_reset_control_deassert(struct rk628 *rk628)
|
||||
static void rk628_dsi0_reset_control_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON02, 0x400000);
|
||||
}
|
||||
|
||||
void rk628_dsi1_reset_control_assert(struct rk628 *rk628)
|
||||
static void rk628_dsi1_reset_control_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON02, 0x800080);
|
||||
}
|
||||
|
||||
void rk628_dsi1_reset_control_deassert(struct rk628 *rk628)
|
||||
static void rk628_dsi1_reset_control_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON02, 0x800000);
|
||||
}
|
||||
|
||||
void rk628_dsi_bridge_pre_enable(struct rk628 *rk628,
|
||||
const struct rk628_dsi *dsi)
|
||||
static void rk628_dsi_bridge_pre_enable(struct rk628 *rk628,
|
||||
const struct rk628_dsi *dsi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
dsi_write(rk628, dsi, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, dsi, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
|
||||
val = DIV_ROUND_UP(lane_mbps >> 3, 20);
|
||||
val = DIV_ROUND_UP(dsi->lane_mbps >> 3, 20);
|
||||
dsi_write(rk628, dsi, DSI_CLKMGR_CFG,
|
||||
TO_CLK_DIVISION(10) | TX_ESC_CLK_DIVISION(val));
|
||||
|
||||
@@ -1082,7 +1152,7 @@ static void rk628_dsi_set_vid_mode(struct rk628 *rk628,
|
||||
const struct rk628_dsi *dsi,
|
||||
const struct rk628_display_mode *mode)
|
||||
{
|
||||
unsigned int lanebyteclk = (lane_mbps * 1000L) >> 3;
|
||||
unsigned int lanebyteclk = (dsi->lane_mbps * 1000L) >> 3;
|
||||
unsigned int dpipclk = mode->clock;
|
||||
u32 hline, hsa, hbp, hline_time, hsa_time, hbp_time;
|
||||
u32 vactive, vsa, vfp, vbp;
|
||||
@@ -1149,9 +1219,22 @@ static void rk628_dsi_set_cmd_mode(struct rk628 *rk628,
|
||||
const struct rk628_dsi *dsi,
|
||||
const struct rk628_display_mode *mode)
|
||||
{
|
||||
int cmd_size;
|
||||
|
||||
dsi_update_bits(rk628, dsi, DSI_CMD_MODE_CFG, DCS_LW_TX, 0);
|
||||
dsi_write(rk628, dsi, DSI_EDPI_CMD_SIZE,
|
||||
EDPI_ALLOWED_CMD_SIZE(mode->hdisplay));
|
||||
|
||||
/* rk628: The maximum capacity of dsi memory is 2048*32 bits */
|
||||
if (mode->hdisplay > 2048)
|
||||
cmd_size = EDPI_ALLOWED_CMD_SIZE(mode->hdisplay / 2);
|
||||
else
|
||||
cmd_size = EDPI_ALLOWED_CMD_SIZE(mode->hdisplay);
|
||||
|
||||
dsi_write(rk628, dsi, DSI_EDPI_CMD_SIZE, cmd_size);
|
||||
|
||||
if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
|
||||
dsi_update_bits(rk628, dsi, DSI_LPCLK_CTRL,
|
||||
AUTO_CLKLANE_CTRL, AUTO_CLKLANE_CTRL);
|
||||
|
||||
dsi_write(rk628, dsi, DSI_MODE_CFG, CMD_VIDEO_MODE(COMMAND_MODE));
|
||||
}
|
||||
|
||||
@@ -1204,15 +1287,86 @@ static void rk628_dsi_bridge_enable(struct rk628 *rk628,
|
||||
dsi_write(rk628, dsi, DSI_PWR_UP, POWER_UP);
|
||||
}
|
||||
|
||||
static int rk628_dsi_color_bar_show(struct seq_file *s, void *data)
|
||||
{
|
||||
seq_puts(s, " Enable color bar:\n");
|
||||
seq_puts(s, " example: echo 1 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n");
|
||||
seq_puts(s, " Disable color bar:\n");
|
||||
seq_puts(s, " example: echo 0 > /sys/kernel/debug/rk628/2-0050/dsi_color_bar\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk628_dsi_color_bar_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, rk628_dsi_color_bar_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t rk628_dsi_color_bar_write(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
struct rk628 *rk628 = ((struct seq_file *)file->private_data)->private;
|
||||
struct rk628_dsi *dsi = &rk628->dsi0;
|
||||
struct rk628_dsi *dsi1 = &rk628->dsi1;
|
||||
u8 mode;
|
||||
|
||||
if (kstrtou8_from_user(ubuf, len, 0, &mode))
|
||||
return -EFAULT;
|
||||
|
||||
dsi_update_bits(rk628, dsi, DSI_VID_MODE_CFG, VPG_EN, mode ? VPG_EN : 0);
|
||||
if (!mode) {
|
||||
dsi_write(rk628, dsi, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, dsi, DSI_PWR_UP, POWER_UP);
|
||||
}
|
||||
|
||||
if (dsi->slave) {
|
||||
dsi_update_bits(rk628, dsi1, DSI_VID_MODE_CFG, VPG_EN, mode ? VPG_EN : 0);
|
||||
if (!mode) {
|
||||
dsi_write(rk628, dsi1, DSI_PWR_UP, RESET);
|
||||
dsi_write(rk628, dsi1, DSI_PWR_UP, POWER_UP);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations rk628_dsi_color_bar_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk628_dsi_color_bar_open,
|
||||
.read = seq_read,
|
||||
.write = rk628_dsi_color_bar_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void rk628_mipi_dsi_create_debugfs_file(struct rk628 *rk628)
|
||||
{
|
||||
if (rk628_output_is_dsi(rk628))
|
||||
debugfs_create_file("dsi_color_bar", 0600, rk628->debug_dir,
|
||||
rk628, &rk628_dsi_color_bar_fops);
|
||||
}
|
||||
|
||||
void rk628_mipi_dsi_pre_enable(struct rk628 *rk628)
|
||||
{
|
||||
const struct rk628_dsi *dsi = &rk628->dsi0;
|
||||
const struct rk628_dsi *dsi1 = &rk628->dsi1;
|
||||
struct rk628_dsi *dsi = &rk628->dsi0;
|
||||
struct rk628_dsi *dsi1 = &rk628->dsi1;
|
||||
u32 rate = rk628_dsi_get_lane_rate(dsi);
|
||||
int bus_width;
|
||||
u32 mask = SW_OUTPUT_MODE_MASK;
|
||||
u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_DSI);
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_DSI));
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
mask = SW_OUTPUT_COMBTX_MODE_MASK;
|
||||
val = SW_OUTPUT_COMBTX_MODE(OUTPUT_MODE_DSI - 2);
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON3,
|
||||
GRF_DPHY_CH1_EN_MASK |
|
||||
GRF_AS_DSIPHY_MASK,
|
||||
(dsi->slave ? GRF_DPHY_CH1_EN(1) : 0) |
|
||||
GRF_AS_DSIPHY(1));
|
||||
}
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON, SW_SPLIT_EN,
|
||||
dsi->slave ? SW_SPLIT_EN : 0);
|
||||
|
||||
@@ -1226,10 +1380,10 @@ void rk628_mipi_dsi_pre_enable(struct rk628 *rk628)
|
||||
|
||||
rk628_combtxphy_set_bus_width(rk628, bus_width);
|
||||
rk628_combtxphy_set_mode(rk628, PHY_MODE_VIDEO_MIPI);
|
||||
lane_mbps = rk628_combtxphy_get_bus_width(rk628);
|
||||
dsi->lane_mbps = rk628_combtxphy_get_bus_width(rk628);
|
||||
|
||||
if (dsi->slave)
|
||||
lane_mbps = rk628_combtxphy_get_bus_width(rk628);
|
||||
if (dsi->slave && dsi1)
|
||||
dsi1->lane_mbps = rk628_combtxphy_get_bus_width(rk628);
|
||||
|
||||
/* rst for dsi0 */
|
||||
rk628_dsi0_reset_control_assert(rk628);
|
||||
@@ -1262,7 +1416,7 @@ void rk628_mipi_dsi_pre_enable(struct rk628 *rk628)
|
||||
#endif
|
||||
|
||||
dev_info(rk628->dev, "rk628_dsi final DSI-Link bandwidth: %d x %d\n",
|
||||
lane_mbps, dsi->slave ? dsi->lanes * 2 : dsi->lanes);
|
||||
dsi->lane_mbps, dsi->slave ? dsi->lanes * 2 : dsi->lanes);
|
||||
}
|
||||
|
||||
void rk628_mipi_dsi_enable(struct rk628 *rk628)
|
||||
|
||||
@@ -155,4 +155,5 @@ int rk628_dsi_parse(struct rk628 *rk628, struct device_node *dsi_np);
|
||||
void rk628_mipi_dsi_pre_enable(struct rk628 *rk628);
|
||||
void rk628_mipi_dsi_enable(struct rk628 *rk628);
|
||||
void rk628_dsi_disable(struct rk628 *rk628);
|
||||
void rk628_mipi_dsi_create_debugfs_file(struct rk628 *rk628);
|
||||
#endif
|
||||
|
||||
163
drivers/misc/rk628/rk628_efuse.c
Normal file
163
drivers/misc/rk628/rk628_efuse.c
Normal file
@@ -0,0 +1,163 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* RK628 eFuse Driver
|
||||
*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
* Author: Weixin Zhou <zwx@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include "rk628.h"
|
||||
|
||||
#define EFUSE_SIZE 64
|
||||
|
||||
#define T_CSB_P_S 0
|
||||
#define T_PGENB_P_S (15 + 200)
|
||||
#define T_LOAD_P_S 0
|
||||
#define T_ADDR_P_S (15 + 200 + 5)
|
||||
#define T_STROBE_P_S ((150 + 2000 + 100) / 9)
|
||||
#define T_CSB_P_L 0
|
||||
#define T_PGENB_P_L (15 + 200 + 10 + 200 + 190 + 10)
|
||||
#define T_LOAD_P_L (15 + 200 + 200 + 190 + 10 + 100 + 15)
|
||||
#define T_ADDR_P_L (15 + 200 + 5 + 200 + 5)
|
||||
#define T_STROBE_P_L ((150 + 2000 + 100 + 2000) / 9)
|
||||
#define T_CSB_R_S 0
|
||||
#define T_PGENB_R_S 0
|
||||
#define T_LOAD_R_S 15
|
||||
#define T_ADDR_R_S (15 + 9)
|
||||
#define T_STROBE_R_S ((150 + 100) / 9)
|
||||
#define T_CSB_R_L 0
|
||||
#define T_PGENB_R_L 0
|
||||
#define T_LOAD_R_L (15 + 5 + 5 + 10 + 15)
|
||||
#define T_ADDR_R_L (15 + 10 + 5 + 1)
|
||||
#define T_STROBE_R_L ((150 + 100 + 50) / 8)
|
||||
|
||||
#define T_CSB_P 0x28
|
||||
#define T_PGENB_P 0x2c
|
||||
#define T_LOAD_P 0x30
|
||||
#define T_ADDR_P 0x34
|
||||
#define T_STROBE_P 0x38
|
||||
#define T_CSB_R 0x3c
|
||||
#define T_PGENB_R 0x40
|
||||
#define T_LOAD_R 0x44
|
||||
#define T_ADDR_R 0x48
|
||||
#define T_STROBE_R 0x4c
|
||||
|
||||
#define RK628_EFUSE_BASE 0xb0000
|
||||
#define RK628_MOD 0x00
|
||||
#define RK628_INT_STATUS 0x0018
|
||||
#define RK628_DOUT 0x0020
|
||||
#define RK628_AUTO_CTRL 0x0024
|
||||
#define RK628_USER_MODE BIT(0)
|
||||
#define RK628_INT_FINISH BIT(0)
|
||||
#define RK628_AUTO_ENB BIT(0)
|
||||
#define RK628_AUTO_RD BIT(1)
|
||||
#define RK628_ADDR_ROW 16
|
||||
#define RK628_ADDR_COL 22
|
||||
#define RK628_A_SHIFT 16
|
||||
#define RK628_A_MASK 0x3ff
|
||||
#define RK628_NBYTES 1
|
||||
|
||||
#define REG_EFUSE_CTRL 0x0000
|
||||
#define REG_EFUSE_DOUT 0x0004
|
||||
|
||||
static inline u32 rk628_read(struct rk628 *rk628, u32 reg)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
rk628_i2c_read(rk628, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void rk628_write(struct rk628 *rk628, u32 val, u32 reg)
|
||||
{
|
||||
rk628_i2c_write(rk628, reg, val);
|
||||
}
|
||||
|
||||
static inline void rk628_efuse_timing_init(struct rk628 *rk628)
|
||||
{
|
||||
u32 base = RK628_EFUSE_BASE;
|
||||
/* enable auto mode */
|
||||
rk628_write(rk628, rk628_read(rk628, base + RK628_MOD)
|
||||
& (~RK628_USER_MODE), base + RK628_MOD);
|
||||
|
||||
/* setup efuse timing */
|
||||
rk628_write(rk628, (T_CSB_P_S << 16) | T_CSB_P_L, base + T_CSB_P);
|
||||
rk628_write(rk628, (T_PGENB_P_S << 16) | T_PGENB_P_L, base + T_PGENB_P);
|
||||
rk628_write(rk628, (T_LOAD_P_S << 16) | T_LOAD_P_L, base + T_LOAD_P);
|
||||
rk628_write(rk628, (T_ADDR_P_S << 16) | T_ADDR_P_L, base + T_ADDR_P);
|
||||
rk628_write(rk628, (T_STROBE_P_S << 16) | T_STROBE_P_L, base + T_STROBE_P);
|
||||
rk628_write(rk628, (T_CSB_R_S << 16) | T_CSB_R_L, base + T_CSB_R);
|
||||
rk628_write(rk628, (T_PGENB_R_S << 16) | T_PGENB_R_L, base + T_PGENB_R);
|
||||
rk628_write(rk628, (T_LOAD_R_S << 16) | T_LOAD_R_L, base + T_LOAD_R);
|
||||
rk628_write(rk628, (T_ADDR_R_S << 16) | T_ADDR_R_L, base + T_ADDR_R);
|
||||
rk628_write(rk628, (T_STROBE_R_S << 16) | T_STROBE_R_L, base + T_STROBE_R);
|
||||
}
|
||||
|
||||
static inline void rk628_efuse_timing_deinit(struct rk628 *rk628)
|
||||
{
|
||||
u32 base = RK628_EFUSE_BASE;
|
||||
/* disable auto mode */
|
||||
rk628_write(rk628, rk628_read(rk628, base + RK628_MOD)
|
||||
| RK628_USER_MODE, base + RK628_MOD);
|
||||
|
||||
/* clear efuse timing */
|
||||
rk628_write(rk628, 0, base + T_CSB_P);
|
||||
rk628_write(rk628, 0, base + T_PGENB_P);
|
||||
rk628_write(rk628, 0, base + T_LOAD_P);
|
||||
rk628_write(rk628, 0, base + T_ADDR_P);
|
||||
rk628_write(rk628, 0, base + T_STROBE_P);
|
||||
rk628_write(rk628, 0, base + T_CSB_R);
|
||||
rk628_write(rk628, 0, base + T_PGENB_R);
|
||||
rk628_write(rk628, 0, base + T_LOAD_R);
|
||||
rk628_write(rk628, 0, base + T_ADDR_R);
|
||||
rk628_write(rk628, 0, base + T_STROBE_R);
|
||||
}
|
||||
|
||||
int rk628_efuse_read(struct rk628 *rk628, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
unsigned int addr_start, addr_end, addr_offset, addr_len;
|
||||
u32 out_value, status;
|
||||
u8 *buf;
|
||||
int ret = 0, i = 0;
|
||||
|
||||
addr_start = rounddown(offset, RK628_NBYTES) / RK628_NBYTES;
|
||||
addr_end = roundup(offset + bytes, RK628_NBYTES) / RK628_NBYTES;
|
||||
addr_offset = offset % RK628_NBYTES;
|
||||
addr_len = addr_end - addr_start;
|
||||
|
||||
if (addr_len == 0 || addr_len > EFUSE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kzalloc(sizeof(*buf) * addr_len * RK628_NBYTES, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
rk628_efuse_timing_init(rk628);
|
||||
|
||||
while (addr_len--) {
|
||||
rk628_write(rk628, RK628_AUTO_RD | RK628_AUTO_ENB |
|
||||
((addr_start++ & RK628_A_MASK) << RK628_A_SHIFT),
|
||||
RK628_EFUSE_BASE + RK628_AUTO_CTRL);
|
||||
udelay(2);
|
||||
status = rk628_read(rk628, RK628_EFUSE_BASE + RK628_INT_STATUS);
|
||||
if (!(status & RK628_INT_FINISH)) {
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
out_value = rk628_read(rk628, RK628_EFUSE_BASE + RK628_DOUT);
|
||||
rk628_write(rk628, RK628_INT_FINISH, RK628_EFUSE_BASE + RK628_INT_STATUS);
|
||||
|
||||
memcpy(&buf[i], &out_value, RK628_NBYTES);
|
||||
i += RK628_NBYTES;
|
||||
}
|
||||
memcpy(val, buf + addr_offset, bytes);
|
||||
err:
|
||||
rk628_efuse_timing_deinit(rk628);
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
17
drivers/misc/rk628/rk628_efuse.h
Normal file
17
drivers/misc/rk628/rk628_efuse.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
* Author: Weixin Zhou <zwx@rock-chips.com>
|
||||
*/
|
||||
|
||||
#ifndef RK628_EFUSE_H
|
||||
#define RK628_EFUSE_H
|
||||
|
||||
#define EFUSE_BASE 0xb0000
|
||||
#define EFUSE_REVISION 0x50
|
||||
|
||||
int rk628_efuse_read(struct rk628 *rk628, unsigned int offset,
|
||||
void *val, size_t bytes);
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
* Author: Guochun Huang <hero.huang@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include "linux/printk.h"
|
||||
#include "rk628.h"
|
||||
#include "rk628_config.h"
|
||||
@@ -12,6 +13,8 @@
|
||||
#include "rk628_gvi.h"
|
||||
#include "panel.h"
|
||||
|
||||
#define GVI_RETRY_TIMEOUT 10
|
||||
|
||||
int rk628_gvi_parse(struct rk628 *rk628, struct device_node *gvi_np)
|
||||
{
|
||||
const char *string;
|
||||
@@ -21,8 +24,6 @@ int rk628_gvi_parse(struct rk628 *rk628, struct device_node *gvi_np)
|
||||
if (!of_device_is_available(gvi_np))
|
||||
return -EINVAL;
|
||||
|
||||
rk628->output_mode = OUTPUT_MODE_GVI;
|
||||
|
||||
if (!of_property_read_u32(gvi_np, "gvi,lanes", &val))
|
||||
rk628->gvi.lanes = val;
|
||||
|
||||
@@ -89,10 +90,17 @@ static void rk628_gvi_get_info(struct rk628_gvi *gvi)
|
||||
|
||||
static unsigned int rk628_gvi_get_lane_rate(struct rk628 *rk628)
|
||||
{
|
||||
const struct rk628_display_mode *mode = &rk628->dst_mode;
|
||||
struct rk628_gvi *gvi = &rk628->gvi;
|
||||
u32 lane_bit_rate, min_lane_rate = 500000, max_lane_rate = 4000000;
|
||||
u64 total_bw;
|
||||
struct rk628_display_mode *src = &rk628->src_mode;
|
||||
const struct rk628_display_mode *dst = &rk628->dst_mode;
|
||||
u64 dst_rate, src_rate;
|
||||
|
||||
src_rate = src->clock * 1000;
|
||||
dst_rate = src_rate * dst->vtotal * dst->htotal;
|
||||
do_div(dst_rate, (src->vtotal * src->htotal));
|
||||
do_div(dst_rate, 1000);
|
||||
|
||||
/**
|
||||
* [ENCODER TOTAL BIT-RATE](bps) = [byte mode](byte) x 10 / [pixel clock](HZ)
|
||||
@@ -101,7 +109,7 @@ static unsigned int rk628_gvi_get_lane_rate(struct rk628 *rk628)
|
||||
*
|
||||
* 500Mbps <= lane_bit_rate <= 4Gbps
|
||||
*/
|
||||
total_bw = (u64)gvi->byte_mode * 10 * mode->clock;/* Kbps */
|
||||
total_bw = (u64)gvi->byte_mode * 10 * dst_rate;/* Kbps */
|
||||
do_div(total_bw, gvi->lanes);
|
||||
lane_bit_rate = total_bw;
|
||||
|
||||
@@ -122,6 +130,8 @@ static void rk628_gvi_pre_enable(struct rk628 *rk628, struct rk628_gvi *gvi)
|
||||
rk628_i2c_update_bits(rk628, GVI_SYS_RST, SYS_RST_SOFT_RST, 0);
|
||||
udelay(10);
|
||||
|
||||
rk628_i2c_write(rk628, GRF_SCALER_CON0, SCL_8_PIXEL_ALIGN(1));
|
||||
|
||||
rk628_i2c_update_bits(rk628, GVI_SYS_CTRL0, SYS_CTRL0_LANE_NUM_MASK,
|
||||
SYS_CTRL0_LANE_NUM(gvi->lanes - 1));
|
||||
rk628_i2c_update_bits(rk628, GVI_SYS_CTRL0, SYS_CTRL0_BYTE_MODE_MASK,
|
||||
@@ -137,6 +147,9 @@ static void rk628_gvi_pre_enable(struct rk628 *rk628, struct rk628_gvi *gvi)
|
||||
rk628_i2c_update_bits(rk628, GVI_SYS_CTRL0, SYS_CTRL0_FRM_RST_EN,
|
||||
gvi->frm_rst ? SYS_CTRL0_FRM_RST_EN : 0);
|
||||
rk628_i2c_update_bits(rk628, GVI_SYS_CTRL1, SYS_CTRL1_LANE_ALIGN_EN, 0);
|
||||
|
||||
rk628_i2c_update_bits(rk628, GVI_SYS_CTRL1, SYS_CTRL1_COLOR_DEPTH_MASK,
|
||||
SYS_CTRL1_COLOR_DEPTH(gvi->color_depth));
|
||||
}
|
||||
|
||||
static void rk628_gvi_enable_color_bar(struct rk628 *rk628,
|
||||
@@ -183,6 +196,50 @@ static void rk628_gvi_enable_color_bar(struct rk628 *rk628,
|
||||
rk628_i2c_update_bits(rk628, GVI_COLOR_BAR_CTRL, COLOR_BAR_EN, 0);
|
||||
}
|
||||
|
||||
static int rk628_gvi_color_bar_show(struct seq_file *s, void *data)
|
||||
{
|
||||
seq_puts(s, " Enable color bar:\n");
|
||||
seq_puts(s, " example: echo 1 > /sys/kernel/debug/rk628/2-0050/gvi_color_bar\n");
|
||||
seq_puts(s, " Disable color bar:\n");
|
||||
seq_puts(s, " example: echo 0 > /sys/kernel/debug/rk628/2-0050/gvi_color_bar\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk628_gvi_color_bar_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, rk628_gvi_color_bar_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t rk628_gvi_color_bar_write(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
struct rk628 *rk628 = ((struct seq_file *)file->private_data)->private;
|
||||
u8 mode;
|
||||
|
||||
if (kstrtou8_from_user(ubuf, len, 0, &mode))
|
||||
return -EFAULT;
|
||||
|
||||
rk628_i2c_update_bits(rk628, GVI_COLOR_BAR_CTRL, COLOR_BAR_EN, mode ? 1 : 0);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations rk628_gvi_color_bar_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk628_gvi_color_bar_open,
|
||||
.read = seq_read,
|
||||
.write = rk628_gvi_color_bar_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void rk628_gvi_create_debugfs_file(struct rk628 *rk628)
|
||||
{
|
||||
if (rk628_output_is_gvi(rk628))
|
||||
debugfs_create_file("gvi_color_bar", 0600, rk628->debug_dir,
|
||||
rk628, &rk628_gvi_color_bar_fops);
|
||||
}
|
||||
|
||||
static void rk628_gvi_post_enable(struct rk628 *rk628, struct rk628_gvi *gvi)
|
||||
{
|
||||
@@ -196,14 +253,22 @@ void rk628_gvi_enable(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_gvi *gvi = &rk628->gvi;
|
||||
unsigned int rate;
|
||||
u32 mask = SW_OUTPUT_MODE_MASK;
|
||||
u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_GVI);
|
||||
int i = 0;
|
||||
|
||||
rk628_gvi_get_info(gvi);
|
||||
rate = rk628_gvi_get_lane_rate(rk628);
|
||||
|
||||
/* set gvi_hpd and gvi_lock mux */
|
||||
rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x06000600);
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_GVI));
|
||||
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
mask = SW_OUTPUT_COMBTX_MODE_MASK;
|
||||
val = SW_OUTPUT_COMBTX_MODE(OUTPUT_MODE_GVI);
|
||||
}
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
rk628_combtxphy_set_bus_width(rk628, rate);
|
||||
rk628_combtxphy_set_gvi_division_mode(rk628, gvi->division_mode);
|
||||
rk628_combtxphy_set_mode(rk628, PHY_MODE_VIDEO_GVI);
|
||||
@@ -213,7 +278,30 @@ void rk628_gvi_enable(struct rk628 *rk628)
|
||||
rk628_panel_prepare(rk628);
|
||||
rk628_gvi_enable_color_bar(rk628, gvi);
|
||||
rk628_gvi_post_enable(rk628, gvi);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
rk628_i2c_read(rk628, GVI_STATUS, &val);
|
||||
if ((val & GVI_LOCKED_MASK) == GVI_LOCKED_STATUS)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
|
||||
if (i == 100 && gvi->retry_times < GVI_RETRY_TIMEOUT) {
|
||||
dev_info(rk628->dev, "GVI Lock failed: 0x%x, try again: %d\n", val, gvi->retry_times);
|
||||
gvi->retry_times++;
|
||||
rk628_gvi_disable(rk628);
|
||||
usleep_range(50000, 51000);
|
||||
rk628_gvi_enable(rk628);
|
||||
}
|
||||
|
||||
if (gvi->retry_times >= GVI_RETRY_TIMEOUT && i == 100) {
|
||||
dev_info(rk628->dev, "GVI Lock failed, please check hardware!\n");
|
||||
return;
|
||||
}
|
||||
rk628_panel_enable(rk628);
|
||||
|
||||
if (i != 100)
|
||||
gvi->retry_times = 0;
|
||||
dev_info(rk628->dev,
|
||||
"GVI-Link bandwidth: %d x %d Mbps, Byte mode: %d, Color Depty: %d, %s division mode\n",
|
||||
rate, gvi->lanes, gvi->byte_mode, gvi->color_depth,
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#define GVI_SYS_RST HOSTREG(0x0014)
|
||||
#define GVI_LINE_FLAG HOSTREG(0x0018)
|
||||
#define GVI_STATUS HOSTREG(0x001c)
|
||||
#define GVI_LOCKED_MASK 0x70
|
||||
#define GVI_LOCKED_STATUS 0x40
|
||||
#define GVI_PLL_LOCK_TIMEOUT HOSTREG(0x0030)
|
||||
#define GVI_HTPDN_TIMEOUT HOSTREG(0x0034)
|
||||
#define GVI_LOCKN_TIMEOUT HOSTREG(0x0038)
|
||||
@@ -214,5 +216,5 @@
|
||||
int rk628_gvi_parse(struct rk628 *rk628, struct device_node *gvi_np);
|
||||
void rk628_gvi_enable(struct rk628 *rk628);
|
||||
void rk628_gvi_disable(struct rk628 *rk628);
|
||||
|
||||
void rk628_gvi_create_debugfs_file(struct rk628 *rk628);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -427,6 +427,7 @@
|
||||
#define MILISECTIMERLIMIT(x) UPDATE(x, 15, 0)
|
||||
#define HDMI_RX_HDCP22_CONTROL HDMIRX_REG(0x081c)
|
||||
#define HDMI_RX_SCDC_REGS0 HDMIRX_REG(0x0820)
|
||||
#define SCDC_TMDSBITCLKRATIO BIT(17)
|
||||
#define HDMI_RX_SCDC_REGS1 HDMIRX_REG(0x0824)
|
||||
#define HDMI_RX_SCDC_REGS2 HDMIRX_REG(0x0828)
|
||||
#define HDMI_RX_SCDC_REGS3 HDMIRX_REG(0x082c)
|
||||
@@ -482,6 +483,11 @@
|
||||
#define HDMI_RX_AUD_CEC_ISET HDMIRX_REG(0x0fa4)
|
||||
#define HDMI_RX_AUD_FIFO_IEN_CLR HDMIRX_REG(0x0fa8)
|
||||
#define HDMI_RX_AUD_FIFO_IEN_SET HDMIRX_REG(0x0fac)
|
||||
#define AFIF_OVERFL_ISTS BIT(4)
|
||||
#define AFIF_UNDERFL_ISTS BIT(3)
|
||||
#define AFIF_THS_PASS_ISTS BIT(2)
|
||||
#define AFIF_TH_MAX_ISTS BIT(1)
|
||||
#define AFIF_TH_MIN_ISTS BIT(0)
|
||||
#define HDMI_RX_AUD_FIFO_ISTS HDMIRX_REG(0x0fb0)
|
||||
#define HDMI_RX_AUD_FIFO_IEN HDMIRX_REG(0x0fb4)
|
||||
#define HDMI_RX_AUD_FIFO_ICLR HDMIRX_REG(0x0fb8)
|
||||
|
||||
@@ -462,6 +462,7 @@ static int rk628_hdmi_config_video_timing(struct rk628_hdmi *hdmi,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
int value;
|
||||
u32 hdmitx_sync_pol = 0;
|
||||
|
||||
/* Set detail external video timing polarity and interlace mode */
|
||||
value = EXTERANL_VIDEO(1);
|
||||
@@ -472,6 +473,12 @@ static int rk628_hdmi_config_video_timing(struct rk628_hdmi *hdmi,
|
||||
value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
|
||||
INETLACE(1) : INETLACE(0);
|
||||
hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
|
||||
hdmitx_sync_pol |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
|
||||
SW_HDMITX_VSYNC_POL : 0;
|
||||
hdmitx_sync_pol |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
|
||||
SW_HDMITX_HSYNC_POL : 0;
|
||||
rk628_i2c_update_bits(hdmi->rk628, GRF_POST_PROC_CON,
|
||||
SW_HDMITX_VSYNC_POL | SW_HDMITX_HSYNC_POL, hdmitx_sync_pol);
|
||||
|
||||
/* Set detail external video timing */
|
||||
value = mode->htotal;
|
||||
@@ -604,7 +611,12 @@ static int rk628_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
|
||||
ret = rockchip_drm_add_modes_noedid(connector);
|
||||
|
||||
#if KERNEL_VERSION(5, 18, 0) <= LINUX_VERSION_CODE
|
||||
info->edid_hdmi_ycbcr444_dc_modes = 0;
|
||||
info->edid_hdmi_rgb444_dc_modes = 0;
|
||||
#else
|
||||
info->edid_hdmi_dc_modes = 0;
|
||||
#endif
|
||||
info->hdmi.y420_dc_modes = 0;
|
||||
info->color_formats = 0;
|
||||
|
||||
@@ -709,13 +721,6 @@ static void rk628_hdmi_bridge_enable(struct drm_bridge *bridge)
|
||||
rk628_hdmi_set_pwr_mode(hdmi, NORMAL);
|
||||
}
|
||||
|
||||
static void rk628_hdmi_bridge_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct rk628_hdmi *hdmi = bridge_to_hdmi(bridge);
|
||||
|
||||
rk628_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
|
||||
}
|
||||
|
||||
static int rk628_hdmi_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
@@ -760,7 +765,6 @@ static const struct drm_bridge_funcs rk628_hdmi_bridge_funcs = {
|
||||
.mode_set = rk628_hdmi_bridge_mode_set,
|
||||
.mode_fixup = rk628_hdmi_bridge_mode_fixup,
|
||||
.enable = rk628_hdmi_bridge_enable,
|
||||
.disable = rk628_hdmi_bridge_disable,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -1091,13 +1095,127 @@ static struct i2c_adapter *rk628_hdmi_i2c_adapter(struct rk628_hdmi *hdmi)
|
||||
return adap;
|
||||
}
|
||||
|
||||
static int rk628_hdmitx_color_bar_show(struct seq_file *s, void *data)
|
||||
{
|
||||
seq_puts(s, " Enable normal color bar:\n");
|
||||
seq_puts(s, " example: echo 1 > /sys/kernel/debug/rk628/2-0050/hdmitx_color_bar\n");
|
||||
seq_puts(s, " Enable special color bar:\n");
|
||||
seq_puts(s, " example: echo 2 > /sys/kernel/debug/rk628/2-0050/hdmitx_color_bar\n");
|
||||
seq_puts(s, " Enable black color bar:\n");
|
||||
seq_puts(s, " example: echo 3 > /sys/kernel/debug/rk628/2-0050/hdmitx_color_bar\n");
|
||||
seq_puts(s, " Disable color bar:\n");
|
||||
seq_puts(s, " example: echo 0 > /sys/kernel/debug/rk628/2-0050/hdmitx_color_bar\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk628_hdmitx_color_bar_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, rk628_hdmitx_color_bar_show, inode->i_private);
|
||||
}
|
||||
|
||||
static ssize_t rk628_hdmitx_color_bar_write(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
struct rk628 *rk628 = ((struct seq_file *)file->private_data)->private;
|
||||
u8 mode;
|
||||
|
||||
if (kstrtou8_from_user(ubuf, len, 0, &mode))
|
||||
return -EFAULT;
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, DISABLE_COLORBAR_BIST_MASK,
|
||||
DISABLE_COLORBAR_BIST(1));
|
||||
break;
|
||||
case 1:
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, DISABLE_COLORBAR_BIST_MASK,
|
||||
DISABLE_COLORBAR_BIST(0));
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, VIDEO_BIST_MODE_MASK,
|
||||
VIDEO_BIST_MODE(0));
|
||||
break;
|
||||
case 2:
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, DISABLE_COLORBAR_BIST_MASK,
|
||||
DISABLE_COLORBAR_BIST(0));
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, VIDEO_BIST_MODE_MASK,
|
||||
VIDEO_BIST_MODE(1));
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, DISABLE_COLORBAR_BIST_MASK,
|
||||
DISABLE_COLORBAR_BIST(0));
|
||||
rk628_i2c_update_bits(rk628, HDMI_COLOR_BAR, VIDEO_BIST_MODE_MASK,
|
||||
VIDEO_BIST_MODE(2));
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations rk628_hdmitx_color_bar_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk628_hdmitx_color_bar_open,
|
||||
.read = seq_read,
|
||||
.write = rk628_hdmitx_color_bar_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void rk628_hdmitx_create_debugfs_file(struct rk628 *rk628)
|
||||
{
|
||||
if (rk628_output_is_hdmi(rk628))
|
||||
debugfs_create_file("hdmitx_color_bar", 0600, rk628->debug_dir,
|
||||
rk628, &rk628_hdmitx_color_bar_fops);
|
||||
}
|
||||
|
||||
void rk628_hdmitx_disable(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, HDMI_SYS_CTRL, POWER_MASK, PWR_OFF(1));
|
||||
rk628_i2c_write(rk628, HDMI_PHY_DRIVER, 0x00);
|
||||
rk628_i2c_write(rk628, HDMI_PHY_PRE_EMPHASIS, 0x00);
|
||||
rk628_i2c_write(rk628, HDMI_PHY_CHG_PWR, 0x00);
|
||||
rk628_i2c_write(rk628, HDMI_PHY_SYS_CTL, 0x15);
|
||||
}
|
||||
|
||||
int rk628_hdmitx_enable(struct rk628 *rk628)
|
||||
{
|
||||
struct device *dev = rk628->dev;
|
||||
struct rk628_hdmi *hdmi;
|
||||
u32 mask = SW_OUTPUT_MODE_MASK;
|
||||
u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_HDMI);
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
/* select int io function */
|
||||
rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x70007000);
|
||||
rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x055c055c);
|
||||
|
||||
/* hdmitx vclk pllref select Pin_vclk */
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
|
||||
SW_HDMITX_VCLK_PLLREF_SEL_MASK,
|
||||
SW_HDMITX_VCLK_PLLREF_SEL(1));
|
||||
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
mask = SW_HDMITX_EN_MASK;
|
||||
val = SW_HDMITX_EN(1);
|
||||
}
|
||||
|
||||
/* set output mode to HDMI */
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
/* hdmitx int en */
|
||||
rk628_i2c_write(rk628, GRF_INTR0_EN, 0x00040004);
|
||||
|
||||
|
||||
if (rk628->hdmitx) {
|
||||
hdmi = rk628->hdmitx;
|
||||
rk628_hdmi_reset(hdmi);
|
||||
rk628_hdmi_i2c_init(hdmi);
|
||||
/* Unmute hotplug interrupt */
|
||||
hdmi_modb(hdmi, HDMI_STATUS, MASK_INT_HOTPLUG_MASK,
|
||||
MASK_INT_HOTPLUG(1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(dev->of_node))
|
||||
return -ENODEV;
|
||||
|
||||
@@ -1108,24 +1226,13 @@ int rk628_hdmitx_enable(struct rk628 *rk628)
|
||||
|
||||
hdmi->dev = dev;
|
||||
hdmi->rk628 = rk628;
|
||||
rk628->hdmitx = hdmi;
|
||||
|
||||
irq = rk628->client->irq;
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
dev_set_drvdata(dev, hdmi);
|
||||
|
||||
/* selete int io function */
|
||||
rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x70007000);
|
||||
rk628_i2c_write(rk628, GRF_GPIO0AB_SEL_CON, 0x055c055c);
|
||||
|
||||
/* hdmitx vclk pllref select Pin_vclk */
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
|
||||
SW_HDMITX_VCLK_PLLREF_SEL_MASK,
|
||||
SW_HDMITX_VCLK_PLLREF_SEL(1));
|
||||
/* set output mode to HDMI */
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_HDMI));
|
||||
|
||||
rk628_hdmi_reset(hdmi);
|
||||
|
||||
hdmi->ddc = rk628_hdmi_i2c_adapter(hdmi);
|
||||
@@ -1142,9 +1249,6 @@ int rk628_hdmitx_enable(struct rk628 *rk628)
|
||||
* and reconfigure the DDC clock.
|
||||
*/
|
||||
hdmi->tmds_rate = 24000 * 1000;
|
||||
|
||||
/* hdmitx int en */
|
||||
rk628_i2c_write(rk628, GRF_INTR0_EN, 0x00040004);
|
||||
rk628_hdmi_i2c_init(hdmi);
|
||||
|
||||
rk628_hdmi_audio_codec_init(hdmi, dev);
|
||||
@@ -1190,6 +1294,8 @@ int rk628_hdmitx_enable(struct rk628 *rk628)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
devm_kfree(dev, hdmi);
|
||||
rk628->hdmitx = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -342,9 +342,30 @@ enum {
|
||||
#define HDMI_CEC_BUSFREETIME_L HDMITX_REG(0xdc)
|
||||
#define HDMI_CEC_BUSFREETIME_H HDMITX_REG(0xdd)
|
||||
#define HDMI_CEC_LOGICADDR HDMITX_REG(0xde)
|
||||
|
||||
#define HDMI_COLOR_BAR HDMITX_REG(0xc9)
|
||||
#define VIDEO_BIST_MODE_MASK GENMASK(7, 6)
|
||||
#define VIDEO_BIST_MODE(x) UPDATE(x, 7, 6)
|
||||
#define DISABLE_COLORBAR_BIST_MASK BIT(4)
|
||||
#define DISABLE_COLORBAR_BIST(x) UPDATE(x, 4, 4)
|
||||
#define HDMI_MAX_REG HDMITX_REG(0xed)
|
||||
|
||||
#ifdef CONFIG_RK628_MISC_HDMITX
|
||||
void rk628_hdmitx_disable(struct rk628 *rk628);
|
||||
int rk628_hdmitx_enable(struct rk628 *rk628);
|
||||
void rk628_hdmitx_create_debugfs_file(struct rk628 *rk628);
|
||||
#else
|
||||
static inline void rk628_hdmitx_disable(struct rk628 *rk628)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int rk628_hdmitx_enable(struct rk628 *rk628)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void rk628_hdmitx_create_debugfs_file(struct rk628 *rk628)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
* Author: Guochun Huang <hero.huang@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/media-bus-format.h>
|
||||
#include "rk628.h"
|
||||
|
||||
#include "rk628_lvds.h"
|
||||
#include "rk628_combtxphy.h"
|
||||
#include "rk628_config.h"
|
||||
#include "panel.h"
|
||||
@@ -24,14 +25,13 @@ static inline void lvds_update_bits(struct rk628 *rk628, u32 reg,
|
||||
|
||||
int rk628_lvds_parse(struct rk628 *rk628, struct device_node *lvds_np)
|
||||
{
|
||||
const char *string;
|
||||
const char *string = NULL;
|
||||
int ret;
|
||||
u32 bus_format;
|
||||
|
||||
if (!of_device_is_available(lvds_np))
|
||||
return -EINVAL;
|
||||
|
||||
rk628->output_mode = OUTPUT_MODE_LVDS;
|
||||
|
||||
if (!of_property_read_string(lvds_np, "bus-format", &string)) {
|
||||
if (!strcmp(string, "jeida_24"))
|
||||
rk628->lvds.format = LVDS_FORMAT_JEIDA_24BIT;
|
||||
@@ -42,6 +42,24 @@ int rk628_lvds_parse(struct rk628 *rk628, struct device_node *lvds_np)
|
||||
else
|
||||
rk628->lvds.format = LVDS_FORMAT_VESA_24BIT;
|
||||
}
|
||||
/* fallback to u32 type */
|
||||
if (!string || strlen(string) == 0) {
|
||||
if (!of_property_read_u32(lvds_np, "bus-format", &bus_format)) {
|
||||
switch (bus_format) {
|
||||
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
|
||||
rk628->lvds.format = LVDS_FORMAT_JEIDA_24BIT;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
|
||||
rk628->lvds.format = LVDS_FORMAT_JEIDA_18BIT;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
|
||||
rk628->lvds.format = LVDS_FORMAT_VESA_24BIT;
|
||||
break;
|
||||
default:
|
||||
rk628->lvds.format = LVDS_FORMAT_VESA_18BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!of_property_read_string(lvds_np, "link-type", &string)) {
|
||||
if (!strcmp(string, "dual_link_odd_even_pixels"))
|
||||
@@ -68,10 +86,17 @@ void rk628_lvds_enable(struct rk628 *rk628)
|
||||
enum lvds_link_type link_type = rk628->lvds.link_type;
|
||||
enum lvds_format format = rk628->lvds.format;
|
||||
const struct rk628_display_mode *mode = &rk628->dst_mode;
|
||||
u32 val, bus_width;
|
||||
u32 val, mask, bus_width;
|
||||
|
||||
lvds_update_bits(rk628, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_LVDS));
|
||||
mask = SW_OUTPUT_MODE_MASK;
|
||||
val = SW_OUTPUT_MODE(OUTPUT_MODE_LVDS);
|
||||
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
mask = SW_OUTPUT_COMBTX_MODE_MASK;
|
||||
val = SW_OUTPUT_COMBTX_MODE(OUTPUT_MODE_LVDS);
|
||||
}
|
||||
|
||||
lvds_update_bits(rk628, GRF_SYSTEM_CON0, mask, val);
|
||||
|
||||
switch (link_type) {
|
||||
case LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,5 +11,5 @@
|
||||
void rk628_post_process_init(struct rk628 *rk628);
|
||||
void rk628_post_process_enable(struct rk628 *rk628);
|
||||
void rk628_post_process_disable(struct rk628 *rk628);
|
||||
|
||||
void rk628_post_process_create_debugfs_file(struct rk628 *rk628);
|
||||
#endif
|
||||
|
||||
@@ -5,46 +5,185 @@
|
||||
* Author: Guochun Huang <hero.huang@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include "rk628.h"
|
||||
#include "rk628_cru.h"
|
||||
#include "rk628_config.h"
|
||||
#include "panel.h"
|
||||
#include "rk628_rgb.h"
|
||||
|
||||
void rk628_rgb_decoder_enable(struct rk628 *rk628)
|
||||
int rk628_rgb_parse(struct rk628 *rk628, struct device_node *rgb_np)
|
||||
{
|
||||
/* config sw_input_mode RGB */
|
||||
int ret = 0;
|
||||
|
||||
rk628->rgb.vccio_rgb = devm_regulator_get_optional(rk628->dev, "vccio-rgb");
|
||||
if (IS_ERR(rk628->rgb.vccio_rgb))
|
||||
rk628->rgb.vccio_rgb = NULL;
|
||||
|
||||
if ((rk628_input_is_bt1120(rk628) || rk628_output_is_bt1120(rk628)) &&
|
||||
of_property_read_bool(rk628->dev->of_node, "bt1120-dual-edge"))
|
||||
rk628->rgb.bt1120_dual_edge = true;
|
||||
|
||||
if (rk628_output_is_bt1120(rk628) || rk628_output_is_rgb(rk628))
|
||||
ret = rk628_panel_info_get(rk628, rgb_np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rk628_rgb_resolution_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct rk628 *rk628 = s->private;
|
||||
u16 width = 0, height = 0;
|
||||
u32 rgb_rx_eval_time, rgb_rx_clkrate;
|
||||
u64 ref_clk, pixel_clk;
|
||||
u32 val;
|
||||
|
||||
rk628_i2c_read(rk628, GRF_RGB_RX_DBG_MEAS0, &val);
|
||||
rgb_rx_eval_time = (val & RGB_RX_EVAL_TIME_MASK) >> 16;
|
||||
|
||||
rk628_i2c_read(rk628, GRF_RGB_RX_DBG_MEAS2, &val);
|
||||
rgb_rx_clkrate = val & RGB_RX_CLKRATE_MASK;
|
||||
|
||||
ref_clk = rk628_cru_clk_get_rate(rk628, CGU_CLK_IMODET);
|
||||
pixel_clk = ref_clk * rgb_rx_clkrate / (rgb_rx_eval_time + 1);
|
||||
|
||||
if (rk628_input_is_rgb(rk628)) {
|
||||
rk628_i2c_read(rk628, GRF_RGB_RX_DBG_MEAS4, &val);
|
||||
height = (val >> 16) & 0xffff;
|
||||
width = val & 0xffff;
|
||||
} else if (rk628_input_is_bt1120(rk628)) {
|
||||
rk628_i2c_read(rk628, GRF_SYSTEM_STATUS3, &val);
|
||||
height = val & DECODER_1120_LAST_LINE_NUM_MASK;
|
||||
|
||||
rk628_i2c_read(rk628, GRF_SYSTEM_STATUS4, &val);
|
||||
width = val & DECODER_1120_LAST_PIX_NUM_MASK;
|
||||
}
|
||||
|
||||
seq_printf(s, "%dx%d pclk:%llu\n", width, height, pixel_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk628_rgb_resolution_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, rk628_rgb_resolution_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations rk628_rgb_resolution_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk628_rgb_resolution_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void rk628_rgb_decoder_create_debugfs_file(struct rk628 *rk628)
|
||||
{
|
||||
if (rk628->version == RK628D_VERSION)
|
||||
return;
|
||||
|
||||
if (rk628_input_is_rgb(rk628) || rk628_input_is_bt1120(rk628))
|
||||
debugfs_create_file("rgb_resolution", 0400, rk628->debug_dir,
|
||||
rk628, &rk628_rgb_resolution_fops);
|
||||
}
|
||||
|
||||
static void rk628_rgb_decoder_enable(struct rk628 *rk628)
|
||||
{
|
||||
/* config sw_input_mode RGB */
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_INPUT_MODE_MASK,
|
||||
SW_INPUT_MODE(INPUT_MODE_RGB));
|
||||
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_RX_DBG_MEAS0,
|
||||
RGB_RX_MODET_EN | RGB_RX_DCLK_EN,
|
||||
RGB_RX_MODET_EN | RGB_RX_DCLK_EN);
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_RX_DBG_MEAS3,
|
||||
RGB_RX_CNT_EN_MASK, RGB_RX_CNT_EN(1));
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0, 0x10000);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1, 0);
|
||||
}
|
||||
|
||||
/* pinctrl for vop pin */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2AB_SEL_CON, 0xffffffff);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_SEL_CON, 0xffff5555);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x10b010b);
|
||||
}
|
||||
|
||||
static void rk628_rgb_encoder_enable(struct rk628 *rk628)
|
||||
{
|
||||
int voltage = 0;
|
||||
u32 d_strength, clk_strength;
|
||||
u64 dclk_delay;
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
|
||||
SW_BT_DATA_OEN_MASK | SW_OUTPUT_RGB_MODE_MASK,
|
||||
SW_OUTPUT_RGB_MODE(OUTPUT_MODE_RGB >> 3));
|
||||
|
||||
if (rk628->version != RK628F_VERSION)
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
|
||||
SW_DCLK_OUT_INV_EN, SW_DCLK_OUT_INV_EN);
|
||||
|
||||
/* pinctrl for vop pin */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2AB_SEL_CON, 0xffffffff);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_SEL_CON, 0xffff5555);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x10b010b);
|
||||
|
||||
/*
|
||||
* Under the same drive strength and DCLK delay, the signal behaves
|
||||
* differently under different voltage power domains. In order to
|
||||
* center the eye diagram of the signal, have sufficient signal setup
|
||||
* and hold time, and ensure that the signal does not overshoot, the
|
||||
* drive strength and DCLK delay need to be set for the power domains
|
||||
* of different voltages.
|
||||
*/
|
||||
if (rk628->rgb.vccio_rgb)
|
||||
voltage = regulator_get_voltage(rk628->rgb.vccio_rgb);
|
||||
|
||||
switch (voltage) {
|
||||
case 1800000:
|
||||
d_strength = 3;
|
||||
clk_strength = 3;
|
||||
dclk_delay = 0x10000000;
|
||||
break;
|
||||
case 3300000:
|
||||
d_strength = 1;
|
||||
clk_strength = 2;
|
||||
dclk_delay = 0x100000000;
|
||||
break;
|
||||
default:
|
||||
d_strength = 1;
|
||||
clk_strength = 2;
|
||||
dclk_delay = 0x100000000;
|
||||
}
|
||||
|
||||
/* rk628: modify IO drive strength for RGB */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3A_D0_CON, 0xffff1011);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3B_D_CON, 0x10001);
|
||||
if (rk628->version == RK628F_VERSION)
|
||||
d_strength = d_strength * 0x1111 | 0xffff0000;
|
||||
else {
|
||||
d_strength = 0xffff7777;
|
||||
clk_strength = 7;
|
||||
}
|
||||
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D0_CON, d_strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D1_CON, d_strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D0_CON, d_strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D1_CON, d_strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D0_CON, d_strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D1_CON, d_strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3A_D0_CON, d_strength & 0xf0fff0ff);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3B_D_CON, clk_strength | 0x000f0000);
|
||||
|
||||
/* rk628: modify DCLK delay for RGB */
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0,
|
||||
dclk_delay & 0xffffffff);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1,
|
||||
dclk_delay >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
void rk628_rgb_encoder_enable(struct rk628 *rk628)
|
||||
static void rk628_rgb_encoder_disable(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
|
||||
SW_BT_DATA_OEN_MASK | SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_RGB));
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON, SW_DCLK_OUT_INV_EN,
|
||||
SW_DCLK_OUT_INV_EN);
|
||||
}
|
||||
|
||||
void rk628_rgb_encoder_disable(struct rk628 *rk628)
|
||||
{
|
||||
rk628_panel_disable(rk628);
|
||||
rk628_panel_unprepare(rk628);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,43 +205,90 @@ void rk628_rgb_tx_enable(struct rk628 *rk628)
|
||||
void rk628_rgb_tx_disable(struct rk628 *rk628)
|
||||
{
|
||||
rk628_panel_disable(rk628);
|
||||
rk628_panel_unprepare(rk628);
|
||||
|
||||
rk628_rgb_encoder_disable(rk628);
|
||||
}
|
||||
|
||||
void rk628_bt1120_decoder_enable(struct rk628 *rk628)
|
||||
static void rk628_bt1120_decoder_timing_cfg(struct rk628 *rk628)
|
||||
{
|
||||
u32 src_hsync_len, src_hback_porch, src_hfront_porch, src_hactive;
|
||||
u32 src_vsync_len, src_vback_porch, src_vfront_porch, src_vactive;
|
||||
u32 dsp_htotal, dsp_hs_end, dsp_hact_st;
|
||||
u32 dsp_vtotal, dsp_vs_end, dsp_vact_st;
|
||||
u32 dsp_hbor_st, dsp_vbor_st;
|
||||
u16 bor_left = 0, bor_up = 0;
|
||||
struct rk628_display_mode *src = &rk628->src_mode;
|
||||
|
||||
src_hactive = src->hdisplay;
|
||||
src_hsync_len = src->hsync_end - src->hsync_start;
|
||||
src_hback_porch = src->htotal - src->hsync_end;
|
||||
src_hfront_porch = src->hsync_start - src->hdisplay;
|
||||
src_vsync_len = src->vsync_end - src->vsync_start;
|
||||
src_vback_porch = src->vtotal - src->vsync_end;
|
||||
src_vfront_porch = src->vsync_start - src->vdisplay;
|
||||
src_vactive = src->vdisplay;
|
||||
|
||||
dsp_htotal = src_hsync_len + src_hback_porch +
|
||||
src_hactive + src_hfront_porch;
|
||||
dsp_vtotal = src_vsync_len + src_vback_porch +
|
||||
src_vactive + src_vfront_porch;
|
||||
dsp_hs_end = src_hsync_len;
|
||||
dsp_vs_end = src_vsync_len;
|
||||
dsp_hbor_st = src_hsync_len + src_hback_porch;
|
||||
dsp_vbor_st = src_vsync_len + src_vback_porch;
|
||||
dsp_hact_st = dsp_hbor_st + bor_left;
|
||||
dsp_vact_st = dsp_vbor_st + bor_up;
|
||||
|
||||
if (rk628->version == RK628F_VERSION)
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_RX_DBG_MEAS0,
|
||||
RGB_RX_MODET_EN | RGB_RX_DCLK_EN,
|
||||
RGB_RX_MODET_EN | RGB_RX_DCLK_EN);
|
||||
|
||||
rk628_i2c_write(rk628, GRF_BT1120_TIMING_CTRL0, BT1120_DSP_HS_END(dsp_hs_end) |
|
||||
BT1120_DSP_HTOTAL(dsp_htotal));
|
||||
rk628_i2c_write(rk628, GRF_BT1120_TIMING_CTRL1, BT1120_DSP_HACT_ST(dsp_hact_st));
|
||||
rk628_i2c_write(rk628, GRF_BT1120_TIMING_CTRL2, BT1120_DSP_VS_END(dsp_vs_end) |
|
||||
BT1120_DSP_VTOTAL(dsp_vtotal));
|
||||
rk628_i2c_write(rk628, GRF_BT1120_TIMING_CTRL3, BT1120_DSP_VACT_ST(dsp_vact_st));
|
||||
}
|
||||
|
||||
static void rk628_bt1120_decoder_enable(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_display_mode *mode = rk628_display_get_src_mode(rk628);
|
||||
|
||||
rk628_set_input_bus_format(rk628, BUS_FMT_YUV422);
|
||||
|
||||
/* pinctrl for vop pin */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2AB_SEL_CON, 0xffffffff);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_SEL_CON, 0xffff5555);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x10b010b);
|
||||
|
||||
/* rk628: modify IO drive strength for RGB */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3A_D0_CON, 0xffff1011);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3B_D_CON, 0x10001);
|
||||
|
||||
/* config sw_input_mode bt1120 */
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_INPUT_MODE_MASK,
|
||||
SW_INPUT_MODE(INPUT_MODE_BT1120));
|
||||
|
||||
if (rk628->version == RK628F_VERSION)
|
||||
rk628_bt1120_decoder_timing_cfg(rk628);
|
||||
|
||||
/* operation resetn_bt1120dec */
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON00, 0x10001000);
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON00, 0x10000000);
|
||||
|
||||
rk628_cru_clk_set_rate(rk628, CGU_BT1120DEC, mode->clock * 1000);
|
||||
|
||||
#ifdef BT1120_DUAL_EDGE
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_DEC_CON0,
|
||||
DEC_DUALEDGE_EN, DEC_DUALEDGE_EN);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0, 0x10000000);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1, 0);
|
||||
#endif
|
||||
if (rk628->rgb.bt1120_dual_edge) {
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_DEC_CON0,
|
||||
DEC_DUALEDGE_EN, DEC_DUALEDGE_EN);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0, 0x10000000);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1, 0);
|
||||
} else {
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0,
|
||||
0x10000);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_DEC_CON1, SW_SET_X_MASK,
|
||||
SW_SET_X(mode->hdisplay));
|
||||
@@ -118,38 +304,82 @@ void rk628_bt1120_decoder_enable(struct rk628 *rk628)
|
||||
SW_CAP_EN_PSYNC | SW_CAP_EN_ASYNC | SW_PROGRESS_EN);
|
||||
}
|
||||
|
||||
void rk628_bt1120_encoder_enable(struct rk628 *rk628)
|
||||
static void rk628_bt1120_encoder_enable(struct rk628 *rk628)
|
||||
{
|
||||
u32 val = 0;
|
||||
int voltage = 0;
|
||||
u32 strength;
|
||||
u64 dclk_delay;
|
||||
|
||||
rk628_set_output_bus_format(rk628, BUS_FMT_YUV422);
|
||||
|
||||
/* pinctrl for vop pin */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2AB_SEL_CON, 0xffffffff);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_SEL_CON, 0xffff5555);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3AB_SEL_CON, 0x10b010b);
|
||||
|
||||
/* rk628: modify IO drive strength for RGB */
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D0_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D1_CON, 0xffff1111);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3A_D0_CON, 0xffff1011);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3B_D_CON, 0x10001);
|
||||
|
||||
/* config sw_input_mode bt1120 */
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
|
||||
SW_BT_DATA_OEN_MASK | SW_OUTPUT_MODE_MASK,
|
||||
SW_OUTPUT_MODE(OUTPUT_MODE_BT1120));
|
||||
SW_BT_DATA_OEN_MASK | SW_OUTPUT_RGB_MODE_MASK,
|
||||
SW_OUTPUT_RGB_MODE(OUTPUT_MODE_BT1120 >> 3));
|
||||
rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_R2Y_EN(1));
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
|
||||
SW_DCLK_OUT_INV_EN, SW_DCLK_OUT_INV_EN);
|
||||
if (rk628->version != RK628F_VERSION)
|
||||
rk628_i2c_update_bits(rk628, GRF_POST_PROC_CON,
|
||||
SW_DCLK_OUT_INV_EN, SW_DCLK_OUT_INV_EN);
|
||||
|
||||
/*
|
||||
* Under the same drive strength and DCLK delay, the signal behaves
|
||||
* differently under different voltage power domains. In order to
|
||||
* center the eye diagram of the signal, have sufficient signal setup
|
||||
* and hold time, and ensure that the signal does not overshoot, the
|
||||
* drive strength and DCLK delay need to be set for the power domains
|
||||
* of different voltages.
|
||||
*/
|
||||
if (rk628->rgb.vccio_rgb)
|
||||
voltage = regulator_get_voltage(rk628->rgb.vccio_rgb);
|
||||
|
||||
switch (voltage) {
|
||||
case 1800000:
|
||||
strength = 3;
|
||||
dclk_delay = 0x100000000;
|
||||
break;
|
||||
case 3300000:
|
||||
strength = 1;
|
||||
dclk_delay = 0x1000000000;
|
||||
break;
|
||||
default:
|
||||
strength = 1;
|
||||
dclk_delay = 0x1000000000;
|
||||
}
|
||||
|
||||
/* rk628: modify IO drive strength for BT1120 */
|
||||
if (rk628->version == RK628F_VERSION)
|
||||
strength = strength * 0x1111 | 0xffff0000;
|
||||
else
|
||||
strength = 0xffff1111;
|
||||
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D0_CON, strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2A_D1_CON, strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D0_CON, strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2B_D1_CON, strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D0_CON, strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO2C_D1_CON, strength);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3A_D0_CON, strength & 0xf0fff0ff);
|
||||
rk628_i2c_write(rk628, GRF_GPIO3B_D_CON, strength & 0x000f000f);
|
||||
|
||||
/* rk628: modify DCLK delay for BT1120 */
|
||||
if (rk628->rgb.bt1120_dual_edge) {
|
||||
val |= ENC_DUALEDGE_EN(1);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0, 0x10000000);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1, 0);
|
||||
} else {
|
||||
if (rk628->version == RK628F_VERSION) {
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0,
|
||||
dclk_delay & 0xffffffff);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1,
|
||||
dclk_delay >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BT1120_DUAL_EDGE
|
||||
val |= ENC_DUALEDGE_EN(1);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON0, 0x10000000);
|
||||
rk628_i2c_write(rk628, GRF_BT1120_DCLK_DELAY_CON1, 0);
|
||||
#endif
|
||||
val |= BT1120_UV_SWAP(1);
|
||||
rk628_i2c_write(rk628, GRF_RGB_ENC_CON, val);
|
||||
}
|
||||
@@ -163,4 +393,3 @@ void rk628_bt1120_tx_enable(struct rk628 *rk628)
|
||||
{
|
||||
rk628_bt1120_encoder_enable(rk628);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#define RK628_RGB_H
|
||||
#include "rk628.h"
|
||||
|
||||
int rk628_rgb_parse(struct rk628 *rk628, struct device_node *rgb_np);
|
||||
void rk628_rgb_rx_enable(struct rk628 *rk628);
|
||||
void rk628_rgb_tx_enable(struct rk628 *rk628);
|
||||
void rk628_rgb_tx_disable(struct rk628 *rk628);
|
||||
void rk628_bt1120_rx_enable(struct rk628 *rk628);
|
||||
void rk628_bt1120_tx_enable(struct rk628 *rk628);
|
||||
void rk628_rgb_decoder_create_debugfs_file(struct rk628 *rk628);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user