mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
Merge commit '270c1dfde4111ba347868d1092ebd60aaf658951'
* commit '270c1dfde4111ba347868d1092ebd60aaf658951': (35 commits) ARM: dts: rockchip: add rv1106g-evb2-v12-nofastae-spi-nor ARM: dts: rockchip: add rv1106g-evb2-v12-nofastae-emmc ARM: dts: rockchip: Add rv1106 nofastae dtsi ARM: configs: rockchip: Add rv1106-tb-nofastae.config ASoC: codecs: Add tda7803 amplifier driver support clk: rockchip: rk3568: Add protect clocks drm/bridge: dw-hdmi-qp: Don't read edid again if edid is exist drm/bridge: dw-hdmi-qp: Add hdcp driver arm64: dts: rockchip: rk3588: Add hdmitx hdcp14 ext memory arm64: configs: rockchip_linux_defconfig: enable CONFIG_DTC_SYMBOLS arm64: dts: rockchip: rk3568: add rk3568-evb8-lp4-v10 support ARM: dts: rockchip: rv1106-evb-cam: add sc3338 ARM: configs: rv1106-smart-door: enable SC230AI and SC301IOT arm64: dts: rockchip: fix timing configs of panel k350c4516t for rk3308/rk3562 evb media: rockchip: vicap fixes error of buffer state while start stream failed media: i2c: nvp6158: add g_frame_interval ops clk: rockchip: rk3328: set ddr clk with sip call Revert "dt-bindings: regulator: Document Rockchip RK860X regulators" arm64: dts: rockchip: rk3568-evb: assign DCLK_VOP2 to PLL_GPLL ARM: dts: rockchip: update rk5640 and hdmi sound for rk3288 evb boards ... Change-Id: I0429c2d6884649bdc3a4cb4938d8923ba790dde6
This commit is contained in:
@@ -2,7 +2,7 @@ Binding for Fairchild FAN53555 regulators
|
||||
|
||||
Required properties:
|
||||
- compatible: one of "fcs,fan53555", "fcs,fan53526", "silergy,syr827" or
|
||||
"silergy,syr828", "rockchip,rk8603", "rockchip,rk8604"
|
||||
"silergy,syr828"
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
|
||||
@@ -1002,6 +1002,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
|
||||
rv1106g-evb2-v10.dtb \
|
||||
rv1106g-evb2-v10-dual-camera.dtb \
|
||||
rv1106g-evb2-v11-emmc.dtb \
|
||||
rv1106g-evb2-v12-nofastae-emmc.dtb \
|
||||
rv1106g-evb2-v12-nofastae-spi-nor.dtb \
|
||||
rv1106g-evb2-v12-wakeup.dtb \
|
||||
rv1106g-smart-door-lock-rmsl-v10.dtb \
|
||||
rv1106g-smart-door-lock-rmsl-v12.dtb \
|
||||
|
||||
@@ -47,43 +47,49 @@
|
||||
};
|
||||
};
|
||||
|
||||
sound: sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,name = "rockchip,rt5640-codec";
|
||||
simple-audio-card,mclk-fs = <512>;
|
||||
rt5640_sound: rt5640-sound {
|
||||
status = "okay";
|
||||
|
||||
simple-audio-card,dai-link@0 {
|
||||
format = "i2s";
|
||||
cpu {
|
||||
sound-dai = <&i2s>;
|
||||
};
|
||||
|
||||
codec {
|
||||
sound-dai = <&rt5640>;
|
||||
};
|
||||
};
|
||||
|
||||
simple-audio-card,dai-link@1 {
|
||||
format = "i2s";
|
||||
cpu {
|
||||
sound-dai = <&i2s>;
|
||||
};
|
||||
|
||||
codec {
|
||||
sound-dai = <&hdmi>;
|
||||
};
|
||||
compatible = "rockchip,multicodecs-card";
|
||||
rockchip,card-name = "rockchip-rt5640";
|
||||
hp-det-gpio = <&gpio7 RK_PA7 GPIO_ACTIVE_HIGH>;
|
||||
io-channels = <&saradc 2>;
|
||||
io-channel-names = "adc-detect";
|
||||
keyup-threshold-microvolt = <1800000>;
|
||||
poll-interval = <100>;
|
||||
rockchip,format = "i2s";
|
||||
rockchip,mclk-fs = <512>;
|
||||
rockchip,cpu = <&i2s>;
|
||||
rockchip,codec = <&rt5640>;
|
||||
rockchip,audio-routing =
|
||||
"Headphone", "HPOL",
|
||||
"Headphone", "HPOR",
|
||||
"Speaker", "SPOLP",
|
||||
"Speaker", "SPOLN",
|
||||
"Speaker", "SPORP",
|
||||
"Speaker", "SPORN",
|
||||
"Headphone", "Headphone Power",
|
||||
"Headphone", "Headphone Power",
|
||||
"Speaker", "Speaker Power",
|
||||
"Speaker", "Speaker Power",
|
||||
"DMIC L1", "Main Mic",
|
||||
"DMIC R1", "Main Mic",
|
||||
"IN3P", "Headset Mic",
|
||||
"Headset Mic", "MICBIAS1";
|
||||
play-pause-key {
|
||||
label = "playpause";
|
||||
linux,code = <KEY_PLAYPAUSE>;
|
||||
press-threshold-microvolt = <2000>;
|
||||
};
|
||||
};
|
||||
|
||||
hdmi_analog_sound: hdmi-analog-sound {
|
||||
compatible = "rockchip,rk3288-hdmi-analog",
|
||||
"rockchip,rk3368-hdmi-analog";
|
||||
rockchip,model = "rockchip,rt5640-codec";
|
||||
rockchip,cpu = <&i2s>;
|
||||
rockchip,codec = <&rt5640>, <&hdmi>;
|
||||
hdmi_sound: hdmi-sound {
|
||||
status = "disabled";
|
||||
compatible = "rockchip,hdmi";
|
||||
rockchip,mclk-fs = <256>;
|
||||
rockchip,card-name = "rockchip-hdmi0";
|
||||
rockchip,cpu = <&i2s>;
|
||||
rockchip,codec = <&hdmi>;
|
||||
rockchip,jack-det;
|
||||
};
|
||||
|
||||
backlight: backlight {
|
||||
@@ -368,8 +374,6 @@
|
||||
reg = <0x1c>;
|
||||
clocks = <&cru SCLK_I2S0_OUT>;
|
||||
clock-names = "mclk";
|
||||
interrupt-parent = <&gpio7>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s0_mclk>;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
remote-endpoint = <&jx_k17_out>;
|
||||
data-lanes = <1 2>;
|
||||
};
|
||||
csi_dphy_input5: endpoint@5 {
|
||||
reg = <5>;
|
||||
remote-endpoint = <&sc3338_out>;
|
||||
data-lanes = <1 2>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
@@ -110,6 +115,28 @@
|
||||
};
|
||||
};
|
||||
|
||||
sc3338: sc3338@30 {
|
||||
compatible = "smartsens,sc3338";
|
||||
status = "okay";
|
||||
reg = <0x30>;
|
||||
clocks = <&cru MCLK_REF_MIPI0>;
|
||||
clock-names = "xvclk";
|
||||
reset-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
|
||||
pwdn-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mipi_refclk_out0>;
|
||||
rockchip,camera-module-index = <0>;
|
||||
rockchip,camera-module-facing = "back";
|
||||
rockchip,camera-module-name = "FKO1";
|
||||
rockchip,camera-module-lens-name = "30IRC-F16";
|
||||
port {
|
||||
sc3338_out: endpoint {
|
||||
remote-endpoint = <&csi_dphy_input5>;
|
||||
data-lanes = <1 2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sc4336: sc4336@30 {
|
||||
compatible = "smartsens,sc4336";
|
||||
status = "okay";
|
||||
|
||||
31
arch/arm/boot/dts/rv1106-tb-nofastae-emmc.dtsi
Normal file
31
arch/arm/boot/dts/rv1106-tb-nofastae-emmc.dtsi
Normal file
@@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "rv1106-tb-nofastae.dtsi"
|
||||
|
||||
/ {
|
||||
reserved-memory {
|
||||
mmc_ecsd: mmc@3f000 {
|
||||
reg = <0x3f000 0x00001000>;
|
||||
};
|
||||
|
||||
mmc_idmac: mmc@100000 {
|
||||
reg = <0x00100000 0x00100000>;
|
||||
};
|
||||
};
|
||||
|
||||
thunder_boot_mmc: thunder-boot-mmc {
|
||||
compatible = "rockchip,thunder-boot-mmc";
|
||||
reg = <0xffa90000 0x4000>;
|
||||
memory-region-src = <&ramdisk_c>;
|
||||
memory-region-dst = <&ramdisk_r>;
|
||||
memory-region-idmac = <&mmc_idmac>;
|
||||
};
|
||||
};
|
||||
|
||||
&emmc {
|
||||
memory-region-ecsd = <&mmc_ecsd>;
|
||||
post-power-on-delay-ms = <0>;
|
||||
};
|
||||
19
arch/arm/boot/dts/rv1106-tb-nofastae-spi-nor.dtsi
Normal file
19
arch/arm/boot/dts/rv1106-tb-nofastae-spi-nor.dtsi
Normal file
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include "rv1106-tb-nofastae.dtsi"
|
||||
|
||||
/ {
|
||||
thunder_boot_spi_nor: thunder-boot-spi-nor {
|
||||
compatible = "rockchip,thunder-boot-sfc";
|
||||
reg = <0xffac0000 0x4000>;
|
||||
memory-region-src = <&ramdisk_c>;
|
||||
memory-region-dst = <&ramdisk_r>;
|
||||
};
|
||||
};
|
||||
|
||||
&emmc {
|
||||
status = "disabled";
|
||||
};
|
||||
35
arch/arm/boot/dts/rv1106-tb-nofastae.dtsi
Normal file
35
arch/arm/boot/dts/rv1106-tb-nofastae.dtsi
Normal file
@@ -0,0 +1,35 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/ {
|
||||
memory: memory {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x08000000>;
|
||||
};
|
||||
|
||||
ramdisk: ramdisk {
|
||||
compatible = "rockchip,ramdisk";
|
||||
memory-region = <&ramdisk_r>;
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
ramdisk_r: ramdisk_r {
|
||||
reg = <0x800000 (10 * 0x00100000)>;
|
||||
};
|
||||
|
||||
ramdisk_c: ramdisk_c {
|
||||
reg = <0x1200000 (5 * 0x00100000)>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&hw_decompress {
|
||||
status = "okay";
|
||||
memory-region = <&ramdisk_c>;
|
||||
};
|
||||
134
arch/arm/boot/dts/rv1106g-evb2-v12-nofastae-emmc.dts
Normal file
134
arch/arm/boot/dts/rv1106g-evb2-v12-nofastae-emmc.dts
Normal file
@@ -0,0 +1,134 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "rv1106.dtsi"
|
||||
#include "rv1106-evb-v10.dtsi"
|
||||
#include "rv1106-evb-cam.dtsi"
|
||||
#include "rv1106-tb-nofastae-emmc.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RV1106G EVB2 V12 Board";
|
||||
compatible = "rockchip,rv1106g-evb2-v12", "rockchip,rv1106";
|
||||
|
||||
chosen {
|
||||
bootargs = "loglevel=0 rootfstype=erofs rootflags=dax console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip";
|
||||
};
|
||||
|
||||
vcc_1v8: vcc-1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_1v8";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
|
||||
vcc_3v3: vcc-3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_3v3";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
vcc3v3_sd: vcc3v3-sd {
|
||||
compatible = "regulator-fixed";
|
||||
gpio = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>;
|
||||
regulator-name = "vcc3v3_sd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc_pwren>;
|
||||
};
|
||||
|
||||
wireless_wlan: wireless-wlan {
|
||||
compatible = "wlan-platdata";
|
||||
WIFI,host_wake_irq = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&fiq_debugger {
|
||||
rockchip,baudrate = <1500000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2m1_xfer>;
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
sdmmc {
|
||||
/omit-if-no-ref/
|
||||
sdmmc_pwren: sdmmc-pwren {
|
||||
rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pwm10 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwm11 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ramdisk_r {
|
||||
reg = <0x800000 (20 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&ramdisk_c {
|
||||
reg = <0x1C00000 (10 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&sdio {
|
||||
max-frequency = <50000000>;
|
||||
bus-width = <1>;
|
||||
cap-sd-highspeed;
|
||||
cap-sdio-irq;
|
||||
keep-power-in-suspend;
|
||||
non-removable;
|
||||
rockchip,default-sample-phase = <90>;
|
||||
no-sd;
|
||||
no-mmc;
|
||||
supports-sdio;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc1m0_cmd &sdmmc1m0_clk &sdmmc1m0_bus4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
max-frequency = <200000000>;
|
||||
no-sdio;
|
||||
no-mmc;
|
||||
bus-width = <4>;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
disable-wp;
|
||||
pinctrl-names = "normal", "idle";
|
||||
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
|
||||
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
|
||||
vmmc-supply = <&vcc3v3_sd>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sfc {
|
||||
assigned-clocks = <&cru SCLK_SFC>;
|
||||
assigned-clock-rates = <125000000>;
|
||||
status = "disabled";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <125000000>;
|
||||
spi-rx-bus-width = <4>;
|
||||
spi-tx-bus-width = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&usbdrd_dwc3 {
|
||||
dr_mode = "peripheral";
|
||||
};
|
||||
134
arch/arm/boot/dts/rv1106g-evb2-v12-nofastae-spi-nor.dts
Normal file
134
arch/arm/boot/dts/rv1106g-evb2-v12-nofastae-spi-nor.dts
Normal file
@@ -0,0 +1,134 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "rv1106.dtsi"
|
||||
#include "rv1106-evb-v10.dtsi"
|
||||
#include "rv1106-evb-cam.dtsi"
|
||||
#include "rv1106-tb-nofastae-spi-nor.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RV1106G EVB2 V12 Board";
|
||||
compatible = "rockchip,rv1106g-evb2-v12", "rockchip,rv1106";
|
||||
|
||||
chosen {
|
||||
bootargs = "loglevel=0 rootfstype=erofs rootflags=dax console=ttyFIQ0 root=/dev/rd0 snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0 driver_async_probe=dwmmc_rockchip";
|
||||
};
|
||||
|
||||
vcc_1v8: vcc-1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_1v8";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
};
|
||||
|
||||
vcc_3v3: vcc-3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_3v3";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
vcc3v3_sd: vcc3v3-sd {
|
||||
compatible = "regulator-fixed";
|
||||
gpio = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>;
|
||||
regulator-name = "vcc3v3_sd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc_pwren>;
|
||||
};
|
||||
|
||||
wireless_wlan: wireless-wlan {
|
||||
compatible = "wlan-platdata";
|
||||
WIFI,host_wake_irq = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&fiq_debugger {
|
||||
rockchip,baudrate = <1500000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart2m1_xfer>;
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
sdmmc {
|
||||
/omit-if-no-ref/
|
||||
sdmmc_pwren: sdmmc-pwren {
|
||||
rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pwm10 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwm11 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ramdisk_r {
|
||||
reg = <0x800000 (10 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&ramdisk_c {
|
||||
reg = <0x1200000 (5 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&sdio {
|
||||
max-frequency = <50000000>;
|
||||
bus-width = <1>;
|
||||
cap-sd-highspeed;
|
||||
cap-sdio-irq;
|
||||
keep-power-in-suspend;
|
||||
non-removable;
|
||||
rockchip,default-sample-phase = <90>;
|
||||
no-sd;
|
||||
no-mmc;
|
||||
supports-sdio;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc1m0_cmd &sdmmc1m0_clk &sdmmc1m0_bus4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
max-frequency = <200000000>;
|
||||
no-sdio;
|
||||
no-mmc;
|
||||
bus-width = <4>;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
disable-wp;
|
||||
pinctrl-names = "normal", "idle";
|
||||
pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_det &sdmmc0_bus4>;
|
||||
pinctrl-1 = <&sdmmc0_idle_pins &sdmmc0_det>;
|
||||
vmmc-supply = <&vcc3v3_sd>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sfc {
|
||||
assigned-clocks = <&cru SCLK_SFC>;
|
||||
assigned-clock-rates = <125000000>;
|
||||
status = "okay";
|
||||
|
||||
flash@0 {
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <125000000>;
|
||||
spi-rx-bus-width = <4>;
|
||||
spi-tx-bus-width = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&usbdrd_dwc3 {
|
||||
dr_mode = "peripheral";
|
||||
};
|
||||
@@ -117,6 +117,14 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&ramdisk_r {
|
||||
reg = <0x12ec000 (15 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&ramdisk_c {
|
||||
reg = <0x21ec000 (7 * 0x00100000)>;
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
max-frequency = <50000000>;
|
||||
bus-width = <1>;
|
||||
|
||||
@@ -69,7 +69,7 @@ CONFIG_DRM_GEM_CMA_HELPER=y
|
||||
# CONFIG_DRM_I2C_NXP_TDA9950 is not set
|
||||
# CONFIG_DRM_I2C_NXP_TDA998X is not set
|
||||
# CONFIG_DRM_I2C_SIL164 is not set
|
||||
# CONFIG_DRM_IGNORE_IOTCL_PERMIT is not set
|
||||
CONFIG_DRM_IGNORE_IOTCL_PERMIT=y
|
||||
# CONFIG_DRM_ITE_IT6161 is not set
|
||||
CONFIG_DRM_KMS_FB_HELPER=y
|
||||
CONFIG_DRM_KMS_HELPER=y
|
||||
|
||||
@@ -29,6 +29,8 @@ CONFIG_SPI=y
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_VIDEO_GC2093=y
|
||||
CONFIG_VIDEO_SC035GS=y
|
||||
CONFIG_VIDEO_SC230AI=y
|
||||
CONFIG_VIDEO_SC301IOT=y
|
||||
CONFIG_VIDEO_SC3338=y
|
||||
CONFIG_WIRELESS=y
|
||||
CONFIG_WLAN=y
|
||||
@@ -233,6 +235,7 @@ CONFIG_MPILIB=y
|
||||
# CONFIG_MTD_MCHP23K256 is not set
|
||||
# CONFIG_MTD_SPI_NAND is not set
|
||||
CONFIG_MTD_SPI_NOR=m
|
||||
# CONFIG_MTD_SPI_NOR_MISC is not set
|
||||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
# CONFIG_MTD_SST25L is not set
|
||||
# CONFIG_NL80211_TESTMODE is not set
|
||||
@@ -257,8 +260,10 @@ CONFIG_RFKILL_RK=y
|
||||
CONFIG_ROCKCHIP_MBOX=y
|
||||
# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set
|
||||
CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=m
|
||||
# CONFIG_ROCKCHIP_RAM_VENDOR_STORAGE is not set
|
||||
CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE=y
|
||||
# CONFIG_RPMSG_QCOM_GLINK_RPM is not set
|
||||
# CONFIG_RPMSG_ROCKCHIP is not set
|
||||
# CONFIG_RTC_DRV_DS1302 is not set
|
||||
# CONFIG_RTC_DRV_DS1305 is not set
|
||||
# CONFIG_RTC_DRV_DS1343 is not set
|
||||
|
||||
3
arch/arm/configs/rv1106-tb-nofastae.config
Normal file
3
arch/arm/configs/rv1106-tb-nofastae.config
Normal file
@@ -0,0 +1,3 @@
|
||||
# CONFIG_ROCKCHIP_MBOX is not set
|
||||
# CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE is not set
|
||||
# CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP is not set
|
||||
@@ -144,6 +144,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb6-ddr3-v10-rk628-rgb2hdmi.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb6-ddr3-v10-rk628-rgb2lvds.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb6-ddr3-v10-rk630-bt656-to-cvbs.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb7-ddr4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb8-lp4-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb8-lp4-v10-linux.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-iotest-ddr3-v10.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-iotest-ddr3-v10-linux.dtb
|
||||
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nvr-demo-v10.dtb
|
||||
|
||||
@@ -45,147 +45,171 @@
|
||||
default-brightness-level = <200>;
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "simple-panel";
|
||||
bus-format = <MEDIA_BUS_FMT_RGB666_1X18>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
|
||||
enable-delay-ms = <20>;
|
||||
reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>;
|
||||
reset-delay-ms = <10>;
|
||||
prepare-delay-ms = <20>;
|
||||
unprepare-delay-ms = <20>;
|
||||
disable-delay-ms = <20>;
|
||||
/* spi-sdo-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>; */
|
||||
spi-sdi-gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
|
||||
spi-scl-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
|
||||
spi-cs-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
|
||||
width-mm = <217>;
|
||||
height-mm = <136>;
|
||||
status = "okay";
|
||||
spi_gpio: spi-gpio {
|
||||
compatible = "spi-gpio";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spi_init_cmd>;
|
||||
rockchip,cmd-type = "spi";
|
||||
pinctrl-0 = <&spi_pins>;
|
||||
spi-delay-us = <10>;
|
||||
status = "okay";
|
||||
|
||||
/* type:0 is cmd, 1 is data */
|
||||
panel-init-sequence = [
|
||||
/* type delay num val1 val2 val3 */
|
||||
00 00 01 e0
|
||||
01 00 01 00
|
||||
01 00 01 07
|
||||
01 00 01 0f
|
||||
01 00 01 0d
|
||||
01 00 01 1b
|
||||
01 00 01 0a
|
||||
01 00 01 3c
|
||||
01 00 01 78
|
||||
01 00 01 4a
|
||||
01 00 01 07
|
||||
01 00 01 0e
|
||||
01 00 01 09
|
||||
01 00 01 1b
|
||||
01 00 01 1e
|
||||
01 00 01 0f
|
||||
00 00 01 e1
|
||||
01 00 01 00
|
||||
01 00 01 22
|
||||
01 00 01 24
|
||||
01 00 01 06
|
||||
01 00 01 12
|
||||
01 00 01 07
|
||||
01 00 01 36
|
||||
01 00 01 47
|
||||
01 00 01 47
|
||||
01 00 01 06
|
||||
01 00 01 0a
|
||||
01 00 01 07
|
||||
01 00 01 30
|
||||
01 00 01 37
|
||||
01 00 01 0f
|
||||
sck-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
|
||||
miso-gpios = <&gpio3 RK_PD2 GPIO_ACTIVE_HIGH>;
|
||||
mosi-gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
|
||||
cs-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
|
||||
num-chipselects = <1>;
|
||||
|
||||
00 00 01 c0
|
||||
01 00 01 10
|
||||
01 00 01 10
|
||||
/*
|
||||
* 320x480 RGB/MCU screen K350C4516T
|
||||
*/
|
||||
panel: panel {
|
||||
compatible = "simple-panel-spi";
|
||||
reg = <0>;
|
||||
bus-format = <MEDIA_BUS_FMT_RGB666_1X18>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
|
||||
enable-delay-ms = <20>;
|
||||
reset-gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_LOW>;
|
||||
reset-delay-ms = <10>;
|
||||
prepare-delay-ms = <20>;
|
||||
unprepare-delay-ms = <20>;
|
||||
disable-delay-ms = <20>;
|
||||
init-delay-ms = <10>;
|
||||
width-mm = <217>;
|
||||
height-mm = <136>;
|
||||
rockchip,cmd-type = "spi";
|
||||
status = "okay";
|
||||
|
||||
00 00 01 c1
|
||||
01 00 01 41
|
||||
// type:0 is cmd, 1 is data
|
||||
panel-init-sequence = [
|
||||
/* type delay num val1 val2 val3 */
|
||||
00 00 01 e0
|
||||
01 00 01 00
|
||||
01 00 01 07
|
||||
01 00 01 0f
|
||||
01 00 01 0d
|
||||
01 00 01 1b
|
||||
01 00 01 0a
|
||||
01 00 01 3c
|
||||
01 00 01 78
|
||||
01 00 01 4a
|
||||
01 00 01 07
|
||||
01 00 01 0e
|
||||
01 00 01 09
|
||||
01 00 01 1b
|
||||
01 00 01 1e
|
||||
01 00 01 0f
|
||||
00 00 01 e1
|
||||
01 00 01 00
|
||||
01 00 01 22
|
||||
01 00 01 24
|
||||
01 00 01 06
|
||||
01 00 01 12
|
||||
01 00 01 07
|
||||
01 00 01 36
|
||||
01 00 01 47
|
||||
01 00 01 47
|
||||
01 00 01 06
|
||||
01 00 01 0a
|
||||
01 00 01 07
|
||||
01 00 01 30
|
||||
01 00 01 37
|
||||
01 00 01 0f
|
||||
|
||||
00 00 01 c5
|
||||
01 00 01 00
|
||||
01 00 01 22
|
||||
01 00 01 80
|
||||
00 00 01 c0
|
||||
01 00 01 10
|
||||
01 00 01 10
|
||||
|
||||
00 00 01 36
|
||||
01 00 01 48
|
||||
00 00 01 c1
|
||||
01 00 01 41
|
||||
|
||||
00 00 01 3a //interface pixel format
|
||||
01 00 01 66 // bpp cfg
|
||||
// 3 11
|
||||
// 16 55
|
||||
// 18 66
|
||||
// 24 77
|
||||
00 00 01 c5
|
||||
01 00 01 00
|
||||
01 00 01 22
|
||||
01 00 01 80
|
||||
|
||||
00 00 01 b0 /* interface mode control */
|
||||
01 00 01 00
|
||||
00 00 01 36
|
||||
01 00 01 48
|
||||
|
||||
00 00 01 b1 /* frame rate 60hz */
|
||||
01 00 01 a0
|
||||
01 00 01 11
|
||||
00 00 01 b4
|
||||
01 00 01 02
|
||||
00 00 01 B6
|
||||
01 00 01 32
|
||||
01 00 01 02
|
||||
00 00 01 3a
|
||||
01 00 01 66 /*
|
||||
* interface pixel format:
|
||||
* 66 for RGB666(18bit)
|
||||
*/
|
||||
|
||||
00 00 01 b7
|
||||
01 00 01 c6
|
||||
00 00 01 b0
|
||||
01 00 01 00
|
||||
|
||||
00 00 01 be
|
||||
01 00 01 00
|
||||
01 00 01 04
|
||||
00 00 01 b1
|
||||
01 00 01 a0 /*
|
||||
* frame rate control:
|
||||
* a0 (60hz) for RGB666(18bit)
|
||||
*/
|
||||
01 00 01 11
|
||||
00 00 01 b4
|
||||
01 00 01 02
|
||||
00 00 01 B6
|
||||
01 00 01 32 /*
|
||||
* display function control:
|
||||
* 32 for RGB
|
||||
* 02 for MCU
|
||||
*/
|
||||
01 00 01 02
|
||||
|
||||
00 00 01 e9
|
||||
01 00 01 00
|
||||
00 00 01 b7
|
||||
01 00 01 c6
|
||||
|
||||
00 00 01 f7
|
||||
01 00 01 a9
|
||||
01 00 01 51
|
||||
01 00 01 2c
|
||||
01 00 01 82
|
||||
00 00 01 be
|
||||
01 00 01 00
|
||||
01 00 01 04
|
||||
|
||||
00 78 01 11
|
||||
00 00 01 29
|
||||
];
|
||||
00 00 01 e9
|
||||
01 00 01 00
|
||||
|
||||
panel-exit-sequence = [
|
||||
/* type delay num val1 val2 val3 */
|
||||
00 0a 01 28
|
||||
00 78 01 10
|
||||
];
|
||||
00 00 01 f7
|
||||
01 00 01 a9
|
||||
01 00 01 51
|
||||
01 00 01 2c
|
||||
01 00 01 82
|
||||
|
||||
display-timings {
|
||||
native-mode = <&kd050fwfba002_timing>;
|
||||
00 78 01 11
|
||||
00 00 01 29
|
||||
];
|
||||
|
||||
kd050fwfba002_timing: timing0 {
|
||||
clock-frequency = <94081500>;
|
||||
hactive = <320>;
|
||||
vactive = <480>;
|
||||
hback-porch = <10>;
|
||||
hfront-porch = <5>;
|
||||
vback-porch = <10>;
|
||||
vfront-porch = <5>;
|
||||
hsync-len = <10>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <0>;
|
||||
panel-exit-sequence = [
|
||||
//type delay num val1 val2 val3
|
||||
00 0a 01 28
|
||||
00 78 01 10
|
||||
];
|
||||
|
||||
display-timings {
|
||||
native-mode = <&kd050fwfba002_timing>;
|
||||
|
||||
kd050fwfba002_timing: timing0 {
|
||||
/*
|
||||
* 10453500 for RGB666(18bit)
|
||||
*/
|
||||
clock-frequency = <10453500>;
|
||||
hactive = <320>;
|
||||
vactive = <480>;
|
||||
hback-porch = <10>;
|
||||
hfront-porch = <5>;
|
||||
vback-porch = <10>;
|
||||
vfront-porch = <5>;
|
||||
hsync-len = <10>;
|
||||
vsync-len = <10>;
|
||||
hsync-active = <0>;
|
||||
vsync-active = <0>;
|
||||
de-active = <0>;
|
||||
pixelclk-active = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&rgb_out_panel>;
|
||||
port {
|
||||
panel_in_rgb: endpoint {
|
||||
remote-endpoint = <&rgb_out_panel>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -196,9 +220,11 @@
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
spi_panel {
|
||||
spi_init_cmd: spi-init-cmd {
|
||||
soft_spi {
|
||||
spi_pins: spi-pins {
|
||||
rockchip,pins =
|
||||
/* spi sdo */
|
||||
<3 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
/* spi sdi */
|
||||
<1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
/* spi scl */
|
||||
@@ -236,14 +262,4 @@
|
||||
|
||||
&vop {
|
||||
status = "okay";
|
||||
|
||||
mcu-timing {
|
||||
mcu-pix-total = <9>;
|
||||
mcu-cs-pst = <1>;
|
||||
mcu-cs-pend = <8>;
|
||||
mcu-rw-pst = <2>;
|
||||
mcu-rw-pend = <5>;
|
||||
|
||||
mcu-hold-mode = <0>; // default set to 0
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,8 +45,40 @@
|
||||
default-brightness-level = <200>;
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "simple-panel";
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
cma {
|
||||
compatible = "shared-dma-pool";
|
||||
reusable;
|
||||
size = <0x0 0x800000>;
|
||||
linux,cma-default;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&display_subsystem {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwm1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
rockchip,data-sync-bypass;
|
||||
|
||||
/*
|
||||
* 320x480 RGB/MCU screen K350C4516T
|
||||
*/
|
||||
mcu_panel: mcu-panel {
|
||||
/*
|
||||
* MEDIA_BUS_FMT_RGB888_3X8 for RGB3x8(8bit)
|
||||
* MEDIA_BUS_FMT_RGB565_1X16 for RGB565(16bit)
|
||||
*/
|
||||
bus-format = <MEDIA_BUS_FMT_RGB565_1X16>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
|
||||
@@ -59,8 +91,6 @@
|
||||
disable-delay-ms = <20>;
|
||||
width-mm = <217>;
|
||||
height-mm = <136>;
|
||||
status = "okay";
|
||||
rockchip,cmd-type = "mcu";
|
||||
|
||||
// type:0 is cmd, 1 is data
|
||||
panel-init-sequence = [
|
||||
@@ -113,23 +143,31 @@
|
||||
00 00 01 36
|
||||
01 00 01 48
|
||||
|
||||
00 00 01 3a //interface pixel format
|
||||
01 00 01 55 // bpp cfg
|
||||
// 3 11
|
||||
// 16 55
|
||||
// 18 66
|
||||
// 24 77
|
||||
00 00 01 3a
|
||||
01 00 01 55 /*
|
||||
* interface pixel format:
|
||||
* 66 for RGB3x8(8bit)
|
||||
* 55 for RGB565(16bit)
|
||||
*/
|
||||
|
||||
00 00 01 b0 //interface mode control
|
||||
00 00 01 b0
|
||||
01 00 01 00
|
||||
|
||||
00 00 01 b1 //frame rate 60hz
|
||||
01 00 01 a0
|
||||
00 00 01 b1
|
||||
01 00 01 a0 /*
|
||||
* frame rate control:
|
||||
* 70 (45hz) for RGB3x8(8bit)
|
||||
* a0 (60hz) for RGB565(16bit)
|
||||
*/
|
||||
01 00 01 11
|
||||
00 00 01 b4
|
||||
01 00 01 02
|
||||
00 00 01 B6
|
||||
01 00 01 02
|
||||
01 00 01 02 /*
|
||||
* display function control:
|
||||
* 32 for RGB
|
||||
* 02 for MCU
|
||||
*/
|
||||
01 00 01 02
|
||||
|
||||
00 00 01 b7
|
||||
@@ -163,7 +201,11 @@
|
||||
native-mode = <&kd050fwfba002_timing>;
|
||||
|
||||
kd050fwfba002_timing: timing0 {
|
||||
clock-frequency = <94081500>;
|
||||
/*
|
||||
* 7840125 for frame rate 45Hz
|
||||
* 10453500 for frame rate 60Hz
|
||||
*/
|
||||
clock-frequency = <10453500>;
|
||||
hactive = <320>;
|
||||
vactive = <480>;
|
||||
hback-porch = <10>;
|
||||
@@ -186,35 +228,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
cma {
|
||||
compatible = "shared-dma-pool";
|
||||
reusable;
|
||||
size = <0x0 0x800000>;
|
||||
linux,cma-default;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&display_subsystem {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pwm1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&rgb {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
rgb_out: port@1 {
|
||||
reg = <1>;
|
||||
@@ -229,15 +242,32 @@
|
||||
};
|
||||
};
|
||||
|
||||
&route_rgb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vop {
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* Default config is as follows:
|
||||
*
|
||||
* mcu-pix-total = <9>;
|
||||
* mcu-cs-pst = <1>;
|
||||
* mcu-cs-pend = <8>;
|
||||
* mcu-rw-pst = <2>;
|
||||
* mcu-rw-pend = <5>;
|
||||
* mcu-hold-mode = <0>; // default set to 0
|
||||
*
|
||||
* To increase the frame rate, reduce all parameters because
|
||||
* the max dclk rate of mcu is 150M in rk3308.
|
||||
*/
|
||||
mcu-timing {
|
||||
mcu-pix-total = <9>;
|
||||
mcu-pix-total = <5>;
|
||||
mcu-cs-pst = <1>;
|
||||
mcu-cs-pend = <8>;
|
||||
mcu-cs-pend = <4>;
|
||||
mcu-rw-pst = <2>;
|
||||
mcu-rw-pend = <5>;
|
||||
mcu-rw-pend = <3>;
|
||||
|
||||
mcu-hold-mode = <0>; // default set to 0
|
||||
};
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
#gpio-cells = <2>;
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "rk805-clkout1", "rk805-clkout2";
|
||||
rk805,system-power-controoler;
|
||||
rockchip,system-power-controller;
|
||||
|
||||
vcc1-supply = <&vcc5v0_sys>;
|
||||
vcc2-supply = <&vcc5v0_sys>;
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
rockchip,data-sync-bypass;
|
||||
pinctrl-names = "default";
|
||||
/*
|
||||
* rgb3x8_pins_m0/rgb3x8_pins_m1 for serial mcu
|
||||
* rgb565_pins for parallel mcu
|
||||
* rgb3x8_pins_m0/rgb3x8_pins_m1 for RGB3x8(8bit)
|
||||
* rgb565_pins for RGB565(16bit)
|
||||
*/
|
||||
pinctrl-0 = <&rgb565_pins>;
|
||||
|
||||
@@ -57,19 +57,19 @@
|
||||
*/
|
||||
mcu_panel: mcu-panel {
|
||||
/*
|
||||
* MEDIA_BUS_FMT_RGB888_3X8 for serial mcu
|
||||
* MEDIA_BUS_FMT_RGB565_1X16 for parallel mcu
|
||||
* MEDIA_BUS_FMT_RGB888_3X8 for RGB3x8(8bit)
|
||||
* MEDIA_BUS_FMT_RGB565_1X16 for RGB565(16bit)
|
||||
*/
|
||||
bus-format = <MEDIA_BUS_FMT_RGB565_1X16>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
|
||||
enable-delay-ms = <20>;
|
||||
reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
|
||||
reset-value = <0>;
|
||||
reset-delay-ms = <10>;
|
||||
prepare-delay-ms = <20>;
|
||||
unprepare-delay-ms = <20>;
|
||||
disable-delay-ms = <20>;
|
||||
init-delay-ms = <10>;
|
||||
width-mm = <217>;
|
||||
height-mm = <136>;
|
||||
|
||||
@@ -124,23 +124,31 @@
|
||||
00 00 01 36
|
||||
01 00 01 48
|
||||
|
||||
00 00 01 3a //interface pixel format
|
||||
01 00 01 55 // bpp cfg
|
||||
// 3 11
|
||||
// 16 55
|
||||
// 18 66
|
||||
// 24 77
|
||||
00 00 01 3a
|
||||
01 00 01 55 /*
|
||||
* interface pixel format:
|
||||
* 66 for RGB3x8(8bit)
|
||||
* 55 for RGB565(16bit)
|
||||
*/
|
||||
|
||||
00 00 01 b0 //interface mode control
|
||||
00 00 01 b0
|
||||
01 00 01 00
|
||||
|
||||
00 00 01 b1 //frame rate 60hz
|
||||
01 00 01 a0
|
||||
00 00 01 b1
|
||||
01 00 01 a0 /*
|
||||
* frame rate control:
|
||||
* 70 (45hz) for RGB3x8(8bit)
|
||||
* a0 (60hz) for RGB565(16bit)
|
||||
*/
|
||||
01 00 01 11
|
||||
00 00 01 b4
|
||||
01 00 01 02
|
||||
00 00 01 B6
|
||||
01 00 01 02
|
||||
01 00 01 02 /*
|
||||
* display function control:
|
||||
* 32 for RGB
|
||||
* 02 for MCU
|
||||
*/
|
||||
01 00 01 02
|
||||
|
||||
00 00 01 b7
|
||||
@@ -174,7 +182,11 @@
|
||||
native-mode = <&kd050fwfba002_timing>;
|
||||
|
||||
kd050fwfba002_timing: timing0 {
|
||||
clock-frequency = <94081500>;
|
||||
/*
|
||||
* 7840125 for frame rate 45Hz
|
||||
* 10453500 for frame rate 60Hz
|
||||
*/
|
||||
clock-frequency = <10453500>;
|
||||
hactive = <320>;
|
||||
vactive = <480>;
|
||||
hback-porch = <10>;
|
||||
@@ -240,12 +252,27 @@
|
||||
};
|
||||
|
||||
&vp0 {
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* Default config is as follows:
|
||||
*
|
||||
* mcu-pix-total = <9>;
|
||||
* mcu-cs-pst = <1>;
|
||||
* mcu-cs-pend = <8>;
|
||||
* mcu-rw-pst = <2>;
|
||||
* mcu-rw-pend = <5>;
|
||||
* mcu-hold-mode = <0>; // default set to 0
|
||||
*
|
||||
* To increase the frame rate, reduce all parameters because
|
||||
* the max dclk rate of mcu is 150M in rk3562.
|
||||
*/
|
||||
mcu-timing {
|
||||
mcu-pix-total = <9>;
|
||||
mcu-pix-total = <5>;
|
||||
mcu-cs-pst = <1>;
|
||||
mcu-cs-pend = <8>;
|
||||
mcu-cs-pend = <4>;
|
||||
mcu-rw-pst = <2>;
|
||||
mcu-rw-pend = <5>;
|
||||
mcu-rw-pend = <3>;
|
||||
|
||||
mcu-hold-mode = <0>; // default set to 0
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
prepare-delay-ms = <20>;
|
||||
unprepare-delay-ms = <20>;
|
||||
disable-delay-ms = <20>;
|
||||
init-delay-ms = <10>;
|
||||
width-mm = <217>;
|
||||
height-mm = <136>;
|
||||
rockchip,cmd-type = "spi";
|
||||
@@ -99,23 +100,29 @@
|
||||
00 00 01 36
|
||||
01 00 01 48
|
||||
|
||||
00 00 01 3a //interface pixel format
|
||||
01 00 01 66 // bpp cfg
|
||||
// 3 11
|
||||
// 16 55
|
||||
// 18 66
|
||||
// 24 77
|
||||
00 00 01 3a
|
||||
01 00 01 66 /*
|
||||
* interface pixel format:
|
||||
* 66 for RGB666(18bit)
|
||||
*/
|
||||
|
||||
00 00 01 b0 /* interface mode control */
|
||||
00 00 01 b0
|
||||
01 00 01 00
|
||||
|
||||
00 00 01 b1 /* frame rate 60hz */
|
||||
01 00 01 a0
|
||||
00 00 01 b1
|
||||
01 00 01 a0 /*
|
||||
* frame rate control:
|
||||
* a0 (60hz) for RGB666(18bit)
|
||||
*/
|
||||
01 00 01 11
|
||||
00 00 01 b4
|
||||
01 00 01 02
|
||||
00 00 01 B6
|
||||
01 00 01 32
|
||||
01 00 01 32 /*
|
||||
* display function control:
|
||||
* 32 for RGB
|
||||
* 02 for MCU
|
||||
*/
|
||||
01 00 01 02
|
||||
|
||||
00 00 01 b7
|
||||
@@ -148,6 +155,9 @@
|
||||
native-mode = <&kd050fwfba002_timing>;
|
||||
|
||||
kd050fwfba002_timing: timing0 {
|
||||
/*
|
||||
* 10453500 for RGB666(18bit)
|
||||
*/
|
||||
clock-frequency = <10453500>;
|
||||
hactive = <320>;
|
||||
vactive = <480>;
|
||||
|
||||
@@ -1857,8 +1857,8 @@
|
||||
|
||||
&vop {
|
||||
status = "okay";
|
||||
assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
|
||||
assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
|
||||
assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>, <&cru DCLK_VOP2>;
|
||||
assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>, <&cru PLL_GPLL>;
|
||||
};
|
||||
|
||||
&vop_mmu {
|
||||
|
||||
17
arch/arm64/boot/dts/rockchip/rk3568-evb8-lp4-v10-linux.dts
Normal file
17
arch/arm64/boot/dts/rockchip/rk3568-evb8-lp4-v10-linux.dts
Normal file
@@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb8-lp4-v10.dtsi"
|
||||
#include "rk3568-linux.dtsi"
|
||||
#include <dt-bindings/display/rockchip_vop.h>
|
||||
|
||||
&vp0 {
|
||||
cursor-win-id = <ROCKCHIP_VOP2_CLUSTER0>;
|
||||
};
|
||||
|
||||
&vp1 {
|
||||
cursor-win-id = <ROCKCHIP_VOP2_CLUSTER1>;
|
||||
};
|
||||
20
arch/arm64/boot/dts/rockchip/rk3568-evb8-lp4-v10.dts
Normal file
20
arch/arm64/boot/dts/rockchip/rk3568-evb8-lp4-v10.dts
Normal file
@@ -0,0 +1,20 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rk3568-evb8-lp4-v10.dtsi"
|
||||
#include "rk3568-android.dtsi"
|
||||
|
||||
&bt_sco {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&bt_sound {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2s3_2ch {
|
||||
status = "okay";
|
||||
};
|
||||
37
arch/arm64/boot/dts/rockchip/rk3568-evb8-lp4-v10.dtsi
Normal file
37
arch/arm64/boot/dts/rockchip/rk3568-evb8-lp4-v10.dtsi
Normal file
@@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "rk3568-evb1-ddr4-v10.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RK3568 EVB8 LP4 V10 Board";
|
||||
compatible = "rockchip,rk3568-evb8-lp4-v10", "rockchip,rk3568";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
/delete-node/ tcs4525@1c;
|
||||
|
||||
vdd_cpu: rk8600@40 {
|
||||
compatible = "rockchip,rk8600";
|
||||
reg = <0x40>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
regulator-compatible = "rk860x-reg";
|
||||
regulator-name = "vdd_cpu";
|
||||
regulator-min-microvolt = <712500>;
|
||||
regulator-max-microvolt = <1390000>;
|
||||
regulator-init-microvolt = <900000>;
|
||||
regulator-ramp-delay = <2300>;
|
||||
rockchip,suspend-voltage-selector = <1>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -126,9 +126,9 @@
|
||||
|
||||
mbist-vmin = <825000 900000 950000>;
|
||||
nvmem-cells = <&cpu_leakage>, <&core_pvtm>, <&mbist_vmin>, <&cpu_opp_info>,
|
||||
<&specification_serial_number>;
|
||||
<&specification_serial_number>, <&remark_spec_serial_number>;
|
||||
nvmem-cell-names = "leakage", "pvtm", "mbist-vmin", "opp-info",
|
||||
"specification_serial_number";
|
||||
"specification_serial_number", "remark_spec_serial_number";
|
||||
rockchip,supported-hw;
|
||||
rockchip,max-volt = <1150000>;
|
||||
rockchip,pvtm-voltage-sel = <
|
||||
@@ -1149,9 +1149,9 @@
|
||||
|
||||
mbist-vmin = <825000 900000 950000>;
|
||||
nvmem-cells = <&npu_leakage>, <&core_pvtm>, <&mbist_vmin>, <&npu_opp_info>,
|
||||
<&specification_serial_number>;
|
||||
<&specification_serial_number>, <&remark_spec_serial_number>;
|
||||
nvmem-cell-names = "leakage", "pvtm", "mbist-vmin", "opp-info",
|
||||
"specification_serial_number";
|
||||
"specification_serial_number", "remark_spec_serial_number";
|
||||
rockchip,supported-hw;
|
||||
rockchip,max-volt = <1000000>;
|
||||
rockchip,temp-hysteresis = <5000>;
|
||||
@@ -1331,9 +1331,9 @@
|
||||
|
||||
mbist-vmin = <825000 900000 950000>;
|
||||
nvmem-cells = <&gpu_leakage>, <&core_pvtm>, <&mbist_vmin>, <&gpu_opp_info>,
|
||||
<&specification_serial_number>;
|
||||
<&specification_serial_number>, <&remark_spec_serial_number>;
|
||||
nvmem-cell-names = "leakage", "pvtm", "mbist-vmin", "opp-info",
|
||||
"specification_serial_number";
|
||||
"specification_serial_number", "remark_spec_serial_number";
|
||||
rockchip,supported-hw;
|
||||
rockchip,max-volt = <1000000>;
|
||||
rockchip,temp-hysteresis = <5000>;
|
||||
@@ -2420,9 +2420,9 @@
|
||||
|
||||
mbist-vmin = <825000 900000 950000>;
|
||||
nvmem-cells = <&log_leakage>, <&core_pvtm>, <&mbist_vmin>, <&dmc_opp_info>,
|
||||
<&specification_serial_number>;
|
||||
<&specification_serial_number>, <&remark_spec_serial_number>;
|
||||
nvmem-cell-names = "leakage", "pvtm", "mbist-vmin", "opp-info",
|
||||
"specification_serial_number";
|
||||
"specification_serial_number", "remark_spec_serial_number";
|
||||
rockchip,supported-hw;
|
||||
rockchip,max-volt = <1000000>;
|
||||
rockchip,temp-hysteresis = <5000>;
|
||||
@@ -2850,6 +2850,10 @@
|
||||
dmc_opp_info: dmc-opp-info@48 {
|
||||
reg = <0x48 0x6>;
|
||||
};
|
||||
remark_spec_serial_number: remark-spec-serial-number@56 {
|
||||
reg = <0x56 0x1>;
|
||||
bits = <0 5>;
|
||||
};
|
||||
};
|
||||
|
||||
i2s0_8ch: i2s@fe400000 {
|
||||
|
||||
@@ -362,7 +362,7 @@
|
||||
|
||||
hdmi1: hdmi@fdea0000 {
|
||||
compatible = "rockchip,rk3588-dw-hdmi";
|
||||
reg = <0x0 0xfdea0000 0x0 0x20000>;
|
||||
reg = <0x0 0xfdea0000 0x0 0x10000>, <0x0 0xfdeb0000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
||||
@@ -4984,7 +4984,7 @@
|
||||
|
||||
hdmi0: hdmi@fde80000 {
|
||||
compatible = "rockchip,rk3588-dw-hdmi";
|
||||
reg = <0x0 0xfde80000 0x0 0x20000>;
|
||||
reg = <0x0 0xfde80000 0x0 0x10000>, <0x0 0xfde90000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
||||
@@ -951,7 +951,6 @@ CONFIG_ROCKCHIP_EFUSE=y
|
||||
CONFIG_ROCKCHIP_OTP=y
|
||||
CONFIG_TEE=y
|
||||
CONFIG_OPTEE=y
|
||||
CONFIG_RK_NAND=y
|
||||
CONFIG_RK_HEADSET=y
|
||||
CONFIG_ROCKCHIP_RKNPU=y
|
||||
CONFIG_EXT4_FS=y
|
||||
|
||||
@@ -144,6 +144,7 @@ CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_SPI_NAND=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_DTC_SYMBOLS=y
|
||||
CONFIG_ZRAM=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
|
||||
@@ -317,14 +317,15 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
|
||||
RK3328_CLKGATE_CON(14), 1, GFLAGS),
|
||||
|
||||
/* PD_DDR */
|
||||
COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IS_CRITICAL,
|
||||
RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
|
||||
RK3328_CLKGATE_CON(0), 4, GFLAGS),
|
||||
GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IS_CRITICAL,
|
||||
COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0,
|
||||
RK3328_CLKSEL_CON(3), 8, 2, 0, 3,
|
||||
ROCKCHIP_DDRCLK_SIP_V2),
|
||||
|
||||
GATE(0, "clk_ddrmsch", "sclk_ddrc", CLK_IGNORE_UNUSED,
|
||||
RK3328_CLKGATE_CON(18), 6, GFLAGS),
|
||||
GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IS_CRITICAL,
|
||||
GATE(0, "clk_ddrupctl", "sclk_ddrc", CLK_IGNORE_UNUSED,
|
||||
RK3328_CLKGATE_CON(18), 5, GFLAGS),
|
||||
GATE(0, "aclk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED,
|
||||
GATE(0, "aclk_ddrupctl", "sclk_ddrc", CLK_IGNORE_UNUSED,
|
||||
RK3328_CLKGATE_CON(18), 4, GFLAGS),
|
||||
GATE(0, "clk_ddrmon", "xin24m", CLK_IGNORE_UNUSED,
|
||||
RK3328_CLKGATE_CON(0), 6, GFLAGS),
|
||||
|
||||
@@ -1618,6 +1618,16 @@ static void rk3568_dump_cru(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int protect_clocks[] = {
|
||||
ACLK_VO,
|
||||
HCLK_VO,
|
||||
ACLK_VOP,
|
||||
HCLK_VOP,
|
||||
DCLK_VOP0,
|
||||
DCLK_VOP1,
|
||||
DCLK_VOP2,
|
||||
};
|
||||
|
||||
static void __init rk3568_pmu_clk_init(struct device_node *np)
|
||||
{
|
||||
struct rockchip_clk_provider *ctx;
|
||||
@@ -1695,6 +1705,8 @@ static void __init rk3568_clk_init(struct device_node *np)
|
||||
|
||||
if (!rk_dump_cru)
|
||||
rk_dump_cru = rk3568_dump_cru;
|
||||
|
||||
rockchip_clk_protect(ctx, protect_clocks, ARRAY_SIZE(protect_clocks));
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(rk3568_cru, "rockchip,rk3568-cru", rk3568_clk_init);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o dw-hdmi-hdcp.o \
|
||||
dw-hdmi-qp.o
|
||||
dw-hdmi-qp.o dw-hdmi-qp-hdcp.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o dw-hdmi-qp-i2s-audio.o
|
||||
obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o dw-hdmi-qp-cec.o
|
||||
|
||||
650
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-hdcp.c
Normal file
650
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-hdcp.c
Normal file
@@ -0,0 +1,650 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) Rockchip Electronics Co.Ltd
|
||||
* Author:
|
||||
* Algea Cao <algea.cao@rock-chips.com>
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/soc/rockchip/rk_vendor_storage.h>
|
||||
#include <crypto/sha.h>
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
|
||||
#include "dw-hdmi-qp.h"
|
||||
#include "dw-hdmi-qp-hdcp.h"
|
||||
|
||||
#define HDCP_KEY_SIZE 308
|
||||
#define HDCP_KEY_SEED_SIZE 2
|
||||
|
||||
#define KSV_LEN 5
|
||||
#define HEADER 10
|
||||
#define SHAMAX 20
|
||||
|
||||
#define MAX_DOWNSTREAM_DEVICE_NUM 5
|
||||
#define DPK_WR_OK_TIMEOUT_US 30000
|
||||
#define HDMI_HDCP1X_ID 5
|
||||
|
||||
/* HDCP Registers */
|
||||
#define HDMI_HDCPREG_RMCTL 0x780e
|
||||
#define HDMI_HDCPREG_RMSTS 0x780f
|
||||
#define HDMI_HDCPREG_SEED0 0x7810
|
||||
#define HDMI_HDCPREG_SEED1 0x7811
|
||||
#define HDMI_HDCPREG_DPK0 0x7812
|
||||
#define HDMI_HDCPREG_DPK1 0x7813
|
||||
#define HDMI_HDCPREG_DPK2 0x7814
|
||||
#define HDMI_HDCPREG_DPK3 0x7815
|
||||
#define HDMI_HDCPREG_DPK4 0x7816
|
||||
#define HDMI_HDCPREG_DPK5 0x7817
|
||||
#define HDMI_HDCPREG_DPK6 0x7818
|
||||
#define HDMI_HDCP2REG_CTRL 0x7904
|
||||
#define HDMI_HDCP2REG_MASK 0x790c
|
||||
#define HDMI_HDCP2REG_MUTE 0x790e
|
||||
|
||||
enum dw_hdmi_hdcp_state {
|
||||
DW_HDCP_DISABLED,
|
||||
DW_HDCP_AUTH_START,
|
||||
DW_HDCP_AUTH_SUCCESS,
|
||||
DW_HDCP_AUTH_FAIL,
|
||||
};
|
||||
|
||||
enum {
|
||||
DW_HDMI_HDCP_KSV_LEN = 8,
|
||||
DW_HDMI_HDCP_SHA_LEN = 20,
|
||||
DW_HDMI_HDCP_DPK_LEN = 280,
|
||||
DW_HDMI_HDCP_KEY_LEN = 308,
|
||||
DW_HDMI_HDCP_SEED_LEN = 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
HDCP14_R0_TIMER_OVR_EN_MASK = 0x01,
|
||||
HDCP14_R0_TIMER_OVR_EN = 0x01,
|
||||
HDCP14_R0_TIMER_OVR_DISABLE = 0x00,
|
||||
|
||||
HDCP14_RI_TIMER_OVR_EN_MASK = 0x80,
|
||||
HDCP14_RI_TIMER_OVR_EN = 0x80,
|
||||
HDCP14_RI_TIMER_OVR_DISABLE = 0x00,
|
||||
|
||||
HDCP14_R0_TIMER_OVR_VALUE_MASK = 0x1e,
|
||||
HDCP14_RI_TIMER_OVR_VALUE_MASK = 0xff00,
|
||||
|
||||
HDCP14_KEY_WR_OK = 0x100,
|
||||
|
||||
HDCP14_HPD_MASK = 0x01,
|
||||
HDCP14_HPD_EN = 0x01,
|
||||
HDCP14_HPD_DISABLE = 0x00,
|
||||
|
||||
HDCP14_ENCRYPTION_ENABLE_MASK = 0x04,
|
||||
HDCP14_ENCRYPTION_ENABLE = 0x04,
|
||||
HDCP14_ENCRYPTION_DISABLE = 0x04,
|
||||
|
||||
HDCP14_KEY_DECRYPT_EN_MASK = 0x400,
|
||||
HDCP14_KEY_DECRYPT_EN = 0x400,
|
||||
HDCP14_KEY_DECRYPT_DISABLE = 0x00,
|
||||
|
||||
HDMI_A_SRMCTRL_SHA1_FAIL_MASK = 0X08,
|
||||
HDMI_A_SRMCTRL_SHA1_FAIL_DISABLE = 0X00,
|
||||
HDMI_A_SRMCTRL_SHA1_FAIL_ENABLE = 0X08,
|
||||
|
||||
HDMI_A_SRMCTRL_KSV_UPDATE_MASK = 0X04,
|
||||
HDMI_A_SRMCTRL_KSV_UPDATE_DISABLE = 0X00,
|
||||
HDMI_A_SRMCTRL_KSV_UPDATE_ENABLE = 0X04,
|
||||
|
||||
HDMI_A_SRMCTRL_KSV_MEM_REQ_MASK = 0X01,
|
||||
HDMI_A_SRMCTRL_KSV_MEM_REQ_DISABLE = 0X00,
|
||||
HDMI_A_SRMCTRL_KSV_MEM_REQ_ENABLE = 0X01,
|
||||
|
||||
HDMI_A_SRMCTRL_KSV_MEM_ACCESS_MASK = 0X02,
|
||||
HDMI_A_SRMCTRL_KSV_MEM_ACCESS_DISABLE = 0X00,
|
||||
HDMI_A_SRMCTRL_KSV_MEM_ACCESS_ENABLE = 0X02,
|
||||
|
||||
HDMI_A_SRM_BASE_MAX_DEVS_EXCEEDED = 0x80,
|
||||
HDMI_A_SRM_BASE_DEVICE_COUNT = 0x7f,
|
||||
|
||||
HDMI_A_SRM_BASE_MAX_CASCADE_EXCEEDED = 0x08,
|
||||
|
||||
HDMI_A_APIINTSTAT_KSVSHA1_CALC_INT = 0x02,
|
||||
|
||||
/* HDCPREG_RMSTS field values */
|
||||
DPK_WR_OK_STS = 0x40,
|
||||
|
||||
HDMI_A_HDCP22_MASK = 0x40,
|
||||
|
||||
HDMI_HDCP2_OVR_EN_MASK = 0x02,
|
||||
HDMI_HDCP2_OVR_ENABLE = 0x02,
|
||||
HDMI_HDCP2_OVR_DISABLE = 0x00,
|
||||
|
||||
HDMI_HDCP2_FORCE_MASK = 0x04,
|
||||
HDMI_HDCP2_FORCE_ENABLE = 0x04,
|
||||
HDMI_HDCP2_FORCE_DISABLE = 0x00,
|
||||
};
|
||||
|
||||
struct sha_t {
|
||||
u8 mlength[8];
|
||||
u8 mblock[64];
|
||||
int mindex;
|
||||
int mcomputed;
|
||||
int mcorrupted;
|
||||
unsigned int mdigest[5];
|
||||
};
|
||||
|
||||
static inline unsigned int shacircularshift(unsigned int bits,
|
||||
unsigned int word)
|
||||
{
|
||||
return (((word << bits) & 0xFFFFFFFF) | (word >> (32 - bits)));
|
||||
}
|
||||
|
||||
static void hdcp_modb(struct dw_qp_hdcp *hdcp, u32 data, u32 mask, u32 reg)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = hdcp->hdmi;
|
||||
u32 val = hdcp->read(hdmi, reg) & ~mask;
|
||||
|
||||
val |= data & mask;
|
||||
hdcp->write(hdmi, val, reg);
|
||||
}
|
||||
|
||||
static int hdcp_load_keys_cb(struct dw_qp_hdcp *hdcp)
|
||||
{
|
||||
u32 size;
|
||||
u8 hdcp_vendor_data[320];
|
||||
|
||||
hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
|
||||
if (!hdcp->keys)
|
||||
return -ENOMEM;
|
||||
|
||||
hdcp->seeds = kmalloc(HDCP_KEY_SEED_SIZE, GFP_KERNEL);
|
||||
if (!hdcp->seeds) {
|
||||
kfree(hdcp->keys);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
size = rk_vendor_read(HDMI_HDCP1X_ID, hdcp_vendor_data, 314);
|
||||
if (size < (HDCP_KEY_SIZE + HDCP_KEY_SEED_SIZE)) {
|
||||
dev_err(hdcp->dev, "HDCP: read size %d\n", size);
|
||||
memset(hdcp->keys, 0, HDCP_KEY_SIZE);
|
||||
memset(hdcp->seeds, 0, HDCP_KEY_SEED_SIZE);
|
||||
} else {
|
||||
memcpy(hdcp->keys, hdcp_vendor_data, HDCP_KEY_SIZE);
|
||||
memcpy(hdcp->seeds, hdcp_vendor_data + HDCP_KEY_SIZE,
|
||||
HDCP_KEY_SEED_SIZE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_hdcp_qp_hdcp_load_key(struct dw_qp_hdcp *hdcp)
|
||||
{
|
||||
int i, j;
|
||||
int ret, val;
|
||||
void __iomem *reg_rmsts_addr;
|
||||
struct dw_hdmi_qp_hdcp_keys *hdcp_keys;
|
||||
struct dw_hdmi_qp *hdmi = hdcp->hdmi;
|
||||
u32 ksv, dkl, dkh;
|
||||
|
||||
if (!hdcp->keys) {
|
||||
ret = hdcp_load_keys_cb(hdcp);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
hdcp_keys = hdcp->keys;
|
||||
|
||||
reg_rmsts_addr = hdcp->regs + HDCP14_KEY_STATUS;
|
||||
|
||||
/* hdcp key has been written */
|
||||
if (hdcp->read(hdmi, HDCP14_KEY_STATUS) & 0x3f) {
|
||||
dev_info(hdcp->dev, "hdcp key has been written\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ksv = hdcp_keys->KSV[0] | hdcp_keys->KSV[1] << 8 |
|
||||
hdcp_keys->KSV[2] << 16 | hdcp_keys->KSV[3] << 24;
|
||||
hdcp->write(hdmi, ksv, HDCP14_AKSV_L);
|
||||
|
||||
ksv = hdcp_keys->KSV[4];
|
||||
hdcp->write(hdmi, ksv, HDCP14_AKSV_H);
|
||||
|
||||
if (hdcp->seeds) {
|
||||
hdcp_modb(hdcp, HDCP14_KEY_DECRYPT_EN,
|
||||
HDCP14_KEY_DECRYPT_EN_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
hdcp->write(hdmi, (hdcp->seeds[0] << 8) | hdcp->seeds[1],
|
||||
HDCP14_KEY_SEED);
|
||||
} else {
|
||||
hdcp_modb(hdcp, HDCP14_KEY_DECRYPT_DISABLE,
|
||||
HDCP14_KEY_DECRYPT_EN_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
}
|
||||
|
||||
for (i = 0; i < DW_HDMI_HDCP_DPK_LEN - 6; i += 7) {
|
||||
dkl = 0;
|
||||
dkh = 0;
|
||||
for (j = 0; j < 4; j++)
|
||||
dkl |= hdcp_keys->devicekey[i + j] << (j * 8);
|
||||
for (j = 4; j < 7; j++)
|
||||
dkh |= hdcp_keys->devicekey[i + j] << ((j - 4) * 8);
|
||||
|
||||
hdcp->write(hdmi, dkh, HDCP14_KEY_H);
|
||||
hdcp->write(hdmi, dkl, HDCP14_KEY_L);
|
||||
|
||||
ret = readx_poll_timeout(readl, reg_rmsts_addr, val,
|
||||
val & HDCP14_KEY_WR_OK, 1000,
|
||||
DPK_WR_OK_TIMEOUT_US);
|
||||
if (ret) {
|
||||
dev_err(hdcp->dev, "hdcp key write err\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dw_hdcp_qp_hdcp_restart(struct dw_qp_hdcp *hdcp)
|
||||
{
|
||||
mutex_lock(&hdcp->mutex);
|
||||
|
||||
if (!hdcp->remaining_times) {
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
hdcp_modb(hdcp, 0, HDCP14_ENCRYPTION_ENABLE_MASK | HDCP14_HPD_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
|
||||
hdcp->write(hdcp->hdmi, 1, HDCP14_CONFIG1);
|
||||
mdelay(50);
|
||||
hdcp->write(hdcp->hdmi, HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N,
|
||||
AVP_1_INT_CLEAR);
|
||||
hdcp_modb(hdcp, HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N,
|
||||
HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N, AVP_1_INT_MASK_N);
|
||||
|
||||
hdcp_modb(hdcp, HDCP14_ENCRYPTION_ENABLE_MASK | HDCP14_HPD_MASK,
|
||||
HDCP14_ENCRYPTION_ENABLE_MASK | HDCP14_HPD_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
|
||||
hdcp->remaining_times--;
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
}
|
||||
|
||||
static int dw_hdcp_qp_hdcp_start(struct dw_qp_hdcp *hdcp)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = hdcp->hdmi;
|
||||
|
||||
dw_hdcp_qp_hdcp_load_key(hdcp);
|
||||
|
||||
mutex_lock(&hdcp->mutex);
|
||||
hdcp->remaining_times = hdcp->retry_times;
|
||||
|
||||
hdcp->write(hdmi, HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N, AVP_1_INT_CLEAR);
|
||||
hdcp_modb(hdcp, HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N,
|
||||
HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N, AVP_1_INT_MASK_N);
|
||||
|
||||
mdelay(50);
|
||||
|
||||
hdcp_modb(hdcp, HDCP14_ENCRYPTION_ENABLE | HDCP14_HPD_EN,
|
||||
HDCP14_ENCRYPTION_ENABLE_MASK | HDCP14_HPD_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
|
||||
hdcp->status = DW_HDCP_AUTH_START;
|
||||
dev_info(hdcp->dev, "start hdcp\n");
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
|
||||
queue_work(hdcp->workqueue, &hdcp->work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_hdcp_qp_hdcp_stop(struct dw_qp_hdcp *hdcp)
|
||||
{
|
||||
mutex_lock(&hdcp->mutex);
|
||||
hdcp_modb(hdcp, 0, HDCP14_ENCRYPTION_ENABLE_MASK | HDCP14_HPD_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
|
||||
hdcp_modb(hdcp, 0, HDCP14_AUTH_CHG_MASK_N | HDCP14_KSV_LIST_DONE_MASK_N, AVP_1_INT_MASK_N);
|
||||
hdcp->write(hdcp->hdmi, 0, HDCP14_CONFIG1);
|
||||
hdcp->status = DW_HDCP_DISABLED;
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sha_reset(struct sha_t *sha)
|
||||
{
|
||||
u32 i = 0;
|
||||
|
||||
sha->mindex = 0;
|
||||
sha->mcomputed = false;
|
||||
sha->mcorrupted = false;
|
||||
for (i = 0; i < sizeof(sha->mlength); i++)
|
||||
sha->mlength[i] = 0;
|
||||
|
||||
sha1_init(sha->mdigest);
|
||||
}
|
||||
|
||||
static void sha_processblock(struct sha_t *sha)
|
||||
{
|
||||
u32 array[SHA1_WORKSPACE_WORDS];
|
||||
|
||||
sha1_transform(sha->mdigest, sha->mblock, array);
|
||||
sha->mindex = 0;
|
||||
}
|
||||
|
||||
static void sha_padmessage(struct sha_t *sha)
|
||||
{
|
||||
/*
|
||||
* Check to see if the current message block is too small to hold
|
||||
* the initial padding bits and length. If so, we will pad the
|
||||
* block, process it, and then continue padding into a second
|
||||
* block.
|
||||
*/
|
||||
if (sha->mindex > 55) {
|
||||
sha->mblock[sha->mindex++] = 0x80;
|
||||
while (sha->mindex < 64)
|
||||
sha->mblock[sha->mindex++] = 0;
|
||||
|
||||
sha_processblock(sha);
|
||||
while (sha->mindex < 56)
|
||||
sha->mblock[sha->mindex++] = 0;
|
||||
} else {
|
||||
sha->mblock[sha->mindex++] = 0x80;
|
||||
while (sha->mindex < 56)
|
||||
sha->mblock[sha->mindex++] = 0;
|
||||
}
|
||||
|
||||
/* Store the message length as the last 8 octets */
|
||||
sha->mblock[56] = sha->mlength[7];
|
||||
sha->mblock[57] = sha->mlength[6];
|
||||
sha->mblock[58] = sha->mlength[5];
|
||||
sha->mblock[59] = sha->mlength[4];
|
||||
sha->mblock[60] = sha->mlength[3];
|
||||
sha->mblock[61] = sha->mlength[2];
|
||||
sha->mblock[62] = sha->mlength[1];
|
||||
sha->mblock[63] = sha->mlength[0];
|
||||
|
||||
sha_processblock(sha);
|
||||
}
|
||||
|
||||
static int sha_result(struct sha_t *sha)
|
||||
{
|
||||
if (sha->mcorrupted)
|
||||
return false;
|
||||
|
||||
if (sha->mcomputed == 0) {
|
||||
sha_padmessage(sha);
|
||||
sha->mcomputed = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sha_input(struct sha_t *sha, const u8 *data, u32 size)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int j = 0;
|
||||
int rc = true;
|
||||
|
||||
if (data == 0 || size == 0)
|
||||
return;
|
||||
|
||||
if (sha->mcomputed || sha->mcorrupted) {
|
||||
sha->mcorrupted = true;
|
||||
return;
|
||||
}
|
||||
while (size-- && !sha->mcorrupted) {
|
||||
sha->mblock[sha->mindex++] = *data;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
rc = true;
|
||||
for (j = 0; j < sizeof(sha->mlength); j++) {
|
||||
sha->mlength[j]++;
|
||||
if (sha->mlength[j] != 0) {
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sha->mcorrupted = (sha->mcorrupted ||
|
||||
rc) ? true : false;
|
||||
}
|
||||
/* if corrupted then message is too long */
|
||||
if (sha->mindex == 64)
|
||||
sha_processblock(sha);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
static int hdcp_verify_ksv(const u8 *data, u32 size)
|
||||
{
|
||||
u32 i = 0;
|
||||
struct sha_t sha;
|
||||
|
||||
if ((!data) || (size < (HEADER + SHAMAX)))
|
||||
return false;
|
||||
|
||||
sha_reset(&sha);
|
||||
sha_input(&sha, data, size - SHAMAX);
|
||||
if (sha_result(&sha) == false)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < SHAMAX; i++) {
|
||||
if (data[size - SHAMAX + i] != (u8)(sha.mdigest[i / 4] >> ((i % 4) * 8)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dw_hdcp_qp_hdcp_2nd_auth(struct dw_qp_hdcp *hdcp)
|
||||
{
|
||||
u8 *data;
|
||||
u32 len;
|
||||
|
||||
len = (hdcp->read(hdcp->hdmi, HDCP14_STATUS0) & HDCP14_RPT_DEVICE_COUNT) >> 9;
|
||||
len = len * KSV_LEN + BSTATUS_LEN + M0_LEN + SHAMAX;
|
||||
|
||||
data = kmalloc(len, GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
hdcp->get_mem(hdcp->hdmi, data, len);
|
||||
|
||||
if (hdcp_verify_ksv(data, len))
|
||||
hdcp->write(hdcp->hdmi, HDCP14_SHA1_MSG_CORRECT_P, HDCP14_CONFIG1);
|
||||
else
|
||||
dw_hdcp_qp_hdcp_restart(hdcp);
|
||||
}
|
||||
|
||||
static void dw_hdcp_qp_hdcp_auth(struct dw_qp_hdcp *hdcp, u32 hdcp_status)
|
||||
{
|
||||
if (!(hdcp_status & BIT(2))) {
|
||||
mutex_lock(&hdcp->mutex);
|
||||
if (hdcp->status == DW_HDCP_DISABLED) {
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return;
|
||||
}
|
||||
dev_err(hdcp->dev, "hdcp auth failed\n");
|
||||
hdcp_modb(hdcp, 0, HDCP14_ENCRYPTION_ENABLE_MASK | HDCP14_HPD_MASK,
|
||||
HDCP14_CONFIG0);
|
||||
hdcp->status = DW_HDCP_AUTH_FAIL;
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
|
||||
dw_hdcp_qp_hdcp_restart(hdcp);
|
||||
} else {
|
||||
mutex_lock(&hdcp->mutex);
|
||||
dev_info(hdcp->dev, "hdcp auth success\n");
|
||||
hdcp->status = DW_HDCP_AUTH_SUCCESS;
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void dw_hdcp_qp_hdcp_isr(struct dw_qp_hdcp *hdcp, u32 avp_int, u32 hdcp_status)
|
||||
{
|
||||
if (hdcp->status == DW_HDCP_DISABLED)
|
||||
return;
|
||||
|
||||
dev_info(hdcp->dev, "hdcp_int is 0x%02x\n", hdcp_status);
|
||||
|
||||
if (avp_int & HDCP14_KSV_LIST_DONE_MASK_N)
|
||||
dw_hdcp_qp_hdcp_2nd_auth(hdcp);
|
||||
|
||||
if (avp_int & HDCP14_AUTH_CHG_MASK_N)
|
||||
dw_hdcp_qp_hdcp_auth(hdcp, hdcp_status);
|
||||
}
|
||||
|
||||
static ssize_t trytimes_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int trytimes = 0;
|
||||
struct dw_qp_hdcp *hdcp = dev_get_drvdata(device);
|
||||
|
||||
if (hdcp)
|
||||
trytimes = hdcp->retry_times;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
|
||||
}
|
||||
|
||||
static ssize_t trytimes_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int trytimes;
|
||||
struct dw_qp_hdcp *hdcp = dev_get_drvdata(device);
|
||||
|
||||
if (!hdcp)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtoint(buf, 0, &trytimes))
|
||||
return -EINVAL;
|
||||
|
||||
if (hdcp->retry_times != trytimes) {
|
||||
hdcp->retry_times = trytimes;
|
||||
hdcp->remaining_times = hdcp->retry_times;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(trytimes);
|
||||
|
||||
static ssize_t status_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int status = DW_HDCP_DISABLED;
|
||||
struct dw_qp_hdcp *hdcp = dev_get_drvdata(device);
|
||||
|
||||
if (hdcp)
|
||||
status = hdcp->status;
|
||||
|
||||
if (status == DW_HDCP_DISABLED)
|
||||
return snprintf(buf, PAGE_SIZE, "hdcp disable\n");
|
||||
else if (status == DW_HDCP_AUTH_START)
|
||||
return snprintf(buf, PAGE_SIZE, "hdcp_auth_start\n");
|
||||
else if (status == DW_HDCP_AUTH_SUCCESS)
|
||||
return snprintf(buf, PAGE_SIZE, "hdcp_auth_success\n");
|
||||
else if (status == DW_HDCP_AUTH_FAIL)
|
||||
return snprintf(buf, PAGE_SIZE, "hdcp_auth_fail\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "unknown status\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(status);
|
||||
|
||||
static struct attribute *dw_hdmi_qp_hdcp_attrs[] = {
|
||||
&dev_attr_trytimes.attr,
|
||||
&dev_attr_status.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(dw_hdmi_qp_hdcp);
|
||||
|
||||
/* If sink is a repeater, we need to wait ksv list ready */
|
||||
static void dw_hdmi_qp_hdcp(struct work_struct *p_work)
|
||||
{
|
||||
struct dw_qp_hdcp *hdcp = container_of(p_work, struct dw_qp_hdcp, work);
|
||||
u32 val;
|
||||
int i = 500;
|
||||
|
||||
while (i--) {
|
||||
usleep_range(7000, 8000);
|
||||
|
||||
mutex_lock(&hdcp->mutex);
|
||||
if (hdcp->status == DW_HDCP_DISABLED) {
|
||||
dev_dbg(hdcp->dev, "hdcp is disabled, don't wait repeater ready\n");
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
val = hdcp->read(hdcp->hdmi, HDCP14_STATUS1);
|
||||
|
||||
/* sink isn't repeater or ksv fifo ready, stop waiting */
|
||||
if (!(val & HDCP14_RCV_REPEATER) || (val & HDCP14_RCV_KSV_FIFO_READY)) {
|
||||
dev_dbg(hdcp->dev, "wait ksv fifo finished\n");
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_unlock(&hdcp->mutex);
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
dev_err(hdcp->dev, "wait repeater ready time out\n");
|
||||
dw_hdcp_qp_hdcp_restart(hdcp);
|
||||
}
|
||||
}
|
||||
|
||||
static int dw_hdcp_qp_hdcp_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct dw_qp_hdcp *hdcp = pdev->dev.platform_data;
|
||||
|
||||
/* retry time if hdcp auth fail. unlimited time if set 0 */
|
||||
hdcp->dev = &pdev->dev;
|
||||
hdcp->hdcp_start = dw_hdcp_qp_hdcp_start;
|
||||
hdcp->hdcp_stop = dw_hdcp_qp_hdcp_stop;
|
||||
hdcp->hdcp_isr = dw_hdcp_qp_hdcp_isr;
|
||||
|
||||
ret = device_add_groups(hdcp->dev, dw_hdmi_qp_hdcp_groups);
|
||||
if (ret) {
|
||||
dev_err(hdcp->dev, "Failed to add sysfs files group\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, hdcp);
|
||||
|
||||
hdcp->workqueue = create_workqueue("hdcp_queue");
|
||||
INIT_WORK(&hdcp->work, dw_hdmi_qp_hdcp);
|
||||
|
||||
hdcp->retry_times = 3;
|
||||
mutex_init(&hdcp->mutex);
|
||||
|
||||
dev_info(hdcp->dev, "%s success\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_hdcp_qp_hdcp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dw_qp_hdcp *hdcp = pdev->dev.platform_data;
|
||||
|
||||
cancel_work_sync(&hdcp->work);
|
||||
flush_workqueue(hdcp->workqueue);
|
||||
destroy_workqueue(hdcp->workqueue);
|
||||
|
||||
device_remove_groups(hdcp->dev, dw_hdmi_qp_hdcp_groups);
|
||||
kfree(hdcp->keys);
|
||||
kfree(hdcp->seeds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver dw_hdcp_qp_hdcp_driver = {
|
||||
.probe = dw_hdcp_qp_hdcp_probe,
|
||||
.remove = dw_hdcp_qp_hdcp_remove,
|
||||
.driver = {
|
||||
.name = DW_HDCP_QP_DRIVER_NAME,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(dw_hdcp_qp_hdcp_driver);
|
||||
MODULE_DESCRIPTION("DW HDMI QP transmitter HDCP driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
55
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-hdcp.h
Normal file
55
drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp-hdcp.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (C) Rockchip Electronics Co.Ltd
|
||||
* Author:
|
||||
* Algea Cao <algea.cao@rock-chips.com>
|
||||
*/
|
||||
#ifndef DW_HDMI_QP_HDCP_H
|
||||
#define DW_HDMI_QP_HDCP_H
|
||||
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
#define DW_HDCP_QP_DRIVER_NAME "dw-hdmi-qp-hdcp"
|
||||
#define PRIVATE_KEY_SIZE 280
|
||||
#define KEY_SHA_SIZE 20
|
||||
|
||||
#define KSV_LEN 5
|
||||
#define BSTATUS_LEN 2
|
||||
#define M0_LEN 8
|
||||
#define SHAMAX 20
|
||||
|
||||
struct dw_hdmi_qp_hdcp_keys {
|
||||
u8 KSV[8];
|
||||
u8 devicekey[PRIVATE_KEY_SIZE];
|
||||
u8 sha1[KEY_SHA_SIZE];
|
||||
};
|
||||
|
||||
struct dw_qp_hdcp {
|
||||
int retry_times;
|
||||
int remaining_times;
|
||||
char *seeds;
|
||||
int invalidkey;
|
||||
char *invalidkeys;
|
||||
int hdcp2_enable;
|
||||
int status;
|
||||
u32 reg_io_width;
|
||||
|
||||
struct dw_hdmi_qp_hdcp_keys *keys;
|
||||
struct device *dev;
|
||||
struct dw_hdmi_qp *hdmi;
|
||||
void __iomem *regs;
|
||||
|
||||
struct mutex mutex;
|
||||
|
||||
struct work_struct work;
|
||||
struct workqueue_struct *workqueue;
|
||||
|
||||
void (*write)(struct dw_hdmi_qp *hdmi, u32 val, int offset);
|
||||
u32 (*read)(struct dw_hdmi_qp *hdmi, int offset);
|
||||
void (*get_mem)(struct dw_hdmi_qp *hdmi, u8 *data, u32 len);
|
||||
int (*hdcp_start)(struct dw_qp_hdcp *hdcp);
|
||||
int (*hdcp_stop)(struct dw_qp_hdcp *hdcp);
|
||||
void (*hdcp_isr)(struct dw_qp_hdcp *hdcp, u32 avp_int, u32 hdcp_status);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
* Author:
|
||||
* Algea Cao <algea.cao@rock-chips.com>
|
||||
*/
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <drm/drm_dsc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
@@ -38,6 +40,7 @@
|
||||
#include "dw-hdmi-qp-audio.h"
|
||||
#include "dw-hdmi-qp.h"
|
||||
#include "dw-hdmi-qp-cec.h"
|
||||
#include "dw-hdmi-qp-hdcp.h"
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
@@ -52,6 +55,19 @@
|
||||
#define HDMI14_MAX_TMDSCLK 340000000
|
||||
#define HDMI20_MAX_TMDSCLK_KHZ 600000
|
||||
|
||||
#define HDMI_VH0 0x20
|
||||
#define HDMI_HDCP_ADDR 0x3a
|
||||
#define HDMI_BCAPS 0x40
|
||||
#define HDMI_HDCP14_SUPPORT BIT(7)
|
||||
#define HDMI_HDCP2_VERSION 0x50
|
||||
#define HDMI_HDCP2_SUPPORT BIT(2)
|
||||
|
||||
#define SINK_CAP_HDCP14 BIT(0)
|
||||
#define SINK_CAP_HDCP2 BIT(1)
|
||||
|
||||
#define HDMI_HDCP2_AUTH BIT(1)
|
||||
#define HDMI_HDCP14_AUTH BIT(0)
|
||||
|
||||
static const unsigned int dw_hdmi_cable[] = {
|
||||
EXTCON_DISP_HDMI,
|
||||
EXTCON_NONE,
|
||||
@@ -231,7 +247,7 @@ struct dw_hdmi_qp {
|
||||
|
||||
struct hdmi_qp_data_info hdmi_data;
|
||||
const struct dw_hdmi_plat_data *plat_data;
|
||||
|
||||
struct dw_qp_hdcp *hdcp;
|
||||
int vic;
|
||||
int main_irq;
|
||||
int avp_irq;
|
||||
@@ -250,6 +266,7 @@ struct dw_hdmi_qp {
|
||||
|
||||
struct i2c_adapter *ddc;
|
||||
void __iomem *regs;
|
||||
void __iomem *hdcp14_mem;
|
||||
bool sink_is_hdmi;
|
||||
bool sink_has_audio;
|
||||
bool dclk_en;
|
||||
@@ -270,6 +287,8 @@ struct dw_hdmi_qp {
|
||||
bool rxsense; /* rxsense state */
|
||||
u8 phy_mask; /* desired phy int mask settings */
|
||||
u8 mc_clkdis; /* clock disable register */
|
||||
u8 hdcp_caps;
|
||||
u8 hdcp_status;
|
||||
|
||||
bool update;
|
||||
bool hdr2sdr;
|
||||
@@ -947,8 +966,6 @@ static void dw_hdmi_i2c_init(struct dw_hdmi_qp *hdmi)
|
||||
/* Software reset */
|
||||
hdmi_writel(hdmi, 0x01, I2CM_CONTROL0);
|
||||
|
||||
hdmi_writel(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0);
|
||||
|
||||
hdmi_modb(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0);
|
||||
|
||||
/* Clear DONE and ERROR interrupts */
|
||||
@@ -1879,6 +1896,58 @@ hdmi_get_tmdsclock(struct dw_hdmi_qp *hdmi, unsigned long mpixelclock)
|
||||
return tmdsclock;
|
||||
}
|
||||
|
||||
static void dw_hdmi_qp_hdcp_enable(struct dw_hdmi_qp *hdmi,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
int ret, val;
|
||||
const struct drm_connector_state *conn_state = connector->state;
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
|
||||
if (conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_DESIRED)
|
||||
return;
|
||||
|
||||
/* sink support hdcp2.x */
|
||||
if (hdmi->hdcp_caps & SINK_CAP_HDCP2) {
|
||||
hdmi_writel(hdmi, HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ, AVP_3_INT_CLEAR);
|
||||
hdmi_modb(hdmi, HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ,
|
||||
HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ, AVP_3_INT_MASK_N);
|
||||
|
||||
hdmi_writel(hdmi, 0x35, HDCP2LOGIC_ESM_GPIO_IN);
|
||||
hdmi_modb(hdmi, 0, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
|
||||
if (hdmi->plat_data->set_hdcp2_enable)
|
||||
hdmi->plat_data->set_hdcp2_enable(data, true);
|
||||
|
||||
/* wait hdcp2.X auth success */
|
||||
ret = regmap_read_poll_timeout(hdmi->regm, HDCP2LOGIC_ESM_GPIO_OUT, val,
|
||||
FIELD_GET(HDCP2_AUTHENTICATION_SUCCESS, val),
|
||||
10000, 2000000);
|
||||
if (ret) {
|
||||
hdmi->hdcp_status &= ~HDMI_HDCP2_AUTH;
|
||||
dev_info(hdmi->dev, "hdcp2 auth failed,start hdcp1.4\n");
|
||||
|
||||
hdmi_writel(hdmi, 0, HDCP2LOGIC_ESM_GPIO_IN);
|
||||
hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
|
||||
|
||||
if (hdmi->plat_data->set_hdcp2_enable)
|
||||
hdmi->plat_data->set_hdcp2_enable(data, false);
|
||||
|
||||
if (hdmi->hdcp && hdmi->hdcp->hdcp_start)
|
||||
hdmi->hdcp->hdcp_start(hdmi->hdcp);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
hdmi->hdcp_status |= HDMI_HDCP2_AUTH;
|
||||
drm_hdcp_update_content_protection(connector, DRM_MODE_CONTENT_PROTECTION_ENABLED);
|
||||
dev_info(hdmi->dev, "HDCP2 authentication succeed\n");
|
||||
} else {
|
||||
if (hdmi->hdcp && hdmi->hdcp->hdcp_start)
|
||||
hdmi->hdcp->hdcp_start(hdmi->hdcp);
|
||||
}
|
||||
exit:
|
||||
if (hdmi->plat_data->set_hdcp_status)
|
||||
hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
|
||||
}
|
||||
|
||||
static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi,
|
||||
const struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
@@ -2040,6 +2109,7 @@ static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi,
|
||||
dev_info(hdmi->dev, "%s DVI mode\n", __func__);
|
||||
}
|
||||
|
||||
dw_hdmi_qp_hdcp_enable(hdmi, hdmi->curr_conn);
|
||||
hdmi->frl_switch = false;
|
||||
return 0;
|
||||
}
|
||||
@@ -2129,6 +2199,58 @@ static bool dw_hdmi_qp_check_output_type_changed(struct dw_hdmi_qp *hdmi)
|
||||
return false;
|
||||
}
|
||||
|
||||
static ssize_t hdcp_ddc_read(struct i2c_adapter *adapter, u8 address,
|
||||
u8 offset, void *buffer)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_msg msgs[2] = {
|
||||
{
|
||||
.addr = address,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &offset,
|
||||
}, {
|
||||
.addr = address,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = buffer,
|
||||
}
|
||||
};
|
||||
|
||||
ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret != ARRAY_SIZE(msgs))
|
||||
return -EPROTO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 dw_hdmi_qp_hdcp_capable(struct dw_hdmi_qp *hdmi)
|
||||
{
|
||||
u8 version = 0;
|
||||
u8 bcaps;
|
||||
int ret;
|
||||
|
||||
ret = hdcp_ddc_read(hdmi->ddc, HDMI_HDCP_ADDR, HDMI_BCAPS, &bcaps);
|
||||
if (ret < 0) {
|
||||
dev_err(hdmi->dev, "get hdcp1.4 capable failed:%d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
if (bcaps & HDMI_HDCP14_SUPPORT)
|
||||
version |= SINK_CAP_HDCP14;
|
||||
|
||||
ret = hdcp_ddc_read(hdmi->ddc, HDMI_HDCP_ADDR, HDMI_HDCP2_VERSION, &bcaps);
|
||||
if (ret < 0) {
|
||||
dev_err(hdmi->dev, "get hdcp2.x capable failed:%d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
if (bcaps & HDMI_HDCP2_SUPPORT)
|
||||
version |= SINK_CAP_HDCP2;
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi =
|
||||
@@ -2139,6 +2261,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
struct drm_property_blob *edid_blob_ptr = connector->edid_blob_ptr;
|
||||
int i, ret = 0;
|
||||
|
||||
if (hdmi->plat_data->right && hdmi->plat_data->right->next_bridge) {
|
||||
@@ -2160,7 +2283,17 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
return 0;
|
||||
|
||||
memset(metedata, 0, sizeof(*metedata));
|
||||
edid = drm_get_edid(connector, hdmi->ddc);
|
||||
|
||||
if (edid_blob_ptr && edid_blob_ptr->length) {
|
||||
edid = kmalloc(edid_blob_ptr->length, GFP_KERNEL);
|
||||
if (!edid)
|
||||
return -ENOMEM;
|
||||
memcpy(edid, edid_blob_ptr->data, edid_blob_ptr->length);
|
||||
} else {
|
||||
edid = drm_get_edid(connector, hdmi->ddc);
|
||||
hdmi->hdcp_caps = dw_hdmi_qp_hdcp_capable(hdmi);
|
||||
}
|
||||
|
||||
if (edid) {
|
||||
dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
|
||||
edid->width_cm, edid->height_cm);
|
||||
@@ -2178,6 +2311,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
if (hdmi->plat_data->get_yuv422_format)
|
||||
hdmi->plat_data->get_yuv422_format(connector, edid);
|
||||
dw_hdmi_update_hdr_property(connector);
|
||||
hdmi->hdcp_caps = dw_hdmi_qp_hdcp_capable(hdmi);
|
||||
if (ret > 0 && hdmi->plat_data->split_mode) {
|
||||
struct dw_hdmi_qp *secondary = NULL;
|
||||
void *secondary_data;
|
||||
@@ -2187,8 +2321,10 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
|
||||
else if (hdmi->plat_data->right)
|
||||
secondary = hdmi->plat_data->right;
|
||||
|
||||
if (!secondary)
|
||||
if (!secondary) {
|
||||
kfree(edid);
|
||||
return -ENOMEM;
|
||||
}
|
||||
secondary_data = secondary->plat_data->phy_data;
|
||||
|
||||
list_for_each_entry(mode, &connector->probed_modes, head)
|
||||
@@ -2460,6 +2596,37 @@ static bool check_hdr_color_change(struct drm_connector_state *old_state,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool check_dw_hdcp_state_changed(struct drm_connector *conn,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *old_state, *new_state;
|
||||
u64 old_cp, new_cp;
|
||||
|
||||
old_state = drm_atomic_get_old_connector_state(state, conn);
|
||||
new_state = drm_atomic_get_new_connector_state(state, conn);
|
||||
old_cp = old_state->content_protection;
|
||||
new_cp = new_state->content_protection;
|
||||
|
||||
if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
|
||||
new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!new_state->crtc) {
|
||||
if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (old_cp == new_cp ||
|
||||
(old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
|
||||
new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
@@ -2605,6 +2772,9 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
}
|
||||
}
|
||||
|
||||
if (check_dw_hdcp_state_changed(connector, state))
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2791,6 +2961,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
const struct drm_connector_state *conn_state = hdmi->curr_conn->state;
|
||||
|
||||
if (hdmi->panel)
|
||||
drm_panel_disable(hdmi->panel);
|
||||
@@ -2799,6 +2970,19 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
hdmi_writel(hdmi, 1, PKTSCHED_PKT_CONTROL0);
|
||||
mdelay(50);
|
||||
|
||||
hdmi_modb(hdmi, 0, HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ,
|
||||
AVP_3_INT_MASK_N);
|
||||
if (hdmi->hdcp && hdmi->hdcp->hdcp_stop)
|
||||
hdmi->hdcp->hdcp_stop(hdmi->hdcp);
|
||||
|
||||
hdmi_writel(hdmi, 0, HDCP2LOGIC_ESM_GPIO_IN);
|
||||
if (conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
drm_hdcp_update_content_protection(hdmi->curr_conn,
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED);
|
||||
|
||||
if (hdmi->plat_data->set_hdcp_status)
|
||||
hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
|
||||
|
||||
extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false);
|
||||
handle_plugged_change(hdmi, false);
|
||||
mutex_lock(&hdmi->mutex);
|
||||
@@ -2815,7 +2999,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
hdmi_writel(hdmi, 0, FLT_CONFIG0);
|
||||
hdmi_writel(hdmi, 0, SCRAMB_CONFIG0);
|
||||
/* set sink frl mode disable */
|
||||
if (hdmi->curr_conn && dw_hdmi_support_scdc(hdmi, &hdmi->curr_conn->display_info))
|
||||
if (dw_hdmi_support_scdc(hdmi, &hdmi->curr_conn->display_info))
|
||||
drm_scdc_writeb(hdmi->ddc, 0x31, 0);
|
||||
|
||||
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
|
||||
@@ -2947,17 +3131,77 @@ static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id)
|
||||
static irqreturn_t dw_hdmi_qp_avp_hardirq(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = dev_id;
|
||||
u32 stat;
|
||||
u32 stat1, stat3;
|
||||
|
||||
stat = hdmi_readl(hdmi, AVP_1_INT_STATUS);
|
||||
if (stat) {
|
||||
dev_dbg(hdmi->dev, "HDCP irq %#x\n", stat);
|
||||
stat &= ~stat;
|
||||
hdmi_writel(hdmi, stat, AVP_1_INT_MASK_N);
|
||||
return IRQ_WAKE_THREAD;
|
||||
stat1 = hdmi_readl(hdmi, AVP_1_INT_STATUS);
|
||||
stat3 = hdmi_readl(hdmi, AVP_3_INT_STATUS);
|
||||
|
||||
if (!stat1 && !stat3)
|
||||
return IRQ_NONE;
|
||||
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
static irqreturn_t dw_hdmi_qp_avp_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = dev_id;
|
||||
struct drm_connector_state *conn_state;
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
u32 stat1, stat3, val;
|
||||
|
||||
stat1 = hdmi_readl(hdmi, AVP_1_INT_STATUS);
|
||||
stat3 = hdmi_readl(hdmi, AVP_3_INT_STATUS);
|
||||
|
||||
hdmi_writel(hdmi, stat1, AVP_1_INT_CLEAR);
|
||||
hdmi_writel(hdmi, stat3, AVP_3_INT_CLEAR);
|
||||
|
||||
if (!hdmi->curr_conn || !hdmi->curr_conn->state)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
conn_state = hdmi->curr_conn->state;
|
||||
val = conn_state->content_protection;
|
||||
|
||||
if (hdmi->hdcp && hdmi->hdcp->hdcp_isr) {
|
||||
u32 hdcp_status = hdmi_readl(hdmi, HDCP14_STATUS0);
|
||||
|
||||
if (stat1 & HDCP14_AUTH_CHG_MASK_N) {
|
||||
/* hdcp14 auth success */
|
||||
if (hdcp_status & BIT(2)) {
|
||||
hdmi->hdcp_status |= HDMI_HDCP14_AUTH;
|
||||
if (conn_state->content_protection !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
val = DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
} else if (!(hdcp_status & BIT(2))) {
|
||||
hdmi->hdcp_status &= ~HDMI_HDCP14_AUTH;
|
||||
if (conn_state->content_protection !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
val = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
}
|
||||
conn_state->content_protection = val;
|
||||
}
|
||||
hdmi->hdcp->hdcp_isr(hdmi->hdcp, stat1, hdcp_status);
|
||||
}
|
||||
|
||||
return IRQ_NONE;
|
||||
if (stat3 & HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ) {
|
||||
stat3 = hdmi_readl(hdmi, HDCP2LOGIC_ESM_GPIO_OUT);
|
||||
if (stat3 & HDCP2_AUTHENTICATION_SUCCESS) {
|
||||
hdmi->hdcp_status |= HDMI_HDCP2_AUTH;
|
||||
if (conn_state->content_protection !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
val = DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
} else if (!(stat3 & HDCP2_AUTHENTICATION_SUCCESS)) {
|
||||
hdmi->hdcp_status &= ~HDMI_HDCP2_AUTH;
|
||||
if (conn_state->content_protection !=
|
||||
DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
val = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
}
|
||||
conn_state->content_protection = val;
|
||||
}
|
||||
|
||||
if (hdmi->plat_data->set_hdcp_status)
|
||||
hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t dw_hdmi_qp_earc_hardirq(int irq, void *dev_id)
|
||||
@@ -2976,21 +3220,6 @@ static irqreturn_t dw_hdmi_qp_earc_hardirq(int irq, void *dev_id)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t dw_hdmi_qp_avp_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = dev_id;
|
||||
u32 stat;
|
||||
|
||||
stat = hdmi_readl(hdmi, AVP_1_INT_STATUS);
|
||||
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
hdmi_writel(hdmi, stat, AVP_1_INT_CLEAR);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t dw_hdmi_qp_earc_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = dev_id;
|
||||
@@ -3383,6 +3612,70 @@ static void dw_hdmi_register_debugfs(struct device *dev, struct dw_hdmi_qp *hdmi
|
||||
hdmi, &dw_hdmi_ctrl_fops);
|
||||
}
|
||||
|
||||
static void dw_hdmi_qp_hdcp14_get_mem(struct dw_hdmi_qp *hdmi, u8 *data, u32 len)
|
||||
{
|
||||
u32 ksv_len, i, val;
|
||||
void *hdmi_data = hdmi->plat_data->phy_data;
|
||||
|
||||
if (hdmi->plat_data->set_hdcp14_mem)
|
||||
hdmi->plat_data->set_hdcp14_mem(hdmi_data, true);
|
||||
|
||||
ksv_len = len - BSTATUS_LEN - M0_LEN - SHAMAX;
|
||||
for (i = 0; i < len; i++) {
|
||||
/* read ksv list */
|
||||
if (i < ksv_len)
|
||||
val = readl(hdmi->hdcp14_mem + HDMI_HDCP14_MEM_KSV0 + i * 4);
|
||||
/* read bstatus */
|
||||
else if (i < len - SHAMAX - M0_LEN)
|
||||
val = readl(hdmi->hdcp14_mem + HDMI_HDCP14_MEM_BSTATUS0 +
|
||||
(i - ksv_len) * 4);
|
||||
/* read M0 */
|
||||
else if (i < len - SHAMAX)
|
||||
val = readl(hdmi->hdcp14_mem + HDMI_HDCP14_MEM_M0_1 +
|
||||
(i - ksv_len - BSTATUS_LEN) * 4);
|
||||
else
|
||||
/* VH0 save in external memory is error, we need to read VH0 via ddc */
|
||||
hdcp_ddc_read(hdmi->ddc, HDMI_HDCP_ADDR, HDMI_VH0 + i - (len - SHAMAX),
|
||||
&val);
|
||||
|
||||
data[i] = val;
|
||||
}
|
||||
|
||||
if (hdmi->plat_data->set_hdcp14_mem)
|
||||
hdmi->plat_data->set_hdcp14_mem(hdmi_data, false);
|
||||
}
|
||||
|
||||
static int dw_hdmi_qp_register_hdcp(struct device *dev,
|
||||
struct dw_hdmi_qp *hdmi)
|
||||
{
|
||||
struct dw_qp_hdcp hdmi_hdcp = {
|
||||
.hdmi = hdmi,
|
||||
.write = hdmi_writel,
|
||||
.read = hdmi_readl,
|
||||
.regs = hdmi->regs,
|
||||
.get_mem = dw_hdmi_qp_hdcp14_get_mem,
|
||||
};
|
||||
struct platform_device_info hdcp_device_info = {
|
||||
.parent = dev,
|
||||
.id = PLATFORM_DEVID_AUTO,
|
||||
.res = NULL,
|
||||
.num_res = 0,
|
||||
.name = DW_HDCP_QP_DRIVER_NAME,
|
||||
.data = &hdmi_hdcp,
|
||||
.size_data = sizeof(hdmi_hdcp),
|
||||
.dma_mask = DMA_BIT_MASK(32),
|
||||
};
|
||||
hdmi->hdcp_dev = platform_device_register_full(&hdcp_device_info);
|
||||
if (IS_ERR(hdmi->hdcp_dev)) {
|
||||
dev_err(dev, "failed to register hdcp!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdmi->hdcp = hdmi->hdcp_dev->dev.platform_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dw_hdmi_qp *
|
||||
__dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
@@ -3558,7 +3851,7 @@ __dw_hdmi_probe(struct platform_device *pdev,
|
||||
hdmi->avp_irq = irq;
|
||||
ret = devm_request_threaded_irq(dev, hdmi->avp_irq,
|
||||
dw_hdmi_qp_avp_hardirq,
|
||||
dw_hdmi_qp_avp_irq, IRQF_SHARED,
|
||||
dw_hdmi_qp_avp_irq, IRQF_ONESHOT,
|
||||
dev_name(dev), hdmi);
|
||||
if (ret)
|
||||
goto err_aud;
|
||||
@@ -3611,6 +3904,20 @@ __dw_hdmi_probe(struct platform_device *pdev,
|
||||
|
||||
dw_hdmi_register_debugfs(dev, hdmi);
|
||||
|
||||
if (hdmi_readl(hdmi, CONFIG_REG) & CONFIG_HDCP14) {
|
||||
iores = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
hdmi->hdcp14_mem = devm_ioremap_resource(dev, iores);
|
||||
|
||||
if (IS_ERR(hdmi->hdcp14_mem)) {
|
||||
ret = PTR_ERR(hdmi->hdcp14_mem);
|
||||
goto err_cec;
|
||||
}
|
||||
|
||||
ret = dw_hdmi_qp_register_hdcp(dev, hdmi);
|
||||
if (ret)
|
||||
goto err_cec;
|
||||
}
|
||||
|
||||
return hdmi;
|
||||
|
||||
err_cec:
|
||||
@@ -3663,6 +3970,8 @@ static void __dw_hdmi_remove(struct dw_hdmi_qp *hdmi)
|
||||
hdmi->bridge.encoder->funcs->destroy(hdmi->bridge.encoder);
|
||||
if (!IS_ERR(hdmi->cec))
|
||||
platform_device_unregister(hdmi->cec);
|
||||
if (!IS_ERR(hdmi->hdcp_dev))
|
||||
platform_device_unregister(hdmi->hdcp_dev);
|
||||
if (hdmi->i2c)
|
||||
i2c_del_adapter(&hdmi->i2c->adap);
|
||||
else
|
||||
@@ -3753,6 +4062,7 @@ void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi)
|
||||
disable_irq(hdmi->earc_irq);
|
||||
|
||||
pinctrl_pm_select_sleep_state(dev);
|
||||
drm_connector_update_edid_property(&hdmi->connector, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define CONFIG_REG 0xc
|
||||
#define CONFIG_CEC BIT(28)
|
||||
#define CONFIG_AUD_UD BIT(23)
|
||||
#define CONFIG_HDCP14 BIT(8)
|
||||
#define CORE_TIMESTAMP_HHMM 0x14
|
||||
#define CORE_TIMESTAMP_MMDD 0x18
|
||||
#define CORE_TIMESTAMP_YYYY 0x1c
|
||||
@@ -139,7 +140,7 @@
|
||||
#define FRAME_COMPOSER_CONFIG8 0x860
|
||||
#define FRAME_COMPOSER_CONFIG9 0x864
|
||||
#define KEEPOUT_REKEY_CFG GENMASK(9, 8)
|
||||
#define KEEPOUT_REKEY_ALWAYS 0x2
|
||||
#define KEEPOUT_REKEY_ALWAYS (0x2 << 8)
|
||||
#define FRAME_COMPOSER_CONTROL0 0x86c
|
||||
/* Video Monitor Registers */
|
||||
#define VIDEO_MONITOR_CONFIG0 0x880
|
||||
@@ -155,9 +156,13 @@
|
||||
#define HDCP2_BYPASS BIT(0)
|
||||
#define HDCP2LOGIC_ESM_GPIO_IN 0x8e4
|
||||
#define HDCP2LOGIC_ESM_GPIO_OUT 0x8e8
|
||||
#define HDCP2_AUTHENTICATION_SUCCESS BIT(6)
|
||||
/* HDCP14 Registers */
|
||||
#define HDCP14_CONFIG0 0x900
|
||||
#define HDCP14_OESS_ESSS_OVR_VALUE BIT(14)
|
||||
#define HDCP14_OESS_ESSS_OVR_EN BIT(13)
|
||||
#define HDCP14_CONFIG1 0x904
|
||||
#define HDCP14_SHA1_MSG_CORRECT_P BIT(3)
|
||||
#define HDCP14_CONFIG2 0x908
|
||||
#define HDCP14_CONFIG3 0x90c
|
||||
#define HDCP14_KEY_SEED 0x914
|
||||
@@ -169,7 +174,10 @@
|
||||
#define HDCP14_AN_H 0x92c
|
||||
#define HDCP14_AN_L 0x930
|
||||
#define HDCP14_STATUS0 0x934
|
||||
#define HDCP14_RPT_DEVICE_COUNT 0xFE00
|
||||
#define HDCP14_STATUS1 0x938
|
||||
#define HDCP14_RCV_REPEATER BIT(6)
|
||||
#define HDCP14_RCV_KSV_FIFO_READY BIT(5)
|
||||
/* Scrambler Registers */
|
||||
#define SCRAMB_CONFIG0 0x960
|
||||
/* Video Configuration Registers */
|
||||
@@ -792,6 +800,7 @@
|
||||
#define AVP_1_INT_STATUS 0x3820
|
||||
#define AVP_1_INT_MASK_N 0x3824
|
||||
#define HDCP14_AUTH_CHG_MASK_N BIT(6)
|
||||
#define HDCP14_KSV_LIST_DONE_MASK_N BIT(1)
|
||||
#define AVP_1_INT_CLEAR 0x3828
|
||||
#define AVP_1_INT_FORCE 0x382c
|
||||
#define AVP_2_INT_STATUS 0x3830
|
||||
@@ -802,6 +811,7 @@
|
||||
#define AVP_3_INT_MASK_N 0x3844
|
||||
#define AVP_3_INT_CLEAR 0x3848
|
||||
#define AVP_3_INT_FORCE 0x384c
|
||||
#define HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ BIT(17)
|
||||
#define AVP_4_INT_STATUS 0x3850
|
||||
#define AVP_4_INT_MASK_N 0x3854
|
||||
#define AVP_4_INT_CLEAR 0x3858
|
||||
@@ -832,4 +842,9 @@
|
||||
#define EARCRX_1_INT_CLEAR 0x4828
|
||||
#define EARCRX_1_INT_FORCE 0x482c
|
||||
|
||||
#define HDMI_HDCP14_MEM_KSV0 0x4f08
|
||||
#define HDMI_HDCP14_MEM_BSTATUS0 0x5958
|
||||
#define HDMI_HDCP14_MEM_M0_1 0x5960
|
||||
#define HDMI_HDCP14_MEM_M0_7 0x597c
|
||||
|
||||
#endif /* __DW_HDMI_QP_H__ */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_dsc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
@@ -105,6 +106,8 @@
|
||||
#define RK3588_HDMI1_LEVEL_INT BIT(24)
|
||||
#define RK3588_HDMI1_INTR_CHANGE_CNT (0x7 << 21)
|
||||
|
||||
#define RK3588_GRF_VO1_CON1 0x0004
|
||||
#define HDCP1_P1_GPIO_IN BIT(9)
|
||||
#define RK3588_GRF_VO1_CON3 0x000c
|
||||
#define RK3588_COLOR_FORMAT_MASK 0xf
|
||||
#define RK3588_RGB 0
|
||||
@@ -129,6 +132,8 @@
|
||||
#define RK3588_HDMI0_GRANT_SW BIT(11)
|
||||
#define RK3588_HDMI1_GRANT_SEL BIT(12)
|
||||
#define RK3588_HDMI1_GRANT_SW BIT(13)
|
||||
#define RK3588_GRF_VO1_CON4 0x0010
|
||||
#define RK3588_HDMI_HDCP14_MEM_EN BIT(15)
|
||||
#define RK3588_GRF_VO1_CON6 0x0018
|
||||
#define RK3588_GRF_VO1_CON7 0x001c
|
||||
|
||||
@@ -216,6 +221,7 @@ struct rockchip_hdmi {
|
||||
struct drm_property *output_type_capacity;
|
||||
struct drm_property *allm_capacity;
|
||||
struct drm_property *allm_enable;
|
||||
struct drm_property *hdcp_state_property;
|
||||
|
||||
struct drm_property_blob *hdr_panel_blob_ptr;
|
||||
struct drm_property_blob *next_hdr_data_ptr;
|
||||
@@ -232,6 +238,7 @@ struct rockchip_hdmi {
|
||||
u8 max_lanes;
|
||||
u8 add_func;
|
||||
u8 edid_colorimetry;
|
||||
u8 hdcp_status;
|
||||
struct rockchip_drm_dsc_cap dsc_cap;
|
||||
struct next_hdr_sink_data next_hdr_data;
|
||||
struct dw_hdmi_link_config link_cfg;
|
||||
@@ -1889,6 +1896,26 @@ static void rk3588_set_color_format(struct rockchip_hdmi *hdmi, u64 bus_format,
|
||||
regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON6, val);
|
||||
}
|
||||
|
||||
static void rk3588_set_hdcp_status(void *data, u8 status)
|
||||
{
|
||||
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
|
||||
|
||||
hdmi->hdcp_status = status;
|
||||
}
|
||||
|
||||
static void rk3588_set_hdcp2_enable(void *data, bool enable)
|
||||
{
|
||||
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
|
||||
u32 val;
|
||||
|
||||
if (enable)
|
||||
val = HIWORD_UPDATE(HDCP1_P1_GPIO_IN, HDCP1_P1_GPIO_IN);
|
||||
else
|
||||
val = HIWORD_UPDATE(0, HDCP1_P1_GPIO_IN);
|
||||
|
||||
regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON1, val);
|
||||
}
|
||||
|
||||
static void rk3588_set_grf_cfg(void *data)
|
||||
{
|
||||
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
|
||||
@@ -2562,6 +2589,18 @@ static void dw_hdmi_rockchip_set_ddc_io(void *data, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
static void dw_hdmi_rockchip_set_hdcp14_mem(void *data, bool enable)
|
||||
{
|
||||
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
|
||||
u32 val;
|
||||
|
||||
val = HIWORD_UPDATE(enable << 15, RK3588_HDMI_HDCP14_MEM_EN);
|
||||
if (!hdmi->id)
|
||||
regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON4, val);
|
||||
else
|
||||
regmap_write(hdmi->vo1_regmap, RK3588_GRF_VO1_CON7, val);
|
||||
}
|
||||
|
||||
static const struct drm_prop_enum_list color_depth_enum_list[] = {
|
||||
{ 0, "Automatic" }, /* Prefer highest color depth */
|
||||
{ 8, "24bit" },
|
||||
@@ -2608,6 +2647,7 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
|
||||
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
|
||||
struct drm_property *prop;
|
||||
struct rockchip_drm_private *private = connector->dev->dev_private;
|
||||
int ret;
|
||||
|
||||
switch (color) {
|
||||
case MEDIA_BUS_FMT_RGB101010_1X30:
|
||||
@@ -2776,6 +2816,21 @@ dw_hdmi_rockchip_attach_properties(struct drm_connector *connector,
|
||||
drm_object_attach_property(&connector->base,
|
||||
connector->colorspace_property, 0);
|
||||
drm_object_attach_property(&connector->base, private->connector_id_prop, hdmi->id);
|
||||
|
||||
ret = drm_connector_attach_content_protection_property(connector, true);
|
||||
if (ret) {
|
||||
dev_err(hdmi->dev, "failed to attach content protection: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
prop = drm_property_create_range(connector->dev, 0, RK_IF_PROP_ENCRYPTED,
|
||||
RK_IF_HDCP_ENCRYPTED_NONE, RK_IF_HDCP_ENCRYPTED_LEVEL2);
|
||||
if (!prop) {
|
||||
dev_err(hdmi->dev, "create hdcp encrypted prop for hdmi%d failed\n", hdmi->id);
|
||||
return;
|
||||
}
|
||||
hdmi->hdcp_state_property = prop;
|
||||
drm_object_attach_property(&connector->base, prop, RK_IF_HDCP_ENCRYPTED_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2909,6 +2964,7 @@ dw_hdmi_rockchip_set_property(struct drm_connector *connector,
|
||||
hdmi->enable_allm = val;
|
||||
if (allm_enable != hdmi->enable_allm)
|
||||
dw_hdmi_qp_set_allm_enable(hdmi->hdmi_qp, hdmi->enable_allm);
|
||||
} else if (property == hdmi->hdcp_state_property) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2985,6 +3041,14 @@ dw_hdmi_rockchip_get_property(struct drm_connector *connector,
|
||||
} else if (property == hdmi->allm_enable) {
|
||||
*val = hdmi->enable_allm;
|
||||
return 0;
|
||||
} else if (property == hdmi->hdcp_state_property) {
|
||||
if (hdmi->hdcp_status & BIT(1))
|
||||
*val = RK_IF_HDCP_ENCRYPTED_LEVEL2;
|
||||
else if (hdmi->hdcp_status & BIT(0))
|
||||
*val = RK_IF_HDCP_ENCRYPTED_LEVEL1;
|
||||
else
|
||||
*val = RK_IF_HDCP_ENCRYPTED_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DRM_ERROR("Unknown property [PROP:%d:%s]\n",
|
||||
@@ -3458,6 +3522,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
plat_data->get_colorimetry =
|
||||
dw_hdmi_rockchip_get_colorimetry;
|
||||
plat_data->get_link_cfg = dw_hdmi_rockchip_get_link_cfg;
|
||||
plat_data->set_hdcp2_enable = rk3588_set_hdcp2_enable;
|
||||
plat_data->set_hdcp_status = rk3588_set_hdcp_status;
|
||||
plat_data->set_grf_cfg = rk3588_set_grf_cfg;
|
||||
plat_data->get_grf_color_fmt = rk3588_get_grf_color_fmt;
|
||||
plat_data->convert_to_split_mode = drm_mode_convert_to_split_mode;
|
||||
@@ -3473,6 +3539,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
dw_hdmi_rockchip_set_prev_bus_format;
|
||||
plat_data->set_ddc_io =
|
||||
dw_hdmi_rockchip_set_ddc_io;
|
||||
plat_data->set_hdcp14_mem =
|
||||
dw_hdmi_rockchip_set_hdcp14_mem;
|
||||
plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
|
||||
|
||||
secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id);
|
||||
|
||||
@@ -2327,7 +2327,7 @@ static void vop_atomic_plane_reset(struct drm_plane *plane)
|
||||
return;
|
||||
|
||||
__drm_atomic_helper_plane_reset(plane, &vop_plane_state->base);
|
||||
win->state.zpos = win->zpos;
|
||||
vop_plane_state->base.zpos = win->zpos;
|
||||
vop_plane_state->global_alpha = 0xff;
|
||||
}
|
||||
|
||||
|
||||
@@ -1883,6 +1883,7 @@ static const struct vop2_cluster_regs rk3568_vop_cluster0 = {
|
||||
.afbc_enable = VOP_REG(RK3568_CLUSTER0_CTRL, 0x1, 1),
|
||||
.enable = VOP_REG(RK3568_CLUSTER0_CTRL, 1, 0),
|
||||
.lb_mode = VOP_REG(RK3568_CLUSTER0_CTRL, 0xf, 4),
|
||||
.frm_reset_en = VOP_REG(RK3568_CLUSTER0_CTRL, 1, 31),
|
||||
.src_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
|
||||
.dst_color_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
|
||||
.src_alpha_ctrl = VOP_REG(RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
|
||||
@@ -1893,6 +1894,7 @@ static const struct vop2_cluster_regs rk3568_vop_cluster1 = {
|
||||
.afbc_enable = VOP_REG(RK3568_CLUSTER1_CTRL, 0x1, 1),
|
||||
.enable = VOP_REG(RK3568_CLUSTER1_CTRL, 1, 0),
|
||||
.lb_mode = VOP_REG(RK3568_CLUSTER1_CTRL, 0xf, 4),
|
||||
.frm_reset_en = VOP_REG(RK3568_CLUSTER1_CTRL, 1, 31),
|
||||
.src_color_ctrl = VOP_REG(RK3568_CLUSTER1_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
|
||||
.dst_color_ctrl = VOP_REG(RK3568_CLUSTER1_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
|
||||
.src_alpha_ctrl = VOP_REG(RK3568_CLUSTER1_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
|
||||
@@ -1903,6 +1905,7 @@ static const struct vop2_cluster_regs rk3588_vop_cluster2 = {
|
||||
.afbc_enable = VOP_REG(RK3588_CLUSTER2_CTRL, 0x1, 1),
|
||||
.enable = VOP_REG(RK3588_CLUSTER2_CTRL, 1, 0),
|
||||
.lb_mode = VOP_REG(RK3588_CLUSTER2_CTRL, 0xf, 4),
|
||||
.frm_reset_en = VOP_REG(RK3588_CLUSTER2_CTRL, 1, 31),
|
||||
.src_color_ctrl = VOP_REG(RK3588_CLUSTER2_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
|
||||
.dst_color_ctrl = VOP_REG(RK3588_CLUSTER2_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
|
||||
.src_alpha_ctrl = VOP_REG(RK3588_CLUSTER2_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
|
||||
@@ -1913,6 +1916,7 @@ static const struct vop2_cluster_regs rk3588_vop_cluster3 = {
|
||||
.afbc_enable = VOP_REG(RK3588_CLUSTER3_CTRL, 0x1, 1),
|
||||
.enable = VOP_REG(RK3588_CLUSTER3_CTRL, 1, 0),
|
||||
.lb_mode = VOP_REG(RK3588_CLUSTER3_CTRL, 0xf, 4),
|
||||
.frm_reset_en = VOP_REG(RK3588_CLUSTER3_CTRL, 1, 31),
|
||||
.src_color_ctrl = VOP_REG(RK3588_CLUSTER3_MIX_SRC_COLOR_CTRL, 0xffffffff, 0),
|
||||
.dst_color_ctrl = VOP_REG(RK3588_CLUSTER3_MIX_DST_COLOR_CTRL, 0xffffffff, 0),
|
||||
.src_alpha_ctrl = VOP_REG(RK3588_CLUSTER3_MIX_SRC_ALPHA_CTRL, 0xffffffff, 0),
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
|
||||
#define GC2093_LANES 2
|
||||
|
||||
#define OF_CAMERA_HDR_MODE "rockchip,camera-hdr-mode"
|
||||
|
||||
static const char * const gc2093_supply_names[] = {
|
||||
"dovdd", /* Digital I/O power */
|
||||
"avdd", /* Analog power */
|
||||
@@ -142,7 +144,6 @@ struct gc2093 {
|
||||
struct mutex lock;
|
||||
bool streaming;
|
||||
bool power_on;
|
||||
unsigned int cfg_num;
|
||||
const struct gc2093_mode *cur_mode;
|
||||
|
||||
u32 module_index;
|
||||
@@ -421,6 +422,138 @@ static const struct reg_sequence gc2093_1080p_hdr_settings[] = {
|
||||
{0x024d, 0x01},
|
||||
};
|
||||
|
||||
/*
|
||||
* window size=1920*1080 mipi@2lane
|
||||
* mclk=27M mipi_clk=792Mbps
|
||||
* pixel_line_total=2640 line_frame_total=1500
|
||||
* row_time=20us frame_rate=50fps
|
||||
*/
|
||||
static const struct reg_sequence gc2093_1080p_25fps_hdr_settings[] = {
|
||||
/* System */
|
||||
{0x03fe, 0x80},
|
||||
{0x03fe, 0x80},
|
||||
{0x03fe, 0x80},
|
||||
{0x03fe, 0x00},
|
||||
{0x03f2, 0x00},
|
||||
{0x03f3, 0x00},
|
||||
{0x03f4, 0x36},
|
||||
{0x03f5, 0xc0},
|
||||
{0x03f6, 0x0B},
|
||||
{0x03f7, 0x01},
|
||||
{0x03f8, 0x58},
|
||||
{0x03f9, 0x40},
|
||||
{0x03fc, 0x8e},
|
||||
/* Cisctl & Analog */
|
||||
{0x0087, 0x18},
|
||||
{0x00ee, 0x30},
|
||||
{0x00d0, 0xbf},
|
||||
{0x01a0, 0x00},
|
||||
{0x01a4, 0x40},
|
||||
{0x01a5, 0x40},
|
||||
{0x01a6, 0x40},
|
||||
{0x01af, 0x09},
|
||||
{0x0001, 0x00},
|
||||
{0x0002, 0x02},
|
||||
{0x0003, 0x04},
|
||||
{0x0004, 0x02},
|
||||
{0x0005, 0x02},
|
||||
{0x0006, 0x94},
|
||||
{0x0007, 0x00},
|
||||
{0x0008, 0x11},
|
||||
{0x0009, 0x00},
|
||||
{0x000a, 0x02},
|
||||
{0x000b, 0x00},
|
||||
{0x000c, 0x04},
|
||||
{0x000d, 0x04},
|
||||
{0x000e, 0x40},
|
||||
{0x000f, 0x07},
|
||||
{0x0010, 0x8c},
|
||||
{0x0013, 0x15},
|
||||
{0x0019, 0x0c},
|
||||
{0x0041, 0x05},
|
||||
{0x0042, 0xdc},
|
||||
{0x0053, 0x60},
|
||||
{0x008d, 0x92},
|
||||
{0x0090, 0x00},
|
||||
{0x00c7, 0xe1},
|
||||
{0x001b, 0x73},
|
||||
{0x0028, 0x0d},
|
||||
{0x0029, 0x24},
|
||||
{0x002b, 0x04},
|
||||
{0x002e, 0x23},
|
||||
{0x0037, 0x03},
|
||||
{0x0043, 0x04},
|
||||
{0x0044, 0x20},
|
||||
{0x004a, 0x01},
|
||||
{0x004b, 0x20},
|
||||
{0x0055, 0x30},
|
||||
{0x006b, 0x44},
|
||||
{0x0077, 0x00},
|
||||
{0x0078, 0x20},
|
||||
{0x007c, 0xa1},
|
||||
{0x00d3, 0xd4},
|
||||
{0x00e6, 0x50},
|
||||
/* Gain */
|
||||
{0x00b6, 0xc0},
|
||||
{0x00b0, 0x60},
|
||||
/* Isp */
|
||||
{0x0102, 0x89},
|
||||
{0x0104, 0x01},
|
||||
{0x010e, 0x01},
|
||||
{0x0158, 0x00},
|
||||
{0x0183, 0x01},
|
||||
{0x0187, 0x50},
|
||||
/* Dark sun*/
|
||||
{0x0123, 0x08},
|
||||
{0x0123, 0x00},
|
||||
{0x0120, 0x01},
|
||||
{0x0121, 0x00},
|
||||
{0x0122, 0x10},
|
||||
{0x0124, 0x03},
|
||||
{0x0125, 0xff},
|
||||
{0x0126, 0x3c},
|
||||
{0x001a, 0x8c},
|
||||
{0x00c6, 0xe0},
|
||||
/* Blk */
|
||||
{0x0026, 0x30},
|
||||
{0x0142, 0x00},
|
||||
{0x0149, 0x1e},
|
||||
{0x014a, 0x0f},
|
||||
{0x014b, 0x00},
|
||||
{0x0155, 0x00},
|
||||
{0x0414, 0x78},
|
||||
{0x0415, 0x78},
|
||||
{0x0416, 0x78},
|
||||
{0x0417, 0x78},
|
||||
{0x0454, 0x78},
|
||||
{0x0455, 0x78},
|
||||
{0x0456, 0x78},
|
||||
{0x0457, 0x78},
|
||||
{0x04e0, 0x18},
|
||||
/* Window */
|
||||
{0x0192, 0x02},
|
||||
{0x0194, 0x03},
|
||||
{0x0195, 0x04},
|
||||
{0x0196, 0x38},
|
||||
{0x0197, 0x07},
|
||||
{0x0198, 0x80},
|
||||
/* MIPI */
|
||||
{0x019a, 0x06},
|
||||
{0x007b, 0x2a},
|
||||
{0x0023, 0x2d},
|
||||
{0x0201, 0x27},
|
||||
{0x0202, 0x56},
|
||||
{0x0203, 0xb6},
|
||||
{0x0212, 0x80},
|
||||
{0x0213, 0x07},
|
||||
{0x0215, 0x12},
|
||||
{0x003e, 0x91},
|
||||
/* HDR En */
|
||||
{0x0027, 0x71},
|
||||
{0x0215, 0x92},
|
||||
{0x024d, 0x01},
|
||||
};
|
||||
|
||||
static const struct gc2093_mode supported_modes[] = {
|
||||
{
|
||||
.width = 1920,
|
||||
@@ -457,6 +590,25 @@ static const struct gc2093_mode supported_modes[] = {
|
||||
.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
|
||||
.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
|
||||
},
|
||||
{
|
||||
.width = 1920,
|
||||
.height = 1080,
|
||||
.max_fps = {
|
||||
.numerator = 10000,
|
||||
.denominator = 250000,
|
||||
},
|
||||
.exp_def = 0x460,
|
||||
.hts_def = 0xa50,
|
||||
.vts_def = 0x5dc,
|
||||
.link_freq_index = LINK_FREQ_396M_INDEX,
|
||||
.reg_list = gc2093_1080p_25fps_hdr_settings,
|
||||
.reg_num = ARRAY_SIZE(gc2093_1080p_25fps_hdr_settings),
|
||||
.hdr_mode = HDR_X2,
|
||||
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
|
||||
.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
|
||||
.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
|
||||
.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
|
||||
},
|
||||
};
|
||||
|
||||
/* pixel rate = link frequency * 2 * lanes / BITS_PER_SAMPLE */
|
||||
@@ -585,6 +737,7 @@ static int gc2093_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_EXPOSURE:
|
||||
dev_dbg(gc2093->dev, "set exposure value 0x%x\n", ctrl->val);
|
||||
if (gc2093->cur_mode->hdr_mode != NO_HDR)
|
||||
goto ctrl_end;
|
||||
dev_dbg(gc2093->dev, "set exposure value 0x%x\n", ctrl->val);
|
||||
@@ -594,28 +747,36 @@ static int gc2093_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ctrl->val & 0xff);
|
||||
break;
|
||||
case V4L2_CID_ANALOGUE_GAIN:
|
||||
dev_dbg(gc2093->dev, "set gain value 0x%x, mode: %d\n",
|
||||
ctrl->val, gc2093->cur_mode->hdr_mode);
|
||||
if (gc2093->cur_mode->hdr_mode != NO_HDR)
|
||||
goto ctrl_end;
|
||||
dev_dbg(gc2093->dev, "set gain value 0x%x\n", ctrl->val);
|
||||
gc2093_set_gain(gc2093, ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_VBLANK:
|
||||
dev_dbg(gc2093->dev, "set blank value 0x%x\n", ctrl->val);
|
||||
vts = gc2093->cur_mode->height + ctrl->val;
|
||||
gc2093->cur_vts = vts;
|
||||
ret = gc2093_write_reg(gc2093, GC2093_REG_VTS_H,
|
||||
(vts >> 8) & 0x3f);
|
||||
ret |= gc2093_write_reg(gc2093, GC2093_REG_VTS_L,
|
||||
vts & 0xff);
|
||||
gc2093_modify_fps_info(gc2093);
|
||||
if (!ret)
|
||||
gc2093->cur_vts = ctrl->val + gc2093->cur_mode->height;
|
||||
if (gc2093->cur_vts != gc2093->cur_mode->vts_def)
|
||||
gc2093_modify_fps_info(gc2093);
|
||||
dev_dbg(gc2093->dev, " set blank value 0x%x\n", ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_HFLIP:
|
||||
regmap_update_bits(gc2093->regmap, GC2093_MIRROR_FLIP_REG,
|
||||
MIRROR_MASK, ctrl->val ? MIRROR_MASK : 0);
|
||||
dev_dbg(gc2093->dev, "set hflip 0x%x\n", ctrl->val);
|
||||
regmap_update_bits(gc2093->regmap, GC2093_MIRROR_FLIP_REG,
|
||||
MIRROR_MASK, ctrl->val ? MIRROR_MASK : 0);
|
||||
break;
|
||||
case V4L2_CID_VFLIP:
|
||||
regmap_update_bits(gc2093->regmap, GC2093_MIRROR_FLIP_REG,
|
||||
FLIP_MASK, ctrl->val ? FLIP_MASK : 0);
|
||||
dev_dbg(gc2093->dev, "set vflip 0x%x\n", ctrl->val);
|
||||
regmap_update_bits(gc2093->regmap, GC2093_MIRROR_FLIP_REG,
|
||||
FLIP_MASK, ctrl->val ? FLIP_MASK : 0);
|
||||
break;
|
||||
default:
|
||||
dev_warn(gc2093->dev, "%s Unhandled id:0x%x, val:0x%x\n",
|
||||
@@ -672,7 +833,7 @@ static int gc2093_initialize_controls(struct gc2093 *gc2093)
|
||||
h_blank, h_blank, 1, h_blank);
|
||||
if (gc2093->hblank)
|
||||
gc2093->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
||||
|
||||
gc2093->cur_fps = mode->max_fps;
|
||||
vblank_def = mode->vts_def - mode->height;
|
||||
gc2093->cur_vts = mode->vts_def;
|
||||
gc2093->vblank = v4l2_ctrl_new_std(handler, &gc2093_ctrl_ops,
|
||||
@@ -819,11 +980,24 @@ static void gc2093_get_module_inf(struct gc2093 *gc2093,
|
||||
strlcpy(inf->base.module, gc2093->module_name, sizeof(inf->base.module));
|
||||
}
|
||||
|
||||
static int gc2093_get_channel_info(struct gc2093 *gc2093,
|
||||
struct rkmodule_channel_info *ch_info)
|
||||
{
|
||||
if (ch_info->index < PAD0 || ch_info->index >= PAD_MAX)
|
||||
return -EINVAL;
|
||||
ch_info->vc = gc2093->cur_mode->vc[ch_info->index];
|
||||
ch_info->width = gc2093->cur_mode->width;
|
||||
ch_info->height = gc2093->cur_mode->height;
|
||||
ch_info->bus_fmt = GC2093_MEDIA_BUS_FMT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long gc2093_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct gc2093 *gc2093 = to_gc2093(sd);
|
||||
struct preisp_hdrae_exp_s *hdrae_exp = arg;
|
||||
struct rkmodule_hdr_cfg *hdr_cfg;
|
||||
struct rkmodule_channel_info *ch_info;
|
||||
long ret = 0;
|
||||
u32 i, h, w;
|
||||
u32 stream = 0;
|
||||
@@ -913,15 +1087,18 @@ static long gc2093_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
hdr_cfg = (struct rkmodule_hdr_cfg *)arg;
|
||||
w = gc2093->cur_mode->width;
|
||||
h = gc2093->cur_mode->height;
|
||||
for (i = 0; i < gc2093->cfg_num; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
if (w == supported_modes[i].width &&
|
||||
h == supported_modes[i].height &&
|
||||
supported_modes[i].hdr_mode == hdr_cfg->hdr_mode) {
|
||||
gc2093->cur_mode = &supported_modes[i];
|
||||
break;
|
||||
}
|
||||
dev_err(gc2093->dev, "i:%d,w:%d, h:%d, hdr:%d\n",
|
||||
i, supported_modes[i].width, supported_modes[i].height,
|
||||
supported_modes[i].hdr_mode);
|
||||
}
|
||||
if (i == gc2093->cfg_num) {
|
||||
if (i == ARRAY_SIZE(supported_modes)) {
|
||||
dev_err(gc2093->dev, "not find hdr mode:%d %dx%d config\n",
|
||||
hdr_cfg->hdr_mode, w, h);
|
||||
ret = -EINVAL;
|
||||
@@ -957,6 +1134,10 @@ static long gc2093_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
usleep_range(delay_us, delay_us + 2000);
|
||||
}
|
||||
break;
|
||||
case RKMODULE_GET_CHANNEL_INFO:
|
||||
ch_info = (struct rkmodule_channel_info *)arg;
|
||||
ret = gc2093_get_channel_info(gc2093, ch_info);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -989,8 +1170,16 @@ static int __gc2093_start_stream(struct gc2093 *gc2093)
|
||||
}
|
||||
}
|
||||
}
|
||||
dev_info(gc2093->dev,
|
||||
"%dx%d@%d, mode %d, vts 0x%x\n",
|
||||
gc2093->cur_mode->width,
|
||||
gc2093->cur_mode->height,
|
||||
gc2093->cur_fps.denominator / gc2093->cur_fps.numerator,
|
||||
gc2093->cur_mode->hdr_mode,
|
||||
gc2093->cur_vts);
|
||||
dev_info(gc2093->dev, "is_tb:%d\n", gc2093->is_thunderboot);
|
||||
return gc2093_write_reg(gc2093, GC2093_REG_CTRL_MODE,
|
||||
GC2093_MODE_STREAMING);
|
||||
GC2093_MODE_STREAMING);
|
||||
}
|
||||
|
||||
static int __gc2093_stop_stream(struct gc2093 *gc2093)
|
||||
@@ -1012,6 +1201,7 @@ static long gc2093_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
struct rkmodule_inf *inf;
|
||||
struct rkmodule_hdr_cfg *hdr;
|
||||
struct preisp_hdrae_exp_s *hdrae;
|
||||
struct rkmodule_channel_info *ch_info;
|
||||
long ret = 0;
|
||||
u32 stream = 0;
|
||||
|
||||
@@ -1081,6 +1271,21 @@ static long gc2093_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
else
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
case RKMODULE_GET_CHANNEL_INFO:
|
||||
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
|
||||
if (!ch_info) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gc2093_ioctl(sd, cmd, ch_info);
|
||||
if (!ret) {
|
||||
ret = copy_to_user(up, ch_info, sizeof(*ch_info));
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
}
|
||||
kfree(ch_info);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOIOCTLCMD;
|
||||
break;
|
||||
@@ -1099,11 +1304,17 @@ static int gc2093_s_stream(struct v4l2_subdev *sd, int on)
|
||||
fps = DIV_ROUND_CLOSEST(gc2093->cur_mode->max_fps.denominator,
|
||||
gc2093->cur_mode->max_fps.numerator);
|
||||
|
||||
dev_info(gc2093->dev, "%s: on: %d, %dx%d@%d\n", __func__, on,
|
||||
gc2093->cur_mode->width,
|
||||
gc2093->cur_mode->height,
|
||||
fps);
|
||||
dev_info(gc2093->dev,
|
||||
"%dx%d@%d, mode %d, vts 0x%x\n",
|
||||
gc2093->cur_mode->width,
|
||||
gc2093->cur_mode->height,
|
||||
gc2093->cur_fps.denominator / gc2093->cur_fps.numerator,
|
||||
gc2093->cur_mode->hdr_mode,
|
||||
gc2093->cur_vts);
|
||||
|
||||
dev_info(gc2093->dev,
|
||||
"stream:%d\n, on:%d",
|
||||
gc2093->streaming, on);
|
||||
mutex_lock(&gc2093->lock);
|
||||
on = !!on;
|
||||
if (on == gc2093->streaming)
|
||||
@@ -1150,7 +1361,10 @@ static int gc2093_g_frame_interval(struct v4l2_subdev *sd,
|
||||
struct gc2093 *gc2093 = to_gc2093(sd);
|
||||
const struct gc2093_mode *mode = gc2093->cur_mode;
|
||||
|
||||
fi->interval = mode->max_fps;
|
||||
if (gc2093->streaming)
|
||||
fi->interval = gc2093->cur_fps;
|
||||
else
|
||||
fi->interval = mode->max_fps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1183,9 +1397,7 @@ static int gc2093_enum_frame_sizes(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_frame_size_enum *fse)
|
||||
{
|
||||
struct gc2093 *gc2093 = to_gc2093(sd);
|
||||
|
||||
if (fse->index >= gc2093->cfg_num)
|
||||
if (fse->index >= ARRAY_SIZE(supported_modes))
|
||||
return -EINVAL;
|
||||
|
||||
if (fse->code != GC2093_MEDIA_BUS_FMT)
|
||||
@@ -1202,9 +1414,7 @@ static int gc2093_enum_frame_interval(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_frame_interval_enum *fie)
|
||||
{
|
||||
struct gc2093 *gc2093 = to_gc2093(sd);
|
||||
|
||||
if (fie->index >= gc2093->cfg_num)
|
||||
if (fie->index >= ARRAY_SIZE(supported_modes))
|
||||
return -EINVAL;
|
||||
|
||||
fie->code = GC2093_MEDIA_BUS_FMT;
|
||||
@@ -1400,6 +1610,136 @@ static const struct dev_pm_ops gc2093_pm_ops = {
|
||||
gc2093_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_VIDEO_ROCKCHIP_THUNDER_BOOT_ISP
|
||||
static u32 rk_cam_hdr;
|
||||
static u32 rk_cam_w;
|
||||
static u32 rk_cam_h;
|
||||
static u32 rk_cam_fps;
|
||||
|
||||
static int __init __maybe_unused rk_cam_hdr_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_hdr = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_hdr fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init __maybe_unused rk_cam_w_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_w = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_w fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init __maybe_unused rk_cam_h_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_h = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_h fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init __maybe_unused rk_cam_fps_setup(char *str)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val = 0;
|
||||
|
||||
ret = kstrtoul(str, 0, &val);
|
||||
if (!ret)
|
||||
rk_cam_fps = (u32)val;
|
||||
else
|
||||
pr_err("get rk_cam_fps fail\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("rk_cam_hdr=", rk_cam_hdr_setup);
|
||||
__setup("rk_cam_w=", rk_cam_w_setup);
|
||||
__setup("rk_cam_h=", rk_cam_h_setup);
|
||||
__setup("rk_cam_fps=", rk_cam_fps_setup);
|
||||
|
||||
static void find_terminal_resolution(struct gc2093 *gc2093)
|
||||
{
|
||||
int i = 0;
|
||||
const struct gc2093_mode *mode = NULL;
|
||||
const struct gc2093_mode *fit_mode = NULL;
|
||||
u32 cur_fps = 0;
|
||||
u32 dst_fps = 0;
|
||||
u32 tmp_fps = 0;
|
||||
|
||||
if (rk_cam_w == 0 || rk_cam_h == 0 ||
|
||||
rk_cam_fps == 0)
|
||||
goto err_find_res;
|
||||
|
||||
dev_info(gc2093->dev, "find resolution width: %d, height: %d, hdr: %d, fps: %d\n",
|
||||
rk_cam_w, rk_cam_h, rk_cam_hdr, rk_cam_fps);
|
||||
dst_fps = rk_cam_fps;
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
mode = &supported_modes[i];
|
||||
cur_fps = mode->max_fps.denominator / mode->max_fps.numerator;
|
||||
if (mode->width == rk_cam_w && mode->height == rk_cam_h &&
|
||||
mode->hdr_mode == rk_cam_hdr) {
|
||||
if (cur_fps == dst_fps) {
|
||||
gc2093->cur_mode = mode;
|
||||
return;
|
||||
}
|
||||
if (cur_fps >= dst_fps) {
|
||||
if (fit_mode) {
|
||||
tmp_fps = fit_mode->max_fps.denominator /
|
||||
fit_mode->max_fps.numerator;
|
||||
if (tmp_fps - dst_fps > cur_fps - dst_fps)
|
||||
fit_mode = mode;
|
||||
} else {
|
||||
fit_mode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fit_mode) {
|
||||
gc2093->cur_mode = fit_mode;
|
||||
return;
|
||||
}
|
||||
err_find_res:
|
||||
dev_err(gc2093->dev, "not match %dx%d@%dfps mode %d\n!",
|
||||
rk_cam_w, rk_cam_h, dst_fps, rk_cam_hdr);
|
||||
gc2093->cur_mode = &supported_modes[0];
|
||||
}
|
||||
#else
|
||||
static void find_terminal_resolution(struct gc2093 *gc2093)
|
||||
{
|
||||
u32 hdr_mode = 0;
|
||||
struct device_node *node = gc2093->dev->of_node;
|
||||
int i = 0;
|
||||
|
||||
of_property_read_u32(node, OF_CAMERA_HDR_MODE, &hdr_mode);
|
||||
for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
|
||||
if (hdr_mode == supported_modes[i].hdr_mode) {
|
||||
gc2093->cur_mode = &supported_modes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(supported_modes))
|
||||
gc2093->cur_mode = &supported_modes[0];
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static int gc2093_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@@ -1447,6 +1787,8 @@ static int gc2093_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
find_terminal_resolution(gc2093);
|
||||
|
||||
gc2093->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_ASIS);
|
||||
if (IS_ERR(gc2093->reset_gpio))
|
||||
dev_warn(dev, "Failed to get reset-gpios\n");
|
||||
@@ -1463,11 +1805,6 @@ static int gc2093_probe(struct i2c_client *client,
|
||||
|
||||
mutex_init(&gc2093->lock);
|
||||
|
||||
/* set default mode */
|
||||
gc2093->cur_mode = &supported_modes[0];
|
||||
gc2093->cfg_num = ARRAY_SIZE(supported_modes);
|
||||
gc2093->cur_vts = gc2093->cur_mode->vts_def;
|
||||
|
||||
sd = &gc2093->subdev;
|
||||
v4l2_i2c_subdev_init(sd, client, &gc2093_subdev_ops);
|
||||
ret = gc2093_initialize_controls(gc2093);
|
||||
|
||||
@@ -1468,6 +1468,7 @@ static void gc8034_get_otp(struct otp_info *otp,
|
||||
inf->pdaf.flag = 1;
|
||||
inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width;
|
||||
inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height;
|
||||
inf->pdaf.pd_offset = otp->pdaf_data.pd_offset;
|
||||
inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode;
|
||||
inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir;
|
||||
inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width;
|
||||
|
||||
@@ -1206,6 +1206,7 @@ static void imx586_get_otp(struct otp_info *otp,
|
||||
inf->pdaf.flag = 1;
|
||||
inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width;
|
||||
inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height;
|
||||
inf->pdaf.pd_offset = otp->pdaf_data.pd_offset;
|
||||
inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode;
|
||||
inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir;
|
||||
inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width;
|
||||
|
||||
@@ -1395,15 +1395,14 @@ static long lt6911uxe_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
break;
|
||||
case RKMODULE_SET_CSI_DPHY_PARAM:
|
||||
dphy_param = (struct rkmodule_csi_dphy_param *)arg;
|
||||
if (dphy_param->vendor == rk3588_dcphy_param.vendor)
|
||||
if (dphy_param->vendor == PHY_VENDOR_SAMSUNG)
|
||||
rk3588_dcphy_param = *dphy_param;
|
||||
dev_dbg(<6911uxe->i2c_client->dev,
|
||||
"sensor set dphy param\n");
|
||||
break;
|
||||
case RKMODULE_GET_CSI_DPHY_PARAM:
|
||||
dphy_param = (struct rkmodule_csi_dphy_param *)arg;
|
||||
if (dphy_param->vendor == rk3588_dcphy_param.vendor)
|
||||
*dphy_param = rk3588_dcphy_param;
|
||||
*dphy_param = rk3588_dcphy_param;
|
||||
dev_dbg(<6911uxe->i2c_client->dev,
|
||||
"sensor get dphy param\n");
|
||||
break;
|
||||
|
||||
@@ -1178,15 +1178,14 @@ static long lt7911uxc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
break;
|
||||
case RKMODULE_SET_CSI_DPHY_PARAM:
|
||||
dphy_param = (struct rkmodule_csi_dphy_param *)arg;
|
||||
if (dphy_param->vendor == rk3588_dcphy_param.vendor)
|
||||
if (dphy_param->vendor == PHY_VENDOR_SAMSUNG)
|
||||
rk3588_dcphy_param = *dphy_param;
|
||||
dev_dbg(<7911uxc->i2c_client->dev,
|
||||
"sensor set dphy param\n");
|
||||
break;
|
||||
case RKMODULE_GET_CSI_DPHY_PARAM:
|
||||
dphy_param = (struct rkmodule_csi_dphy_param *)arg;
|
||||
if (dphy_param->vendor == rk3588_dcphy_param.vendor)
|
||||
*dphy_param = rk3588_dcphy_param;
|
||||
*dphy_param = rk3588_dcphy_param;
|
||||
dev_dbg(<7911uxc->i2c_client->dev,
|
||||
"sensor get dphy param\n");
|
||||
break;
|
||||
|
||||
@@ -924,6 +924,17 @@ static int nvp6158_set_fmt(struct v4l2_subdev *sd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nvp6158_g_frame_interval(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_frame_interval *fi)
|
||||
{
|
||||
struct nvp6158 *nvp6158 = to_nvp6158(sd);
|
||||
const struct nvp6158_framesize *size = nvp6158->frame_size;
|
||||
|
||||
fi->interval = size->max_fps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvp6158_get_module_inf(struct nvp6158 *nvp6158,
|
||||
struct rkmodule_inf *inf)
|
||||
{
|
||||
@@ -1174,6 +1185,7 @@ static const struct dev_pm_ops nvp6158_pm_ops = {
|
||||
static const struct v4l2_subdev_video_ops nvp6158_video_ops = {
|
||||
.s_stream = nvp6158_stream,
|
||||
.querystd = nvp6158_querystd,
|
||||
.g_frame_interval = nvp6158_g_frame_interval,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_pad_ops nvp6158_subdev_pad_ops = {
|
||||
|
||||
@@ -649,6 +649,11 @@ static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev,
|
||||
checksum += otp_ptr->pdaf_data.dccmap_checksum;
|
||||
base_addr += 1;
|
||||
|
||||
ret |= read_reg_otp(client, base_addr,
|
||||
2, &otp_ptr->pdaf_data.pd_offset);
|
||||
checksum += otp_ptr->pdaf_data.pd_offset;
|
||||
base_addr += 2;
|
||||
|
||||
memset(pdaf_buf, 0, RK_PDAF_RESERVED_SIZE);
|
||||
ret |= read_reg_otp_buf(client, base_addr,
|
||||
RK_PDAF_RESERVED_SIZE, pdaf_buf);
|
||||
@@ -931,7 +936,7 @@ static int otp_eeprom_show(struct seq_file *p, void *v)
|
||||
seq_printf(p, "flag=%d;\n", dev->otp->pdaf_data.flag);
|
||||
seq_printf(p, "gainmap_width=%d;\n", gainmap_w);
|
||||
seq_printf(p, "gainmap_height=%d;\n", gainmap_h);
|
||||
|
||||
seq_printf(p, "pd_offset=%d\n", dev->otp->pdaf_data.pd_offset);
|
||||
seq_printf(p, "gainmap_table=\n");
|
||||
for (i = 0; i < gainmap_h; i++) {
|
||||
for (j = 0; j < gainmap_w; j++) {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#define RK_LSC_RESERVED_SIZE 0x0020
|
||||
#define RK_GAINMAP_SIZE 0x0800
|
||||
#define RK_DCCMAP_SIZE 0x0200
|
||||
#define RK_PDAF_RESERVED_SIZE 0x0020
|
||||
#define RK_PDAF_RESERVED_SIZE 0x001e
|
||||
#define RK_AF_RESERVED_SIZE 0x0014
|
||||
#define RKOTP_MAX_MODULE 0x0008
|
||||
|
||||
@@ -151,6 +151,7 @@ struct pdaf_otp_info {
|
||||
u32 dccmap_height;
|
||||
u32 dccmap[RK_DCCMAP_SIZE];
|
||||
u32 dccmap_checksum;
|
||||
u32 pd_offset;
|
||||
u32 checksum;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
@@ -6203,6 +6203,7 @@ static void ov50c40_get_otp(struct otp_info *otp,
|
||||
inf->pdaf.flag = 1;
|
||||
inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width;
|
||||
inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height;
|
||||
inf->pdaf.pd_offset = otp->pdaf_data.pd_offset;
|
||||
inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode;
|
||||
inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir;
|
||||
inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width;
|
||||
|
||||
@@ -1265,6 +1265,7 @@ static void s5kjn1_get_otp(struct otp_info *otp,
|
||||
inf->pdaf.flag = 1;
|
||||
inf->pdaf.gainmap_width = otp->pdaf_data.gainmap_width;
|
||||
inf->pdaf.gainmap_height = otp->pdaf_data.gainmap_height;
|
||||
inf->pdaf.pd_offset = otp->pdaf_data.pd_offset;
|
||||
inf->pdaf.dcc_mode = otp->pdaf_data.dcc_mode;
|
||||
inf->pdaf.dcc_dir = otp->pdaf_data.dcc_dir;
|
||||
inf->pdaf.dccmap_width = otp->pdaf_data.dccmap_width;
|
||||
|
||||
@@ -5079,10 +5079,12 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream,
|
||||
dev->wait_line = 0;
|
||||
stream->is_line_wake_up = false;
|
||||
}
|
||||
tasklet_disable(&stream->vb_done_tasklet);
|
||||
if (can_reset && hw_dev->dummy_buf.vaddr)
|
||||
rkcif_destroy_dummy_buf(stream);
|
||||
}
|
||||
if (can_reset && hw_dev->dummy_buf.vaddr)
|
||||
rkcif_destroy_dummy_buf(stream);
|
||||
if (mode == RKCIF_STREAM_MODE_CAPTURE)
|
||||
tasklet_disable(&stream->vb_done_tasklet);
|
||||
|
||||
stream->cur_stream_mode &= ~mode;
|
||||
INIT_LIST_HEAD(&stream->vb_done_list);
|
||||
v4l2_info(&dev->v4l2_dev, "stream[%d] stopping finished, dma_en 0x%x\n", stream->id, stream->dma_en);
|
||||
@@ -6213,8 +6215,10 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode)
|
||||
}
|
||||
mutex_unlock(&hw_dev->dev_lock);
|
||||
|
||||
if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
|
||||
if (mode == RKCIF_STREAM_MODE_CAPTURE)
|
||||
tasklet_enable(&stream->vb_done_tasklet);
|
||||
|
||||
if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
|
||||
ret = dev->pipe.open(&dev->pipe, &node->vdev.entity, true);
|
||||
if (ret < 0) {
|
||||
v4l2_err(v4l2_dev, "open cif pipeline failed %d\n",
|
||||
@@ -6232,7 +6236,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode)
|
||||
rkmodule_stream_seq == RKMODULE_START_STREAM_FRONT) {
|
||||
ret = dev->pipe.set_stream(&dev->pipe, true);
|
||||
if (ret < 0)
|
||||
goto runtime_put;
|
||||
goto destroy_buf;
|
||||
}
|
||||
}
|
||||
if (dev->chip_id >= CHIP_RK1808_CIF) {
|
||||
@@ -6248,7 +6252,7 @@ int rkcif_do_start_stream(struct rkcif_stream *stream, unsigned int mode)
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto runtime_put;
|
||||
goto destroy_buf;
|
||||
|
||||
if (stream->cur_stream_mode == RKCIF_STREAM_MODE_NONE) {
|
||||
ret = media_pipeline_start(&node->vdev.entity, &dev->pipe.pipe);
|
||||
@@ -6294,15 +6298,19 @@ stop_stream:
|
||||
rkcif_stream_stop(stream);
|
||||
pipe_stream_off:
|
||||
dev->pipe.set_stream(&dev->pipe, false);
|
||||
runtime_put:
|
||||
pm_runtime_put_sync(dev->dev);
|
||||
|
||||
destroy_buf:
|
||||
if (stream->next_buf)
|
||||
vb2_buffer_done(&stream->next_buf->vb.vb2_buf,
|
||||
VB2_BUF_STATE_QUEUED);
|
||||
if (mode == RKCIF_STREAM_MODE_CAPTURE)
|
||||
tasklet_disable(&stream->vb_done_tasklet);
|
||||
if (stream->curr_buf)
|
||||
vb2_buffer_done(&stream->curr_buf->vb.vb2_buf,
|
||||
VB2_BUF_STATE_QUEUED);
|
||||
list_add_tail(&stream->curr_buf->queue, &stream->buf_head);
|
||||
if (stream->next_buf &&
|
||||
stream->next_buf != stream->curr_buf)
|
||||
list_add_tail(&stream->next_buf->queue, &stream->buf_head);
|
||||
|
||||
stream->curr_buf = NULL;
|
||||
stream->next_buf = NULL;
|
||||
atomic_set(&stream->buf_cnt, 0);
|
||||
while (!list_empty(&stream->buf_head)) {
|
||||
struct rkcif_buffer *buf;
|
||||
|
||||
|
||||
@@ -627,36 +627,39 @@ static int sditf_start_stream(struct sditf_priv *priv)
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
struct v4l2_subdev_format fmt;
|
||||
unsigned int mode = RKCIF_STREAM_MODE_TOISP;
|
||||
int ret = 0;
|
||||
|
||||
sditf_check_capture_mode(cif_dev);
|
||||
sditf_get_set_fmt(&priv->sd, NULL, &fmt);
|
||||
if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
|
||||
if (priv->toisp_inf.link_mode == TOISP0) {
|
||||
sditf_channel_enable(priv, 0);
|
||||
ret = sditf_channel_enable(priv, 0);
|
||||
} else if (priv->toisp_inf.link_mode == TOISP1) {
|
||||
sditf_channel_enable(priv, 1);
|
||||
ret = sditf_channel_enable(priv, 1);
|
||||
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
|
||||
sditf_channel_enable(priv, 0);
|
||||
sditf_channel_enable(priv, 1);
|
||||
ret = sditf_channel_enable(priv, 0);
|
||||
ret |= sditf_channel_enable(priv, 1);
|
||||
}
|
||||
mode = RKCIF_STREAM_MODE_TOISP;
|
||||
} else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
|
||||
mode = RKCIF_STREAM_MODE_TOISP_RDBK;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == NO_HDR ||
|
||||
priv->hdr_cfg.hdr_mode == HDR_COMPR) {
|
||||
rkcif_do_start_stream(&cif_dev->stream[0], mode);
|
||||
ret = rkcif_do_start_stream(&cif_dev->stream[0], mode);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
rkcif_do_start_stream(&cif_dev->stream[0], mode);
|
||||
rkcif_do_start_stream(&cif_dev->stream[1], mode);
|
||||
ret = rkcif_do_start_stream(&cif_dev->stream[0], mode);
|
||||
ret |= rkcif_do_start_stream(&cif_dev->stream[1], mode);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
rkcif_do_start_stream(&cif_dev->stream[0], mode);
|
||||
rkcif_do_start_stream(&cif_dev->stream[1], mode);
|
||||
rkcif_do_start_stream(&cif_dev->stream[2], mode);
|
||||
ret = rkcif_do_start_stream(&cif_dev->stream[0], mode);
|
||||
ret |= rkcif_do_start_stream(&cif_dev->stream[1], mode);
|
||||
ret |= rkcif_do_start_stream(&cif_dev->stream[2], mode);
|
||||
}
|
||||
INIT_LIST_HEAD(&priv->buf_free_list);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sditf_stop_stream(struct sditf_priv *priv)
|
||||
@@ -718,6 +721,8 @@ static int sditf_s_stream(struct v4l2_subdev *sd, int on)
|
||||
}
|
||||
|
||||
}
|
||||
if (on && ret)
|
||||
atomic_dec(&priv->stream_cnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -745,6 +750,7 @@ static int sditf_s_power(struct v4l2_subdev *sd, int on)
|
||||
} else {
|
||||
v4l2_pipeline_pm_put(&node->vdev.entity);
|
||||
pm_runtime_put_sync(cif_dev->dev);
|
||||
priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ;
|
||||
}
|
||||
v4l2_info(&node->vdev, "s_power %d, entity use_count %d\n",
|
||||
on, node->vdev.entity.use_count);
|
||||
|
||||
@@ -2169,9 +2169,12 @@
|
||||
#define ISP3X_CAC_LUT_MODE(x) (((x) & 0x3) << 24)
|
||||
|
||||
/* CNR */
|
||||
#define ISP3X_CNR_THUMB_MIX_CUR_EN BIT(4)
|
||||
|
||||
#define ISP3X_CNR_GLOBAL_GAIN_ALPHA_MAX GENMASK(15, 12)
|
||||
|
||||
/* YNR */
|
||||
#define ISP3X_YNR_THUMB_MIX_CUR_EN BIT(24)
|
||||
#define ISP3X_YNR_EN_SHD BIT(31)
|
||||
|
||||
/* BLS */
|
||||
@@ -2201,6 +2204,9 @@
|
||||
/* HDRTMO */
|
||||
|
||||
/* HDRDRC */
|
||||
#define ISP3X_DRC_WEIPRE_FRAME_MASK GENMASK(23, 16)
|
||||
|
||||
#define ISP3X_DRC_IIR_WEIGHT_MASK GENMASK(22, 16)
|
||||
|
||||
/* HDRMGE */
|
||||
|
||||
|
||||
@@ -518,7 +518,9 @@ static void rkisp_dvfs(struct rkisp_device *dev)
|
||||
do_div(data_rate, 1000 * 1000);
|
||||
/* increase margin: 25% * num */
|
||||
data_rate += (data_rate >> 2) * num;
|
||||
|
||||
/* one frame two-run, data double */
|
||||
if (hw->is_multi_overflow && num > 1)
|
||||
data_rate *= 2;
|
||||
/* compare with isp clock adjustment table */
|
||||
for (i = 0; i < hw->num_clk_rate_tbl; i++)
|
||||
if (data_rate <= hw->clk_rate_tbl[i].clk_rate)
|
||||
@@ -541,45 +543,36 @@ static void rkisp_multi_overflow_hdl(struct rkisp_device *dev, bool on)
|
||||
struct rkisp_hw_dev *hw = dev->hw_dev;
|
||||
|
||||
if (on) {
|
||||
/* enable bay3d and mi */
|
||||
/* enable mi */
|
||||
rkisp_update_regs(dev, ISP3X_MI_WR_CTRL, ISP3X_MI_WR_CTRL);
|
||||
rkisp_update_regs(dev, ISP3X_ISP_CTRL1, ISP3X_ISP_CTRL1);
|
||||
if (dev->isp_ver == ISP_V21) {
|
||||
rkisp_update_regs(dev, ISP21_BAY3D_CTRL, ISP21_BAY3D_CTRL);
|
||||
} else if (dev->isp_ver == ISP_V30) {
|
||||
if (dev->isp_ver == ISP_V30) {
|
||||
rkisp_update_regs(dev, ISP3X_MPFBC_CTRL, ISP3X_MPFBC_CTRL);
|
||||
rkisp_update_regs(dev, ISP3X_MI_BP_WR_CTRL, ISP3X_MI_BP_WR_CTRL);
|
||||
rkisp_update_regs(dev, ISP3X_BAY3D_CTRL, ISP3X_BAY3D_CTRL);
|
||||
rkisp_update_regs(dev, ISP3X_SWS_CFG, ISP3X_SWS_CFG);
|
||||
} else if (dev->isp_ver == ISP_V32) {
|
||||
rkisp_update_regs(dev, ISP3X_MI_BP_WR_CTRL, ISP3X_MI_BP_WR_CTRL);
|
||||
rkisp_update_regs(dev, ISP32_MI_BPDS_WR_CTRL, ISP32_MI_BPDS_WR_CTRL);
|
||||
rkisp_update_regs(dev, ISP32_MI_MPDS_WR_CTRL, ISP32_MI_MPDS_WR_CTRL);
|
||||
rkisp_update_regs(dev, ISP3X_BAY3D_CTRL, ISP3X_BAY3D_CTRL);
|
||||
}
|
||||
} else {
|
||||
/* disabled bay3d and mi. rv1106 sdmmc workaround, 3a_wr no close */
|
||||
/* disabled mi. rv1106 sdmmc workaround, 3a_wr no close */
|
||||
writel(CIF_MI_CTRL_INIT_OFFSET_EN | CIF_MI_CTRL_INIT_BASE_EN,
|
||||
hw->base_addr + ISP3X_MI_WR_CTRL);
|
||||
if (dev->isp_ver == ISP_V21) {
|
||||
writel(0, hw->base_addr + ISP21_BAY3D_CTRL);
|
||||
} else if (dev->isp_ver == ISP_V30) {
|
||||
if (dev->isp_ver == ISP_V30) {
|
||||
writel(0, hw->base_addr + ISP3X_MPFBC_CTRL);
|
||||
writel(0, hw->base_addr + ISP3X_MI_BP_WR_CTRL);
|
||||
writel(0, hw->base_addr + ISP3X_BAY3D_CTRL);
|
||||
writel(0xc, hw->base_addr + ISP3X_SWS_CFG);
|
||||
if (hw->is_unite) {
|
||||
writel(0, hw->base_next_addr + ISP3X_MI_WR_CTRL);
|
||||
writel(0, hw->base_next_addr + ISP3X_MPFBC_CTRL);
|
||||
writel(0, hw->base_next_addr + ISP3X_MI_BP_WR_CTRL);
|
||||
writel(0, hw->base_next_addr + ISP3X_BAY3D_CTRL);
|
||||
writel(0xc, hw->base_next_addr + ISP3X_SWS_CFG);
|
||||
}
|
||||
} else if (dev->isp_ver == ISP_V32) {
|
||||
writel(0, hw->base_addr + ISP3X_MI_BP_WR_CTRL);
|
||||
writel(0, hw->base_addr + ISP32_MI_BPDS_WR_CTRL);
|
||||
writel(0, hw->base_addr + ISP32_MI_MPDS_WR_CTRL);
|
||||
writel(0, hw->base_addr + ISP3X_BAY3D_CTRL);
|
||||
}
|
||||
}
|
||||
rkisp_unite_write(dev, ISP3X_MI_WR_INIT, CIF_MI_INIT_SOFT_UPD, true, hw->is_unite);
|
||||
@@ -741,19 +734,54 @@ run_next:
|
||||
if (dev->sw_rd_cnt) {
|
||||
/* the frame first running to off mi to save bandwidth */
|
||||
rkisp_multi_overflow_hdl(dev, false);
|
||||
/* FST_FRAME for YNR/CNR/SHP/ADRC/DHAZ no to refer to sram info */
|
||||
val = ISP3X_YNR_FST_FRAME | ISP3X_CNR_FST_FRAME | ISP32_SHP_FST_FRAME |
|
||||
ISP3X_ADRC_FST_FRAME | ISP3X_DHAZ_FST_FRAME;
|
||||
|
||||
/* FST_FRAME no to read sram thumb */
|
||||
val = ISP3X_YNR_FST_FRAME | ISP3X_DHAZ_FST_FRAME;
|
||||
if (dev->isp_ver == ISP_V32)
|
||||
val |= ISP32_SHP_FST_FRAME;
|
||||
else
|
||||
val |= ISP3X_CNR_FST_FRAME;
|
||||
rkisp_unite_set_bits(dev, ISP3X_ISP_CTRL1, 0, val, false, hw->is_unite);
|
||||
/* ADRC low iir thumb weight for first sensor switch */
|
||||
val = rkisp_read_reg_cache(dev, ISP3X_DRC_IIRWG_GAIN);
|
||||
val &= ~ISP3X_DRC_IIR_WEIGHT_MASK;
|
||||
writel(val, hw->base_addr + ISP3X_DRC_IIRWG_GAIN);
|
||||
/* ADRC iir5x5 and cur3x3 weight */
|
||||
val = rkisp_read_reg_cache(dev, ISP3X_DRC_EXPLRATIO);
|
||||
val &= ~ISP3X_DRC_WEIPRE_FRAME_MASK;
|
||||
writel(val, hw->base_addr + ISP3X_DRC_EXPLRATIO);
|
||||
/* YNR_THUMB_MIX_CUR_EN for thumb read addr to 0 */
|
||||
val = rkisp_read_reg_cache(dev, ISP3X_YNR_GLOBAL_CTRL);
|
||||
val |= ISP3X_YNR_THUMB_MIX_CUR_EN;
|
||||
writel(val, hw->base_addr + ISP3X_YNR_GLOBAL_CTRL);
|
||||
if (dev->isp_ver == ISP_V21 || dev->isp_ver == ISP_V30) {
|
||||
/* CNR_THUMB_MIX_CUR_EN for thumb read addr to 0 */
|
||||
val = rkisp_read_reg_cache(dev, ISP3X_CNR_CTRL);
|
||||
val |= ISP3X_CNR_THUMB_MIX_CUR_EN;
|
||||
writel(val, hw->base_addr + ISP3X_CNR_CTRL);
|
||||
if (hw->is_unite)
|
||||
writel(val, hw->base_next_addr + ISP3X_CNR_CTRL);
|
||||
}
|
||||
|
||||
params_vdev->rdbk_times += dev->sw_rd_cnt;
|
||||
stats_vdev->rdbk_drop = true;
|
||||
is_upd = true;
|
||||
} else if (is_try) {
|
||||
/* the frame second running to on mi */
|
||||
rkisp_multi_overflow_hdl(dev, true);
|
||||
rkisp_update_regs(dev, ISP_LDCH_BASE, ISP_LDCH_BASE);
|
||||
val = ISP3X_YNR_FST_FRAME | ISP3X_CNR_FST_FRAME | ISP32_SHP_FST_FRAME |
|
||||
ISP3X_ADRC_FST_FRAME | ISP3X_DHAZ_FST_FRAME;
|
||||
|
||||
val = ISP3X_YNR_FST_FRAME | ISP3X_DHAZ_FST_FRAME | ISP3X_CNR_FST_FRAME;
|
||||
if (dev->isp_ver == ISP_V32)
|
||||
val |= ISP32_SHP_FST_FRAME;
|
||||
else
|
||||
val |= ISP3X_CNR_FST_FRAME;
|
||||
rkisp_unite_clear_bits(dev, ISP3X_ISP_CTRL1, val, false, hw->is_unite);
|
||||
val = rkisp_read_reg_cache(dev, ISP3X_DRC_IIRWG_GAIN);
|
||||
writel(val, hw->base_addr + ISP3X_DRC_IIRWG_GAIN);
|
||||
val = rkisp_read_reg_cache(dev, ISP3X_DRC_EXPLRATIO);
|
||||
writel(val, hw->base_addr + ISP3X_DRC_EXPLRATIO);
|
||||
|
||||
is_upd = true;
|
||||
}
|
||||
}
|
||||
@@ -818,6 +846,8 @@ run_next:
|
||||
val &= ~SW_IBUF_OP_MODE(0xf);
|
||||
tmp = SW_IBUF_OP_MODE(dev->rd_mode);
|
||||
val |= tmp | SW_CSI2RX_EN | SW_DMA_2FRM_MODE(dma2frm);
|
||||
if (dev->isp_ver > ISP_V20)
|
||||
dma2frm = dev->sw_rd_cnt;
|
||||
v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
|
||||
"readback frame:%d time:%d 0x%x\n",
|
||||
cur_frame_id, dma2frm + 1, val);
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
|
||||
#define DRIVER_NAME "rknpu"
|
||||
#define DRIVER_DESC "RKNPU driver"
|
||||
#define DRIVER_DATE "20230721"
|
||||
#define DRIVER_DATE "20230825"
|
||||
#define DRIVER_MAJOR 0
|
||||
#define DRIVER_MINOR 9
|
||||
#define DRIVER_PATCHLEVEL 1
|
||||
#define DRIVER_PATCHLEVEL 2
|
||||
|
||||
#define LOG_TAG "RKNPU"
|
||||
|
||||
@@ -75,6 +75,7 @@ struct rknpu_config {
|
||||
int num_resets;
|
||||
__u64 nbuf_phyaddr;
|
||||
__u64 nbuf_size;
|
||||
__u64 max_submit_number;
|
||||
};
|
||||
|
||||
struct rknpu_timer {
|
||||
@@ -101,6 +102,7 @@ struct rknpu_device {
|
||||
void __iomem *base[RKNPU_MAX_CORES];
|
||||
struct device *dev;
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
|
||||
struct device *fake_dev;
|
||||
struct drm_device *drm_dev;
|
||||
#endif
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
|
||||
|
||||
@@ -46,6 +46,7 @@ struct rknpu_job {
|
||||
atomic_t interrupt_count;
|
||||
ktime_t hw_recoder_time;
|
||||
ktime_t commit_pc_time;
|
||||
atomic_t submit_count[RKNPU_MAX_CORES];
|
||||
};
|
||||
|
||||
irqreturn_t rknpu_core0_irq_handler(int irq, void *data);
|
||||
|
||||
@@ -63,7 +63,7 @@ static int rknpu_load_show(struct seq_file *m, void *data)
|
||||
|
||||
div_value = (RKNPU_LOAD_INTERVAL / 100000);
|
||||
do_div(busy_time_total, div_value);
|
||||
load = busy_time_total;
|
||||
load = busy_time_total > 100 ? 100 : busy_time_total;
|
||||
|
||||
if (rknpu_dev->config->num_irqs > 1)
|
||||
seq_printf(m, "%2.d%%,", load);
|
||||
|
||||
@@ -117,7 +117,8 @@ static const struct rknpu_config rk356x_rknpu_config = {
|
||||
.num_irqs = ARRAY_SIZE(rknpu_irqs),
|
||||
.num_resets = ARRAY_SIZE(rknpu_resets),
|
||||
.nbuf_phyaddr = 0,
|
||||
.nbuf_size = 0
|
||||
.nbuf_size = 0,
|
||||
.max_submit_number = (1 << 12) - 1
|
||||
};
|
||||
|
||||
static const struct rknpu_config rk3588_rknpu_config = {
|
||||
@@ -135,7 +136,8 @@ static const struct rknpu_config rk3588_rknpu_config = {
|
||||
.num_irqs = ARRAY_SIZE(rk3588_npu_irqs),
|
||||
.num_resets = ARRAY_SIZE(rk3588_npu_resets),
|
||||
.nbuf_phyaddr = 0,
|
||||
.nbuf_size = 0
|
||||
.nbuf_size = 0,
|
||||
.max_submit_number = (1 << 12) - 1
|
||||
};
|
||||
|
||||
static const struct rknpu_config rv1106_rknpu_config = {
|
||||
@@ -153,7 +155,8 @@ static const struct rknpu_config rv1106_rknpu_config = {
|
||||
.num_irqs = ARRAY_SIZE(rknpu_irqs),
|
||||
.num_resets = ARRAY_SIZE(rknpu_resets),
|
||||
.nbuf_phyaddr = 0,
|
||||
.nbuf_size = 0
|
||||
.nbuf_size = 0,
|
||||
.max_submit_number = (1 << 16) - 1
|
||||
};
|
||||
|
||||
static const struct rknpu_config rk3562_rknpu_config = {
|
||||
@@ -171,7 +174,8 @@ static const struct rknpu_config rk3562_rknpu_config = {
|
||||
.num_irqs = ARRAY_SIZE(rknpu_irqs),
|
||||
.num_resets = ARRAY_SIZE(rknpu_resets),
|
||||
.nbuf_phyaddr = 0xfe400000,
|
||||
.nbuf_size = 256 * 1024
|
||||
.nbuf_size = 256 * 1024,
|
||||
.max_submit_number = (1 << 16) - 1
|
||||
};
|
||||
|
||||
/* driver probe and init */
|
||||
@@ -539,6 +543,9 @@ static const struct drm_ioctl_desc rknpu_ioctls[] = {
|
||||
DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
|
||||
DEFINE_DRM_GEM_FOPS(rknpu_drm_driver_fops);
|
||||
#else
|
||||
static const struct file_operations rknpu_drm_driver_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
@@ -552,6 +559,7 @@ static const struct file_operations rknpu_drm_driver_fops = {
|
||||
.release = drm_release,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct drm_driver rknpu_drm_driver = {
|
||||
#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE
|
||||
@@ -582,7 +590,11 @@ static struct drm_driver rknpu_drm_driver = {
|
||||
.gem_prime_import = drm_gem_prime_import,
|
||||
#endif
|
||||
.gem_prime_import_sg_table = rknpu_gem_prime_import_sg_table,
|
||||
#if KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE
|
||||
.gem_prime_mmap = drm_gem_prime_mmap,
|
||||
#else
|
||||
.gem_prime_mmap = rknpu_gem_prime_mmap,
|
||||
#endif
|
||||
.ioctls = rknpu_ioctls,
|
||||
.num_ioctls = ARRAY_SIZE(rknpu_ioctls),
|
||||
.fops = &rknpu_drm_driver_fops,
|
||||
@@ -602,7 +614,7 @@ static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
|
||||
container_of(timer, struct rknpu_device, timer);
|
||||
struct rknpu_subcore_data *subcore_data = NULL;
|
||||
struct rknpu_job *job = NULL;
|
||||
ktime_t now = ktime_get();
|
||||
ktime_t now;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
@@ -613,9 +625,10 @@ static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
|
||||
|
||||
job = subcore_data->job;
|
||||
if (job) {
|
||||
now = ktime_get();
|
||||
subcore_data->timer.busy_time +=
|
||||
ktime_us_delta(now, job->hw_recoder_time);
|
||||
job->hw_recoder_time = ktime_get();
|
||||
job->hw_recoder_time = now;
|
||||
}
|
||||
|
||||
subcore_data->timer.busy_time_record =
|
||||
@@ -667,6 +680,42 @@ static bool rknpu_is_iommu_enable(struct device *dev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
|
||||
static int drm_fake_dev_register(struct rknpu_device *rknpu_dev)
|
||||
{
|
||||
const struct platform_device_info rknpu_dev_info = {
|
||||
.name = "rknpu_dev",
|
||||
.id = PLATFORM_DEVID_AUTO,
|
||||
.dma_mask = rknpu_dev->config->dma_mask,
|
||||
};
|
||||
struct platform_device *pdev = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
pdev = platform_device_register_full(&rknpu_dev_info);
|
||||
if (pdev) {
|
||||
ret = of_dma_configure(&pdev->dev, NULL, true);
|
||||
if (ret) {
|
||||
platform_device_unregister(pdev);
|
||||
pdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
rknpu_dev->fake_dev = pdev ? &pdev->dev : NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void drm_fake_dev_unregister(struct rknpu_device *rknpu_dev)
|
||||
{
|
||||
struct platform_device *pdev = NULL;
|
||||
|
||||
if (!rknpu_dev->fake_dev)
|
||||
return;
|
||||
|
||||
pdev = to_platform_device(rknpu_dev->fake_dev);
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
}
|
||||
|
||||
static int rknpu_drm_probe(struct rknpu_device *rknpu_dev)
|
||||
{
|
||||
struct device *dev = rknpu_dev->dev;
|
||||
@@ -685,6 +734,8 @@ static int rknpu_drm_probe(struct rknpu_device *rknpu_dev)
|
||||
drm_dev->dev_private = rknpu_dev;
|
||||
rknpu_dev->drm_dev = drm_dev;
|
||||
|
||||
drm_fake_dev_register(rknpu_dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_drm:
|
||||
@@ -701,6 +752,8 @@ static void rknpu_drm_remove(struct rknpu_device *rknpu_dev)
|
||||
{
|
||||
struct drm_device *drm_dev = rknpu_dev->drm_dev;
|
||||
|
||||
drm_fake_dev_unregister(rknpu_dev);
|
||||
|
||||
drm_dev_unregister(drm_dev);
|
||||
|
||||
#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
|
||||
@@ -2123,6 +2176,6 @@ MODULE_ALIAS("rockchip-rknpu");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_VERSION(RKNPU_GET_DRV_VERSION_STRING(DRIVER_MAJOR, DRIVER_MINOR,
|
||||
DRIVER_PATCHLEVEL));
|
||||
#if defined(CONFIG_ROCKCHIP_RKNPU_DMA_HEAP) && KERNEL_VERSION(5, 16, 0) < LINUX_VERSION_CODE
|
||||
#if KERNEL_VERSION(5, 16, 0) < LINUX_VERSION_CODE
|
||||
MODULE_IMPORT_NS(DMA_BUF);
|
||||
#endif
|
||||
|
||||
@@ -985,6 +985,7 @@ static int rknpu_gem_mmap_buffer(struct rknpu_gem_object *rknpu_obj,
|
||||
* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
|
||||
* the whole buffer.
|
||||
*/
|
||||
vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
|
||||
vma->vm_flags &= ~VM_PFNMAP;
|
||||
vma->vm_pgoff = 0;
|
||||
|
||||
@@ -1329,19 +1330,29 @@ void rknpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
|
||||
int rknpu_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
|
||||
{
|
||||
struct rknpu_gem_object *rknpu_obj = to_rknpu_obj(obj);
|
||||
void *vaddr = NULL;
|
||||
|
||||
if (!rknpu_obj->pages)
|
||||
return -EINVAL;
|
||||
|
||||
map->vaddr = vmap(rknpu_obj->pages, rknpu_obj->num_pages, VM_MAP,
|
||||
vaddr = vmap(rknpu_obj->pages, rknpu_obj->num_pages, VM_MAP,
|
||||
PAGE_KERNEL);
|
||||
if (!vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
iosys_map_set_vaddr(map, vaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rknpu_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
|
||||
{
|
||||
vunmap(map->vaddr);
|
||||
struct rknpu_gem_object *rknpu_obj = to_rknpu_obj(obj);
|
||||
|
||||
if (rknpu_obj->pages) {
|
||||
vunmap(map->vaddr);
|
||||
map->vaddr = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1412,10 +1423,12 @@ int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct rknpu_gem_object *rknpu_obj = NULL;
|
||||
struct rknpu_device *rknpu_dev = dev->dev_private;
|
||||
struct rknpu_mem_sync *args = data;
|
||||
struct scatterlist *sg;
|
||||
dma_addr_t sg_phys_addr;
|
||||
unsigned long length, offset = 0;
|
||||
unsigned long sg_left, size = 0;
|
||||
unsigned long sg_offset, sg_left, size = 0;
|
||||
unsigned long len = 0;
|
||||
int i;
|
||||
|
||||
@@ -1439,6 +1452,8 @@ int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
} else {
|
||||
WARN_ON(!rknpu_dev->fake_dev);
|
||||
|
||||
length = args->size;
|
||||
offset = args->offset;
|
||||
|
||||
@@ -1462,17 +1477,23 @@ int rknpu_gem_sync_ioctl(struct drm_device *dev, void *data,
|
||||
if (len <= offset)
|
||||
continue;
|
||||
|
||||
sg_phys_addr = sg_phys(sg);
|
||||
|
||||
sg_left = len - offset;
|
||||
sg_offset = sg->length - sg_left;
|
||||
|
||||
size = (length < sg_left) ? length : sg_left;
|
||||
|
||||
if (args->flags & RKNPU_MEM_SYNC_TO_DEVICE) {
|
||||
dma_sync_sg_for_device(dev->dev, sg, 1,
|
||||
DMA_TO_DEVICE);
|
||||
dma_sync_single_range_for_device(
|
||||
rknpu_dev->fake_dev, sg_phys_addr,
|
||||
sg_offset, size, DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
if (args->flags & RKNPU_MEM_SYNC_FROM_DEVICE) {
|
||||
dma_sync_sg_for_cpu(dev->dev, sg, 1,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_sync_single_range_for_cpu(
|
||||
rknpu_dev->fake_dev, sg_phys_addr,
|
||||
sg_offset, size, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
||||
offset += size;
|
||||
|
||||
@@ -23,16 +23,25 @@
|
||||
#define REG_READ(offset) _REG_READ(rknpu_core_base, offset)
|
||||
#define REG_WRITE(value, offset) _REG_WRITE(rknpu_core_base, value, offset)
|
||||
|
||||
static int rknpu_core_index(int core_mask)
|
||||
static int rknpu_wait_core_index(int core_mask)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (core_mask & RKNPU_CORE0_MASK)
|
||||
switch (core_mask & ((1 << RKNPU_MAX_CORES) - 1)) {
|
||||
case RKNPU_CORE0_MASK:
|
||||
case RKNPU_CORE0_MASK | RKNPU_CORE1_MASK:
|
||||
case RKNPU_CORE0_MASK | RKNPU_CORE1_MASK | RKNPU_CORE2_MASK:
|
||||
index = 0;
|
||||
else if (core_mask & RKNPU_CORE1_MASK)
|
||||
break;
|
||||
case RKNPU_CORE1_MASK:
|
||||
index = 1;
|
||||
else if (core_mask & RKNPU_CORE2_MASK)
|
||||
break;
|
||||
case RKNPU_CORE2_MASK:
|
||||
index = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
@@ -58,14 +67,24 @@ static int rknpu_core_mask(int core_index)
|
||||
return core_mask;
|
||||
}
|
||||
|
||||
static int rknn_get_task_number(struct rknpu_job *job, int core_index)
|
||||
static int rknpu_get_task_number(struct rknpu_job *job, int core_index)
|
||||
{
|
||||
struct rknpu_device *rknpu_dev = job->rknpu_dev;
|
||||
int task_num = job->args->task_number;
|
||||
|
||||
if (job->use_core_num == 2)
|
||||
task_num = job->args->subcore_task[core_index].task_number;
|
||||
else if (job->use_core_num == 3)
|
||||
task_num = job->args->subcore_task[core_index + 2].task_number;
|
||||
if (core_index >= RKNPU_MAX_CORES || core_index < 0) {
|
||||
LOG_ERROR("core_index: %d set error!", core_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rknpu_dev->config->num_irqs > 1) {
|
||||
if (job->use_core_num == 1 || job->use_core_num == 2)
|
||||
task_num =
|
||||
job->args->subcore_task[core_index].task_number;
|
||||
else if (job->use_core_num == 3)
|
||||
task_num = job->args->subcore_task[core_index + 2]
|
||||
.task_number;
|
||||
}
|
||||
|
||||
return task_num;
|
||||
}
|
||||
@@ -159,7 +178,7 @@ static inline int rknpu_job_wait(struct rknpu_job *job)
|
||||
struct rknpu_subcore_data *subcore_data = NULL;
|
||||
struct rknpu_job *entry, *q;
|
||||
void __iomem *rknpu_core_base = NULL;
|
||||
int core_index = rknpu_core_index(job->args->core_mask);
|
||||
int core_index = rknpu_wait_core_index(job->args->core_mask);
|
||||
unsigned long flags;
|
||||
int wait_count = 0;
|
||||
bool continue_wait = false;
|
||||
@@ -179,7 +198,6 @@ static inline int rknpu_job_wait(struct rknpu_job *job)
|
||||
|
||||
if (ret == 0) {
|
||||
int64_t commit_time = 0;
|
||||
|
||||
spin_lock_irqsave(&rknpu_dev->irq_lock, flags);
|
||||
commit_time = ktime_us_delta(ktime_get(),
|
||||
job->commit_pc_time);
|
||||
@@ -245,7 +263,8 @@ static inline int rknpu_job_wait(struct rknpu_job *job)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rknpu_job_commit_pc(struct rknpu_job *job, int core_index)
|
||||
static inline int rknpu_job_subcore_commit_pc(struct rknpu_job *job,
|
||||
int core_index)
|
||||
{
|
||||
struct rknpu_device *rknpu_dev = job->rknpu_dev;
|
||||
struct rknpu_submit *args = job->args;
|
||||
@@ -262,12 +281,14 @@ static inline int rknpu_job_commit_pc(struct rknpu_job *job, int core_index)
|
||||
struct rknpu_task *last_task = NULL;
|
||||
void __iomem *rknpu_core_base = rknpu_dev->base[core_index];
|
||||
int task_start = args->task_start;
|
||||
int task_end = args->task_start + args->task_number - 1;
|
||||
int task_end;
|
||||
int task_number = args->task_number;
|
||||
int task_pp_en = args->flags & RKNPU_JOB_PINGPONG ? 1 : 0;
|
||||
int pc_data_amount_scale = rknpu_dev->config->pc_data_amount_scale;
|
||||
int pc_task_number_bits = rknpu_dev->config->pc_task_number_bits;
|
||||
int i = 0;
|
||||
int submit_index = atomic_read(&job->submit_count[core_index]);
|
||||
int max_submit_number = rknpu_dev->config->max_submit_number;
|
||||
|
||||
if (!task_obj) {
|
||||
job->ret = -EINVAL;
|
||||
@@ -282,38 +303,40 @@ static inline int rknpu_job_commit_pc(struct rknpu_job *job, int core_index)
|
||||
}
|
||||
}
|
||||
|
||||
if (job->use_core_num == 1) {
|
||||
switch (job->use_core_num) {
|
||||
case 1:
|
||||
case 2:
|
||||
task_start = args->subcore_task[core_index].task_start;
|
||||
task_end = args->subcore_task[core_index].task_start +
|
||||
args->subcore_task[core_index].task_number -
|
||||
1;
|
||||
task_number =
|
||||
args->subcore_task[core_index].task_number;
|
||||
} else if (job->use_core_num == 2) {
|
||||
task_start = args->subcore_task[core_index].task_start;
|
||||
task_end = args->subcore_task[core_index].task_start +
|
||||
args->subcore_task[core_index].task_number -
|
||||
1;
|
||||
task_number =
|
||||
args->subcore_task[core_index].task_number;
|
||||
} else if (job->use_core_num == 3) {
|
||||
break;
|
||||
case 3:
|
||||
task_start =
|
||||
args->subcore_task[core_index + 2].task_start;
|
||||
task_end =
|
||||
args->subcore_task[core_index + 2].task_start +
|
||||
args->subcore_task[core_index + 2].task_number -
|
||||
1;
|
||||
task_number =
|
||||
args->subcore_task[core_index + 2].task_number;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown use core num %d\n",
|
||||
job->use_core_num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
task_start = task_start + submit_index * max_submit_number;
|
||||
task_number = task_number - submit_index * max_submit_number;
|
||||
task_number = task_number > max_submit_number ? max_submit_number :
|
||||
task_number;
|
||||
task_end = task_start + task_number - 1;
|
||||
|
||||
task_base = task_obj->kv_addr;
|
||||
|
||||
first_task = &task_base[task_start];
|
||||
last_task = &task_base[task_end];
|
||||
|
||||
spin_lock(&rknpu_dev->lock);
|
||||
REG_WRITE(first_task->regcmd_addr, RKNPU_OFFSET_PC_DATA_ADDR);
|
||||
spin_unlock(&rknpu_dev->lock);
|
||||
|
||||
REG_WRITE((first_task->regcfg_amount + RKNPU_PC_DATA_EXTRA_AMOUNT +
|
||||
pc_data_amount_scale - 1) /
|
||||
@@ -340,21 +363,50 @@ static inline int rknpu_job_commit_pc(struct rknpu_job *job, int core_index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rknpu_job_commit(struct rknpu_job *job, int core_index)
|
||||
static inline int rknpu_job_subcore_commit(struct rknpu_job *job, int core_index)
|
||||
{
|
||||
struct rknpu_device *rknpu_dev = job->rknpu_dev;
|
||||
struct rknpu_submit *args = job->args;
|
||||
void __iomem *rknpu_core_base = rknpu_dev->base[core_index];
|
||||
|
||||
// switch to slave mode
|
||||
spin_lock(&rknpu_dev->lock);
|
||||
REG_WRITE(0x1, RKNPU_OFFSET_PC_DATA_ADDR);
|
||||
spin_unlock(&rknpu_dev->lock);
|
||||
|
||||
if (!(args->flags & RKNPU_JOB_PC)) {
|
||||
job->ret = -EINVAL;
|
||||
return job->ret;
|
||||
}
|
||||
|
||||
return rknpu_job_commit_pc(job, core_index);
|
||||
return rknpu_job_subcore_commit_pc(job, core_index);
|
||||
}
|
||||
|
||||
static void rknpu_job_commit(struct rknpu_job *job)
|
||||
{
|
||||
switch (job->args->core_mask & ((1 << RKNPU_MAX_CORES) - 1)) {
|
||||
case RKNPU_CORE0_MASK:
|
||||
rknpu_job_subcore_commit(job, 0);
|
||||
break;
|
||||
case RKNPU_CORE1_MASK:
|
||||
rknpu_job_subcore_commit(job, 1);
|
||||
break;
|
||||
case RKNPU_CORE2_MASK:
|
||||
rknpu_job_subcore_commit(job, 2);
|
||||
break;
|
||||
case RKNPU_CORE0_MASK | RKNPU_CORE1_MASK:
|
||||
rknpu_job_subcore_commit(job, 0);
|
||||
rknpu_job_subcore_commit(job, 1);
|
||||
break;
|
||||
case RKNPU_CORE0_MASK | RKNPU_CORE1_MASK | RKNPU_CORE2_MASK:
|
||||
rknpu_job_subcore_commit(job, 0);
|
||||
rknpu_job_subcore_commit(job, 1);
|
||||
rknpu_job_subcore_commit(job, 2);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown core mask: %d\n", job->args->core_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void rknpu_job_next(struct rknpu_device *rknpu_dev, int core_index)
|
||||
@@ -385,30 +437,7 @@ static void rknpu_job_next(struct rknpu_device *rknpu_dev, int core_index)
|
||||
spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags);
|
||||
|
||||
if (atomic_dec_and_test(&job->run_count)) {
|
||||
switch (job->args->core_mask & ((1 << RKNPU_MAX_CORES) - 1)) {
|
||||
case RKNPU_CORE0_MASK:
|
||||
rknpu_job_commit(job, 0);
|
||||
break;
|
||||
case RKNPU_CORE1_MASK:
|
||||
rknpu_job_commit(job, 1);
|
||||
break;
|
||||
case RKNPU_CORE2_MASK:
|
||||
rknpu_job_commit(job, 2);
|
||||
break;
|
||||
case RKNPU_CORE0_MASK | RKNPU_CORE1_MASK:
|
||||
rknpu_job_commit(job, 0);
|
||||
rknpu_job_commit(job, 1);
|
||||
break;
|
||||
case RKNPU_CORE0_MASK | RKNPU_CORE1_MASK | RKNPU_CORE2_MASK:
|
||||
rknpu_job_commit(job, 0);
|
||||
rknpu_job_commit(job, 1);
|
||||
rknpu_job_commit(job, 2);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown core mask: %#x\n",
|
||||
job->args->core_mask);
|
||||
break;
|
||||
}
|
||||
rknpu_job_commit(job);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,15 +446,22 @@ static void rknpu_job_done(struct rknpu_job *job, int ret, int core_index)
|
||||
struct rknpu_device *rknpu_dev = job->rknpu_dev;
|
||||
struct rknpu_subcore_data *subcore_data = NULL;
|
||||
unsigned long flags;
|
||||
ktime_t now = ktime_get();
|
||||
int max_submit_number = rknpu_dev->config->max_submit_number;
|
||||
|
||||
if (atomic_inc_return(&job->submit_count[core_index]) <
|
||||
(rknpu_get_task_number(job, core_index) + max_submit_number - 1) /
|
||||
max_submit_number) {
|
||||
rknpu_job_commit(job);
|
||||
return;
|
||||
}
|
||||
|
||||
subcore_data = &rknpu_dev->subcore_datas[core_index];
|
||||
|
||||
spin_lock_irqsave(&rknpu_dev->irq_lock, flags);
|
||||
subcore_data->job = NULL;
|
||||
subcore_data->task_num -= rknn_get_task_number(job, core_index);
|
||||
subcore_data->task_num -= rknpu_get_task_number(job, core_index);
|
||||
subcore_data->timer.busy_time +=
|
||||
ktime_us_delta(now, job->hw_recoder_time);
|
||||
ktime_us_delta(ktime_get(), job->hw_recoder_time);
|
||||
spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags);
|
||||
|
||||
if (atomic_dec_and_test(&job->interrupt_count)) {
|
||||
@@ -498,7 +534,7 @@ static void rknpu_job_schedule(struct rknpu_job *job)
|
||||
if (job->args->core_mask & rknpu_core_mask(i)) {
|
||||
subcore_data = &rknpu_dev->subcore_datas[i];
|
||||
list_add_tail(&job->head[i], &subcore_data->todo_list);
|
||||
subcore_data->task_num += rknn_get_task_number(job, i);
|
||||
subcore_data->task_num += rknpu_get_task_number(job, i);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&rknpu_dev->irq_lock, flags);
|
||||
@@ -525,7 +561,7 @@ static void rknpu_job_abort(struct rknpu_job *job)
|
||||
if (job == subcore_data->job && !job->irq_entry[i]) {
|
||||
subcore_data->job = NULL;
|
||||
subcore_data->task_num -=
|
||||
rknn_get_task_number(job, i);
|
||||
rknpu_get_task_number(job, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "rknpu_ioctl.h"
|
||||
#include "rknpu_mem.h"
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
|
||||
|
||||
int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data,
|
||||
struct file *file)
|
||||
{
|
||||
@@ -108,7 +110,7 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data,
|
||||
}
|
||||
|
||||
page_count = length >> PAGE_SHIFT;
|
||||
pages = kmalloc_array(page_count, sizeof(struct page), GFP_KERNEL);
|
||||
pages = vmalloc(page_count * sizeof(struct page));
|
||||
if (!pages) {
|
||||
LOG_ERROR("alloc pages failed\n");
|
||||
ret = -ENOMEM;
|
||||
@@ -146,7 +148,8 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data,
|
||||
goto err_unmap_kv_addr;
|
||||
}
|
||||
|
||||
kfree(pages);
|
||||
vfree(pages);
|
||||
pages = NULL;
|
||||
dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL);
|
||||
dma_buf_detach(dmabuf, attachment);
|
||||
|
||||
@@ -169,7 +172,8 @@ err_unmap_kv_addr:
|
||||
rknpu_obj->kv_addr = NULL;
|
||||
|
||||
err_free_pages:
|
||||
kfree(pages);
|
||||
vfree(pages);
|
||||
pages = NULL;
|
||||
|
||||
err_detach_dma_buf:
|
||||
dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL);
|
||||
@@ -292,7 +296,9 @@ int rknpu_mem_sync_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
{
|
||||
struct rknpu_mem_object *rknpu_obj = NULL;
|
||||
struct rknpu_mem_sync args;
|
||||
#ifdef CONFIG_DMABUF_PARTIAL
|
||||
struct dma_buf *dmabuf;
|
||||
#endif
|
||||
int ret = -EFAULT;
|
||||
|
||||
if (unlikely(copy_from_user(&args, (struct rknpu_mem_sync *)data,
|
||||
@@ -310,7 +316,6 @@ int rknpu_mem_sync_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
}
|
||||
|
||||
rknpu_obj = (struct rknpu_mem_object *)(uintptr_t)args.obj_addr;
|
||||
dmabuf = rknpu_obj->dmabuf;
|
||||
|
||||
#ifndef CONFIG_DMABUF_PARTIAL
|
||||
if (args.flags & RKNPU_MEM_SYNC_TO_DEVICE) {
|
||||
@@ -322,6 +327,7 @@ int rknpu_mem_sync_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
DMA_FROM_DEVICE, true);
|
||||
}
|
||||
#else
|
||||
dmabuf = rknpu_obj->dmabuf;
|
||||
if (args.flags & RKNPU_MEM_SYNC_TO_DEVICE) {
|
||||
dmabuf->ops->end_cpu_access_partial(dmabuf, DMA_TO_DEVICE,
|
||||
args.offset, args.size);
|
||||
@@ -334,3 +340,5 @@ int rknpu_mem_sync_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1312,7 +1312,11 @@ int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin,
|
||||
return 0;
|
||||
|
||||
if (of_property_match_string(np, "nvmem-cell-names",
|
||||
"specification_serial_number") >= 0) {
|
||||
"remark_spec_serial_number") >= 0)
|
||||
rockchip_nvmem_cell_read_u8(np, "remark_spec_serial_number", &value);
|
||||
|
||||
if (!value && of_property_match_string(np, "nvmem-cell-names",
|
||||
"specification_serial_number") >= 0) {
|
||||
ret = rockchip_nvmem_cell_read_u8(np,
|
||||
"specification_serial_number",
|
||||
&value);
|
||||
@@ -1321,14 +1325,15 @@ int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin,
|
||||
"Failed to get specification_serial_number\n");
|
||||
return ret;
|
||||
}
|
||||
/* M */
|
||||
if (value == 0xd)
|
||||
*bin = 1;
|
||||
/* J */
|
||||
else if (value == 0xa)
|
||||
*bin = 2;
|
||||
}
|
||||
|
||||
/* M */
|
||||
if (value == 0xd)
|
||||
*bin = 1;
|
||||
/* J */
|
||||
else if (value == 0xa)
|
||||
*bin = 2;
|
||||
|
||||
if (*bin < 0)
|
||||
*bin = 0;
|
||||
dev_info(dev, "bin=%d\n", *bin);
|
||||
|
||||
@@ -1302,13 +1302,6 @@ static int rga_mm_sync_dma_sg_for_device(struct rga_internal_buffer *buffer,
|
||||
struct sg_table *sgt;
|
||||
struct rga_scheduler_t *scheduler;
|
||||
|
||||
sgt = rga_mm_lookup_sgt(buffer);
|
||||
if (sgt == NULL) {
|
||||
pr_err("%s(%d), failed to get sgt, core = 0x%x\n",
|
||||
__func__, __LINE__, job->core);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scheduler = buffer->dma_buffer->scheduler;
|
||||
if (scheduler == NULL) {
|
||||
pr_err("%s(%d), failed to get scheduler, core = 0x%x\n",
|
||||
@@ -1316,7 +1309,18 @@ static int rga_mm_sync_dma_sg_for_device(struct rga_internal_buffer *buffer,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dma_sync_sg_for_device(scheduler->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) {
|
||||
dma_sync_single_for_device(scheduler->dev, buffer->phys_addr, buffer->size, dir);
|
||||
} else {
|
||||
sgt = rga_mm_lookup_sgt(buffer);
|
||||
if (sgt == NULL) {
|
||||
pr_err("%s(%d), failed to get sgt, core = 0x%x\n",
|
||||
__func__, __LINE__, job->core);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dma_sync_sg_for_device(scheduler->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1328,13 +1332,6 @@ static int rga_mm_sync_dma_sg_for_cpu(struct rga_internal_buffer *buffer,
|
||||
struct sg_table *sgt;
|
||||
struct rga_scheduler_t *scheduler;
|
||||
|
||||
sgt = rga_mm_lookup_sgt(buffer);
|
||||
if (sgt == NULL) {
|
||||
pr_err("%s(%d), failed to get sgt, core = 0x%x\n",
|
||||
__func__, __LINE__, job->core);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
scheduler = buffer->dma_buffer->scheduler;
|
||||
if (scheduler == NULL) {
|
||||
pr_err("%s(%d), failed to get scheduler, core = 0x%x\n",
|
||||
@@ -1342,7 +1339,18 @@ static int rga_mm_sync_dma_sg_for_cpu(struct rga_internal_buffer *buffer,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dma_sync_sg_for_cpu(scheduler->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
if (buffer->mm_flag & RGA_MEM_PHYSICAL_CONTIGUOUS) {
|
||||
dma_sync_single_for_cpu(scheduler->dev, buffer->phys_addr, buffer->size, dir);
|
||||
} else {
|
||||
sgt = rga_mm_lookup_sgt(buffer);
|
||||
if (sgt == NULL) {
|
||||
pr_err("%s(%d), failed to get sgt, core = 0x%x\n",
|
||||
__func__, __LINE__, job->core);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dma_sync_sg_for_cpu(scheduler->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -244,6 +244,8 @@ struct dw_hdmi_plat_data {
|
||||
int (*get_next_hdr_data)(void *data, struct edid *edid,
|
||||
struct drm_connector *connector);
|
||||
struct dw_hdmi_link_config *(*get_link_cfg)(void *data);
|
||||
void (*set_hdcp_status)(void *data, u8 status);
|
||||
void (*set_hdcp2_enable)(void *data, bool enable);
|
||||
void (*set_grf_cfg)(void *data);
|
||||
u64 (*get_grf_color_fmt)(void *data);
|
||||
void (*convert_to_split_mode)(struct drm_display_mode *mode);
|
||||
@@ -256,6 +258,7 @@ struct dw_hdmi_plat_data {
|
||||
void (*set_prev_bus_format)(void *data, unsigned long bus_format);
|
||||
int (*get_colorimetry)(void *data, struct edid *edid);
|
||||
void (*set_ddc_io)(void *data, bool enable);
|
||||
void (*set_hdcp14_mem)(void *data, bool enable);
|
||||
|
||||
/* Vendor Property support */
|
||||
const struct dw_hdmi_property_ops *property_ops;
|
||||
|
||||
@@ -326,6 +326,7 @@ struct rkmodule_pdaf_inf {
|
||||
__u32 dccmap_height;
|
||||
__u32 dcc_mode;
|
||||
__u32 dcc_dir;
|
||||
__u32 pd_offset;
|
||||
__u16 gainmap[RKMODULE_PADF_GAINMAP_LEN];
|
||||
__u16 dccmap[RKMODULE_PDAF_DCCMAP_LEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
@@ -216,6 +216,7 @@ config SND_SOC_ALL_CODECS
|
||||
imply SND_SOC_TAS5720
|
||||
imply SND_SOC_TAS6424
|
||||
imply SND_SOC_TDA7419
|
||||
imply SND_SOC_TDA7803
|
||||
imply SND_SOC_TFA9879
|
||||
imply SND_SOC_TLV320ADCX140
|
||||
imply SND_SOC_TLV320AIC23_I2C
|
||||
@@ -1442,6 +1443,11 @@ config SND_SOC_TDA7419
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_TDA7803
|
||||
tristate "ST TDA7803 audio processor"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_TFA9879
|
||||
tristate "NXP Semiconductors TFA9879 amplifier"
|
||||
depends on I2C
|
||||
|
||||
@@ -232,6 +232,7 @@ snd-soc-tas571x-objs := tas571x.o
|
||||
snd-soc-tas5720-objs := tas5720.o
|
||||
snd-soc-tas6424-objs := tas6424.o
|
||||
snd-soc-tda7419-objs := tda7419.o
|
||||
snd-soc-tda7803-objs := tda7803.o
|
||||
snd-soc-tas2770-objs := tas2770.o
|
||||
snd-soc-tfa9879-objs := tfa9879.o
|
||||
snd-soc-tlv320aic23-objs := tlv320aic23.o
|
||||
@@ -560,6 +561,7 @@ obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
|
||||
obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o
|
||||
obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
|
||||
obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
|
||||
obj-$(CONFIG_SND_SOC_TDA7803) += snd-soc-tda7803.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
|
||||
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
|
||||
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
|
||||
|
||||
171
sound/soc/codecs/tda7803.c
Normal file
171
sound/soc/codecs/tda7803.c
Normal file
@@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/soc.h>
|
||||
|
||||
#include "tda7803.h"
|
||||
|
||||
#define TDA7803_SAMPLE_RATE \
|
||||
(SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
|
||||
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
|
||||
|
||||
struct tda7803_priv {
|
||||
struct regmap *regmap;
|
||||
u32 input_format;
|
||||
};
|
||||
|
||||
static int tda7803_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
struct tda7803_priv *tda7803 = snd_soc_component_get_drvdata(component);
|
||||
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
||||
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
||||
int val = 0;
|
||||
|
||||
snd_soc_component_write(component, TDA7803_REG2, DIGITAL_MUTE_OFF |
|
||||
CH2_4_UMUTE | CH1_3_UMUTE |
|
||||
MUTE_TIME_SETTING_1_45MS);
|
||||
snd_soc_component_write(component, TDA7803_REG7, AMPLIEFIR_SWITCH_ON);
|
||||
|
||||
switch (tda7803->input_format) {
|
||||
case 0:
|
||||
val = INPUT_FORMAT_TDM_8CH_MODEL1;
|
||||
break;
|
||||
case 1:
|
||||
val = INPUT_FORMAT_TDM_8CH_MODEL2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_dai_set_fmt(codec_dai, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda7803_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
int val = 0;
|
||||
|
||||
switch (params_rate(params)) {
|
||||
case 44100:
|
||||
val = SAMPLE_FREQUENCY_RANGE_44100HZ;
|
||||
break;
|
||||
case 48000:
|
||||
val = SAMPLE_FREQUENCY_RANGE_48000HZ;
|
||||
break;
|
||||
case 96000:
|
||||
val = SAMPLE_FREQUENCY_RANGE_96000HZ;
|
||||
break;
|
||||
case 192000:
|
||||
val = SAMPLE_FREQUENCY_RANGE_192000HZ;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_component_write(component, TDA7803_REG3, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda7803_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
|
||||
snd_soc_component_write(component, TDA7803_REG3, fmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops tda7803_ops = {
|
||||
.startup = tda7803_startup,
|
||||
.hw_params = tda7803_hw_params,
|
||||
.set_fmt = tda7803_set_fmt,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver tda7803_dai = {
|
||||
.name = "tda7803-hifi",
|
||||
.playback = {
|
||||
.stream_name = "Playback",
|
||||
.channels_min = 2,
|
||||
.channels_max = 8,
|
||||
.rates = TDA7803_SAMPLE_RATE,
|
||||
.formats = SNDRV_PCM_FMTBIT_S32_LE |
|
||||
SNDRV_PCM_FMTBIT_S24_LE |
|
||||
SNDRV_PCM_FMTBIT_S16_LE,
|
||||
},
|
||||
.ops = &tda7803_ops,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver soc_codec_dev_tda7803 = {
|
||||
.name = "tda7803",
|
||||
};
|
||||
|
||||
static const struct regmap_config tda7803_i2c_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = TDA7803_REGMAX,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int tda7803_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tda7803_priv *tda7803;
|
||||
int val;
|
||||
|
||||
tda7803 = devm_kzalloc(&i2c->dev, sizeof(*tda7803), GFP_KERNEL);
|
||||
if (!tda7803)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, tda7803);
|
||||
|
||||
tda7803->regmap = devm_regmap_init_i2c(i2c, &tda7803_i2c_regmap);
|
||||
if (IS_ERR(tda7803->regmap))
|
||||
return PTR_ERR(tda7803->regmap);
|
||||
|
||||
if (!device_property_read_u32(&i2c->dev, "st,tda7803-format", &val))
|
||||
tda7803->input_format = val;
|
||||
|
||||
return devm_snd_soc_register_component(&i2c->dev,
|
||||
&soc_codec_dev_tda7803,
|
||||
&tda7803_dai, 1);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tda7803_i2c_id[] = {
|
||||
{ "tda7803", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tda7803_i2c_id);
|
||||
|
||||
static const struct of_device_id tda7803_of_match[] = {
|
||||
{ .compatible = "st,tda7803" },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct i2c_driver tda7803_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "tda7803",
|
||||
.of_match_table = of_match_ptr(tda7803_of_match),
|
||||
},
|
||||
.probe = tda7803_i2c_probe,
|
||||
.id_table = tda7803_i2c_id,
|
||||
};
|
||||
module_i2c_driver(tda7803_i2c_driver);
|
||||
|
||||
MODULE_AUTHOR("Jun Zeng <jun.zeng@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("TDA7803 audio processor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
138
sound/soc/codecs/tda7803.h
Normal file
138
sound/soc/codecs/tda7803.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TDA7803_H__
|
||||
#define __TDA7803_H__
|
||||
|
||||
/* tda7803 registers space*/
|
||||
#define TDA7803_REG0 (0x00)
|
||||
#define CH1_AMP_SBI_MODE (0x00 << 0)
|
||||
#define CH1_AMP_ABI_MODE (0x01 << 0)
|
||||
#define CH2_AMP_SBI_MODE (0x00 << 1)
|
||||
#define CH2_AMP_ABI_MODE (0x01 << 1)
|
||||
#define CH3_AMP_SBI_MODE (0x00 << 2)
|
||||
#define CH3_AMP_ABI_MODE (0x01 << 2)
|
||||
#define CH4_AMP_SBI_MODE (0x00 << 3)
|
||||
#define CH4_AMP_ABI_MODE (0x01 << 3)
|
||||
#define CH1_TRI_MODE_OFF (0x00 << 4)
|
||||
#define CH1_TRI_MODE_ON (0x01 << 4)
|
||||
#define CH2_TRI_MODE_OFF (0x00 << 5)
|
||||
#define CH2_TRI_MODE_ON (0x01 << 5)
|
||||
#define CH3_TRI_MODE_OFF (0x00 << 6)
|
||||
#define CH3_TRI_MODE_ON (0x01 << 6)
|
||||
#define CH4_TRI_MODE_OFF (0x00 << 7)
|
||||
#define CH4_TRI_MODE_ON (0x01 << 7)
|
||||
|
||||
#define TDA7803_REG1 (0x01)
|
||||
#define CH2_4_GAIN_GV1 (0x00 << 0)
|
||||
#define CH2_4_GAIN_GV2 (0x01 << 0)
|
||||
#define CH2_4_GAIN_GV3 (0x02 << 0)
|
||||
#define CH2_4_GAIN_GV4 (0x03 << 0)
|
||||
#define CH1_3_GAIN_GV1 (0x00 << 2)
|
||||
#define CH1_3_GAIN_GV2 (0x01 << 2)
|
||||
#define CH1_3_GAIN_GV3 (0x02 << 2)
|
||||
#define CH1_3_GAIN_GV4 (0x03 << 2)
|
||||
#define GAIN_SELECT_NO (0x00 << 4)
|
||||
#define GAIN_SELECT_6DB (0x01 << 4)
|
||||
#define GAIN_SELECT_12DB (0x02 << 4)
|
||||
#define GAIN_SELECT_NOT_USED (0x03 << 4)
|
||||
#define IMPEDANCE_OPTIMIZER_REAR_2OHM (0x00 << 6)
|
||||
#define IMPEDANCE_OPTIMIZER_REAR_4OHM (0x01 << 6)
|
||||
#define IMPEDANCE_OPTIMIZER_FRONT_2OHM (0x00 << 7)
|
||||
#define IMPEDANCE_OPTIMIZER_FRONT_4OHM (0x01 << 7)
|
||||
|
||||
#define TDA7803_REG2 (0x02)
|
||||
#define LOW_BATTERY_MUTE_THRESHOLD_1 (0x00 << 0)
|
||||
#define LOW_BATTERY_MUTE_THRESHOLD_2 (0x01 << 0)
|
||||
#define DIGITAL_MUTE_ON (0x00 << 2)
|
||||
#define DIGITAL_MUTE_OFF (0x01 << 2)
|
||||
#define CH2_4_MUTE (0x00 << 3)
|
||||
#define CH2_4_UMUTE (0x01 << 3)
|
||||
#define CH1_3_MUTE (0x00 << 4)
|
||||
#define CH1_3_UMUTE (0x01 << 4)
|
||||
#define MUTE_TIME_SETTING_1_45MS (0x00 << 5)
|
||||
#define MUTE_TIME_SETTING_5_8MS (0x01 << 5)
|
||||
#define MUTE_TIME_SETTING_11_6MS (0x02 << 5)
|
||||
#define MUTE_TIME_SETTING_23_2MS (0x03 << 5)
|
||||
#define MUTE_TIME_SETTING_46_4MS (0x04 << 5)
|
||||
#define MUTE_TIME_SETTING_92_8MS (0x05 << 5)
|
||||
#define MUTE_TIME_SETTING_185_5MS (0x06 << 5)
|
||||
#define MUTE_TIME_SETTING_371_1MS (0x07 << 5)
|
||||
|
||||
#define TDA7803_REG3 (0x03)
|
||||
#define HIGH_PASS_FILTER_DISABLE (0x00 << 0)
|
||||
#define HIGH_PASS_FILTER_ENABLE (0x01 << 0)
|
||||
#define INPUT_OFFSET_DETECTION_DIS (0x00 << 1)
|
||||
#define INPUT_OFFSET_DETECTION_EN (0x01 << 1)
|
||||
#define NOISE_GATING_FUNCTION_EN (0x00 << 2)
|
||||
#define NOISE_GATING_FUNCTION_DIS (0x01 << 2)
|
||||
#define INPUT_FORMAT_I2S_STD (0x00 << 3)
|
||||
#define INPUT_FORMAT_TDM_4CH (0x01 << 3)
|
||||
#define INPUT_FORMAT_TDM_8CH_MODEL1 (0x02 << 3)
|
||||
#define INPUT_FORMAT_TDM_8CH_MODEL2 (0x03 << 3)
|
||||
#define INPUT_FORMAT_TDM_16CH_MODEL1 (0x04 << 3)
|
||||
#define INPUT_FORMAT_TDM_16CH_MODEL2 (0x05 << 3)
|
||||
#define INPUT_FORMAT_TDM_16CH_MODEL3 (0x06 << 3)
|
||||
#define INPUT_FORMAT_TDM_16CH_MODEL4 (0x07 << 3)
|
||||
#define SAMPLE_FREQUENCY_RANGE_44100HZ (0x00 << 6)
|
||||
#define SAMPLE_FREQUENCY_RANGE_48000HZ (0x01 << 6)
|
||||
#define SAMPLE_FREQUENCY_RANGE_96000HZ (0x02 << 6)
|
||||
#define SAMPLE_FREQUENCY_RANGE_192000HZ (0x03 << 6)
|
||||
|
||||
#define TDA7803_REG4 (0x04)
|
||||
#define DIAGNOSTIC_MODE_DISABLE (0x00 << 0)
|
||||
#define DIAGNOSTIC_MODE_ENABLE (0x01 << 0)
|
||||
#define CH2_4_SPEAKER_MODE (0x00 << 1)
|
||||
#define CH2_4_LINE_DRIVER_MODE (0x01 << 1)
|
||||
#define CH1_3_SPEAKER_MODE (0x00 << 2)
|
||||
#define CH1_3_LINE_DRIVER_MODE (0x01 << 2)
|
||||
#define DIAGNOSTIC_DISABLE (0X00 << 3)
|
||||
#define DIAGNOSTIC_ENABLE (0X01 << 3)
|
||||
#define DIAGNOSTIC_CURRENT_THRESHOLD_HIGH (0X00 << 4)
|
||||
#define DIAGNOSTIC_CURRENT_THRESHOLD_LOW (0X01 << 4)
|
||||
#define OFFSET_INFORMATION_YES (0X00 << 5)
|
||||
#define OFFSET_INFORMATION_NO (0X01 << 5)
|
||||
#define SHORT_FAULT_INFORMATION_YES (0X00 << 6)
|
||||
#define SHORT_FAULT_INFORMATION_NO (0X01 << 6)
|
||||
|
||||
#define TDA7803_REG5 (0x05)
|
||||
#define CAPABILITY_ENHANCER_DISABLE (0x00 << 1)
|
||||
#define CAPABILITY_ENHANCER_ENABLE (0x0F << 1)
|
||||
#define THERMAL_THRESHOLD_DEFAULT (0x00 << 6)
|
||||
#define THERMAL_THRESHOLD_TW_NEGATIVE_10 (0x01 << 6)
|
||||
#define THERMAL_THRESHOLD_TW_NEGATIVE_20 (0x02 << 6)
|
||||
|
||||
#define TDA7803_REG6 (0x06)
|
||||
#define PARALLEL_MODE_CONFIG_MODE_1 (0x00 << 2)
|
||||
#define PARALLEL_MODE_CONFIG_MODE_2 (0x01 << 2)
|
||||
#define PARALLEL_MODE_CONFIG_MODE_3 (0x02 << 2)
|
||||
#define PARALLEL_MODE_CONFIG_MODE_4 (0x03 << 2)
|
||||
#define DIAGNOSITC_PULSE_STRETCH_MODE_1 (0x00 << 5)
|
||||
#define DIAGNOSITC_PULSE_STRETCH_MODE_2 (0x01 << 5)
|
||||
#define DIAGNOSITC_PULSE_STRETCH_MODE_3 (0x02 << 5)
|
||||
#define DIAGNOSITC_PULSE_STRETCH_MODE_4 (0x03 << 5)
|
||||
#define DIAGNOSITC_PULSE_STRETCH_MODE_5 (0x04 << 5)
|
||||
#define DIAGNOSITC_PULSE_STRETCH_DEFAULT (0x05 << 5)
|
||||
|
||||
#define TDA7803_REG7 (0x07)
|
||||
#define AMPLIEFIR_SWITCH_OFF (0x00 << 0)
|
||||
#define AMPLIEFIR_SWITCH_ON (0x01 << 0)
|
||||
#define CLIPP_LEVEL_1_REAR_CHANNELS2_4 (0x00 << 1)
|
||||
#define CLIPP_LEVEL_2_REAR_CHANNELS2_4 (0x01 << 1)
|
||||
#define CLIPP_LEVEL_3_REAR_CHANNELS2_4 (0x02 << 1)
|
||||
#define NOT_CLIPP_FOR_REAR_CHANNELS2_4 (0x03 << 1)
|
||||
#define CLIPP_LEVEL_1_REAR_CHANNELS1_3 (0x00 << 3)
|
||||
#define CLIPP_LEVEL_2_REAR_CHANNELS1_3 (0x01 << 3)
|
||||
#define CLIPP_LEVEL_3_REAR_CHANNELS1_3 (0x02 << 3)
|
||||
#define NOT_CLIPP_FOR_REAR_CHANNELS1_3 (0x03 << 3)
|
||||
#define TEMPERATURE_WARNING_TW1 (0x00 << 5)
|
||||
#define TEMPERATURE_WARNING_TW2 (0x01 << 5)
|
||||
#define TEMPERATURE_WARNING_TW3 (0x02 << 5)
|
||||
#define TEMPERATURE_WARNING_TW4 (0x03 << 5)
|
||||
#define NOT_TEMPERATURE_WARNING (0x04 << 5)
|
||||
|
||||
#define TDA7803_REGMAX (0x08)
|
||||
#endif /* __TDA7803_H__ */
|
||||
Reference in New Issue
Block a user