mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
Merge tag 'android-12.1-mid-rkr12'
Android 12.1 Mid release rkr12;aosp:refs/tags/android-12.1.0_r11 * tag 'android-12.1-mid-rkr12': (48 commits) mmc: sdhci-of-dwcmshc: improve HS400ES compatibility for some eMMC devices video: rockchip: mpp: Fix mmu sharing on multi device ASoC: codecs: Add driver support for rk730 soc: rockchip: power-domain: Add new keepon_startup module parameter video: rockchip: rga3: remove useless functions in rga_job.c PCI: rockchip: dw: Support applications that do not perform phy operations dma-buf: heaps: sram_heap: init sram-heap depend on sram driver UPSTREAM: drm: log errors in drm_gem_fb_init_with_funcs arm64: dts: rockchip: rk3588-nvr: add dp sound support media: rockchip: ispp: fec add compat_ioctl32 media: rockchip: isp: fix stream switch when readback mode media: rockchip: isp: frame start to update buf for isp30 media: rockchip: isp: fix fbc output for isp30 multi sensor Revert "drm/bridge: analogix_dp: Fix sync polarity configuration in msa packet" ASoC: rockchip: i2s-tdm: Add support for platform shutdown ARM: dts: rockchip: add rv1106g-evb-v11-spi-nand-cvr.dts media: i2c: update hi556 sensor driver ARM: dts: rockchip: add rv1103g-evb-v11.dts ARM: dts: rockchip: rv1106-evb: Add adc-key ARM: rv1106-evb.config: enable CONFIG_KEYBOARD_ADC ... Change-Id: I081d6b895e0bf7ccce1dec335956f152bbc2bbd9
This commit is contained in:
@@ -975,6 +975,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
|
||||
rv1103g-battery-ipc-v10.dtb \
|
||||
rv1103g-battery-ipc-v11.dtb \
|
||||
rv1103g-evb-v10.dtb \
|
||||
rv1103g-evb-v11.dtb \
|
||||
rv1103g-rmsl311-dloc-sl-v10.dtb \
|
||||
rv1103g-scaner-v10.dtb \
|
||||
rv1106g-38x38-ipc-v10.dtb \
|
||||
@@ -983,6 +984,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
|
||||
rv1106g-evb1-rgb-display-v11.dtb \
|
||||
rv1106g-evb1-v10.dtb \
|
||||
rv1106g-evb1-v11.dtb \
|
||||
rv1106g-evb1-v11-cvr.dtb \
|
||||
rv1106g-evb1-v11-spi-nand-cvr.dtb \
|
||||
rv1106g-evb1-v11-sii902x-bt11202hdmi.dtb \
|
||||
rv1106g-evb1-v11-sii902x-rgb2hdmi.dtb \
|
||||
rv1106g-evb1-v10-dual-cam.dtb \
|
||||
|
||||
@@ -670,12 +670,12 @@
|
||||
compatible = "rockchip,rk3128-mipi-dsi";
|
||||
reg = <0x10110000 0x4000>;
|
||||
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru PCLK_MIPI>, <&cru HCLK_VIO_H2P>, <&video_phy>;
|
||||
clock-names = "pclk", "h2p", "hs_clk";
|
||||
clocks = <&cru PCLK_MIPI>, <&cru HCLK_VIO_H2P>;
|
||||
clock-names = "pclk", "hclk";
|
||||
resets = <&cru SRST_VIO_MIPI_DSI>;
|
||||
reset-names = "apb";
|
||||
phys = <&video_phy>;
|
||||
phy-names = "mipi_dphy";
|
||||
phy-names = "dphy";
|
||||
power-domains = <&power RK3128_PD_VIO>;
|
||||
rockchip,grf = <&grf>;
|
||||
#address-cells = <1>;
|
||||
@@ -996,14 +996,15 @@
|
||||
};
|
||||
|
||||
video_phy: video-phy@20038000 {
|
||||
compatible = "rockchip,rk3128-video-phy";
|
||||
compatible = "rockchip,rk3128-dsi-dphy", "rockchip,rk3128-video-phy";
|
||||
reg = <0x20038000 0x4000>, <0x10110000 0x4000>;
|
||||
reg-names = "phy", "host";
|
||||
clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPIPHY>,
|
||||
<&cru PCLK_MIPI>;
|
||||
clock-names = "ref", "pclk_phy", "pclk_host";
|
||||
clock-names = "ref", "pclk", "pclk_host";
|
||||
#clock-cells = <0>;
|
||||
resets = <&cru SRST_MIPIPHY_P>;
|
||||
reset-names = "rst";
|
||||
reset-names = "apb";
|
||||
power-domains = <&power RK3128_PD_VIO>;
|
||||
#phy-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
83
arch/arm/boot/dts/rv1103g-evb-v11.dts
Normal file
83
arch/arm/boot/dts/rv1103g-evb-v11.dts
Normal file
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "rv1103.dtsi"
|
||||
#include "rv1103-evb-v10.dtsi"
|
||||
#include "rv1103-evb-cam.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RV1103G EVB V11 Board";
|
||||
compatible = "rockchip,rv1103g-evb-v11", "rockchip,rv1103";
|
||||
|
||||
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 = <&gpio1 RK_PC6 GPIO_ACTIVE_LOW>;
|
||||
regulator-name = "vcc3v3_sd";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
enable-active-low;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc_pwren>;
|
||||
};
|
||||
|
||||
vcc3v3_wifi: vcc3v3-wifi {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc3v3_wifi";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
enable-active-low;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
gpio = <&gpio1 RK_PC7 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wifi_pwren>;
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
sdmmc {
|
||||
/omit-if-no-ref/
|
||||
sdmmc_pwren: sdmmc-pwren {
|
||||
rockchip,pins = <1 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
||||
wifi {
|
||||
wifi_pwren: wifi-pwren {
|
||||
rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&saradc {
|
||||
status = "okay";
|
||||
vref-supply = <&vcc_1v8>;
|
||||
};
|
||||
|
||||
&usbdrd_dwc3 {
|
||||
dr_mode = "host";
|
||||
};
|
||||
@@ -3,9 +3,28 @@
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
#include "rv1106-amp.dtsi"
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
adc-keys {
|
||||
compatible = "adc-keys";
|
||||
io-channels = <&saradc 0>;
|
||||
io-channel-names = "buttons";
|
||||
poll-interval = <100>;
|
||||
keyup-threshold-microvolt = <1800000>;
|
||||
|
||||
key_volumeup-key {
|
||||
label = "key_volumeup";
|
||||
linux,code = <KEY_VOLUMEUP>;
|
||||
press-threshold-microvolt = <0>;
|
||||
};
|
||||
|
||||
key_volumedown-key {
|
||||
label = "key_volumedown";
|
||||
linux,code = <KEY_VOLUMEDOWN>;
|
||||
press-threshold-microvolt = <400781>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&fiq_debugger {
|
||||
|
||||
19
arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts
Normal file
19
arch/arm/boot/dts/rv1106g-evb1-v11-cvr.dts
Normal file
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "rv1106g-evb1-v11.dts"
|
||||
#include "rv1106-evb-ext-rgb-v10.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RV1106G EVB1 V11 Board For CVR";
|
||||
compatible = "rockchip,rv1106g-evb1-v11-cvr", "rockchip,rv1106";
|
||||
};
|
||||
|
||||
&saradc {
|
||||
status = "okay";
|
||||
vref-supply = <&vcc_1v8>;
|
||||
};
|
||||
19
arch/arm/boot/dts/rv1106g-evb1-v11-spi-nand-cvr.dts
Normal file
19
arch/arm/boot/dts/rv1106g-evb1-v11-spi-nand-cvr.dts
Normal file
@@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "rv1106g-evb1-v10-spi-nand.dts"
|
||||
#include "rv1106-evb-ext-rgb-v10.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Rockchip RV1106G EVB1 V11 Board For CVR";
|
||||
compatible = "rockchip,rv1106g-evb1-v11-spi-nand-cvr", "rockchip,rv1106";
|
||||
};
|
||||
|
||||
&saradc {
|
||||
status = "okay";
|
||||
vref-supply = <&vcc_1v8>;
|
||||
};
|
||||
@@ -254,8 +254,6 @@ CONFIG_PINCTRL_RK805=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_GPIO_GENERIC_PLATFORM=y
|
||||
CONFIG_GPIO_TPS65910=y
|
||||
CONFIG_POWER_AVS=y
|
||||
CONFIG_ROCKCHIP_IODOMAIN=y
|
||||
CONFIG_POWER_RESET=y
|
||||
CONFIG_POWER_RESET_GPIO_RESTART=y
|
||||
CONFIG_SYSCON_REBOOT_MODE=y
|
||||
@@ -438,15 +436,22 @@ CONFIG_ROCKCHIP_IOMMU=y
|
||||
CONFIG_CPU_RK312X=y
|
||||
CONFIG_CPU_RK3288=y
|
||||
CONFIG_CPU_RK322X=y
|
||||
CONFIG_ROCKCHIP_CPUINFO=y
|
||||
CONFIG_ROCKCHIP_GRF=y
|
||||
CONFIG_ROCKCHIP_IODOMAIN=y
|
||||
CONFIG_ROCKCHIP_IPA=y
|
||||
CONFIG_ROCKCHIP_OPP=y
|
||||
CONFIG_ROCKCHIP_PM_DOMAINS=y
|
||||
CONFIG_ROCKCHIP_PVTM=y
|
||||
CONFIG_ROCKCHIP_SUSPEND_MODE=y
|
||||
CONFIG_ROCKCHIP_SYSTEM_MONITOR=y
|
||||
CONFIG_ROCKCHIP_VENDOR_STORAGE_UPDATE_LOADER=y
|
||||
CONFIG_PM_DEVFREQ=y
|
||||
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_DEVFREQ_GOV_POWERSAVE=y
|
||||
CONFIG_DEVFREQ_GOV_USERSPACE=y
|
||||
CONFIG_ARM_ROCKCHIP_DMC_DEVFREQ=y
|
||||
CONFIG_EXTCON=y
|
||||
CONFIG_MEMORY=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_IIO_BUFFER=y
|
||||
@@ -462,8 +467,7 @@ CONFIG_PWM_ROCKCHIP=y
|
||||
CONFIG_PHY_ROCKCHIP_DP=y
|
||||
CONFIG_PHY_ROCKCHIP_INNO_HDMI=y
|
||||
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
|
||||
CONFIG_PHY_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y
|
||||
CONFIG_PHY_ROCKCHIP_INNO_VIDEO_PHY=y
|
||||
CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y
|
||||
CONFIG_PHY_ROCKCHIP_USB=y
|
||||
CONFIG_ANDROID=y
|
||||
CONFIG_ROCKCHIP_EFUSE=y
|
||||
|
||||
@@ -12,6 +12,7 @@ CONFIG_FB=y
|
||||
CONFIG_FILE_LOCKING=y
|
||||
CONFIG_I2C_GPIO=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_INPUT=y
|
||||
CONFIG_IPV6=m
|
||||
CONFIG_JFFS2_FS=y
|
||||
CONFIG_KCMP=y
|
||||
@@ -374,6 +375,7 @@ CONFIG_DRM_SII902X=y
|
||||
# CONFIG_EXT4_FS_SECURITY is not set
|
||||
CONFIG_EXT4_USE_FOR_EXT2=y
|
||||
# CONFIG_EXTCON_ADC_JACK is not set
|
||||
# CONFIG_EXTCON_FSA9480 is not set
|
||||
# CONFIG_EXTCON_GPIO is not set
|
||||
# CONFIG_EXTCON_MAX3355 is not set
|
||||
# CONFIG_EXTCON_PTN5150 is not set
|
||||
@@ -425,12 +427,15 @@ CONFIG_FS_POSIX_ACL=y
|
||||
CONFIG_GRACE_PERIOD=y
|
||||
CONFIG_HDMI=y
|
||||
# CONFIG_HI8435 is not set
|
||||
# CONFIG_HID is not set
|
||||
# CONFIG_HID_PID is not set
|
||||
# CONFIG_HISI_HIKEY_USB is not set
|
||||
CONFIG_I2C_ALGOBIT=y
|
||||
# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
|
||||
# CONFIG_I2C_DEMUX_PINCTRL is not set
|
||||
# CONFIG_I2C_DIOLAN_U2C is not set
|
||||
# CONFIG_I2C_GPIO_FAULT_INJECTOR is not set
|
||||
# CONFIG_I2C_HID is not set
|
||||
# CONFIG_I2C_MUX_GPIO is not set
|
||||
# CONFIG_I2C_MUX_GPMUX is not set
|
||||
# CONFIG_I2C_MUX_LTC4306 is not set
|
||||
@@ -446,6 +451,20 @@ CONFIG_I2C_ALGOBIT=y
|
||||
# CONFIG_INET6_ESP is not set
|
||||
# CONFIG_INET6_IPCOMP is not set
|
||||
# CONFIG_INFINEON_DHD is not set
|
||||
# CONFIG_INPUT_EVBUG is not set
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_INPUT_FF_MEMLESS is not set
|
||||
# CONFIG_INPUT_JOYDEV is not set
|
||||
# CONFIG_INPUT_JOYSTICK is not set
|
||||
CONFIG_INPUT_KEYBOARD=y
|
||||
# CONFIG_INPUT_MATRIXKMAP is not set
|
||||
# CONFIG_INPUT_MISC is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
# CONFIG_INPUT_MOUSEDEV is not set
|
||||
# CONFIG_INPUT_POLLDEV is not set
|
||||
# CONFIG_INPUT_SPARSEKMAP is not set
|
||||
# CONFIG_INPUT_TABLET is not set
|
||||
# CONFIG_INPUT_TOUCHSCREEN is not set
|
||||
# CONFIG_INV_ICM42600_SPI is not set
|
||||
# CONFIG_INV_MPU6050_SPI is not set
|
||||
# CONFIG_IPV6_MIP6 is not set
|
||||
@@ -475,6 +494,33 @@ CONFIG_JFFS2_FS_WRITEBUFFER=y
|
||||
# CONFIG_JFFS2_RUBIN is not set
|
||||
# CONFIG_JFFS2_SUMMARY is not set
|
||||
CONFIG_JFFS2_ZLIB=y
|
||||
CONFIG_KEYBOARD_ADC=y
|
||||
# CONFIG_KEYBOARD_ADP5588 is not set
|
||||
# CONFIG_KEYBOARD_ADP5589 is not set
|
||||
# CONFIG_KEYBOARD_ATKBD is not set
|
||||
# CONFIG_KEYBOARD_BCM is not set
|
||||
# CONFIG_KEYBOARD_CAP11XX is not set
|
||||
# CONFIG_KEYBOARD_DLINK_DIR685 is not set
|
||||
# CONFIG_KEYBOARD_GPIO is not set
|
||||
# CONFIG_KEYBOARD_GPIO_POLLED is not set
|
||||
# CONFIG_KEYBOARD_LKKBD is not set
|
||||
# CONFIG_KEYBOARD_LM8333 is not set
|
||||
# CONFIG_KEYBOARD_MATRIX is not set
|
||||
# CONFIG_KEYBOARD_MAX7359 is not set
|
||||
# CONFIG_KEYBOARD_MCS is not set
|
||||
# CONFIG_KEYBOARD_MPR121 is not set
|
||||
# CONFIG_KEYBOARD_NEWTON is not set
|
||||
# CONFIG_KEYBOARD_OMAP4 is not set
|
||||
# CONFIG_KEYBOARD_OPENCORES is not set
|
||||
# CONFIG_KEYBOARD_QT1050 is not set
|
||||
# CONFIG_KEYBOARD_QT1070 is not set
|
||||
# CONFIG_KEYBOARD_QT2160 is not set
|
||||
# CONFIG_KEYBOARD_SAMSUNG is not set
|
||||
# CONFIG_KEYBOARD_STOWAWAY is not set
|
||||
# CONFIG_KEYBOARD_SUNKBD is not set
|
||||
# CONFIG_KEYBOARD_TCA6416 is not set
|
||||
# CONFIG_KEYBOARD_TCA8418 is not set
|
||||
# CONFIG_KEYBOARD_XTKBD is not set
|
||||
# CONFIG_KEYS_REQUEST_CACHE is not set
|
||||
# CONFIG_KEY_DH_OPERATIONS is not set
|
||||
# CONFIG_KS7010 is not set
|
||||
@@ -603,9 +649,11 @@ CONFIG_PKCS7_MESSAGE_PARSER=y
|
||||
CONFIG_PWRSEQ_SIMPLE=y
|
||||
# CONFIG_R8188EU is not set
|
||||
# CONFIG_R8712U is not set
|
||||
# CONFIG_RC_CORE is not set
|
||||
CONFIG_REGMAP_SPI=y
|
||||
# CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY is not set
|
||||
# CONFIG_REGULATOR_TPS6524X is not set
|
||||
# CONFIG_RMI4_CORE is not set
|
||||
# CONFIG_ROCKCHIP_ANALOGIX_DP is not set
|
||||
# CONFIG_ROCKCHIP_CDN_DP is not set
|
||||
# CONFIG_ROCKCHIP_DRM_CUBIC_LUT is not set
|
||||
@@ -619,6 +667,7 @@ CONFIG_REGMAP_SPI=y
|
||||
# CONFIG_ROCKCHIP_LVDS is not set
|
||||
# CONFIG_ROCKCHIP_MMC_VENDOR_STORAGE is not set
|
||||
CONFIG_ROCKCHIP_MTD_VENDOR_STORAGE=y
|
||||
# CONFIG_ROCKCHIP_REMOTECTL is not set
|
||||
CONFIG_ROCKCHIP_RGA_DEBUGGER=y
|
||||
# CONFIG_ROCKCHIP_RGA_DEBUG_FS is not set
|
||||
CONFIG_ROCKCHIP_RGB=y
|
||||
@@ -651,16 +700,22 @@ CONFIG_ROCKCHIP_VOP=y
|
||||
# CONFIG_SDIO_UART is not set
|
||||
# CONFIG_SECONDARY_TRUSTED_KEYRING is not set
|
||||
# CONFIG_SENSORS_HMC5843_SPI is not set
|
||||
# CONFIG_SENSORS_LIS3_I2C is not set
|
||||
# CONFIG_SENSORS_LIS3_SPI is not set
|
||||
# CONFIG_SENSORS_RM3100_SPI is not set
|
||||
# CONFIG_SENSOR_DEVICE is not set
|
||||
# CONFIG_SERIAL_IFX6X60 is not set
|
||||
# CONFIG_SERIAL_MAX3100 is not set
|
||||
# CONFIG_SERIAL_MAX310X is not set
|
||||
CONFIG_SGL_ALLOC=y
|
||||
# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set
|
||||
# CONFIG_SND_BCD2000 is not set
|
||||
CONFIG_SND_JACK_INPUT_DEV=y
|
||||
# CONFIG_SND_SOC_ADAU1761_SPI is not set
|
||||
# CONFIG_SND_SOC_AK4104 is not set
|
||||
# CONFIG_SND_SOC_CS4271_SPI is not set
|
||||
# CONFIG_SND_SOC_CS42L52 is not set
|
||||
# CONFIG_SND_SOC_CS42L56 is not set
|
||||
# CONFIG_SND_SOC_ES8328_SPI is not set
|
||||
# CONFIG_SND_SOC_PCM179X_SPI is not set
|
||||
# CONFIG_SND_SOC_PCM186X_SPI is not set
|
||||
@@ -673,6 +728,7 @@ CONFIG_SGL_ALLOC=y
|
||||
# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set
|
||||
# CONFIG_SND_SOC_WM8770 is not set
|
||||
# CONFIG_SND_SOC_WM8804_SPI is not set
|
||||
# CONFIG_SND_SOC_WM8962 is not set
|
||||
# CONFIG_SND_SOC_ZL38060 is not set
|
||||
# CONFIG_SND_SPI is not set
|
||||
CONFIG_SND_USB=y
|
||||
@@ -842,6 +898,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=2
|
||||
# CONFIG_USB_G_SERIAL is not set
|
||||
# CONFIG_USB_G_WEBCAM is not set
|
||||
# CONFIG_USB_HCD_TEST_MODE is not set
|
||||
# CONFIG_USB_HID is not set
|
||||
# CONFIG_USB_HSIC_USB3503 is not set
|
||||
# CONFIG_USB_HSIC_USB4604 is not set
|
||||
# CONFIG_USB_HUB_USB251XB is not set
|
||||
@@ -851,6 +908,7 @@ CONFIG_USB_GADGET_VBUS_DRAW=2
|
||||
# CONFIG_USB_ISP116X_HCD is not set
|
||||
# CONFIG_USB_ISP1301 is not set
|
||||
# CONFIG_USB_ISP1760 is not set
|
||||
# CONFIG_USB_KBD is not set
|
||||
# CONFIG_USB_LCD is not set
|
||||
# CONFIG_USB_LD is not set
|
||||
# CONFIG_USB_LEGOTOWER is not set
|
||||
@@ -863,6 +921,7 @@ CONFIG_USB_LIBCOMPOSITE=y
|
||||
# CONFIG_USB_MDC800 is not set
|
||||
# CONFIG_USB_MIDI_GADGET is not set
|
||||
# CONFIG_USB_MON is not set
|
||||
# CONFIG_USB_MOUSE is not set
|
||||
# CONFIG_USB_MUSB_HDRC is not set
|
||||
# CONFIG_USB_MV_U3D is not set
|
||||
# CONFIG_USB_MV_UDC is not set
|
||||
|
||||
@@ -181,6 +181,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dp1_sound {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gmac0 {
|
||||
/* Use rgmii-rxid mode to disable rx delay inside Soc */
|
||||
phy-mode = "rgmii-rxid";
|
||||
@@ -678,6 +682,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spdif_tx5 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
dp {
|
||||
dp1_hdmi_ctl: dp-hdmi-ctl {
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dp0_sound {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dp1 {
|
||||
pinctrl-0 = <&dp1m2_pins &dp1_hdmi_reset>;
|
||||
pinctrl-names = "default";
|
||||
@@ -193,6 +197,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&spdif_tx2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
dp {
|
||||
dp1_hdmi_reset: dp-hdmi-reset {
|
||||
|
||||
@@ -28,6 +28,26 @@
|
||||
};
|
||||
};
|
||||
|
||||
dp0_sound: dp0-sound {
|
||||
status = "disabled";
|
||||
compatible = "rockchip,hdmi";
|
||||
rockchip,card-name= "rockchip,dp0";
|
||||
rockchip,mclk-fs = <512>;
|
||||
rockchip,cpu = <&spdif_tx2>;
|
||||
rockchip,codec = <&dp0 1>;
|
||||
rockchip,jack-det;
|
||||
};
|
||||
|
||||
dp1_sound: dp1-sound {
|
||||
status = "disabled";
|
||||
compatible = "rockchip,hdmi";
|
||||
rockchip,card-name= "rockchip,dp1";
|
||||
rockchip,mclk-fs = <512>;
|
||||
rockchip,cpu = <&spdif_tx5>;
|
||||
rockchip,codec = <&dp1 1>;
|
||||
rockchip,jack-det;
|
||||
};
|
||||
|
||||
hdmi0_sound: hdmi0-sound {
|
||||
status = "disabled";
|
||||
compatible = "simple-audio-card";
|
||||
|
||||
@@ -534,7 +534,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
||||
GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
|
||||
GATE(0, "pclk_ddrupctl", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 7, GFLAGS),
|
||||
GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
|
||||
GATE(0, "pclk_mipiphy", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 0, GFLAGS),
|
||||
GATE(PCLK_MIPIPHY, "pclk_mipiphy", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS),
|
||||
|
||||
GATE(0, "pclk_pmu", "pclk_pmu_pre", CLK_IS_CRITICAL, RK2928_CLKGATE_CON(9), 2, GFLAGS),
|
||||
GATE(0, "pclk_pmu_niu", "pclk_pmu_pre", CLK_IS_CRITICAL, RK2928_CLKGATE_CON(9), 3, GFLAGS),
|
||||
|
||||
@@ -958,7 +958,7 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
|
||||
COMPOSITE_NODIV(HCLK_USB, "hclk_usb", gpll150_gpll100_gpll75_xin24m_p, CLK_IS_CRITICAL,
|
||||
RK3568_CLKSEL_CON(32), 2, 2, MFLAGS,
|
||||
RK3568_CLKGATE_CON(16), 1, GFLAGS),
|
||||
COMPOSITE_NOMUX(PCLK_USB, "pclk_usb", "aclk_usb", 0,
|
||||
COMPOSITE_NOMUX(PCLK_USB, "pclk_usb", "aclk_usb", CLK_IS_CRITICAL,
|
||||
RK3568_CLKSEL_CON(32), 4, 4, DFLAGS,
|
||||
RK3568_CLKGATE_CON(16), 2, GFLAGS),
|
||||
GATE(HCLK_USB2HOST0, "hclk_usb2host0", "hclk_usb", 0,
|
||||
|
||||
@@ -1890,7 +1890,7 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
|
||||
COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0,
|
||||
RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3588_CLKGATE_CON(52), 0, GFLAGS),
|
||||
FACTOR(0, "aclk_vop_div2_src", "aclk_vop_root", 0, 1, 2),
|
||||
FACTOR(ACLK_VOP_DIV2_SRC, "aclk_vop_div2_src", "aclk_vop_root", 0, 1, 2),
|
||||
COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0,
|
||||
RK3588_CLKSEL_CON(110), 8, 2, MFLAGS,
|
||||
RK3588_CLKGATE_CON(52), 1, GFLAGS),
|
||||
@@ -1906,8 +1906,9 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
|
||||
COMPOSITE_NODIV(HCLK_VO1USB_TOP_ROOT, "hclk_vo1usb_top_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
|
||||
RK3588_CLKSEL_CON(170), 6, 2, MFLAGS,
|
||||
RK3588_CLKGATE_CON(74), 2, GFLAGS),
|
||||
MUX(ACLK_VOP_SUB_SRC, "aclk_vop_sub_src", aclk_vop_sub_src_p, 0,
|
||||
RK3588_CLKSEL_CON(115), 9, 1, MFLAGS),
|
||||
COMPOSITE_NODIV(ACLK_VOP, "aclk_vop", aclk_vop_sub_src_p, CLK_SET_RATE_PARENT,
|
||||
RK3588_CLKSEL_CON(115), 9, 1, MFLAGS,
|
||||
RK3588_CLKGATE_CON(52), 9, GFLAGS),
|
||||
GATE(PCLK_EDP0, "pclk_edp0", "pclk_vo1_root", 0,
|
||||
RK3588_CLKGATE_CON(62), 0, GFLAGS),
|
||||
GATE(CLK_EDP0_24M, "clk_edp0_24m", "xin24m", 0,
|
||||
@@ -2064,8 +2065,6 @@ static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
|
||||
RK3588_CLKGATE_CON(72), 4, GFLAGS),
|
||||
GATE(HCLK_VOP, "hclk_vop", "hclk_vop_root", 0,
|
||||
RK3588_CLKGATE_CON(52), 8, GFLAGS),
|
||||
GATE(ACLK_VOP, "aclk_vop", "aclk_vop_sub_src", 0,
|
||||
RK3588_CLKGATE_CON(52), 9, GFLAGS),
|
||||
COMPOSITE(DCLK_VOP0_SRC, "dclk_vop0_src", gpll_cpll_v0pll_aupll_p, 0,
|
||||
RK3588_CLKSEL_CON(111), 7, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK3588_CLKGATE_CON(52), 10, GFLAGS),
|
||||
|
||||
@@ -22,3 +22,10 @@ config DMABUF_HEAPS_CMA
|
||||
Choose this option to enable dma-buf CMA heap. This heap is backed
|
||||
by the Contiguous Memory Allocator (CMA). If your system has these
|
||||
regions, you should say Y here.
|
||||
|
||||
config DMABUF_HEAPS_SRAM
|
||||
tristate "Export on-chip SRAM pools using DMA-Heaps"
|
||||
depends on DMABUF_HEAPS && SRAM
|
||||
help
|
||||
This driver allows the export of on-chip SRAM marked as exportable
|
||||
to userspace using the DMA-Heaps interface.
|
||||
|
||||
@@ -3,3 +3,4 @@ obj-$(CONFIG_DMABUF_HEAPS_DEFERRED_FREE) += deferred-free-helper.o
|
||||
obj-$(CONFIG_DMABUF_HEAPS_PAGE_POOL) += page_pool.o
|
||||
obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += rk_system_heap.o
|
||||
obj-$(CONFIG_DMABUF_HEAPS_CMA) += rk_cma_heap.o
|
||||
obj-$(CONFIG_DMABUF_HEAPS_SRAM) += sram_heap.o
|
||||
|
||||
437
drivers/dma-buf/heaps/sram_heap.c
Normal file
437
drivers/dma-buf/heaps/sram_heap.c
Normal file
@@ -0,0 +1,437 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* SRAM DMA-Heap exporter && support alloc page and dmabuf on kernel
|
||||
*
|
||||
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
|
||||
*
|
||||
* Author: Andrew F. Davis <afd@ti.com>
|
||||
*
|
||||
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* Author: Huang Lee <Putin.li@rock-chips.com>
|
||||
*/
|
||||
#define pr_fmt(fmt) "sram_heap: " fmt
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-heap.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/sram_heap.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define RK3588_SRAM_BASE 0xff001000
|
||||
|
||||
struct sram_dma_heap {
|
||||
struct dma_heap *heap;
|
||||
struct gen_pool *pool;
|
||||
};
|
||||
|
||||
struct sram_dma_heap_buffer {
|
||||
struct gen_pool *pool;
|
||||
struct list_head attachments;
|
||||
struct mutex attachments_lock;
|
||||
unsigned long len;
|
||||
void *vaddr;
|
||||
phys_addr_t paddr;
|
||||
};
|
||||
|
||||
struct dma_heap_attachment {
|
||||
struct device *dev;
|
||||
struct sg_table *table;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static int dma_heap_attach(struct dma_buf *dmabuf,
|
||||
struct dma_buf_attachment *attachment)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
struct dma_heap_attachment *a;
|
||||
struct sg_table *table;
|
||||
|
||||
a = kzalloc(sizeof(*a), GFP_KERNEL);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
table = kmalloc(sizeof(*table), GFP_KERNEL);
|
||||
if (!table)
|
||||
goto table_alloc_failed;
|
||||
|
||||
if (sg_alloc_table(table, 1, GFP_KERNEL))
|
||||
goto sg_alloc_failed;
|
||||
|
||||
/*
|
||||
* The referenced pfn and page are for setting the sram address to the
|
||||
* sgtable, and cannot be used for other purposes, and cannot be accessed
|
||||
* directly or indirectly.
|
||||
*
|
||||
* And not sure if there is a problem with the 32-bit system.
|
||||
*
|
||||
* page cannot support kmap func.
|
||||
*/
|
||||
sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);
|
||||
|
||||
a->table = table;
|
||||
a->dev = attachment->dev;
|
||||
INIT_LIST_HEAD(&a->list);
|
||||
|
||||
attachment->priv = a;
|
||||
|
||||
mutex_lock(&buffer->attachments_lock);
|
||||
list_add(&a->list, &buffer->attachments);
|
||||
mutex_unlock(&buffer->attachments_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
sg_alloc_failed:
|
||||
kfree(table);
|
||||
table_alloc_failed:
|
||||
kfree(a);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void dma_heap_detatch(struct dma_buf *dmabuf,
|
||||
struct dma_buf_attachment *attachment)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
struct dma_heap_attachment *a = attachment->priv;
|
||||
|
||||
mutex_lock(&buffer->attachments_lock);
|
||||
list_del(&a->list);
|
||||
mutex_unlock(&buffer->attachments_lock);
|
||||
|
||||
sg_free_table(a->table);
|
||||
kfree(a->table);
|
||||
kfree(a);
|
||||
}
|
||||
|
||||
static struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
struct dma_heap_attachment *a = attachment->priv;
|
||||
struct sg_table *table = a->table;
|
||||
int ret = 0;
|
||||
|
||||
ret = dma_map_sgtable(attachment->dev, table, direction, DMA_ATTR_SKIP_CPU_SYNC);
|
||||
if (ret)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
|
||||
struct sg_table *table,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
dma_unmap_sgtable(attachment->dev, table, direction, DMA_ATTR_SKIP_CPU_SYNC);
|
||||
}
|
||||
|
||||
static void dma_heap_dma_buf_release(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
|
||||
gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
|
||||
kfree(buffer);
|
||||
}
|
||||
|
||||
static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
int ret;
|
||||
|
||||
/* SRAM mappings are not cached */
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
|
||||
ret = vm_iomap_memory(vma, buffer->paddr, buffer->len);
|
||||
if (ret)
|
||||
pr_err("Could not map buffer to userspace\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *dma_heap_vmap(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
|
||||
return buffer->vaddr;
|
||||
}
|
||||
|
||||
static const struct dma_buf_ops sram_dma_heap_buf_ops = {
|
||||
.attach = dma_heap_attach,
|
||||
.detach = dma_heap_detatch,
|
||||
.map_dma_buf = dma_heap_map_dma_buf,
|
||||
.unmap_dma_buf = dma_heap_unmap_dma_buf,
|
||||
.release = dma_heap_dma_buf_release,
|
||||
.mmap = dma_heap_mmap,
|
||||
.vmap = dma_heap_vmap,
|
||||
};
|
||||
|
||||
static struct dma_buf *sram_dma_heap_allocate(struct dma_heap *heap,
|
||||
unsigned long len,
|
||||
unsigned long fd_flags,
|
||||
unsigned long heap_flags)
|
||||
{
|
||||
struct sram_dma_heap *sram_dma_heap = dma_heap_get_drvdata(heap);
|
||||
struct sram_dma_heap_buffer *buffer;
|
||||
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct dma_buf *dmabuf;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
buffer->pool = sram_dma_heap->pool;
|
||||
INIT_LIST_HEAD(&buffer->attachments);
|
||||
mutex_init(&buffer->attachments_lock);
|
||||
buffer->len = len;
|
||||
|
||||
buffer->vaddr = (void *)gen_pool_alloc(buffer->pool, buffer->len);
|
||||
if (!buffer->vaddr) {
|
||||
ret = -ENOMEM;
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
buffer->paddr = gen_pool_virt_to_phys(buffer->pool, (unsigned long)buffer->vaddr);
|
||||
if (buffer->paddr == -1) {
|
||||
ret = -ENOMEM;
|
||||
goto free_pool;
|
||||
}
|
||||
|
||||
/* create the dmabuf */
|
||||
exp_info.ops = &sram_dma_heap_buf_ops;
|
||||
exp_info.size = buffer->len;
|
||||
exp_info.flags = fd_flags;
|
||||
exp_info.priv = buffer;
|
||||
dmabuf = dma_buf_export(&exp_info);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
ret = PTR_ERR(dmabuf);
|
||||
goto free_pool;
|
||||
}
|
||||
|
||||
return dmabuf;
|
||||
|
||||
free_pool:
|
||||
gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
|
||||
free_buffer:
|
||||
kfree(buffer);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static struct dma_heap_ops sram_dma_heap_ops = {
|
||||
.allocate = sram_dma_heap_allocate,
|
||||
};
|
||||
|
||||
static struct sram_dma_heap *sram_dma_heap_global;
|
||||
|
||||
static int sram_dma_heap_export(const char *name,
|
||||
struct gen_pool *sram_gp)
|
||||
{
|
||||
struct sram_dma_heap *sram_dma_heap;
|
||||
struct dma_heap_export_info exp_info;
|
||||
|
||||
pr_info("Exporting SRAM pool '%s'\n", name);
|
||||
|
||||
sram_dma_heap = kzalloc(sizeof(*sram_dma_heap), GFP_KERNEL);
|
||||
if (!sram_dma_heap)
|
||||
return -ENOMEM;
|
||||
sram_dma_heap->pool = sram_gp;
|
||||
|
||||
exp_info.name = "sram_dma_heap";
|
||||
exp_info.ops = &sram_dma_heap_ops;
|
||||
exp_info.priv = sram_dma_heap;
|
||||
|
||||
sram_dma_heap_global = sram_dma_heap;
|
||||
|
||||
sram_dma_heap->heap = dma_heap_add(&exp_info);
|
||||
if (IS_ERR(sram_dma_heap->heap)) {
|
||||
int ret = PTR_ERR(sram_dma_heap->heap);
|
||||
|
||||
kfree(sram_dma_heap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dma_buf *sram_heap_alloc_dma_buf(size_t size)
|
||||
{
|
||||
struct sram_dma_heap *sram_dma_heap = sram_dma_heap_global;
|
||||
struct sram_dma_heap_buffer *buffer;
|
||||
|
||||
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
|
||||
struct dma_buf *dmabuf;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
buffer->pool = sram_dma_heap->pool;
|
||||
INIT_LIST_HEAD(&buffer->attachments);
|
||||
mutex_init(&buffer->attachments_lock);
|
||||
buffer->len = size;
|
||||
|
||||
buffer->vaddr = (void *)gen_pool_alloc(buffer->pool, buffer->len);
|
||||
if (!buffer->vaddr) {
|
||||
ret = -ENOMEM;
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
buffer->paddr = gen_pool_virt_to_phys(buffer->pool, (unsigned long)buffer->vaddr);
|
||||
if (buffer->paddr == -1) {
|
||||
ret = -ENOMEM;
|
||||
goto free_pool;
|
||||
}
|
||||
|
||||
/* create the dmabuf */
|
||||
exp_info.ops = &sram_dma_heap_buf_ops;
|
||||
exp_info.size = buffer->len;
|
||||
exp_info.priv = buffer;
|
||||
dmabuf = dma_buf_export(&exp_info);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
ret = PTR_ERR(dmabuf);
|
||||
goto free_pool;
|
||||
}
|
||||
|
||||
return dmabuf;
|
||||
|
||||
free_pool:
|
||||
gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
|
||||
free_buffer:
|
||||
kfree(buffer);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sram_heap_alloc_dma_buf);
|
||||
|
||||
struct page *sram_heap_alloc_pages(size_t size)
|
||||
{
|
||||
struct sram_dma_heap *sram_dma_heap = sram_dma_heap_global;
|
||||
|
||||
void *vaddr;
|
||||
phys_addr_t paddr;
|
||||
struct page *p;
|
||||
|
||||
int ret = -ENOMEM;
|
||||
|
||||
vaddr = (void *)gen_pool_alloc(sram_dma_heap->pool, size);
|
||||
if (!vaddr) {
|
||||
ret = -ENOMEM;
|
||||
pr_err("no memory");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
paddr = gen_pool_virt_to_phys(sram_dma_heap->pool, (unsigned long)vaddr);
|
||||
if (paddr == -1) {
|
||||
ret = -ENOMEM;
|
||||
pr_err("gen_pool_virt_to_phys failed");
|
||||
goto free_pool;
|
||||
}
|
||||
|
||||
p = pfn_to_page(PFN_DOWN(paddr));
|
||||
|
||||
return p;
|
||||
|
||||
free_pool:
|
||||
gen_pool_free(sram_dma_heap->pool, (unsigned long)vaddr, size);
|
||||
failed:
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sram_heap_alloc_pages);
|
||||
|
||||
static u64 gen_pool_phys_to_virt(struct gen_pool *pool, phys_addr_t paddr)
|
||||
{
|
||||
struct gen_pool_chunk *chunk;
|
||||
u64 vaddr = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
|
||||
/* TODO: only suit for simple chunk now */
|
||||
vaddr = chunk->start_addr + (paddr - chunk->phys_addr);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
void sram_heap_free_pages(struct page *p)
|
||||
{
|
||||
struct sram_dma_heap *sram_dma_heap = sram_dma_heap_global;
|
||||
void *vaddr;
|
||||
|
||||
vaddr = (void *)gen_pool_phys_to_virt(sram_dma_heap->pool, page_to_phys(p));
|
||||
|
||||
gen_pool_free(sram_dma_heap->pool, (unsigned long)vaddr, PAGE_SIZE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sram_heap_free_pages);
|
||||
|
||||
void sram_heap_free_dma_buf(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
|
||||
gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
|
||||
kfree(buffer);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sram_heap_free_dma_buf);
|
||||
|
||||
void *sram_heap_get_vaddr(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
|
||||
return buffer->vaddr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sram_heap_get_vaddr);
|
||||
|
||||
phys_addr_t sram_heap_get_paddr(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct sram_dma_heap_buffer *buffer = dmabuf->priv;
|
||||
|
||||
return buffer->paddr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sram_heap_get_paddr);
|
||||
|
||||
static int rk_add_default_sram_heap(void)
|
||||
{
|
||||
struct device_node *np = NULL;
|
||||
struct gen_pool *sram_gp = NULL;
|
||||
int ret = 0;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "rockchip,sram-heap");
|
||||
if (!np) {
|
||||
pr_info("failed to get device node of sram-heap\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(np)) {
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
sram_gp = of_gen_pool_get(np, "rockchip,sram", 0);
|
||||
/* release node */
|
||||
of_node_put(np);
|
||||
if (sram_gp == NULL) {
|
||||
pr_err("sram gen pool is NULL");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = sram_dma_heap_export("sram-heap", sram_gp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(rk_add_default_sram_heap);
|
||||
MODULE_DESCRIPTION("Rockchip DMA-BUF SRAM Heap");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1785,8 +1785,13 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
|
||||
|
||||
/* Input video interlaces & hsync pol & vsync pol */
|
||||
video->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
|
||||
video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
|
||||
video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
|
||||
if (dp->plat_data->dev_type == RK3588_EDP) {
|
||||
video->v_sync_polarity = true;
|
||||
video->h_sync_polarity = true;
|
||||
} else {
|
||||
video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
|
||||
video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
|
||||
}
|
||||
|
||||
/* Input video dynamic_range & colorimetry */
|
||||
vic = drm_match_cea_mode(mode);
|
||||
|
||||
@@ -255,6 +255,8 @@ struct dw_hdmi_qp {
|
||||
bool allm_enable;
|
||||
bool support_hdmi;
|
||||
int force_output;
|
||||
int vp_id;
|
||||
int old_vp_id;
|
||||
|
||||
struct mutex mutex; /* for state below and previous_mode */
|
||||
struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */
|
||||
@@ -2262,13 +2264,23 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
struct drm_connector_state *new_state =
|
||||
drm_atomic_get_new_connector_state(state, connector);
|
||||
struct drm_crtc *crtc = new_state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_crtc *old_crtc = old_state->crtc;
|
||||
struct drm_crtc_state *crtc_state, *old_crtc_state;
|
||||
struct dw_hdmi_qp *hdmi =
|
||||
container_of(connector, struct dw_hdmi_qp, connector);
|
||||
struct drm_display_mode *mode = NULL;
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
struct hdmi_vmode_qp *vmode = &hdmi->hdmi_data.video_mode;
|
||||
|
||||
if (old_crtc) {
|
||||
old_crtc_state = drm_atomic_get_crtc_state(state, old_crtc);
|
||||
if (IS_ERR(old_crtc_state))
|
||||
return PTR_ERR(old_crtc_state);
|
||||
|
||||
if (hdmi->plat_data->get_vp_id)
|
||||
hdmi->old_vp_id = hdmi->plat_data->get_vp_id(old_crtc_state);
|
||||
}
|
||||
|
||||
if (!crtc)
|
||||
return 0;
|
||||
|
||||
@@ -2276,6 +2288,9 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (hdmi->plat_data->get_vp_id)
|
||||
hdmi->vp_id = hdmi->plat_data->get_vp_id(crtc_state);
|
||||
|
||||
mode = &crtc_state->mode;
|
||||
/*
|
||||
* If HDMI is enabled in uboot, it's need to record
|
||||
@@ -2319,7 +2334,7 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
if (hdmi->initialized && !hdmi->dclk_en) {
|
||||
mutex_lock(&hdmi->audio_mutex);
|
||||
if (hdmi->plat_data->dclk_set)
|
||||
hdmi->plat_data->dclk_set(data, true);
|
||||
hdmi->plat_data->dclk_set(data, true, hdmi->vp_id);
|
||||
hdmi->dclk_en = true;
|
||||
mutex_unlock(&hdmi->audio_mutex);
|
||||
hdmi->curr_conn = connector;
|
||||
@@ -2500,7 +2515,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
if (hdmi->dclk_en) {
|
||||
mutex_lock(&hdmi->audio_mutex);
|
||||
if (hdmi->plat_data->dclk_set)
|
||||
hdmi->plat_data->dclk_set(data, false);
|
||||
hdmi->plat_data->dclk_set(data, false, hdmi->old_vp_id);
|
||||
hdmi->dclk_en = false;
|
||||
mutex_unlock(&hdmi->audio_mutex);
|
||||
};
|
||||
@@ -2542,7 +2557,7 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
if (!hdmi->dclk_en) {
|
||||
mutex_lock(&hdmi->audio_mutex);
|
||||
if (hdmi->plat_data->dclk_set)
|
||||
hdmi->plat_data->dclk_set(data, true);
|
||||
hdmi->plat_data->dclk_set(data, true, hdmi->vp_id);
|
||||
hdmi->dclk_en = true;
|
||||
mutex_unlock(&hdmi->audio_mutex);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#define HWVER_131 0x31333100 /* IP version 1.31 */
|
||||
@@ -239,8 +241,11 @@ struct debugfs_entries {
|
||||
|
||||
struct dw_mipi_dsi {
|
||||
struct drm_bridge bridge;
|
||||
struct drm_connector connector;
|
||||
struct drm_encoder *encoder;
|
||||
struct mipi_dsi_host dsi_host;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct drm_panel *panel;
|
||||
struct drm_bridge *next_bridge;
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
|
||||
@@ -250,6 +255,7 @@ struct dw_mipi_dsi {
|
||||
u32 channel;
|
||||
u32 lanes;
|
||||
u32 format;
|
||||
struct drm_display_mode mode;
|
||||
unsigned long mode_flags;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@@ -299,6 +305,11 @@ static inline struct dw_mipi_dsi *bridge_to_dsi(struct drm_bridge *bridge)
|
||||
return container_of(bridge, struct dw_mipi_dsi, bridge);
|
||||
}
|
||||
|
||||
static inline struct dw_mipi_dsi *con_to_dsi(struct drm_connector *con)
|
||||
{
|
||||
return container_of(con, struct dw_mipi_dsi, connector);
|
||||
}
|
||||
|
||||
static inline void dsi_write(struct dw_mipi_dsi *dsi, u32 reg, u32 val)
|
||||
{
|
||||
writel(val, dsi->base + reg);
|
||||
@@ -314,8 +325,6 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = host_to_dsi(host);
|
||||
const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_panel *panel;
|
||||
int max_data_lanes = dsi->plat_data->max_data_lanes;
|
||||
int ret;
|
||||
|
||||
@@ -324,20 +333,13 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
|
||||
dsi->format = device->format;
|
||||
dsi->mode_flags = device->mode_flags;
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0,
|
||||
&panel, &bridge);
|
||||
if (ret)
|
||||
ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, -1,
|
||||
&dsi->panel, &dsi->next_bridge);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "Failed to find panel or bridge: %d\n", ret);
|
||||
return ret;
|
||||
|
||||
if (panel) {
|
||||
bridge = drm_panel_bridge_add_typed(panel,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
if (IS_ERR(bridge))
|
||||
return PTR_ERR(bridge);
|
||||
}
|
||||
|
||||
dsi->panel_bridge = bridge;
|
||||
|
||||
drm_bridge_add(&dsi->bridge);
|
||||
|
||||
if (pdata->host_ops && pdata->host_ops->attach) {
|
||||
@@ -602,6 +604,9 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)
|
||||
dsi_write(dsi, DSI_PWR_UP, RESET);
|
||||
dsi_write(dsi, DSI_PHY_RSTZ, PHY_RSTZ);
|
||||
pm_runtime_put(dsi->dev);
|
||||
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_disable(dsi->slave);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi)
|
||||
@@ -855,31 +860,29 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
|
||||
dsi_write(dsi, DSI_INT_MSK1, 0);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_post_disable(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
dw_mipi_dsi_set_mode(dsi, 0);
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_set_mode(dsi->slave, 0);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
/*
|
||||
* Switch to command mode before panel-bridge post_disable &
|
||||
* panel unprepare.
|
||||
* Note: panel-bridge disable & panel disable has been called
|
||||
* before by the drm framework.
|
||||
*/
|
||||
dw_mipi_dsi_set_mode(dsi, 0);
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_set_mode(dsi->slave, 0);
|
||||
if (dsi->panel)
|
||||
drm_panel_disable(dsi->panel);
|
||||
|
||||
/*
|
||||
* TODO Only way found to call panel-bridge post_disable &
|
||||
* panel unprepare before the dsi "final" disable...
|
||||
* This needs to be fixed in the drm_bridge framework and the API
|
||||
* needs to be updated to manage our own call chains...
|
||||
*/
|
||||
if (dsi->panel_bridge->funcs->post_disable)
|
||||
dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge);
|
||||
dw_mipi_dsi_post_disable(dsi);
|
||||
}
|
||||
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_disable(dsi->slave);
|
||||
static void dw_mipi_dsi_bridge_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
if (dsi->panel)
|
||||
drm_panel_unprepare(dsi->panel);
|
||||
|
||||
dw_mipi_dsi_disable(dsi);
|
||||
}
|
||||
@@ -898,11 +901,23 @@ static unsigned int dw_mipi_dsi_get_lanes(struct dw_mipi_dsi *dsi)
|
||||
return dsi->lanes;
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
drm_mode_copy(&dsi->mode, adjusted_mode);
|
||||
|
||||
if (dsi->slave)
|
||||
drm_mode_copy(&dsi->slave->mode, adjusted_mode);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_pre_enable(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
void *priv_data = dsi->plat_data->priv_data;
|
||||
const struct drm_display_mode *adjusted_mode = &dsi->mode;
|
||||
int ret;
|
||||
u32 lanes = dw_mipi_dsi_get_lanes(dsi);
|
||||
|
||||
@@ -946,27 +961,23 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
|
||||
|
||||
/* Switch to cmd mode for panel-bridge pre_enable & panel prepare */
|
||||
dw_mipi_dsi_set_mode(dsi, 0);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
dw_mipi_dsi_mode_set(dsi, adjusted_mode);
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
|
||||
|
||||
DRM_DEV_INFO(dsi->dev, "final DSI-Link bandwidth: %u x %d Mbps\n",
|
||||
dsi->lane_mbps, dsi->slave ? dsi->lanes * 2 : dsi->lanes);
|
||||
dw_mipi_dsi_pre_enable(dsi->slave);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
static void dw_mipi_dsi_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
/* Switch to video/cmd mode for panel-bridge enable & panel enable */
|
||||
dw_mipi_dsi_pre_enable(dsi);
|
||||
|
||||
if (dsi->panel)
|
||||
drm_panel_prepare(dsi->panel);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_enable(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||||
dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO);
|
||||
if (dsi->slave)
|
||||
@@ -976,6 +987,22 @@ static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_set_mode(dsi->slave, 0);
|
||||
}
|
||||
|
||||
if (dsi->slave)
|
||||
dw_mipi_dsi_enable(dsi->slave);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
dw_mipi_dsi_enable(dsi);
|
||||
|
||||
if (dsi->panel)
|
||||
drm_panel_enable(dsi->panel);
|
||||
|
||||
DRM_DEV_INFO(dsi->dev, "final DSI-Link bandwidth: %u x %d Mbps\n",
|
||||
dsi->lane_mbps, dsi->slave ? dsi->lanes * 2 : dsi->lanes);
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
@@ -1006,15 +1033,20 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
|
||||
/* Set the encoder type as caller does not know it */
|
||||
bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
|
||||
|
||||
/* Attach the panel-bridge to the dsi bridge */
|
||||
return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
|
||||
flags);
|
||||
/* Attach the next-bridge to the dsi bridge */
|
||||
if (dsi->next_bridge)
|
||||
return drm_bridge_attach(bridge->encoder, dsi->next_bridge,
|
||||
bridge, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
|
||||
.mode_set = dw_mipi_dsi_bridge_mode_set,
|
||||
.pre_enable = dw_mipi_dsi_bridge_pre_enable,
|
||||
.enable = dw_mipi_dsi_bridge_enable,
|
||||
.post_disable = dw_mipi_dsi_bridge_post_disable,
|
||||
.disable = dw_mipi_dsi_bridge_disable,
|
||||
.mode_valid = dw_mipi_dsi_bridge_mode_valid,
|
||||
.attach = dw_mipi_dsi_bridge_attach,
|
||||
};
|
||||
@@ -1209,6 +1241,81 @@ void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_mipi_dsi_remove);
|
||||
|
||||
static int dw_mipi_dsi_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = con_to_dsi(connector);
|
||||
|
||||
if (dsi->next_bridge && (dsi->next_bridge->ops & DRM_BRIDGE_OP_MODES))
|
||||
return drm_bridge_get_modes(dsi->next_bridge, connector);
|
||||
|
||||
if (dsi->panel)
|
||||
return drm_panel_get_modes(dsi->panel, connector);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct drm_connector_helper_funcs dw_mipi_dsi_connector_helper_funcs = {
|
||||
.get_modes = dw_mipi_dsi_connector_get_modes,
|
||||
};
|
||||
|
||||
static enum drm_connector_status
|
||||
dw_mipi_dsi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = con_to_dsi(connector);
|
||||
|
||||
if (dsi->next_bridge && (dsi->next_bridge->ops & DRM_BRIDGE_OP_DETECT))
|
||||
return drm_bridge_detect(dsi->next_bridge);
|
||||
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.detect = dw_mipi_dsi_connector_detect,
|
||||
.destroy = dw_mipi_dsi_drm_connector_destroy,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int dw_mipi_dsi_connector_init(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
struct drm_encoder *encoder = dsi->encoder;
|
||||
struct drm_connector *connector = &dsi->connector;
|
||||
struct drm_device *drm_dev = dsi->bridge.dev;
|
||||
struct device *dev = dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_init(drm_dev, connector,
|
||||
&dw_mipi_dsi_atomic_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "Failed to initialize connector\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(connector,
|
||||
&dw_mipi_dsi_connector_helper_funcs);
|
||||
ret = drm_connector_attach_encoder(connector, encoder);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev, "Failed to attach encoder: %d\n", ret);
|
||||
goto connector_cleanup;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
connector_cleanup:
|
||||
connector->funcs->destroy(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind/unbind API, used from platforms based on the component framework.
|
||||
*/
|
||||
@@ -1216,6 +1323,8 @@ int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dsi->encoder = encoder;
|
||||
|
||||
ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initialize bridge with drm\n");
|
||||
@@ -1233,7 +1342,33 @@ EXPORT_SYMBOL_GPL(dw_mipi_dsi_unbind);
|
||||
|
||||
struct drm_connector *dw_mipi_dsi_get_connector(struct dw_mipi_dsi *dsi)
|
||||
{
|
||||
return drm_panel_bridge_connector(dsi->panel_bridge);
|
||||
struct drm_connector *connector = NULL;
|
||||
enum drm_bridge_attach_flags flags = 0;
|
||||
int ret;
|
||||
|
||||
if (dsi->next_bridge) {
|
||||
enum drm_bridge_attach_flags flags;
|
||||
struct list_head *connector_list =
|
||||
&dsi->next_bridge->dev->mode_config.connector_list;
|
||||
|
||||
flags = dsi->next_bridge->ops & DRM_BRIDGE_OP_MODES ?
|
||||
DRM_BRIDGE_ATTACH_NO_CONNECTOR : 0;
|
||||
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
|
||||
list_for_each_entry(connector, connector_list, head)
|
||||
if (drm_connector_has_possible_encoder(connector,
|
||||
dsi->encoder))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dsi->panel || (dsi->next_bridge && (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))) {
|
||||
ret = dw_mipi_dsi_connector_init(dsi);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
connector = &dsi->connector;
|
||||
}
|
||||
|
||||
return connector;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_mipi_dsi_get_connector);
|
||||
|
||||
|
||||
@@ -155,8 +155,10 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
||||
int ret, i;
|
||||
|
||||
info = drm_get_format_info(dev, mode_cmd);
|
||||
if (!info)
|
||||
if (!info) {
|
||||
drm_dbg_kms(dev, "Failed to get FB format info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < info->num_planes; i++) {
|
||||
unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
|
||||
@@ -175,6 +177,9 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
||||
+ mode_cmd->offsets[i];
|
||||
|
||||
if (objs[i]->size < min_size) {
|
||||
drm_dbg_kms(dev,
|
||||
"GEM object size (%zu) smaller than minimum size (%u) for plane %d\n",
|
||||
objs[i]->size, min_size, i);
|
||||
drm_gem_object_put(objs[i]);
|
||||
ret = -EINVAL;
|
||||
goto err_gem_object_put;
|
||||
|
||||
@@ -149,6 +149,11 @@
|
||||
#define PX30_DSI_TURNDISABLE BIT(5)
|
||||
#define PX30_DSI_LCDC_SEL BIT(0)
|
||||
|
||||
#define RK3128_GRF_LVDS_CON0 0x0150
|
||||
#define RK3128_DSI_FORCETXSTOPMODE (0xf << 10)
|
||||
#define RK3128_DSI_FORCERXMODE (0x1 << 9)
|
||||
#define RK3128_DSI_TURNDISABLE (0x1 << 8)
|
||||
|
||||
#define RK3288_GRF_SOC_CON6 0x025c
|
||||
#define RK3288_DSI0_LCDC_SEL BIT(6)
|
||||
#define RK3288_DSI1_LCDC_SEL BIT(9)
|
||||
@@ -213,6 +218,7 @@ enum {
|
||||
|
||||
enum soc_type {
|
||||
PX30,
|
||||
RK3128,
|
||||
RK3288,
|
||||
RK3399,
|
||||
RK3568,
|
||||
@@ -1283,6 +1289,21 @@ static const struct rockchip_dw_dsi_chip_data px30_chip_data[] = {
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static const struct rockchip_dw_dsi_chip_data rk3128_chip_data[] = {
|
||||
{
|
||||
.reg = 0x10110000,
|
||||
.lanecfg1_grf_reg = RK3128_GRF_LVDS_CON0,
|
||||
.lanecfg1 = HIWORD_UPDATE(0, RK3128_DSI_TURNDISABLE |
|
||||
RK3128_DSI_FORCETXSTOPMODE |
|
||||
RK3128_DSI_FORCERXMODE),
|
||||
.flags = DW_MIPI_NEEDS_HCLK,
|
||||
.max_data_lanes = 4,
|
||||
.max_bit_rate_per_lane = 1000000000UL,
|
||||
.soc_type = RK3128,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
|
||||
{
|
||||
.reg = 0xff960000,
|
||||
@@ -1407,6 +1428,9 @@ static const struct of_device_id dw_mipi_dsi_rockchip_dt_ids[] = {
|
||||
{
|
||||
.compatible = "rockchip,px30-mipi-dsi",
|
||||
.data = &px30_chip_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3128-mipi-dsi",
|
||||
.data = &rk3128_chip_data,
|
||||
}, {
|
||||
.compatible = "rockchip,rk3288-mipi-dsi",
|
||||
.data = &rk3288_chip_data,
|
||||
|
||||
@@ -184,7 +184,6 @@ struct rockchip_hdmi {
|
||||
unsigned long enc_out_encoding;
|
||||
int color_changed;
|
||||
int hpd_irq;
|
||||
int vp_id;
|
||||
|
||||
struct drm_property *color_depth_property;
|
||||
struct drm_property *hdmi_output_property;
|
||||
@@ -2006,7 +2005,6 @@ dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
secondary:
|
||||
drm_mode_copy(&mode, &crtc_state->mode);
|
||||
|
||||
hdmi->vp_id = s->vp_id;
|
||||
if (hdmi->plat_data->split_mode)
|
||||
drm_mode_convert_to_origin_mode(&mode);
|
||||
|
||||
@@ -2216,14 +2214,23 @@ struct dw_hdmi_link_config *dw_hdmi_rockchip_get_link_cfg(void *data)
|
||||
return &hdmi->link_cfg;
|
||||
}
|
||||
|
||||
static int dw_hdmi_dclk_set(void *data, bool enable)
|
||||
static int dw_hdmi_rockchip_get_vp_id(struct drm_crtc_state *crtc_state)
|
||||
{
|
||||
struct rockchip_crtc_state *s;
|
||||
|
||||
s = to_rockchip_crtc_state(crtc_state);
|
||||
|
||||
return s->vp_id;
|
||||
}
|
||||
|
||||
static int dw_hdmi_dclk_set(void *data, bool enable, int vp_id)
|
||||
{
|
||||
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
|
||||
char clk_name[16];
|
||||
struct clk *dclk;
|
||||
int ret;
|
||||
|
||||
snprintf(clk_name, sizeof(clk_name), "dclk_vp%d", hdmi->vp_id);
|
||||
snprintf(clk_name, sizeof(clk_name), "dclk_vp%d", vp_id);
|
||||
|
||||
dclk = devm_clk_get(hdmi->dev, clk_name);
|
||||
if (IS_ERR(dclk)) {
|
||||
@@ -2235,7 +2242,7 @@ static int dw_hdmi_dclk_set(void *data, bool enable)
|
||||
ret = clk_prepare_enable(dclk);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(hdmi->dev, "failed to enable dclk for video port%d - %d\n",
|
||||
hdmi->vp_id, ret);
|
||||
vp_id, ret);
|
||||
} else {
|
||||
clk_disable_unprepare(dclk);
|
||||
}
|
||||
@@ -3147,6 +3154,7 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
|
||||
plat_data->convert_to_origin_mode = drm_mode_convert_to_origin_mode;
|
||||
plat_data->dclk_set = dw_hdmi_dclk_set;
|
||||
plat_data->link_clk_set = dw_hdmi_link_clk_set;
|
||||
plat_data->get_vp_id = dw_hdmi_rockchip_get_vp_id;
|
||||
|
||||
plat_data->property_ops = &dw_hdmi_rockchip_property_ops;
|
||||
|
||||
|
||||
@@ -836,6 +836,7 @@ static int update_state(struct drm_device *drm_dev,
|
||||
const struct drm_encoder_helper_funcs *encoder_helper_funcs;
|
||||
const struct drm_connector_helper_funcs *connector_helper_funcs;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *bridge;
|
||||
|
||||
connector_helper_funcs = connector->helper_private;
|
||||
if (!connector_helper_funcs)
|
||||
@@ -860,6 +861,9 @@ static int update_state(struct drm_device *drm_dev,
|
||||
conn_state);
|
||||
else if (encoder_helper_funcs->mode_set)
|
||||
encoder_helper_funcs->mode_set(encoder, mode, mode);
|
||||
|
||||
bridge = drm_bridge_chain_get_first_bridge(encoder);
|
||||
drm_bridge_chain_mode_set(bridge, mode, mode);
|
||||
}
|
||||
|
||||
primary_state = drm_atomic_get_plane_state(state, crtc->primary);
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
static int cru_debug;
|
||||
|
||||
#define PLL_RATE_MIN 30000000
|
||||
|
||||
#define cru_dbg(format, ...) do { \
|
||||
if (cru_debug) \
|
||||
pr_info("%s: " format, __func__, ## __VA_ARGS__); \
|
||||
@@ -157,6 +155,7 @@ static long clk_virtual_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
vop2_clk->rate = rate;
|
||||
|
||||
cru_dbg("%s rate: %ld\n", clk_hw_get_name(hw), rate);
|
||||
return rate;
|
||||
}
|
||||
|
||||
@@ -245,10 +244,6 @@ static long vop2_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
if ((*prate % rate))
|
||||
*prate = rate;
|
||||
|
||||
/* SOC PLL can't output a too low pll freq */
|
||||
if (*prate < PLL_RATE_MIN)
|
||||
*prate = rate << vop2_clk->div.width;
|
||||
}
|
||||
|
||||
cru_dbg("%s rate: %ld(prate: %ld)\n", clk_hw_get_name(hw), rate, *prate);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -195,6 +196,7 @@ struct rk_hdmirx_dev {
|
||||
struct dentry *debugfs_dir;
|
||||
struct freq_qos_request min_sta_freq_req;
|
||||
struct hdmirx_audiostate audio_state;
|
||||
struct extcon_dev *extcon;
|
||||
struct hdmirx_cec *cec;
|
||||
struct mutex stream_lock;
|
||||
struct mutex work_lock;
|
||||
@@ -245,6 +247,11 @@ struct rk_hdmirx_dev {
|
||||
spinlock_t rst_lock;
|
||||
};
|
||||
|
||||
static const unsigned int hdmirx_extcon_cable[] = {
|
||||
EXTCON_JACK_VIDEO_IN,
|
||||
EXTCON_NONE,
|
||||
};
|
||||
|
||||
static bool tx_5v_power_present(struct rk_hdmirx_dev *hdmirx_dev);
|
||||
static void hdmirx_set_fmt(struct hdmirx_stream *stream,
|
||||
struct v4l2_pix_format_mplane *pixm, bool try);
|
||||
@@ -2672,12 +2679,14 @@ static void hdmirx_plugin(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
}
|
||||
hdmirx_dma_config(hdmirx_dev);
|
||||
hdmirx_interrupts_setup(hdmirx_dev, true);
|
||||
extcon_set_state_sync(hdmirx_dev->extcon, EXTCON_JACK_VIDEO_IN, true);
|
||||
hdmirx_audio_handle_plugged_change(hdmirx_dev, 1);
|
||||
}
|
||||
|
||||
static void hdmirx_plugout(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
{
|
||||
hdmirx_audio_handle_plugged_change(hdmirx_dev, 0);
|
||||
extcon_set_state_sync(hdmirx_dev->extcon, EXTCON_JACK_VIDEO_IN, false);
|
||||
hdmirx_update_bits(hdmirx_dev, SCDC_CONFIG, POWERPROVIDED, 0);
|
||||
hdmirx_interrupts_setup(hdmirx_dev, false);
|
||||
hdmirx_hpd_ctrl(hdmirx_dev, false);
|
||||
@@ -4102,6 +4111,19 @@ static int hdmirx_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_unreg_video_dev;
|
||||
|
||||
hdmirx_dev->extcon = devm_extcon_dev_allocate(dev, hdmirx_extcon_cable);
|
||||
if (IS_ERR(hdmirx_dev->extcon)) {
|
||||
ret = PTR_ERR(hdmirx_dev->extcon);
|
||||
dev_err(&pdev->dev, "allocate extcon failed\n");
|
||||
goto err_unreg_video_dev;
|
||||
}
|
||||
|
||||
ret = devm_extcon_dev_register(dev, hdmirx_dev->extcon);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register extcon: %d\n", ret);
|
||||
goto err_unreg_video_dev;
|
||||
}
|
||||
|
||||
irq = gpiod_to_irq(hdmirx_dev->hdmirx_det_gpio);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "failed to get hdmirx-det gpio irq\n");
|
||||
|
||||
@@ -1552,6 +1552,9 @@ static void rkisp_stream_fast(struct work_struct *work)
|
||||
if (ispdev->isp_ver != ISP_V32)
|
||||
return;
|
||||
|
||||
rkisp_chk_tb_over(ispdev);
|
||||
if (ispdev->tb_head.complete != RKISP_TB_OK)
|
||||
return;
|
||||
ret = v4l2_pipeline_pm_get(&stream->vnode.vdev.entity);
|
||||
if (ret < 0) {
|
||||
dev_err(ispdev->dev, "%s PM get fail:%d\n", __func__, ret);
|
||||
@@ -1559,11 +1562,8 @@ static void rkisp_stream_fast(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
rkisp_chk_tb_over(ispdev);
|
||||
if (ispdev->tb_head.complete != RKISP_TB_OK) {
|
||||
v4l2_pipeline_pm_put(&stream->vnode.vdev.entity);
|
||||
return;
|
||||
}
|
||||
if (ispdev->hw_dev->dev_num > 1)
|
||||
ispdev->hw_dev->is_single = false;
|
||||
ispdev->is_pre_on = true;
|
||||
ispdev->is_rdbk_auto = true;
|
||||
ispdev->pipe.open(&ispdev->pipe, &stream->vnode.vdev.entity, true);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define CIF_ISP_REQ_BUFS_MIN 0
|
||||
|
||||
static int mi_frame_end(struct rkisp_stream *stream);
|
||||
static int mi_frame_start(struct rkisp_stream *stream, u32 mis);
|
||||
|
||||
static const struct capture_fmt mp_fmts[] = {
|
||||
/* yuv422 */
|
||||
@@ -856,6 +857,7 @@ static struct streams_ops rkisp_mp_streams_ops = {
|
||||
.is_stream_stopped = mp_is_stream_stopped,
|
||||
.update_mi = update_mi,
|
||||
.frame_end = mi_frame_end,
|
||||
.frame_start = mi_frame_start,
|
||||
};
|
||||
|
||||
static struct streams_ops rkisp_sp_streams_ops = {
|
||||
@@ -866,6 +868,7 @@ static struct streams_ops rkisp_sp_streams_ops = {
|
||||
.is_stream_stopped = sp_is_stream_stopped,
|
||||
.update_mi = update_mi,
|
||||
.frame_end = mi_frame_end,
|
||||
.frame_start = mi_frame_start,
|
||||
};
|
||||
|
||||
static struct streams_ops rkisp_fbc_streams_ops = {
|
||||
@@ -875,6 +878,7 @@ static struct streams_ops rkisp_fbc_streams_ops = {
|
||||
.is_stream_stopped = fbc_is_stream_stopped,
|
||||
.update_mi = update_mi,
|
||||
.frame_end = mi_frame_end,
|
||||
.frame_start = mi_frame_start,
|
||||
};
|
||||
|
||||
static struct streams_ops rkisp_bp_streams_ops = {
|
||||
@@ -884,8 +888,63 @@ static struct streams_ops rkisp_bp_streams_ops = {
|
||||
.is_stream_stopped = bp_is_stream_stopped,
|
||||
.update_mi = update_mi,
|
||||
.frame_end = mi_frame_end,
|
||||
.frame_start = mi_frame_start,
|
||||
};
|
||||
|
||||
static void stream_self_update(struct rkisp_stream *stream)
|
||||
{
|
||||
struct rkisp_device *dev = stream->ispdev;
|
||||
u32 val, mask = ISP3X_MPSELF_UPD | ISP3X_SPSELF_UPD | ISP3X_BPSELF_UPD;
|
||||
bool is_unite = dev->hw_dev->is_unite;
|
||||
|
||||
if (stream->id == RKISP_STREAM_FBC) {
|
||||
val = ISP3X_MPFBC_FORCE_UPD;
|
||||
rkisp_unite_set_bits(dev, ISP3X_MPFBC_CTRL, 0, val, false, is_unite);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (stream->id) {
|
||||
case RKISP_STREAM_MP:
|
||||
val = ISP3X_MPSELF_UPD;
|
||||
break;
|
||||
case RKISP_STREAM_SP:
|
||||
val = ISP3X_SPSELF_UPD;
|
||||
break;
|
||||
case RKISP_STREAM_BP:
|
||||
val = ISP3X_BPSELF_UPD;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
rkisp_unite_set_bits(dev, ISP3X_MI_WR_XTD_FORMAT_CTRL, mask, val, false, is_unite);
|
||||
}
|
||||
|
||||
static int mi_frame_start(struct rkisp_stream *stream, u32 mis)
|
||||
{
|
||||
struct rkisp_device *dev = stream->ispdev;
|
||||
unsigned long lock_flags = 0;
|
||||
|
||||
/* readback start to update stream buf if null */
|
||||
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
|
||||
if (stream->streaming && !mis && !stream->curr_buf) {
|
||||
if (!stream->next_buf && !list_empty(&stream->buf_queue)) {
|
||||
stream->next_buf = list_first_entry(&stream->buf_queue,
|
||||
struct rkisp_buffer, queue);
|
||||
list_del(&stream->next_buf->queue);
|
||||
stream->ops->update_mi(stream);
|
||||
}
|
||||
if (dev->hw_dev->is_single && stream->next_buf) {
|
||||
stream->curr_buf = stream->next_buf;
|
||||
stream->next_buf = NULL;
|
||||
stream_self_update(stream);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a frame end come. The next frame
|
||||
* is processing and we should set up buffer for next-next frame,
|
||||
|
||||
@@ -1645,6 +1645,11 @@ rkisp_start_streaming(struct vb2_queue *queue, unsigned int count)
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&dev->hw_dev->dev_lock);
|
||||
if (dev->is_pre_on &&
|
||||
!dev->hw_dev->is_single &&
|
||||
!atomic_read(&dev->hw_dev->refcnt) &&
|
||||
!atomic_read(&dev->cap_dev.refcnt))
|
||||
rkisp_hw_enum_isp_size(dev->hw_dev);
|
||||
|
||||
v4l2_dbg(1, rkisp_debug, v4l2_dev, "%s %s id:%d\n",
|
||||
__func__, node->vdev.name, stream->id);
|
||||
|
||||
@@ -592,7 +592,7 @@ int rkisp_csi_config_patch(struct rkisp_device *dev)
|
||||
if (dev->hdr.op_mode == HDR_NORMAL || dev->hdr.op_mode == HDR_COMPR)
|
||||
dev->hdr.op_mode = HDR_RDBK_FRAME1;
|
||||
|
||||
if (dev->isp_inp == INP_CIF && dev->hw_dev->is_single && dev->isp_ver > ISP_V21)
|
||||
if (dev->isp_inp == INP_CIF && dev->isp_ver > ISP_V21)
|
||||
mode.rdbk_mode = dev->is_rdbk_auto ? RKISP_VICAP_RDBK_AUTO : RKISP_VICAP_ONLINE;
|
||||
else
|
||||
mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ;
|
||||
|
||||
@@ -387,9 +387,7 @@ static void update_rawrd(struct rkisp_stream *stream)
|
||||
rkisp_next_write(dev, stream->config->mi.y_base_ad_init, val, false);
|
||||
}
|
||||
stream->frame_end = false;
|
||||
if (stream->id == RKISP_STREAM_RAWRD2 &&
|
||||
(stream->out_isp_fmt.fmt_type == FMT_YUV ||
|
||||
dev->dmarx_dev.trigger == T_AUTO)) {
|
||||
if (stream->id == RKISP_STREAM_RAWRD2 && stream->out_isp_fmt.fmt_type == FMT_YUV) {
|
||||
struct vb2_v4l2_buffer *vbuf = &stream->curr_buf->vb;
|
||||
struct isp2x_csi_trigger trigger = {
|
||||
.frame_timestamp = vbuf->vb2_buf.timestamp,
|
||||
|
||||
@@ -990,28 +990,18 @@ static int __maybe_unused rkisp_runtime_suspend(struct device *dev)
|
||||
return pinctrl_pm_select_sleep_state(dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused rkisp_runtime_resume(struct device *dev)
|
||||
void rkisp_hw_enum_isp_size(struct rkisp_hw_dev *hw_dev)
|
||||
{
|
||||
struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
|
||||
void __iomem *base = hw_dev->base_addr;
|
||||
struct rkisp_device *isp;
|
||||
int mult = hw_dev->is_unite ? 2 : 1;
|
||||
int ret, i;
|
||||
u32 w, h, i;
|
||||
|
||||
ret = pinctrl_pm_select_default_state(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
enable_sys_clk(hw_dev);
|
||||
memset(hw_dev->isp_size, 0, sizeof(hw_dev->isp_size));
|
||||
if (!hw_dev->max_in.is_fix) {
|
||||
hw_dev->max_in.w = 0;
|
||||
hw_dev->max_in.h = 0;
|
||||
}
|
||||
hw_dev->dev_link_num = 0;
|
||||
for (i = 0; i < hw_dev->dev_num; i++) {
|
||||
void *buf;
|
||||
u32 w, h;
|
||||
|
||||
isp = hw_dev->isp[i];
|
||||
if (!isp || (isp && !isp->is_hw_link))
|
||||
continue;
|
||||
@@ -1030,6 +1020,33 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev)
|
||||
if (hw_dev->max_in.h < h)
|
||||
hw_dev->max_in.h = h;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < hw_dev->dev_num; i++) {
|
||||
isp = hw_dev->isp[i];
|
||||
if (!isp || (isp && !isp->is_hw_link))
|
||||
continue;
|
||||
rkisp_params_check_bigmode(&isp->params_vdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int __maybe_unused rkisp_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct rkisp_hw_dev *hw_dev = dev_get_drvdata(dev);
|
||||
void __iomem *base = hw_dev->base_addr;
|
||||
struct rkisp_device *isp;
|
||||
int mult = hw_dev->is_unite ? 2 : 1;
|
||||
int ret, i;
|
||||
void *buf;
|
||||
|
||||
ret = pinctrl_pm_select_default_state(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
enable_sys_clk(hw_dev);
|
||||
for (i = 0; i < hw_dev->dev_num; i++) {
|
||||
isp = hw_dev->isp[i];
|
||||
if (!isp)
|
||||
continue;
|
||||
buf = isp->sw_base_addr;
|
||||
memset(buf, 0, RKISP_ISP_SW_MAX_SIZE * mult);
|
||||
memcpy_fromio(buf, base, RKISP_ISP_SW_REG_SIZE);
|
||||
@@ -1040,12 +1057,7 @@ static int __maybe_unused rkisp_runtime_resume(struct device *dev)
|
||||
}
|
||||
default_sw_reg_flag(hw_dev->isp[i]);
|
||||
}
|
||||
for (i = 0; i < hw_dev->dev_num; i++) {
|
||||
isp = hw_dev->isp[i];
|
||||
if (!isp || (isp && !isp->is_hw_link))
|
||||
continue;
|
||||
rkisp_params_check_bigmode(&isp->params_vdev);
|
||||
}
|
||||
rkisp_hw_enum_isp_size(hw_dev);
|
||||
hw_dev->monitor.is_en = rkisp_monitor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -104,4 +104,5 @@ struct rkisp_hw_dev {
|
||||
|
||||
int rkisp_register_irq(struct rkisp_hw_dev *dev);
|
||||
void rkisp_soft_reset(struct rkisp_hw_dev *dev, bool is_secure);
|
||||
void rkisp_hw_enum_isp_size(struct rkisp_hw_dev *hw_dev);
|
||||
#endif
|
||||
|
||||
@@ -3371,6 +3371,31 @@ isp_bay3d_enable(struct rkisp_isp_params_vdev *params_vdev, bool en)
|
||||
return;
|
||||
}
|
||||
|
||||
value = priv_val->buf_3dnr_iir.size;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_WR_SIZE);
|
||||
value = priv_val->buf_3dnr_iir.dma_addr;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_WR_BASE);
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_IIR_RD_BASE);
|
||||
|
||||
value = priv_val->buf_3dnr_ds.size;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_DS_WR_SIZE);
|
||||
value = priv_val->buf_3dnr_ds.dma_addr;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_DS_WR_BASE);
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_DS_RD_BASE);
|
||||
|
||||
value = priv_val->is_sram ?
|
||||
ispdev->hw_dev->sram.dma_addr : priv_val->buf_3dnr_cur.dma_addr;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_WR_BASE);
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_RD_BASE);
|
||||
value = priv_val->bay3d_cur_size;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_WR_SIZE);
|
||||
isp3_param_write(params_vdev, value, ISP32_MI_BAY3D_CUR_RD_SIZE);
|
||||
value = priv_val->bay3d_cur_wsize;
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_WR_LENGTH);
|
||||
isp3_param_write(params_vdev, value, ISP3X_MI_BAY3D_CUR_RD_LENGTH);
|
||||
value = priv_val->bay3d_cur_wrap_line << 16 | 28;
|
||||
isp3_param_write(params_vdev, value, ISP3X_BAY3D_MI_ST);
|
||||
|
||||
/* mibuf_size for fifo_cur_full, set to max: (3072 - 2) / 2, 2 align */
|
||||
value = 0x5fe << 16;
|
||||
isp3_param_set_bits(params_vdev, ISP3X_BAY3D_IN_IRQ_LINECNT, value);
|
||||
@@ -4085,7 +4110,6 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev,
|
||||
u32 w = ALIGN(isp_sdev->in_crop.width, 16);
|
||||
u32 h = ALIGN(isp_sdev->in_crop.height, 16);
|
||||
u32 val, wrap_line, wsize, div;
|
||||
dma_addr_t dma_addr;
|
||||
bool is_alloc;
|
||||
|
||||
priv_val->is_lo8x8 = (!new_params->others.bay3d_cfg.lo4x8_en &&
|
||||
@@ -4120,10 +4144,6 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev,
|
||||
goto err_3dnr;
|
||||
}
|
||||
}
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_IIR_WR_SIZE);
|
||||
val = priv_val->buf_3dnr_iir.dma_addr;
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_IIR_WR_BASE);
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_IIR_RD_BASE);
|
||||
|
||||
div = priv_val->is_lo8x8 ? 64 : 16;
|
||||
val = w * h / div;
|
||||
@@ -4145,10 +4165,6 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev,
|
||||
goto err_3dnr;
|
||||
}
|
||||
}
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_DS_WR_SIZE);
|
||||
val = priv_val->buf_3dnr_ds.dma_addr;
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_DS_WR_BASE);
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_DS_RD_BASE);
|
||||
|
||||
wrap_line = priv_val->is_lo8x8 ? 76 : 36;
|
||||
wsize = is_bwopt_dis ? w : w * 2;
|
||||
@@ -4177,22 +4193,13 @@ rkisp_alloc_internal_buf(struct rkisp_isp_params_vdev *params_vdev,
|
||||
dev_err(dev->dev, "alloc bay3d cur buf fail:%d\n", ret);
|
||||
goto err_3dnr;
|
||||
}
|
||||
dma_addr = priv_val->buf_3dnr_cur.dma_addr;
|
||||
priv_val->is_sram = false;
|
||||
} else if (val <= dev->hw_dev->sram.size) {
|
||||
dma_addr = dev->hw_dev->sram.dma_addr;
|
||||
priv_val->is_sram = true;
|
||||
} else {
|
||||
dma_addr = priv_val->buf_3dnr_cur.dma_addr;
|
||||
}
|
||||
isp3_param_write(params_vdev, val, ISP3X_MI_BAY3D_CUR_WR_SIZE);
|
||||
isp3_param_write(params_vdev, val, ISP32_MI_BAY3D_CUR_RD_SIZE);
|
||||
isp3_param_write(params_vdev, wsize, ISP3X_MI_BAY3D_CUR_WR_LENGTH);
|
||||
isp3_param_write(params_vdev, wsize, ISP3X_MI_BAY3D_CUR_RD_LENGTH);
|
||||
isp3_param_write(params_vdev, dma_addr, ISP3X_MI_BAY3D_CUR_WR_BASE);
|
||||
isp3_param_write(params_vdev, dma_addr, ISP3X_MI_BAY3D_CUR_RD_BASE);
|
||||
val = wrap_line << 16 | 28;
|
||||
isp3_param_write(params_vdev, val, ISP3X_BAY3D_MI_ST);
|
||||
priv_val->bay3d_cur_size = val;
|
||||
priv_val->bay3d_cur_wsize = wsize;
|
||||
priv_val->bay3d_cur_wrap_line = wrap_line;
|
||||
}
|
||||
return 0;
|
||||
err_3dnr:
|
||||
@@ -4421,14 +4428,7 @@ rkisp_params_first_cfg_v32(struct rkisp_isp_params_vdev *params_vdev)
|
||||
|
||||
static void rkisp_save_first_param_v32(struct rkisp_isp_params_vdev *params_vdev, void *param)
|
||||
{
|
||||
struct rkisp_isp_params_val_v32 *priv_val =
|
||||
(struct rkisp_isp_params_val_v32 *)params_vdev->priv_val;
|
||||
|
||||
memcpy(params_vdev->isp32_params, param, params_vdev->vdev_fmt.fmt.meta.buffersize);
|
||||
|
||||
if (!params_vdev->first_params)
|
||||
return;
|
||||
tasklet_enable(&priv_val->lsc_tasklet);
|
||||
rkisp_alloc_internal_buf(params_vdev, params_vdev->isp32_params);
|
||||
}
|
||||
|
||||
@@ -4718,7 +4718,6 @@ rkisp_params_stream_stop_v32(struct rkisp_isp_params_vdev *params_vdev)
|
||||
int i;
|
||||
|
||||
priv_val = (struct rkisp_isp_params_val_v32 *)params_vdev->priv_val;
|
||||
tasklet_disable(&priv_val->lsc_tasklet);
|
||||
rkisp_free_buffer(ispdev, &priv_val->buf_3dnr_iir);
|
||||
rkisp_free_buffer(ispdev, &priv_val->buf_3dnr_cur);
|
||||
rkisp_free_buffer(ispdev, &priv_val->buf_3dnr_ds);
|
||||
@@ -4944,7 +4943,6 @@ int rkisp_init_params_vdev_v32(struct rkisp_isp_params_vdev *params_vdev)
|
||||
tasklet_init(&priv_val->lsc_tasklet,
|
||||
isp_lsc_cfg_sram_task,
|
||||
(unsigned long)params_vdev);
|
||||
tasklet_disable(&priv_val->lsc_tasklet);
|
||||
priv_val->buf_info_owner = 0;
|
||||
priv_val->buf_info_cnt = 0;
|
||||
priv_val->buf_info_idx = -1;
|
||||
|
||||
@@ -185,6 +185,9 @@ struct rkisp_isp_params_val_v32 {
|
||||
u32 buf_info_cnt;
|
||||
int buf_info_idx;
|
||||
|
||||
u32 bay3d_cur_size;
|
||||
u32 bay3d_cur_wsize;
|
||||
u32 bay3d_cur_wrap_line;
|
||||
struct rkisp_dummy_buffer buf_3dnr_iir;
|
||||
struct rkisp_dummy_buffer buf_3dnr_cur;
|
||||
struct rkisp_dummy_buffer buf_3dnr_ds;
|
||||
|
||||
@@ -614,7 +614,7 @@ void rkisp_trigger_read_back(struct rkisp_device *dev, u8 dma2frm, u32 mode, boo
|
||||
rkisp_stream_frame_start(dev, 0);
|
||||
if (!hw->is_single && !is_try) {
|
||||
rkisp_update_regs(dev, CTRL_VI_ISP_PATH, SUPER_IMP_COLOR_CR);
|
||||
rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, DUAL_CROP_S_V_SIZE);
|
||||
rkisp_update_regs(dev, DUAL_CROP_M_H_OFFS, ISP3X_DUAL_CROP_FBC_V_SIZE);
|
||||
rkisp_update_regs(dev, ISP_ACQ_PROP, DUAL_CROP_CTRL);
|
||||
rkisp_update_regs(dev, SELF_RESIZE_SCALE_HY, MI_WR_CTRL);
|
||||
rkisp_update_regs(dev, ISP32_BP_RESIZE_SCALE_HY, SELF_RESIZE_CTRL);
|
||||
@@ -722,6 +722,40 @@ run_next:
|
||||
rkisp_unite_write(dev, CSI2RX_CTRL0, val, true, hw->is_unite);
|
||||
}
|
||||
|
||||
static void rkisp_fast_switch_rx_buf(struct rkisp_device *dev, bool is_current)
|
||||
{
|
||||
struct rkisp_stream *stream;
|
||||
struct rkisp_buffer *buf;
|
||||
u32 i, val;
|
||||
|
||||
for (i = RKISP_STREAM_RAWRD0; i < RKISP_MAX_DMARX_STREAM; i++) {
|
||||
stream = &dev->dmarx_dev.stream[i];
|
||||
if (!stream->ops)
|
||||
continue;
|
||||
buf = NULL;
|
||||
if (is_current)
|
||||
buf = stream->curr_buf;
|
||||
else if (!list_empty(&stream->buf_queue))
|
||||
buf = list_first_entry(&stream->buf_queue,
|
||||
struct rkisp_buffer, queue);
|
||||
if (!buf)
|
||||
continue;
|
||||
val = buf->buff_addr[RKISP_PLANE_Y];
|
||||
/* f1 -> f0 -> f1 for normal
|
||||
* L:f1 L:f1 -> L:f0 S:f0 -> L:f1 S:f1 for hdr2
|
||||
*/
|
||||
if (dev->rd_mode == HDR_RDBK_FRAME2 && !is_current &&
|
||||
rkisp_read_reg_cache(dev, ISP3X_HDRMGE_GAIN0) == 0xfff0040) {
|
||||
if (i == RKISP_STREAM_RAWRD2)
|
||||
continue;
|
||||
else
|
||||
rkisp_write(dev, ISP3X_MI_RAWS_RD_BASE, val, false);
|
||||
}
|
||||
rkisp_write(dev, stream->config->mi.y_base_ad_init, val, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd)
|
||||
{
|
||||
struct rkisp_hw_dev *hw = dev->hw_dev;
|
||||
@@ -766,10 +800,14 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/* wait 2 frame to start isp for fast */
|
||||
if (dev->is_pre_on && max == 1 && !atomic_read(&dev->isp_sdev.frm_sync_seq))
|
||||
goto end;
|
||||
|
||||
if (max) {
|
||||
v4l2_dbg(2, rkisp_debug, &dev->v4l2_dev,
|
||||
"trigger fifo len:%d\n", max);
|
||||
isp = hw->isp[id];
|
||||
v4l2_dbg(2, rkisp_debug, &isp->v4l2_dev,
|
||||
"trigger fifo len:%d\n", max);
|
||||
rkisp_rdbk_trigger_event(isp, T_CMD_DEQUEUE, &t);
|
||||
isp->dmarx_dev.pre_frame = isp->dmarx_dev.cur_frame;
|
||||
if (t.frame_id > isp->dmarx_dev.pre_frame.id &&
|
||||
@@ -790,9 +828,10 @@ static void rkisp_rdbk_trigger_handle(struct rkisp_device *dev, u32 cmd)
|
||||
isp->sw_rd_cnt = 1;
|
||||
times = 0;
|
||||
}
|
||||
if (dev->is_pre_on && t.frame_id == 0) {
|
||||
dev->is_first_double = true;
|
||||
dev->skip_frame = 1;
|
||||
if (isp->is_pre_on && t.frame_id == 0) {
|
||||
isp->is_first_double = true;
|
||||
isp->skip_frame = 1;
|
||||
rkisp_fast_switch_rx_buf(isp, false);
|
||||
}
|
||||
}
|
||||
end:
|
||||
@@ -865,10 +904,12 @@ void rkisp_check_idle(struct rkisp_device *dev, u32 irq)
|
||||
if (!completion_done(&dev->hw_dev->monitor.cmpl))
|
||||
complete(&dev->hw_dev->monitor.cmpl);
|
||||
}
|
||||
if (dev->irq_ends != dev->irq_ends_mask || !IS_HDR_RDBK(dev->rd_mode))
|
||||
if ((dev->irq_ends & dev->irq_ends_mask) != dev->irq_ends_mask ||
|
||||
!IS_HDR_RDBK(dev->rd_mode))
|
||||
return;
|
||||
|
||||
if (dev->is_first_double) {
|
||||
rkisp_fast_switch_rx_buf(dev, true);
|
||||
dev->skip_frame = 0;
|
||||
dev->irq_ends = 0;
|
||||
return;
|
||||
@@ -2776,9 +2817,16 @@ static void rkisp_rx_qbuf_online(struct rkisp_stream *stream,
|
||||
static void rkisp_rx_qbuf_rdbk(struct rkisp_stream *stream,
|
||||
struct rkisp_rx_buf_pool *pool)
|
||||
{
|
||||
struct rkisp_device *dev = stream->ispdev;
|
||||
unsigned long lock_flags = 0;
|
||||
struct rkisp_buffer *ispbuf = &pool->buf;
|
||||
|
||||
struct isp2x_csi_trigger trigger = {
|
||||
.frame_timestamp = ispbuf->vb.vb2_buf.timestamp,
|
||||
.sof_timestamp = ispbuf->vb.vb2_buf.timestamp,
|
||||
.frame_id = ispbuf->vb.sequence,
|
||||
.mode = 0,
|
||||
.times = 0,
|
||||
};
|
||||
spin_lock_irqsave(&stream->vbq_lock, lock_flags);
|
||||
if (list_empty(&stream->buf_queue) && !stream->curr_buf) {
|
||||
stream->curr_buf = ispbuf;
|
||||
@@ -2787,6 +2835,8 @@ static void rkisp_rx_qbuf_rdbk(struct rkisp_stream *stream,
|
||||
list_add_tail(&ispbuf->queue, &stream->buf_queue);
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->vbq_lock, lock_flags);
|
||||
if (stream->id == RKISP_STREAM_RAWRD2)
|
||||
rkisp_rdbk_trigger_event(dev, T_CMD_QUEUE, &trigger);
|
||||
}
|
||||
|
||||
static int rkisp_rx_qbuf(struct rkisp_device *dev,
|
||||
@@ -3639,12 +3689,14 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
|
||||
head->enable = 0;
|
||||
dma_sync_single_for_device(isp_dev->dev, isp_dev->resmem_addr,
|
||||
sizeof(struct rkisp_thunderboot_resmem_head),
|
||||
DMA_FROM_DEVICE);
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 100 * USEC_PER_MSEC);
|
||||
shm_head_poll_timeout(isp_dev, !!head->complete, 5000, 200 * USEC_PER_MSEC);
|
||||
if (head->complete != RKISP_TB_OK) {
|
||||
v4l2_err(&isp_dev->v4l2_dev, "wait thunderboot over timeout\n");
|
||||
} else {
|
||||
struct rkisp_isp_params_vdev *params_vdev = &isp_dev->params_vdev;
|
||||
void *param = NULL;
|
||||
u32 size = 0;
|
||||
|
||||
switch (isp_dev->hw_dev->isp_ver) {
|
||||
@@ -3657,13 +3709,14 @@ void rkisp_chk_tb_over(struct rkisp_device *isp_dev)
|
||||
if (size && size < isp_dev->resmem_size) {
|
||||
dma_sync_single_for_cpu(isp_dev->dev, isp_dev->resmem_addr,
|
||||
size, DMA_FROM_DEVICE);
|
||||
isp_dev->params_vdev.is_first_cfg = true;
|
||||
params_vdev->is_first_cfg = true;
|
||||
if (isp_dev->hw_dev->isp_ver == ISP_V32) {
|
||||
struct rkisp32_thunderboot_resmem_head *tmp = resmem_va;
|
||||
|
||||
memcpy(isp_dev->params_vdev.isp32_params, &tmp->cfg,
|
||||
sizeof(struct isp32_isp_params_cfg));
|
||||
param = &tmp->cfg;
|
||||
}
|
||||
if (param)
|
||||
params_vdev->ops->save_first_param(params_vdev, param);
|
||||
} else if (size > isp_dev->resmem_size) {
|
||||
v4l2_err(&isp_dev->v4l2_dev,
|
||||
"resmem size:%zu no enough for head:%d\n",
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/soc/rockchip/rockchip_thunderboot_service.h>
|
||||
|
||||
#include "rkisp_tb_helper.h"
|
||||
|
||||
static struct platform_device *rkisp_tb_pdev;
|
||||
static struct clk_bulk_data *rkisp_tb_clk;
|
||||
static int rkisp_tb_clk_num;
|
||||
static struct rk_tb_client tb_cl;
|
||||
|
||||
struct shm_data {
|
||||
int npages;
|
||||
@@ -187,6 +189,11 @@ static int __maybe_unused rkisp_tb_clocks_loader_unprotect(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkisp_tb_cb(void *data)
|
||||
{
|
||||
rkisp_tb_clocks_loader_unprotect();
|
||||
}
|
||||
|
||||
static int __maybe_unused rkisp_tb_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
@@ -220,6 +227,12 @@ static int rkisp_tb_plat_probe(struct platform_device *pdev)
|
||||
rkisp_tb_clk_num = 0;
|
||||
}
|
||||
rkisp_tb_clocks_loader_protect();
|
||||
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE)) {
|
||||
tb_cl.cb = rkisp_tb_cb;
|
||||
return rk_tb_client_register_cb(&tb_cl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -264,6 +277,9 @@ long rkisp_tb_shm_ioctl(struct rkisp_thunderboot_shmem *shmem)
|
||||
|
||||
void rkisp_tb_unprotect_clk(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE))
|
||||
return;
|
||||
|
||||
rkisp_tb_clocks_loader_unprotect();
|
||||
}
|
||||
EXPORT_SYMBOL(rkisp_tb_unprotect_clk);
|
||||
|
||||
@@ -281,7 +281,7 @@ static int fec_running(struct rkispp_fec_dev *fec,
|
||||
v4l2_dbg(3, rkispp_debug, &fec->v4l2_dev,
|
||||
"0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x\n"
|
||||
"0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x\n"
|
||||
"0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x\n",
|
||||
"0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x\n",
|
||||
RKISPP_CTRL_SYS_STATUS, readl(base + RKISPP_CTRL_SYS_STATUS),
|
||||
RKISPP_FEC_CTRL, readl(base + RKISPP_FEC_CTRL),
|
||||
RKISPP_FEC_RD_VIR_STRIDE, readl(base + RKISPP_FEC_RD_VIR_STRIDE),
|
||||
@@ -415,6 +415,9 @@ static const struct v4l2_file_operations fec_fops = {
|
||||
.poll = v4l2_m2m_fop_poll,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
.mmap = v4l2_m2m_fop_mmap,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl32 = video_ioctl2,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct video_device fec_videodev = {
|
||||
|
||||
@@ -1302,7 +1302,7 @@ static int rk808_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
ret = regmap_add_irq_chip(rk808->regmap, client->irq,
|
||||
IRQF_ONESHOT, -1,
|
||||
IRQF_ONESHOT | IRQF_SHARED, -1,
|
||||
rk808->regmap_irq_chip, &rk808->irq_data);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "Failed to add irq_chip %d\n", ret);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
|
||||
#define DWCMSHC_EMMC_DLL_START_POINT 16
|
||||
#define DWCMSHC_EMMC_DLL_INC 8
|
||||
#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
|
||||
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
|
||||
|
||||
#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
|
||||
@@ -233,8 +234,11 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
sdhci_writel(host, extra, DWCMSHC_HOST_CTRL3);
|
||||
|
||||
if (clock <= 52000000) {
|
||||
/* Disable DLL and reset both of sample and drive clock */
|
||||
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
|
||||
/*
|
||||
* Disable DLL and reset both of sample and drive clock.
|
||||
* The bypass bit and start bit need to set if DLL is not locked.
|
||||
*/
|
||||
sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
|
||||
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK);
|
||||
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
|
||||
sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
|
||||
@@ -264,7 +268,8 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
extra |= DLL_RXCLK_NO_INVERTER;
|
||||
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
|
||||
|
||||
/* Init DLL settings */
|
||||
/* Init DLL settings, clean start bit before resetting */
|
||||
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
|
||||
extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT |
|
||||
0x2 << DWCMSHC_EMMC_DLL_INC |
|
||||
DWCMSHC_EMMC_DLL_START;
|
||||
|
||||
@@ -1279,7 +1279,7 @@ static int rk_pcie_phy_init(struct rk_pcie *rk_pcie)
|
||||
int ret;
|
||||
struct device *dev = rk_pcie->pci->dev;
|
||||
|
||||
rk_pcie->phy = devm_phy_get(dev, "pcie-phy");
|
||||
rk_pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
|
||||
if (IS_ERR(rk_pcie->phy)) {
|
||||
if (PTR_ERR(rk_pcie->phy) != -EPROBE_DEFER)
|
||||
dev_info(dev, "missing phy\n");
|
||||
|
||||
@@ -104,7 +104,6 @@ obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o
|
||||
obj-$(CONFIG_CHARGER_BD99954) += bd99954-charger.o
|
||||
obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o
|
||||
obj-$(CONFIG_RN5T618_POWER) += rn5t618_power.o
|
||||
obj-$(CONFIG_BATTERY_CW2015) += cw2015_battery.o
|
||||
obj-$(CONFIG_BATTERY_RK816) += rk816_battery.o
|
||||
obj-$(CONFIG_BATTERY_RK817) += rk817_battery.o
|
||||
obj-$(CONFIG_CHARGER_RK817) += rk817_charger.o
|
||||
|
||||
@@ -188,19 +188,17 @@ static blk_status_t do_blktrans_all_request(struct nand_blk_dev *dev,
|
||||
struct request *req)
|
||||
{
|
||||
unsigned long block, nsect;
|
||||
char *buf = NULL;
|
||||
char *buf = NULL, *page_buf;
|
||||
struct req_iterator rq_iter;
|
||||
struct bio_vec bvec;
|
||||
int ret = BLK_STS_IOERR;
|
||||
unsigned long totle_nsect;
|
||||
unsigned long rq_len = 0;
|
||||
|
||||
block = blk_rq_pos(req);
|
||||
nsect = blk_rq_cur_bytes(req) >> 9;
|
||||
totle_nsect = (req->__data_len) >> 9;
|
||||
|
||||
if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
|
||||
get_capacity(req->rq_disk))
|
||||
if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(req->rq_disk))
|
||||
return BLK_STS_IOERR;
|
||||
|
||||
switch (req_op(req)) {
|
||||
@@ -211,20 +209,16 @@ static blk_status_t do_blktrans_all_request(struct nand_blk_dev *dev,
|
||||
case REQ_OP_READ:
|
||||
buf = mtd_read_temp_buffer;
|
||||
req_check_buffer_align(req, &buf);
|
||||
ret = nand_dev_transfer(dev,
|
||||
block,
|
||||
totle_nsect,
|
||||
buf,
|
||||
REQ_OP_READ);
|
||||
ret = nand_dev_transfer(dev, block, totle_nsect, buf, REQ_OP_READ);
|
||||
if (buf == mtd_read_temp_buffer) {
|
||||
char *p = buf;
|
||||
|
||||
rq_for_each_segment(bvec, req, rq_iter) {
|
||||
memcpy(page_address(bvec.bv_page) +
|
||||
bvec.bv_offset,
|
||||
p,
|
||||
bvec.bv_len);
|
||||
page_buf = kmap_atomic(bvec.bv_page);
|
||||
|
||||
memcpy(page_buf + bvec.bv_offset, p, bvec.bv_len);
|
||||
p += bvec.bv_len;
|
||||
kunmap_atomic(page_buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,34 +227,21 @@ static blk_status_t do_blktrans_all_request(struct nand_blk_dev *dev,
|
||||
else
|
||||
return BLK_STS_OK;
|
||||
case REQ_OP_WRITE:
|
||||
rq_for_each_segment(bvec, req, rq_iter) {
|
||||
if ((page_address(bvec.bv_page) + bvec.bv_offset) == (buf + rq_len)) {
|
||||
rq_len += bvec.bv_len;
|
||||
} else {
|
||||
if (rq_len) {
|
||||
ret = nand_dev_transfer(dev,
|
||||
block,
|
||||
rq_len >> 9,
|
||||
buf,
|
||||
REQ_OP_WRITE);
|
||||
if (ret)
|
||||
return BLK_STS_IOERR;
|
||||
else
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
block += rq_len >> 9;
|
||||
buf = (page_address(bvec.bv_page) + bvec.bv_offset);
|
||||
rq_len = bvec.bv_len;
|
||||
buf = mtd_read_temp_buffer;
|
||||
req_check_buffer_align(req, &buf);
|
||||
|
||||
if (buf == mtd_read_temp_buffer) {
|
||||
char *p = buf;
|
||||
|
||||
rq_for_each_segment(bvec, req, rq_iter) {
|
||||
page_buf = kmap_atomic(bvec.bv_page);
|
||||
memcpy(p, page_buf + bvec.bv_offset, bvec.bv_len);
|
||||
p += bvec.bv_len;
|
||||
kunmap_atomic(page_buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (rq_len) {
|
||||
ret = nand_dev_transfer(dev,
|
||||
block,
|
||||
rq_len >> 9,
|
||||
buf,
|
||||
REQ_OP_WRITE);
|
||||
}
|
||||
ret = nand_dev_transfer(dev, block, totle_nsect, buf, REQ_OP_WRITE);
|
||||
|
||||
if (ret)
|
||||
return BLK_STS_IOERR;
|
||||
|
||||
@@ -881,7 +881,9 @@ u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
|
||||
u32 sec_per_page = p_nand_info->sec_per_page;
|
||||
u32 data_size = sec_per_page * SFC_NAND_SECTOR_SIZE;
|
||||
struct nand_mega_area *meta = &p_nand_info->meta;
|
||||
int retries = 0;
|
||||
|
||||
retry:
|
||||
ret = sfc_nand_read_page_raw(cs, addr, gp_page_buf);
|
||||
memcpy(p_data, gp_page_buf, data_size);
|
||||
p_spare[0] = gp_page_buf[(data_size + meta->off0) / 4];
|
||||
@@ -903,6 +905,10 @@ u32 sfc_nand_read_page(u8 cs, u32 addr, u32 *p_data, u32 *p_spare)
|
||||
|
||||
if (p_spare)
|
||||
rkflash_print_hex("spare:", p_spare, 4, 2);
|
||||
if (ret == SFC_NAND_ECC_ERROR && retries < 1) {
|
||||
retries++;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
#include <asm/div64.h>
|
||||
|
||||
#ifndef FPGA_PLATFORM
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
#include <../drivers/devfreq/governor.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "rknpu_drv.h"
|
||||
#include "rknpu_mm.h"
|
||||
@@ -191,6 +193,7 @@ static int rknpu_freq_show(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
static ssize_t rknpu_freq_set(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
@@ -233,6 +236,13 @@ static ssize_t rknpu_freq_set(struct file *file, const char __user *ubuf,
|
||||
|
||||
return len;
|
||||
}
|
||||
#else
|
||||
static ssize_t rknpu_freq_set(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rknpu_volt_show(struct seq_file *m, void *data)
|
||||
{
|
||||
|
||||
@@ -41,8 +41,10 @@
|
||||
#include <soc/rockchip/rockchip_opp_select.h>
|
||||
#include <soc/rockchip/rockchip_system_monitor.h>
|
||||
#include <soc/rockchip/rockchip_ipa.h>
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
#include <../drivers/devfreq/governor.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "rknpu_ioctl.h"
|
||||
#include "rknpu_reset.h"
|
||||
@@ -1062,6 +1064,7 @@ static struct devfreq_dev_profile npu_devfreq_profile = {
|
||||
.get_cur_freq = npu_devfreq_get_cur_freq,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
static int devfreq_rknpu_ondemand_func(struct devfreq *df, unsigned long *freq)
|
||||
{
|
||||
struct rknpu_device *rknpu_dev = df->data;
|
||||
@@ -1085,6 +1088,7 @@ static struct devfreq_governor devfreq_rknpu_ondemand = {
|
||||
.get_target_freq = devfreq_rknpu_ondemand_func,
|
||||
.event_handler = devfreq_rknpu_ondemand_handler,
|
||||
};
|
||||
#endif
|
||||
|
||||
static unsigned long npu_get_static_power(struct devfreq *devfreq,
|
||||
unsigned long voltage)
|
||||
@@ -1191,11 +1195,13 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev)
|
||||
dev_pm_opp_put(opp);
|
||||
dp->initial_freq = rknpu_dev->current_freq;
|
||||
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
ret = devfreq_add_governor(&devfreq_rknpu_ondemand);
|
||||
if (ret) {
|
||||
LOG_DEV_ERROR(dev, "failed to add rknpu_ondemand governor\n");
|
||||
goto err_remove_table;
|
||||
}
|
||||
#endif
|
||||
|
||||
rknpu_dev->devfreq = devm_devfreq_add_device(dev, dp, "rknpu_ondemand",
|
||||
(void *)rknpu_dev);
|
||||
@@ -1247,7 +1253,9 @@ out:
|
||||
return 0;
|
||||
|
||||
err_remove_governor:
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
devfreq_remove_governor(&devfreq_rknpu_ondemand);
|
||||
#endif
|
||||
err_remove_table:
|
||||
dev_pm_opp_of_remove_table(dev);
|
||||
|
||||
@@ -1325,11 +1333,13 @@ static int rknpu_devfreq_init(struct rknpu_device *rknpu_dev)
|
||||
}
|
||||
dp->initial_freq = rknpu_dev->current_freq;
|
||||
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
ret = devfreq_add_governor(&devfreq_rknpu_ondemand);
|
||||
if (ret) {
|
||||
LOG_DEV_ERROR(dev, "failed to add rknpu_ondemand governor\n");
|
||||
goto err_remove_table;
|
||||
}
|
||||
#endif
|
||||
|
||||
rknpu_dev->devfreq = devm_devfreq_add_device(dev, dp, "rknpu_ondemand",
|
||||
(void *)rknpu_dev);
|
||||
@@ -1380,7 +1390,9 @@ out:
|
||||
return 0;
|
||||
|
||||
err_remove_governor:
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
devfreq_remove_governor(&devfreq_rknpu_ondemand);
|
||||
#endif
|
||||
err_remove_table:
|
||||
dev_pm_opp_of_remove_table(dev);
|
||||
|
||||
@@ -1396,7 +1408,9 @@ static int rknpu_devfreq_remove(struct rknpu_device *rknpu_dev)
|
||||
devfreq_unregister_opp_notifier(rknpu_dev->dev,
|
||||
rknpu_dev->devfreq);
|
||||
dev_pm_opp_of_remove_table(rknpu_dev->dev);
|
||||
#ifdef CONFIG_PM_DEVFREQ
|
||||
devfreq_remove_governor(&devfreq_rknpu_ondemand);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -52,6 +52,7 @@ struct rockchip_domain_info {
|
||||
int mem_status_mask;
|
||||
int repair_status_mask;
|
||||
bool keepon_startup;
|
||||
bool always_on;
|
||||
u32 pwr_offset;
|
||||
u32 mem_offset;
|
||||
u32 req_offset;
|
||||
@@ -117,6 +118,35 @@ module_param_named(always_on, pm_domain_always_on, bool, 0644);
|
||||
MODULE_PARM_DESC(always_on,
|
||||
"Always keep pm domains power on except for system suspend.");
|
||||
|
||||
#ifdef MODULE
|
||||
static bool keepon_startup = true;
|
||||
static void rockchip_pd_keepon_do_release(void);
|
||||
|
||||
static int pd_param_set_keepon_startup(const char *val,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = param_set_bool(val, kp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!keepon_startup)
|
||||
rockchip_pd_keepon_do_release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops pd_keepon_startup_ops = {
|
||||
.set = pd_param_set_keepon_startup,
|
||||
.get = param_get_bool,
|
||||
};
|
||||
|
||||
module_param_cb(keepon_startup, &pd_keepon_startup_ops, &keepon_startup, 0644);
|
||||
MODULE_PARM_DESC(keepon_startup,
|
||||
"Keep pm domains power on during system startup.");
|
||||
#endif
|
||||
|
||||
static void rockchip_pmu_lock(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
mutex_lock(&pd->pmu->mutex);
|
||||
@@ -847,6 +877,26 @@ static void rockchip_pd_qos_init(struct rockchip_pm_domain *pd)
|
||||
}
|
||||
}
|
||||
|
||||
static int rockchip_pd_add_alwasy_on_flag(struct rockchip_pm_domain *pd)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (pd->genpd.flags & GENPD_FLAG_ALWAYS_ON)
|
||||
return 0;
|
||||
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
if (!rockchip_pmu_domain_is_on(pd)) {
|
||||
error = rockchip_pd_power(pd, true);
|
||||
if (error) {
|
||||
dev_err(pd->pmu->dev,
|
||||
"failed to power on domain '%s': %d\n",
|
||||
pd->genpd.name, error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
||||
struct device_node *node)
|
||||
{
|
||||
@@ -1033,20 +1083,11 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
||||
pd->genpd.detach_dev = rockchip_pd_detach_dev;
|
||||
if (pd_info->active_wakeup)
|
||||
pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||
#ifndef MODULE
|
||||
if (pd_info->keepon_startup) {
|
||||
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
|
||||
if (!rockchip_pmu_domain_is_on(pd)) {
|
||||
error = rockchip_pd_power(pd, true);
|
||||
if (error) {
|
||||
dev_err(pmu->dev,
|
||||
"failed to power on domain '%s': %d\n",
|
||||
node->name, error);
|
||||
goto err_unprepare_clocks;
|
||||
}
|
||||
}
|
||||
if (pd_info->always_on || pd_info->keepon_startup) {
|
||||
error = rockchip_pd_add_alwasy_on_flag(pd);
|
||||
if (error)
|
||||
goto err_unprepare_clocks;
|
||||
}
|
||||
#endif
|
||||
rockchip_pd_qos_init(pd);
|
||||
|
||||
pm_genpd_init(&pd->genpd, NULL, !rockchip_pmu_domain_is_on(pd));
|
||||
@@ -1181,46 +1222,36 @@ err_out:
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
static void rockchip_pd_keepon_do_release(struct generic_pm_domain *genpd,
|
||||
struct rockchip_pm_domain *pd)
|
||||
{
|
||||
struct pm_domain_data *pm_data;
|
||||
int enable_count;
|
||||
|
||||
pd->genpd.flags &= (~GENPD_FLAG_ALWAYS_ON);
|
||||
list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
|
||||
if (!atomic_read(&pm_data->dev->power.usage_count)) {
|
||||
enable_count = 0;
|
||||
if (!pm_runtime_enabled(pm_data->dev)) {
|
||||
pm_runtime_enable(pm_data->dev);
|
||||
enable_count = 1;
|
||||
}
|
||||
pm_runtime_get_sync(pm_data->dev);
|
||||
pm_runtime_put_sync(pm_data->dev);
|
||||
if (enable_count)
|
||||
pm_runtime_disable(pm_data->dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __init rockchip_pd_keepon_release(void)
|
||||
static void rockchip_pd_keepon_do_release(void)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
struct rockchip_pm_domain *pd;
|
||||
int i;
|
||||
|
||||
if (!g_pmu)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
for (i = 0; i < g_pmu->genpd_data.num_domains; i++) {
|
||||
genpd = g_pmu->genpd_data.domains[i];
|
||||
if (genpd) {
|
||||
pd = to_rockchip_pd(genpd);
|
||||
if (pd->info->keepon_startup)
|
||||
rockchip_pd_keepon_do_release(genpd, pd);
|
||||
if (pd->info->always_on)
|
||||
continue;
|
||||
if (!pd->info->keepon_startup)
|
||||
continue;
|
||||
if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON))
|
||||
continue;
|
||||
genpd->flags &= (~GENPD_FLAG_ALWAYS_ON);
|
||||
queue_work(pm_wq, &genpd->power_off_work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
static int __init rockchip_pd_keepon_release(void)
|
||||
{
|
||||
rockchip_pd_keepon_do_release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall_sync(rockchip_pd_keepon_release);
|
||||
|
||||
@@ -819,6 +819,7 @@ static int mpp_task_run(struct mpp_dev *mpp,
|
||||
*/
|
||||
mpp_reset_down_read(mpp->reset_group);
|
||||
|
||||
mpp_iommu_dev_activate(mpp->iommu_info, mpp);
|
||||
if (mpp->dev_ops->run)
|
||||
mpp->dev_ops->run(mpp, task);
|
||||
|
||||
@@ -2032,39 +2033,21 @@ int mpp_task_dump_reg(struct mpp_dev *mpp,
|
||||
|
||||
int mpp_task_dump_hw_reg(struct mpp_dev *mpp)
|
||||
{
|
||||
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) {
|
||||
u32 i;
|
||||
u32 s = mpp->var->hw_info->reg_start;
|
||||
u32 e = mpp->var->hw_info->reg_end;
|
||||
u32 i;
|
||||
u32 s = mpp->var->hw_info->reg_start;
|
||||
u32 e = mpp->var->hw_info->reg_end;
|
||||
|
||||
mpp_err("--- dump hardware register ---\n");
|
||||
for (i = s; i <= e; i++) {
|
||||
u32 reg = i * sizeof(u32);
|
||||
mpp_err("--- dump hardware register ---\n");
|
||||
for (i = s; i <= e; i++) {
|
||||
u32 reg = i * sizeof(u32);
|
||||
|
||||
mpp_err("reg[%03d]: %04x: 0x%08x\n",
|
||||
mpp_err("reg[%03d]: %04x: 0x%08x\n",
|
||||
i, reg, readl_relaxed(mpp->reg_base + reg));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpp_iommu_handle(struct iommu_domain *iommu,
|
||||
struct device *iommu_dev,
|
||||
unsigned long iova,
|
||||
int status, void *arg)
|
||||
{
|
||||
struct mpp_dev *mpp = (struct mpp_dev *)arg;
|
||||
|
||||
dev_err(mpp->dev, "fault addr 0x%08lx status %x\n", iova, status);
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
|
||||
if (mpp->iommu_info->hdl)
|
||||
mpp->iommu_info->hdl(iommu, iommu_dev, iova, status, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mpp_reg_show(struct mpp_dev *mpp, u32 offset)
|
||||
{
|
||||
if (!mpp)
|
||||
@@ -2167,10 +2150,6 @@ int mpp_dev_probe(struct mpp_dev *mpp,
|
||||
if (ret)
|
||||
goto failed;
|
||||
}
|
||||
/* set iommu fault handler */
|
||||
if (mpp->iommu_info)
|
||||
iommu_set_fault_handler(mpp->iommu_info->domain,
|
||||
mpp_iommu_handle, mpp);
|
||||
|
||||
/* read hardware id */
|
||||
if (hw_info->reg_id >= 0) {
|
||||
@@ -2270,6 +2249,7 @@ irqreturn_t mpp_dev_irq(int irq, void *param)
|
||||
/* normal condition, set state and wake up isr thread */
|
||||
set_bit(TASK_STATE_IRQ, &task->state);
|
||||
}
|
||||
mpp_iommu_dev_deactivate(mpp->iommu_info, mpp);
|
||||
} else {
|
||||
mpp_debug(DEBUG_IRQ_CHECK, "error, task is null\n");
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ struct mpp_task;
|
||||
struct mpp_session;
|
||||
struct mpp_dma_session;
|
||||
struct mpp_taskqueue;
|
||||
struct iommu_domain;
|
||||
|
||||
/* data common struct for parse out */
|
||||
struct mpp_request {
|
||||
@@ -342,6 +343,8 @@ struct mpp_dev {
|
||||
void __iomem *reg_base;
|
||||
struct mpp_grf_info *grf_info;
|
||||
struct mpp_iommu_info *iommu_info;
|
||||
int (*fault_handler)(struct iommu_domain *iommu, struct device *iommu_dev,
|
||||
unsigned long iova, int status, void *arg);
|
||||
|
||||
atomic_t reset_request;
|
||||
atomic_t session_index;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "mpp_debug.h"
|
||||
#include "mpp_iommu.h"
|
||||
#include "mpp_common.h"
|
||||
|
||||
static struct mpp_dma_buffer *
|
||||
mpp_dma_find_buffer_fd(struct mpp_dma_session *dma, int fd)
|
||||
@@ -388,6 +389,29 @@ int mpp_iommu_attach(struct mpp_iommu_info *info)
|
||||
return iommu_attach_group(info->domain, info->group);
|
||||
}
|
||||
|
||||
static int mpp_iommu_handle(struct iommu_domain *iommu,
|
||||
struct device *iommu_dev,
|
||||
unsigned long iova,
|
||||
int status, void *arg)
|
||||
{
|
||||
struct mpp_dev *mpp = (struct mpp_dev *)arg;
|
||||
|
||||
dev_err(iommu_dev, "fault addr 0x%08lx status %x arg %p\n",
|
||||
iova, status, arg);
|
||||
|
||||
if (!mpp) {
|
||||
dev_err(iommu_dev, "pagefault without device to handle\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mpp->dev_ops && mpp->dev_ops->dump_dev)
|
||||
mpp->dev_ops->dump_dev(mpp);
|
||||
else
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mpp_iommu_info *
|
||||
mpp_iommu_probe(struct device *dev)
|
||||
{
|
||||
@@ -446,10 +470,12 @@ mpp_iommu_probe(struct device *dev)
|
||||
}
|
||||
|
||||
init_rwsem(&info->rw_sem);
|
||||
spin_lock_init(&info->dev_lock);
|
||||
info->dev = dev;
|
||||
info->pdev = pdev;
|
||||
info->group = group;
|
||||
info->domain = domain;
|
||||
info->dev_active = NULL;
|
||||
info->irq = platform_get_irq(pdev, 0);
|
||||
info->got_irq = (info->irq < 0) ? false : true;
|
||||
|
||||
@@ -507,3 +533,47 @@ int mpp_iommu_flush_tlb(struct mpp_iommu_info *info)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mpp_iommu_dev_activate(struct mpp_iommu_info *info, struct mpp_dev *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&info->dev_lock, flags);
|
||||
|
||||
if (info->dev_active || !dev) {
|
||||
dev_err(info->dev, "can not activate %s -> %s\n",
|
||||
info->dev_active ? dev_name(info->dev_active->dev) : NULL,
|
||||
dev ? dev_name(dev->dev) : NULL);
|
||||
ret = -EINVAL;
|
||||
} else {
|
||||
info->dev_active = dev;
|
||||
/* switch domain pagefault handler and arg depending on device */
|
||||
iommu_set_fault_handler(info->domain, dev->fault_handler ?
|
||||
dev->fault_handler : mpp_iommu_handle, dev);
|
||||
|
||||
dev_dbg(info->dev, "activate -> %p %s\n", dev, dev_name(dev->dev));
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&info->dev_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mpp_iommu_dev_deactivate(struct mpp_iommu_info *info, struct mpp_dev *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&info->dev_lock, flags);
|
||||
|
||||
if (info->dev_active != dev)
|
||||
dev_err(info->dev, "can not deactivate %s when %s activated\n",
|
||||
dev_name(dev->dev),
|
||||
info->dev_active ? dev_name(info->dev_active->dev) : NULL);
|
||||
|
||||
dev_dbg(info->dev, "deactivate %p\n", info->dev_active);
|
||||
info->dev_active = NULL;
|
||||
spin_unlock_irqrestore(&info->dev_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ struct mpp_rk_iommu {
|
||||
u32 is_paged;
|
||||
};
|
||||
|
||||
struct mpp_dev;
|
||||
|
||||
struct mpp_iommu_info {
|
||||
struct rw_semaphore rw_sem;
|
||||
|
||||
@@ -73,6 +75,10 @@ struct mpp_iommu_info {
|
||||
struct iommu_group *group;
|
||||
struct mpp_rk_iommu *iommu;
|
||||
iommu_fault_handler_t hdl;
|
||||
|
||||
spinlock_t dev_lock;
|
||||
struct mpp_dev *dev_active;
|
||||
|
||||
u32 av1d_iommu;
|
||||
int irq;
|
||||
int got_irq;
|
||||
@@ -110,6 +116,9 @@ int mpp_iommu_flush_tlb(struct mpp_iommu_info *info);
|
||||
int mpp_av1_iommu_disable(struct device *dev);
|
||||
int mpp_av1_iommu_enable(struct device *dev);
|
||||
|
||||
int mpp_iommu_dev_activate(struct mpp_iommu_info *info, struct mpp_dev *dev);
|
||||
int mpp_iommu_dev_deactivate(struct mpp_iommu_info *info, struct mpp_dev *dev);
|
||||
|
||||
static inline int mpp_iommu_down_read(struct mpp_iommu_info *info)
|
||||
{
|
||||
if (info)
|
||||
|
||||
@@ -420,8 +420,10 @@ static int rkvdec2_isr(struct mpp_dev *mpp)
|
||||
RKVDEC_TIMEOUT_STA | RKVDEC_ERROR_STA;
|
||||
if (err_mask & task->irq_status) {
|
||||
atomic_inc(&mpp->reset_request);
|
||||
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status);
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) {
|
||||
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status);
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
}
|
||||
}
|
||||
|
||||
mpp_task_finish(mpp_task->session, mpp_task);
|
||||
@@ -1442,7 +1444,7 @@ static int rkvdec2_core_probe(struct platform_device *pdev)
|
||||
mpp->dev_ops->task_worker = rkvdec2_soft_ccu_worker;
|
||||
kthread_init_work(&mpp->work, rkvdec2_soft_ccu_worker);
|
||||
|
||||
mpp->iommu_info->hdl = rkvdec2_ccu_iommu_fault_handle;
|
||||
mpp->fault_handler = rkvdec2_ccu_iommu_fault_handle;
|
||||
/* get irq request */
|
||||
ret = devm_request_threaded_irq(dev, mpp->irq, rkvdec2_soft_ccu_irq, NULL,
|
||||
IRQF_SHARED, dev_name(dev), mpp);
|
||||
|
||||
@@ -1066,6 +1066,7 @@ static int rkvdec2_link_power_on(struct mpp_dev *mpp)
|
||||
mpp_clk_set_rate(&dec->cabac_clk_info, CLK_MODE_ADVANCED);
|
||||
mpp_clk_set_rate(&dec->hevc_cabac_clk_info, CLK_MODE_ADVANCED);
|
||||
mpp_devfreq_set_core_rate(mpp, CLK_MODE_ADVANCED);
|
||||
mpp_iommu_dev_activate(mpp->iommu_info, mpp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1092,6 +1093,7 @@ static void rkvdec2_link_power_off(struct mpp_dev *mpp)
|
||||
mpp_clk_set_rate(&dec->cabac_clk_info, CLK_MODE_NORMAL);
|
||||
mpp_clk_set_rate(&dec->hevc_cabac_clk_info, CLK_MODE_NORMAL);
|
||||
mpp_devfreq_set_core_rate(mpp, CLK_MODE_NORMAL);
|
||||
mpp_iommu_dev_deactivate(mpp->iommu_info, mpp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1614,6 +1616,8 @@ static int rkvdec2_ccu_power_on(struct mpp_taskqueue *queue,
|
||||
pm_stay_awake(mpp->dev);
|
||||
if (mpp->hw_ops->clk_on)
|
||||
mpp->hw_ops->clk_on(mpp);
|
||||
|
||||
mpp_iommu_dev_activate(mpp->iommu_info, mpp);
|
||||
}
|
||||
mpp_debug(DEBUG_CCU, "power on\n");
|
||||
}
|
||||
@@ -1642,6 +1646,7 @@ static int rkvdec2_ccu_power_off(struct mpp_taskqueue *queue,
|
||||
pm_relax(mpp->dev);
|
||||
pm_runtime_mark_last_busy(mpp->dev);
|
||||
pm_runtime_put_autosuspend(mpp->dev);
|
||||
mpp_iommu_dev_deactivate(mpp->iommu_info, mpp);
|
||||
}
|
||||
mpp_debug(DEBUG_CCU, "power off\n");
|
||||
}
|
||||
|
||||
@@ -530,9 +530,11 @@ static int rkvenc_isr(struct mpp_dev *mpp)
|
||||
|
||||
if (task->irq_status & RKVENC_INT_ERROR_BITS) {
|
||||
atomic_inc(&mpp->reset_request);
|
||||
/* dump register */
|
||||
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status);
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG)) {
|
||||
/* dump error register */
|
||||
mpp_debug(DEBUG_DUMP_ERR_REG, "irq_status: %08x\n", task->irq_status);
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
}
|
||||
}
|
||||
|
||||
/* unmap reserve buffer */
|
||||
|
||||
@@ -1200,9 +1200,10 @@ static int rkvenc_isr(struct mpp_dev *mpp)
|
||||
|
||||
if (task->irq_status & enc->hw_info->err_mask) {
|
||||
atomic_inc(&mpp->reset_request);
|
||||
/* dump register */
|
||||
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
/* dump register */
|
||||
if (mpp_debug_unlikely(DEBUG_DUMP_ERR_REG))
|
||||
mpp_task_dump_hw_reg(mpp);
|
||||
}
|
||||
|
||||
mpp_task_finish(mpp_task->session, mpp_task);
|
||||
|
||||
@@ -21,8 +21,6 @@ enum job_flags {
|
||||
RGA_JOB_UNSUPPORT_RGA_MMU = 1 << 4,
|
||||
};
|
||||
|
||||
struct rga_scheduler_t *rga_job_get_scheduler(struct rga_job *job);
|
||||
|
||||
void rga_job_session_destroy(struct rga_session *session);
|
||||
|
||||
void rga_job_scheduler_dump_info(struct rga_scheduler_t *scheduler);
|
||||
@@ -52,10 +50,4 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job
|
||||
int rga_request_manager_init(struct rga_pending_request_manager **request_manager_session);
|
||||
int rga_request_manager_remove(struct rga_pending_request_manager **request_manager_session);
|
||||
|
||||
struct rga_job *
|
||||
rga_scheduler_get_pending_job_list(struct rga_scheduler_t *scheduler);
|
||||
|
||||
struct rga_job *
|
||||
rga_scheduler_get_running_job(struct rga_scheduler_t *scheduler);
|
||||
|
||||
#endif /* __LINUX_RKRGA_JOB_H_ */
|
||||
|
||||
@@ -270,8 +270,8 @@ int rga_kernel_commit(struct rga_req *cmd)
|
||||
struct rga_pending_request_manager *request_manager = rga_drvdata->pend_request_manager;
|
||||
|
||||
session = rga_session_init();
|
||||
if (!session)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(session))
|
||||
return PTR_ERR(session);
|
||||
|
||||
request_id = rga_request_alloc(0, session);
|
||||
if (request_id < 0) {
|
||||
@@ -561,22 +561,38 @@ static int rga_session_manager_remove(struct rga_session_manager **session_manag
|
||||
|
||||
static struct rga_session *rga_session_init(void)
|
||||
{
|
||||
int new_id;
|
||||
|
||||
struct rga_session_manager *session_manager = NULL;
|
||||
struct rga_session *session = kzalloc(sizeof(*session), GFP_KERNEL);
|
||||
struct rga_session *session = NULL;
|
||||
|
||||
session_manager = rga_drvdata->session_manager;
|
||||
if (session_manager == NULL) {
|
||||
pr_err("rga_session_manager is null!\n");
|
||||
kfree(session);
|
||||
return NULL;
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
session = kzalloc(sizeof(*session), GFP_KERNEL);
|
||||
if (!session) {
|
||||
pr_err("rga_session alloc failed\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
mutex_lock(&session_manager->lock);
|
||||
|
||||
idr_preload(GFP_KERNEL);
|
||||
session->id = idr_alloc(&session_manager->ctx_id_idr, session, 1, 0, GFP_ATOMIC);
|
||||
session_manager->session_cnt++;
|
||||
new_id = idr_alloc_cyclic(&session_manager->ctx_id_idr, session, 1, 0, GFP_NOWAIT);
|
||||
idr_preload_end();
|
||||
if (new_id < 0) {
|
||||
mutex_unlock(&session_manager->lock);
|
||||
|
||||
pr_err("rga_session alloc id failed!\n");
|
||||
kfree(session);
|
||||
return ERR_PTR(new_id);
|
||||
}
|
||||
|
||||
session->id = new_id;
|
||||
session_manager->session_cnt++;
|
||||
|
||||
mutex_unlock(&session_manager->lock);
|
||||
|
||||
@@ -1140,8 +1156,8 @@ static int rga_open(struct inode *inode, struct file *file)
|
||||
struct rga_session *session = NULL;
|
||||
|
||||
session = rga_session_init();
|
||||
if (!session)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(session))
|
||||
return PTR_ERR(session);
|
||||
|
||||
file->private_data = (void *)session;
|
||||
|
||||
|
||||
@@ -14,42 +14,6 @@
|
||||
#include "rga_iommu.h"
|
||||
#include "rga_debugger.h"
|
||||
|
||||
struct rga_job *
|
||||
rga_scheduler_get_pending_job_list(struct rga_scheduler_t *scheduler)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct rga_job *job;
|
||||
|
||||
spin_lock_irqsave(&scheduler->irq_lock, flags);
|
||||
|
||||
job = list_first_entry_or_null(&scheduler->todo_list,
|
||||
struct rga_job, head);
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
struct rga_job *
|
||||
rga_scheduler_get_running_job(struct rga_scheduler_t *scheduler)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct rga_job *job;
|
||||
|
||||
spin_lock_irqsave(&scheduler->irq_lock, flags);
|
||||
|
||||
job = scheduler->running_job;
|
||||
|
||||
spin_unlock_irqrestore(&scheduler->irq_lock, flags);
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
struct rga_scheduler_t *rga_job_get_scheduler(struct rga_job *job)
|
||||
{
|
||||
return job->scheduler;
|
||||
}
|
||||
|
||||
static void rga_job_free(struct rga_job *job)
|
||||
{
|
||||
free_page((unsigned long)job);
|
||||
@@ -411,7 +375,7 @@ static struct rga_scheduler_t *rga_job_schedule(struct rga_job *job)
|
||||
job->scheduler = rga_drvdata->scheduler[0];
|
||||
}
|
||||
|
||||
scheduler = rga_job_get_scheduler(job);
|
||||
scheduler = job->scheduler;
|
||||
if (scheduler == NULL) {
|
||||
pr_err("failed to get scheduler, %s(%d)\n", __func__, __LINE__);
|
||||
job->ret = -EFAULT;
|
||||
@@ -832,8 +796,6 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job
|
||||
rga_request_get(request);
|
||||
mutex_unlock(&request_manager->lock);
|
||||
|
||||
rga_job_cleanup(job);
|
||||
|
||||
spin_lock_irqsave(&request->lock, flags);
|
||||
|
||||
if (job->ret < 0) {
|
||||
@@ -848,6 +810,8 @@ int rga_request_release_signal(struct rga_scheduler_t *scheduler, struct rga_job
|
||||
|
||||
spin_unlock_irqrestore(&request->lock, flags);
|
||||
|
||||
rga_job_cleanup(job);
|
||||
|
||||
if ((failed_count + finished_count) >= request->task_count) {
|
||||
spin_lock_irqsave(&request->lock, flags);
|
||||
|
||||
@@ -1188,6 +1152,7 @@ static int rga_request_free_cb(int id, void *ptr, void *data)
|
||||
|
||||
int rga_request_alloc(uint32_t flags, struct rga_session *session)
|
||||
{
|
||||
int new_id;
|
||||
struct rga_pending_request_manager *request_manager;
|
||||
struct rga_request *request;
|
||||
|
||||
@@ -1218,17 +1183,17 @@ int rga_request_alloc(uint32_t flags, struct rga_session *session)
|
||||
mutex_lock(&request_manager->lock);
|
||||
|
||||
idr_preload(GFP_KERNEL);
|
||||
request->id = idr_alloc(&request_manager->request_idr, request, 1, 0, GFP_KERNEL);
|
||||
new_id = idr_alloc_cyclic(&request_manager->request_idr, request, 1, 0, GFP_NOWAIT);
|
||||
idr_preload_end();
|
||||
|
||||
if (request->id <= 0) {
|
||||
pr_err("alloc request_id failed!\n");
|
||||
if (new_id < 0) {
|
||||
pr_err("request alloc id failed!\n");
|
||||
|
||||
mutex_unlock(&request_manager->lock);
|
||||
kfree(request);
|
||||
return -EFAULT;
|
||||
return new_id;
|
||||
}
|
||||
|
||||
request->id = new_id;
|
||||
request_manager->request_count++;
|
||||
|
||||
mutex_unlock(&request_manager->lock);
|
||||
|
||||
@@ -1869,7 +1869,7 @@ void rga_mm_unmap_job_info(struct rga_job *job)
|
||||
uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer,
|
||||
struct rga_session *session)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0, new_id;
|
||||
struct rga_mm *mm;
|
||||
struct rga_internal_buffer *internal_buffer;
|
||||
|
||||
@@ -1911,9 +1911,14 @@ uint32_t rga_mm_import_buffer(struct rga_external_buffer *external_buffer,
|
||||
* allocation under our spinlock.
|
||||
*/
|
||||
idr_preload(GFP_KERNEL);
|
||||
internal_buffer->handle = idr_alloc(&mm->memory_idr, internal_buffer, 1, 0, GFP_KERNEL);
|
||||
new_id = idr_alloc_cyclic(&mm->memory_idr, internal_buffer, 1, 0, GFP_NOWAIT);
|
||||
idr_preload_end();
|
||||
if (new_id < 0) {
|
||||
pr_err("internal_buffer alloc id failed!\n");
|
||||
goto FREE_INTERNAL_BUFFER;
|
||||
}
|
||||
|
||||
internal_buffer->handle = new_id;
|
||||
mm->buffer_count++;
|
||||
|
||||
if (DEBUGGER_EN(MM)) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define __DW_HDMI__
|
||||
|
||||
#include <drm/drm_property.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <sound/hdmi-codec.h>
|
||||
#include <media/cec.h>
|
||||
|
||||
@@ -248,8 +249,9 @@ struct dw_hdmi_plat_data {
|
||||
u64 (*get_grf_color_fmt)(void *data);
|
||||
void (*convert_to_split_mode)(struct drm_display_mode *mode);
|
||||
void (*convert_to_origin_mode)(struct drm_display_mode *mode);
|
||||
int (*dclk_set)(void *data, bool enable);
|
||||
int (*dclk_set)(void *data, bool enable, int vp_id);
|
||||
int (*link_clk_set)(void *data, bool enable);
|
||||
int (*get_vp_id)(struct drm_crtc_state *crtc_state);
|
||||
|
||||
/* Vendor Property support */
|
||||
const struct dw_hdmi_property_ops *property_ops;
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
#define PCLK_GMAC 367
|
||||
#define PCLK_PMU_PRE 368
|
||||
#define PCLK_SIM_CARD 369
|
||||
#define PCLK_MIPIPHY 370
|
||||
|
||||
/* hclk gates */
|
||||
#define HCLK_SFC 439
|
||||
|
||||
@@ -631,7 +631,7 @@
|
||||
#define CLK_DSIHOST1 635
|
||||
#define CLK_VOP_PMU 636
|
||||
#define ACLK_VOP_DOBY 637
|
||||
#define ACLK_VOP_SUB_SRC 638
|
||||
#define ACLK_VOP_DIV2_SRC 638
|
||||
#define CLK_USBDP_PHY0_IMMORTAL 639
|
||||
#define CLK_USBDP_PHY1_IMMORTAL 640
|
||||
#define CLK_PMU0 641
|
||||
|
||||
49
include/linux/sram_heap.h
Normal file
49
include/linux/sram_heap.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* SRAM DMA-Heap exporter && support alloc page and dmabuf on kernel
|
||||
*
|
||||
* Copyright (C) Rockchip Electronics Co., Ltd.
|
||||
*
|
||||
* Author: Huang Lee <Putin.li@rock-chips.com>
|
||||
*/
|
||||
#ifndef _LINUX_SRAM_HEAP_H
|
||||
#define _LINUX_SRAM_HEAP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#if IS_REACHABLE(CONFIG_DMABUF_HEAPS_SRAM)
|
||||
struct dma_buf *sram_heap_alloc_dma_buf(size_t size);
|
||||
struct page *sram_heap_alloc_pages(size_t size);
|
||||
void sram_heap_free_pages(struct page *p);
|
||||
void sram_heap_free_dma_buf(struct dma_buf *dmabuf);
|
||||
void *sram_heap_get_vaddr(struct dma_buf *dmabuf);
|
||||
phys_addr_t sram_heap_get_paddr(struct dma_buf *dmabuf);
|
||||
|
||||
#else
|
||||
static inline struct dma_buf *sram_heap_alloc_dma_buf(size_t size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct page *sram_heap_alloc_pages(size_t size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void sram_heap_free_pages(struct page *p) {}
|
||||
static inline void sram_heap_free_dma_buf(struct dma_buf *dmabuf) {}
|
||||
|
||||
static inline void *sram_heap_get_vaddr(struct dma_buf *dmabuf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline phys_addr_t sram_heap_get_paddr(struct dma_buf *dmabuf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -161,6 +161,7 @@ config SND_SOC_ALL_CODECS
|
||||
imply SND_SOC_RK3228
|
||||
imply SND_SOC_RK3308
|
||||
imply SND_SOC_RK3328
|
||||
imply SND_SOC_RK730
|
||||
imply SND_SOC_RK817
|
||||
imply SND_SOC_RT274
|
||||
imply SND_SOC_RT286
|
||||
@@ -1096,6 +1097,10 @@ config SND_SOC_RK3328
|
||||
tristate "Rockchip RK3328 audio CODEC"
|
||||
select REGMAP_MMIO
|
||||
|
||||
config SND_SOC_RK730
|
||||
tristate "Rockchip RK730 CODEC"
|
||||
select REGMAP_I2C
|
||||
|
||||
config SND_SOC_RK817
|
||||
tristate "Rockchip RK817 CODEC"
|
||||
depends on MFD_RK808
|
||||
|
||||
@@ -168,6 +168,7 @@ snd-soc-rk312x-objs := rk312x_codec.o
|
||||
snd-soc-rk3228-objs := rk3228_codec.o
|
||||
snd-soc-rk3308-objs := rk3308_codec.o
|
||||
snd-soc-rk3328-objs := rk3328_codec.o
|
||||
snd-soc-rk730-objs := rk730.o
|
||||
snd-soc-rk817-objs := rk817_codec.o
|
||||
snd-soc-rk-codec-digital-objs := rk_codec_digital.o
|
||||
snd-soc-rl6231-objs := rl6231.o
|
||||
@@ -492,6 +493,7 @@ obj-$(CONFIG_SND_SOC_RK312X) += snd-soc-rk312x.o
|
||||
obj-$(CONFIG_SND_SOC_RK3228) += snd-soc-rk3228.o
|
||||
obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o
|
||||
obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o
|
||||
obj-$(CONFIG_SND_SOC_RK730) += snd-soc-rk730.o
|
||||
obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o
|
||||
obj-$(CONFIG_SND_SOC_RK_CODEC_DIGITAL) += snd-soc-rk-codec-digital.o
|
||||
obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o
|
||||
|
||||
971
sound/soc/codecs/rk730.c
Normal file
971
sound/soc/codecs/rk730.c
Normal file
@@ -0,0 +1,971 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* rk730.c -- RK730 ALSA SoC Audio driver
|
||||
*
|
||||
* Copyright (C) 2022 Rockchip Electronics Co.,Ltd
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/clk.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
#include <sound/pcm_params.h>
|
||||
#include <sound/soc.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#include "rk730.h"
|
||||
|
||||
enum rk730_mix_mode {
|
||||
RK730_MIX_MODE_1_PATH,
|
||||
RK730_MIX_MODE_2_PATHS,
|
||||
RK730_MIX_MODE_3_PATHS,
|
||||
};
|
||||
|
||||
enum rk730_chop_freq {
|
||||
RK730_CHOP_FREQ_NONE,
|
||||
RK730_CHOP_FREQ_200KHZ,
|
||||
RK730_CHOP_FREQ_400KHZ,
|
||||
RK730_CHOP_FREQ_800KHZ,
|
||||
};
|
||||
|
||||
struct rk730_priv {
|
||||
struct regmap *regmap;
|
||||
struct clk *mclk;
|
||||
atomic_t mix_mode;
|
||||
};
|
||||
|
||||
/* ADC Digital Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(adc_dig_tlv, -95625, 375, 0);
|
||||
/* DAC Digital Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(dac_dig_tlv, -95625, 375, 0);
|
||||
/* D2S Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(d2s_tlv, -1800, 300, 0);
|
||||
/* ADC Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(adc_tlv, -1200, 300, 0);
|
||||
/* MUX Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(mux_tlv, -600, 600, 0);
|
||||
/* MIX Buf Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(mix_buf_tlv, -1800, 300, 0);
|
||||
/* HP Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(hp_tlv, 0, 300, 0);
|
||||
/* LINEOUT Volume */
|
||||
static const DECLARE_TLV_DB_SCALE(lineout_tlv, 0, 300, 0);
|
||||
/* MIC Boost Volume */
|
||||
static const DECLARE_TLV_DB_RANGE(micboost_tlv,
|
||||
0, 2, TLV_DB_SCALE_ITEM(0, 600, 0),
|
||||
3, 4, TLV_DB_SCALE_ITEM(2400, 1200, 0),
|
||||
5, 7, TLV_DB_SCALE_ITEM(4200, 600, 0),
|
||||
8, 8, TLV_DB_SCALE_ITEM(-300, 0, 0),
|
||||
16, 16, TLV_DB_SCALE_ITEM(-600, 0, 0),
|
||||
24, 24, TLV_DB_SCALE_ITEM(-900, 0, 0)
|
||||
);
|
||||
|
||||
static const char * const mux_out_l_text[] = { "DIFF", "MIC1N", "MIC2N" };
|
||||
static const char * const mux_out_r_text[] = { "DIFF", "MIC2P", "MIC1P" };
|
||||
static const char * const mux_input_l_text[] = { "DIFF", "VINP1", "VINN1" };
|
||||
static const char * const mux_input_r_text[] = { "DIFF", "VINP2", "VINN2" };
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(mux_out_l_enum, RK730_MUXER_0, 2, mux_out_l_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mux_out_r_enum, RK730_MUXER_0, 6, mux_out_r_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mux_input_l_enum, RK730_ADC_PGA_BLOCK_0,
|
||||
4, mux_input_l_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mux_input_r_enum, RK730_ADC_PGA_BLOCK_1,
|
||||
4, mux_input_r_text);
|
||||
|
||||
static const struct snd_kcontrol_new mux_out_l =
|
||||
SOC_DAPM_ENUM("Left Out Mux", mux_out_l_enum);
|
||||
static const struct snd_kcontrol_new mux_out_r =
|
||||
SOC_DAPM_ENUM("Right Out Mux", mux_out_r_enum);
|
||||
static const struct snd_kcontrol_new mux_input_l =
|
||||
SOC_DAPM_ENUM("Left Input Mux", mux_input_l_enum);
|
||||
static const struct snd_kcontrol_new mux_input_r =
|
||||
SOC_DAPM_ENUM("Right Input Mux", mux_input_r_enum);
|
||||
|
||||
static const struct snd_kcontrol_new mix_ctls[] = {
|
||||
SOC_DAPM_SINGLE("Left Out Mux Switch", RK730_MUXER_0, 0, 1, 1),
|
||||
SOC_DAPM_SINGLE("Right Out Mux Switch", RK730_MUXER_0, 4, 1, 1),
|
||||
};
|
||||
|
||||
static const char * const adc_hpf_cutoff_text[] = {
|
||||
"3.79Hz", "60Hz", "243Hz", "493Hz",
|
||||
};
|
||||
|
||||
static const char * const dac_hpf_cutoff_text[] = {
|
||||
"80Hz", "100Hz", "120Hz", "140Hz",
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(adc_hpf_cutoff_enum, RK730_DADC_HPF,
|
||||
4, adc_hpf_cutoff_text);
|
||||
static SOC_ENUM_SINGLE_DECL(dac_hpf_cutoff_enum, RK730_DDAC_MUTE_MIXCTL,
|
||||
5, dac_hpf_cutoff_text);
|
||||
|
||||
static const char * const chop_freq_text[] = {
|
||||
"Disabled", "200kHz", "400kHz", "800kHz",
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(dac_ref_buf_chop_freq_enum, RK730_HK_TOP_1,
|
||||
6, chop_freq_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mic_chop_freq_enum, RK730_MIC_BOOST_3,
|
||||
6, chop_freq_text);
|
||||
static SOC_ENUM_SINGLE_DECL(adc_pga_chop_freq_enum, RK730_ADC_PGA_BLOCK_1,
|
||||
6, chop_freq_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mux_out_chop_freq_enum, RK730_MUXER_1,
|
||||
0, chop_freq_text);
|
||||
static SOC_ENUM_SINGLE_DECL(mix_chop_freq_enum, RK730_MIXER_2,
|
||||
6, chop_freq_text);
|
||||
static SOC_ENUM_SINGLE_DECL(hp_lo_chop_freq_enum, RK730_HP_1,
|
||||
5, chop_freq_text);
|
||||
|
||||
static const char * const micbias_volt_text[] = {
|
||||
"2.0v", "2.2v", "2.5v", "2.8v",
|
||||
};
|
||||
|
||||
static const char * const charge_pump_volt_text[] = {
|
||||
"2.1v", "2.3v", "2.5v", "2.7v",
|
||||
};
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(micbias_volt_enum, RK730_MIC_BIAS,
|
||||
2, micbias_volt_text);
|
||||
static SOC_ENUM_SINGLE_DECL(charge_pump_volt_enum, RK730_CHARGE_PUMP,
|
||||
1, charge_pump_volt_text);
|
||||
|
||||
static int rk730_adc_vol_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int val = snd_soc_component_read(component, mc->reg);
|
||||
unsigned int sign = snd_soc_component_read(component, RK730_DADC_SR_ACL);
|
||||
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||
unsigned int shift = mc->shift;
|
||||
int mid = mc->max / 2;
|
||||
int uv;
|
||||
|
||||
uv = (val >> shift) & mask;
|
||||
sign &= RK730_DADC_SR_ACL_VOLL_POL_MASK;
|
||||
if (sign)
|
||||
uv = mid + uv;
|
||||
else
|
||||
uv = mid - uv;
|
||||
|
||||
ucontrol->value.integer.value[0] = uv;
|
||||
ucontrol->value.integer.value[1] = uv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_adc_vol_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int rreg = mc->rreg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||
unsigned int val, val_mask, sign, sign_mask;
|
||||
int uv = ucontrol->value.integer.value[0];
|
||||
int min = mc->min;
|
||||
int mid = mc->max / 2;
|
||||
|
||||
sign_mask = RK730_DADC_SR_ACL_VOLL_POL_MASK | RK730_DADC_SR_ACL_VOLR_POL_MASK;
|
||||
|
||||
if (uv > mid) {
|
||||
sign = RK730_DADC_SR_ACL_VOLL_POS | RK730_DADC_SR_ACL_VOLR_POS;
|
||||
uv = uv - mid;
|
||||
} else {
|
||||
sign = RK730_DADC_SR_ACL_VOLL_NEG | RK730_DADC_SR_ACL_VOLR_NEG;
|
||||
uv = mid - uv;
|
||||
}
|
||||
|
||||
val = ((uv + min) & mask);
|
||||
val_mask = mask << shift;
|
||||
val = val << shift;
|
||||
|
||||
snd_soc_component_update_bits(component, reg, val_mask, val);
|
||||
snd_soc_component_update_bits(component, rreg, val_mask, val);
|
||||
snd_soc_component_update_bits(component, RK730_DADC_SR_ACL, sign_mask, sign);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rk730_dac_vol_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int val = snd_soc_component_read(component, mc->reg);
|
||||
unsigned int sign = snd_soc_component_read(component, RK730_DDAC_SR_LMT);
|
||||
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||
unsigned int shift = mc->shift;
|
||||
int mid = mc->max / 2;
|
||||
int uv;
|
||||
|
||||
uv = (val >> shift) & mask;
|
||||
sign &= RK730_DDAC_SR_LMT_VOLL_POL_MASK;
|
||||
if (sign)
|
||||
uv = mid + uv;
|
||||
else
|
||||
uv = mid - uv;
|
||||
|
||||
ucontrol->value.integer.value[0] = uv;
|
||||
ucontrol->value.integer.value[1] = uv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_dac_vol_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct soc_mixer_control *mc =
|
||||
(struct soc_mixer_control *)kcontrol->private_value;
|
||||
unsigned int reg = mc->reg;
|
||||
unsigned int rreg = mc->rreg;
|
||||
unsigned int shift = mc->shift;
|
||||
unsigned int mask = (1 << fls(mc->max)) - 1;
|
||||
unsigned int val, val_mask, sign, sign_mask;
|
||||
int uv = ucontrol->value.integer.value[0];
|
||||
int min = mc->min;
|
||||
int mid = mc->max / 2;
|
||||
|
||||
sign_mask = RK730_DDAC_SR_LMT_VOLL_POL_MASK | RK730_DDAC_SR_LMT_VOLR_POL_MASK;
|
||||
|
||||
if (uv > mid) {
|
||||
sign = RK730_DDAC_SR_LMT_VOLL_POS | RK730_DDAC_SR_LMT_VOLR_POS;
|
||||
uv = uv - mid;
|
||||
} else {
|
||||
sign = RK730_DDAC_SR_LMT_VOLL_NEG | RK730_DDAC_SR_LMT_VOLR_NEG;
|
||||
uv = mid - uv;
|
||||
}
|
||||
|
||||
val = ((uv + min) & mask);
|
||||
val_mask = mask << shift;
|
||||
val = val << shift;
|
||||
|
||||
snd_soc_component_update_bits(component, reg, val_mask, val);
|
||||
snd_soc_component_update_bits(component, rreg, val_mask, val);
|
||||
snd_soc_component_update_bits(component, RK730_DDAC_SR_LMT, sign_mask, sign);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rk730_cp_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
usleep_range(5000, 5100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_pll_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
snd_soc_component_write(component, RK730_SYSPLL_0, 0x00);
|
||||
else
|
||||
snd_soc_component_write(component, RK730_SYSPLL_0, 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_adc_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
snd_soc_component_update_bits(component, RK730_ADC_0,
|
||||
RK730_ADC_0_DEM_EN_MASK,
|
||||
RK730_ADC_0_DEM_EN);
|
||||
snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE,
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_EN_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_EN_MASK,
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_CKE_EN |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_CKE_EN |
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_EN |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_EN);
|
||||
usleep_range(20000, 21000);
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_TXCR_3_TXCMD,
|
||||
RK730_DI2S_TXCR_3_TXCMD_TXS_MASK,
|
||||
RK730_DI2S_TXCR_3_TXCMD_TXS_EN);
|
||||
} else {
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_TXCR_3_TXCMD,
|
||||
RK730_DI2S_TXCR_3_TXCMD_TXS_MASK,
|
||||
RK730_DI2S_TXCR_3_TXCMD_TXS_DIS);
|
||||
snd_soc_component_update_bits(component, RK730_ADC_0,
|
||||
RK730_ADC_0_DEM_EN_MASK,
|
||||
RK730_ADC_0_DEM_DIS);
|
||||
snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE,
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_EN_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_EN_MASK,
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_CKE_DIS |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_CKE_DIS |
|
||||
RK730_DTOP_DIGEN_CLKE_ADC_DIS |
|
||||
RK730_DTOP_DIGEN_CLKE_I2STX_DIS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_dac_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event)) {
|
||||
snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE,
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_EN_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_EN_MASK,
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_CKE_EN |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_EN |
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_EN |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_EN);
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_RXCMD_TSD,
|
||||
RK730_DI2S_RXCMD_TSD_RXS_MASK,
|
||||
RK730_DI2S_RXCMD_TSD_RXS_EN);
|
||||
} else {
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_RXCMD_TSD,
|
||||
RK730_DI2S_RXCMD_TSD_RXS_MASK,
|
||||
RK730_DI2S_RXCMD_TSD_RXS_DIS);
|
||||
snd_soc_component_update_bits(component, RK730_DTOP_DIGEN_CLKE,
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_EN_MASK |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_EN_MASK,
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_CKE_DIS |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_DIS |
|
||||
RK730_DTOP_DIGEN_CLKE_DAC_DIS |
|
||||
RK730_DTOP_DIGEN_CLKE_I2SRX_DIS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_mux_out_event(struct snd_soc_dapm_widget *w,
|
||||
struct snd_kcontrol *kcontrol, int event)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
|
||||
struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component);
|
||||
unsigned int val;
|
||||
|
||||
if (SND_SOC_DAPM_EVENT_ON(event))
|
||||
val = atomic_inc_return(&rk730->mix_mode);
|
||||
else
|
||||
val = atomic_dec_return(&rk730->mix_mode);
|
||||
|
||||
snd_soc_component_update_bits(component, RK730_MIXER_2,
|
||||
RK730_MIXER_2_MIX_R_MODE_MASK |
|
||||
RK730_MIXER_2_MIX_L_MODE_MASK,
|
||||
RK730_MIXER_2_MIX_R_MODE(val) |
|
||||
RK730_MIXER_2_MIX_L_MODE(val));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new rk730_snd_controls[] = {
|
||||
SOC_DOUBLE_R_TLV("ADC Volume", RK730_ADC_PGA_BLOCK_0, RK730_ADC_PGA_BLOCK_1,
|
||||
1, 0x7, 1, adc_tlv),
|
||||
SOC_DOUBLE_R_TLV("D2S Volume", RK730_DAC_1, RK730_DAC_2,
|
||||
1, 0x6, 1, d2s_tlv),
|
||||
|
||||
SOC_DOUBLE_R_TLV("MIC1 Boost Volume", RK730_MIC_BOOST_0, RK730_MIC_BOOST_1,
|
||||
1, 0x18, 0, micboost_tlv),
|
||||
SOC_DOUBLE_R_TLV("MIC2 Boost Volume", RK730_MIC_BOOST_2, RK730_MIC_BOOST_3,
|
||||
1, 0x18, 0, micboost_tlv),
|
||||
|
||||
SOC_DOUBLE_TLV("Out Mux Volume", RK730_MUXER_0, 1, 5, 0x1, 0, mux_tlv),
|
||||
|
||||
SOC_SINGLE_TLV("Left Out Mux -> Left Out Mixer Volume",
|
||||
RK730_MIXER_0, 1, 0x6, 1, mix_buf_tlv),
|
||||
SOC_SINGLE_TLV("Left Out Mux -> Right Out Mixer Volume",
|
||||
RK730_MIXER_0, 5, 0x6, 1, mix_buf_tlv),
|
||||
SOC_SINGLE_TLV("Right Out Mux -> Left Out Mixer Volume",
|
||||
RK730_MIXER_1, 1, 0x6, 1, mix_buf_tlv),
|
||||
SOC_SINGLE_TLV("Right Out Mux -> Right Out Mixer Volume",
|
||||
RK730_MIXER_1, 5, 0x6, 1, mix_buf_tlv),
|
||||
|
||||
SOC_SINGLE_TLV("HP Volume", RK730_HP_0, 6, 0x3, 0, hp_tlv),
|
||||
SOC_SINGLE_TLV("Line Out Volume", RK730_LINEOUT_1, 2, 0x3, 0, lineout_tlv),
|
||||
|
||||
SOC_DOUBLE_R_EXT_TLV("ADC Digital Volume",
|
||||
RK730_DADC_VOLL, RK730_DADC_VOLR, 0, 0x1fe, 0,
|
||||
rk730_adc_vol_get,
|
||||
rk730_adc_vol_put,
|
||||
adc_dig_tlv),
|
||||
SOC_DOUBLE_R_EXT_TLV("DAC Digital Volume",
|
||||
RK730_DDAC_VOLL, RK730_DDAC_VOLR, 0, 0x1fe, 0,
|
||||
rk730_dac_vol_get,
|
||||
rk730_dac_vol_put,
|
||||
dac_dig_tlv),
|
||||
|
||||
SOC_ENUM("ADC HPF Cutoff", adc_hpf_cutoff_enum),
|
||||
SOC_ENUM("DAC HPF Cutoff", dac_hpf_cutoff_enum),
|
||||
SOC_ENUM("DAC Ref Buf Chop Freq", dac_ref_buf_chop_freq_enum),
|
||||
SOC_ENUM("MIC Chop Freq", mic_chop_freq_enum),
|
||||
SOC_ENUM("ADC PGA Chop Freq", adc_pga_chop_freq_enum),
|
||||
SOC_ENUM("Out Mux Chop Freq", mux_out_chop_freq_enum),
|
||||
SOC_ENUM("Mixer Chop Freq", mix_chop_freq_enum),
|
||||
SOC_ENUM("HP / Lineout Chop Freq", hp_lo_chop_freq_enum),
|
||||
SOC_ENUM("Mic Bias Volt", micbias_volt_enum),
|
||||
SOC_ENUM("Charge Pump Volt", charge_pump_volt_enum),
|
||||
|
||||
SOC_SINGLE("ADCL HPF Switch", RK730_DADC_HPF, 7, 1, 0),
|
||||
SOC_SINGLE("ADCR HPF Switch", RK730_DADC_HPF, 6, 1, 0),
|
||||
SOC_SINGLE("DAC HPF Switch", RK730_DDAC_MUTE_MIXCTL, 7, 1, 0),
|
||||
SOC_SINGLE("ADC Volume Bypass Switch", RK730_DTOP_VUCTL, 7, 1, 0),
|
||||
SOC_SINGLE("DAC Volume Bypass Switch", RK730_DTOP_VUCTL, 6, 1, 0),
|
||||
SOC_SINGLE("ADC Fade Switch", RK730_DTOP_VUCTL, 5, 1, 0),
|
||||
SOC_SINGLE("DAC Fade Switch", RK730_DTOP_VUCTL, 4, 1, 0),
|
||||
SOC_SINGLE("ADC Zero Crossing Switch", RK730_DTOP_VUCTL, 1, 1, 0),
|
||||
SOC_SINGLE("DAC Zero Crossing Switch", RK730_DTOP_VUCTL, 0, 1, 0),
|
||||
SOC_SINGLE("MIC1N / MIC2P Exchanged Switch", RK730_MIC_BOOST_2, 7, 1, 0),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_widget rk730_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_SUPPLY_S("ANA LDO", 0, RK730_LDO, 7, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("OSC CLK", 1, RK730_HK_TOP_2, 4, 0, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("VAG BUF", 1, RK730_HK_TOP_2, 2, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("ADC BUF", 1, RK730_HK_TOP_2, 1, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("DAC BUF", 1, RK730_HK_TOP_2, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("MICBIAS", 1, RK730_MIC_BIAS, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, RK730_CHARGE_PUMP, 0, 0,
|
||||
rk730_cp_event, SND_SOC_DAPM_POST_PMU),
|
||||
SND_SOC_DAPM_SUPPLY_S("PLL", 2, SND_SOC_NOPM, 0, 0, rk730_pll_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_SUPPLY_S("DAC Bias", 2, RK730_DAC_0, 2, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("HP Bias", 2, RK730_HP_0, 5, 1, NULL, 0),
|
||||
SND_SOC_DAPM_SUPPLY_S("Line Out Bias", 2, RK730_LINEOUT_1, 7, 1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_ADC_E("ADCL", "HiFi Capture", RK730_ADC_0, 0, 1,
|
||||
rk730_adc_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_ADC_E("ADCR", "HiFi Capture", RK730_ADC_0, 1, 1,
|
||||
rk730_adc_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_DAC_E("DACL", "HiFi Playback", RK730_DAC_0, 0, 1,
|
||||
rk730_dac_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_DAC_E("DACR", "HiFi Playback", RK730_DAC_0, 1, 1,
|
||||
rk730_dac_event,
|
||||
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_PGA("ADCL PGA", RK730_ADC_PGA_BLOCK_0, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("ADCR PGA", RK730_ADC_PGA_BLOCK_1, 0, 1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PGA("D2SL", RK730_DAC_1, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("D2SR", RK730_DAC_2, 0, 1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PGA("MIC1P", RK730_MIC_BOOST_0, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("MIC1N", RK730_MIC_BOOST_1, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("MIC2P", RK730_MIC_BOOST_2, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("MIC2N", RK730_MIC_BOOST_3, 0, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("DIFFL", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("DIFFR", SND_SOC_NOPM, 0, 0, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_PGA("HP Out", RK730_HP_0, 2, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("HP Out Stage", RK730_HP_0, 3, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Line Out", RK730_LINEOUT_0, 2, 1, NULL, 0),
|
||||
SND_SOC_DAPM_PGA("Line Out Stage", RK730_LINEOUT_0, 3, 1, NULL, 0),
|
||||
|
||||
SND_SOC_DAPM_MUX_E("Left Out Mux", SND_SOC_NOPM, 0, 0, &mux_out_l,
|
||||
rk730_mux_out_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
SND_SOC_DAPM_MUX_E("Right Out Mux", SND_SOC_NOPM, 0, 0, &mux_out_r,
|
||||
rk730_mux_out_event,
|
||||
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
|
||||
|
||||
SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &mux_input_l),
|
||||
SND_SOC_DAPM_MUX("Right Input Mux", SND_SOC_NOPM, 0, 0, &mux_input_r),
|
||||
|
||||
SND_SOC_DAPM_MIXER("Left Out Mixer", RK730_MIXER_2, 0, 1,
|
||||
mix_ctls, ARRAY_SIZE(mix_ctls)),
|
||||
SND_SOC_DAPM_MIXER("Right Out Mixer", RK730_MIXER_2, 3, 1,
|
||||
mix_ctls, ARRAY_SIZE(mix_ctls)),
|
||||
|
||||
SND_SOC_DAPM_OUTPUT("HPL"),
|
||||
SND_SOC_DAPM_OUTPUT("HPR"),
|
||||
SND_SOC_DAPM_OUTPUT("LINEOUTL"),
|
||||
SND_SOC_DAPM_OUTPUT("LINEOUTR"),
|
||||
|
||||
SND_SOC_DAPM_INPUT("MIC1"),
|
||||
SND_SOC_DAPM_INPUT("MIC2"),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route rk730_dapm_routes[] = {
|
||||
{ "DACL", NULL, "ANA LDO" },
|
||||
{ "DACR", NULL, "ANA LDO" },
|
||||
{ "DACL", NULL, "OSC CLK" },
|
||||
{ "DACR", NULL, "OSC CLK" },
|
||||
{ "DACL", NULL, "VAG BUF" },
|
||||
{ "DACR", NULL, "VAG BUF" },
|
||||
{ "DACL", NULL, "DAC BUF" },
|
||||
{ "DACR", NULL, "DAC BUF" },
|
||||
{ "DACL", NULL, "PLL" },
|
||||
{ "DACR", NULL, "PLL" },
|
||||
{ "DACL", NULL, "DAC Bias" },
|
||||
{ "DACR", NULL, "DAC Bias" },
|
||||
|
||||
{ "D2SL", NULL, "DACL" },
|
||||
{ "D2SR", NULL, "DACR" },
|
||||
|
||||
{ "Left Out Mixer", NULL, "D2SL" },
|
||||
{ "Left Out Mixer", "Left Out Mux Switch", "Left Out Mux" },
|
||||
{ "Left Out Mixer", "Right Out Mux Switch", "Right Out Mux" },
|
||||
{ "Right Out Mixer", NULL, "D2SR" },
|
||||
{ "Right Out Mixer", "Left Out Mux Switch", "Left Out Mux" },
|
||||
{ "Right Out Mixer", "Right Out Mux Switch", "Right Out Mux" },
|
||||
|
||||
{ "Left Out Mux", "DIFF", "DIFFL" },
|
||||
{ "Left Out Mux", "MIC1N", "MIC1N" },
|
||||
{ "Left Out Mux", "MIC2N", "MIC2N" },
|
||||
|
||||
{ "Right Out Mux", "DIFF", "DIFFR" },
|
||||
{ "Right Out Mux", "MIC1P", "MIC1P" },
|
||||
{ "Right Out Mux", "MIC2P", "MIC2P" },
|
||||
|
||||
{ "HP Out", NULL, "HP Bias" },
|
||||
{ "HP Out", NULL, "HP Bias" },
|
||||
{ "Line Out", NULL, "Line Out Bias" },
|
||||
|
||||
{ "HP Out", NULL, "Left Out Mixer" },
|
||||
{ "HP Out", NULL, "Right Out Mixer" },
|
||||
{ "Line Out", NULL, "Left Out Mixer" },
|
||||
{ "Line Out", NULL, "Right Out Mixer" },
|
||||
|
||||
{ "HP Out Stage", NULL, "HP Out" },
|
||||
{ "Line Out Stage", NULL, "Line Out" },
|
||||
|
||||
{ "HPL", NULL, "HP Out Stage" },
|
||||
{ "HPR", NULL, "HP Out Stage" },
|
||||
{ "HPL", NULL, "Charge Pump" },
|
||||
{ "HPR", NULL, "Charge Pump" },
|
||||
|
||||
{ "LINEOUTL", NULL, "Line Out Stage" },
|
||||
{ "LINEOUTR", NULL, "Line Out Stage" },
|
||||
{ "LINEOUTL", NULL, "Charge Pump" },
|
||||
{ "LINEOUTR", NULL, "Charge Pump" },
|
||||
|
||||
{ "ADCL", NULL, "ANA LDO" },
|
||||
{ "ADCR", NULL, "ANA LDO" },
|
||||
{ "ADCL", NULL, "OSC CLK" },
|
||||
{ "ADCR", NULL, "OSC CLK" },
|
||||
{ "ADCL", NULL, "ADC BUF" },
|
||||
{ "ADCR", NULL, "ADC BUF" },
|
||||
{ "ADCL", NULL, "VAG BUF" },
|
||||
{ "ADCR", NULL, "VAG BUF" },
|
||||
{ "ADCL", NULL, "PLL" },
|
||||
{ "ADCR", NULL, "PLL" },
|
||||
|
||||
{ "ADCL", NULL, "ADCL PGA" },
|
||||
{ "ADCR", NULL, "ADCR PGA" },
|
||||
{ "ADCL PGA", NULL, "Left Input Mux" },
|
||||
{ "ADCR PGA", NULL, "Right Input Mux" },
|
||||
|
||||
{ "Left Input Mux", "DIFF", "DIFFL" },
|
||||
{ "Left Input Mux", "VINP1", "MIC1P" },
|
||||
{ "Left Input Mux", "VINN1", "MIC1N" },
|
||||
{ "Right Input Mux", "DIFF", "DIFFR" },
|
||||
{ "Right Input Mux", "VINP2", "MIC2P" },
|
||||
{ "Right Input Mux", "VINN2", "MIC2N" },
|
||||
|
||||
{ "DIFFL", NULL, "MIC1P" },
|
||||
{ "DIFFL", NULL, "MIC1N" },
|
||||
{ "DIFFR", NULL, "MIC2P" },
|
||||
{ "DIFFR", NULL, "MIC2N" },
|
||||
|
||||
{ "MIC1P", NULL, "MIC1" },
|
||||
{ "MIC1N", NULL, "MIC1" },
|
||||
{ "MIC2P", NULL, "MIC2" },
|
||||
{ "MIC2N", NULL, "MIC2" },
|
||||
|
||||
{ "MIC1", NULL, "MICBIAS" },
|
||||
{ "MIC2", NULL, "MICBIAS" },
|
||||
};
|
||||
|
||||
static unsigned int samplerate_to_bit(unsigned int samplerate)
|
||||
{
|
||||
switch (samplerate) {
|
||||
case 8000:
|
||||
case 11025:
|
||||
case 12000:
|
||||
return 0;
|
||||
case 16000:
|
||||
case 22050:
|
||||
case 24000:
|
||||
return 1;
|
||||
case 32000:
|
||||
case 44100:
|
||||
case 48000:
|
||||
return 2;
|
||||
case 64000:
|
||||
case 88200:
|
||||
case 96000:
|
||||
return 3;
|
||||
case 128000:
|
||||
case 176400:
|
||||
case 192000:
|
||||
return 4;
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int rk730_dai_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;
|
||||
unsigned int width, rate;
|
||||
|
||||
width = min(params_width(params), 24);
|
||||
rate = samplerate_to_bit(params_rate(params));
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_RXCR_2,
|
||||
RK730_DI2S_XCR2_VDW_MASK,
|
||||
RK730_DI2S_XCR2_VDW(width));
|
||||
snd_soc_component_update_bits(component, RK730_DDAC_SR_LMT,
|
||||
RK730_DDAC_SR_LMT_SRT_MASK,
|
||||
RK730_DDAC_SR_LMT_SRT(rate));
|
||||
} else {
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_TXCR_2,
|
||||
RK730_DI2S_XCR2_VDW_MASK,
|
||||
RK730_DI2S_XCR2_VDW(width));
|
||||
snd_soc_component_update_bits(component, RK730_DADC_SR_ACL,
|
||||
RK730_DADC_SR_ACL_SRT_MASK,
|
||||
RK730_DADC_SR_ACL_SRT(rate));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
|
||||
{
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
|
||||
case SND_SOC_DAIFMT_CBS_CFS:
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_CKM,
|
||||
RK730_DI2S_CKM_MST_MASK,
|
||||
RK730_DI2S_CKM_MST_SLAVE);
|
||||
break;
|
||||
case SND_SOC_DAIFMT_CBM_CFM:
|
||||
snd_soc_component_update_bits(component, RK730_DI2S_CKM,
|
||||
RK730_DI2S_CKM_MST_MASK,
|
||||
RK730_DI2S_CKM_MST_MASTER);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_dai_mute(struct snd_soc_dai *codec_dai, int mute, int direction)
|
||||
{
|
||||
struct snd_soc_component *component = codec_dai->component;
|
||||
|
||||
if (mute)
|
||||
snd_soc_component_update_bits(component, RK730_DDAC_MUTE_MIXCTL,
|
||||
RK730_DDAC_MUTE_MIXCTL_MUTE_MASK,
|
||||
RK730_DDAC_MUTE_MIXCTL_MUTE);
|
||||
else
|
||||
snd_soc_component_update_bits(component, RK730_DDAC_MUTE_MIXCTL,
|
||||
RK730_DDAC_MUTE_MIXCTL_MUTE_MASK,
|
||||
RK730_DDAC_MUTE_MIXCTL_UNMUTE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_set_bias_level(struct snd_soc_component *component,
|
||||
enum snd_soc_bias_level level)
|
||||
{
|
||||
struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
switch (level) {
|
||||
case SND_SOC_BIAS_ON:
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_PREPARE:
|
||||
/*
|
||||
* SND_SOC_BIAS_PREPARE is called while preparing for a
|
||||
* transition to ON or away from ON. If current bias_level
|
||||
* is SND_SOC_BIAS_ON, then it is preparing for a transition
|
||||
* away from ON. Disable the clock in that case, otherwise
|
||||
* enable it.
|
||||
*/
|
||||
if (!IS_ERR(rk730->mclk)) {
|
||||
if (snd_soc_component_get_bias_level(component) ==
|
||||
SND_SOC_BIAS_ON)
|
||||
clk_disable_unprepare(rk730->mclk);
|
||||
else
|
||||
clk_prepare_enable(rk730->mclk);
|
||||
}
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_STANDBY:
|
||||
if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
|
||||
regcache_sync(rk730->regmap);
|
||||
break;
|
||||
|
||||
case SND_SOC_BIAS_OFF:
|
||||
regcache_mark_dirty(rk730->regmap);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RK730_RATES SNDRV_PCM_RATE_8000_192000
|
||||
#define RK730_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
|
||||
SNDRV_PCM_FMTBIT_S32_LE)
|
||||
|
||||
static const struct snd_soc_dai_ops rk730_dai_ops = {
|
||||
.set_fmt = rk730_dai_set_fmt,
|
||||
.hw_params = rk730_dai_hw_params,
|
||||
.mute_stream = rk730_dai_mute,
|
||||
.no_capture_mute = 1,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_driver rk730_dai = {
|
||||
.name = "HiFi",
|
||||
.playback = {
|
||||
.stream_name = "HiFi Playback",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = RK730_RATES,
|
||||
.formats = RK730_FORMATS,
|
||||
},
|
||||
.capture = {
|
||||
.stream_name = "HiFi Capture",
|
||||
.channels_min = 1,
|
||||
.channels_max = 2,
|
||||
.rates = RK730_RATES,
|
||||
.formats = RK730_FORMATS,
|
||||
},
|
||||
.ops = &rk730_dai_ops,
|
||||
};
|
||||
|
||||
static int rk730_reset(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
clk_prepare_enable(rk730->mclk);
|
||||
snd_soc_component_write(component, RK730_DTOP_LPT_SRST, 0x40);
|
||||
udelay(10);
|
||||
/* WA: Initial micbias default, ADC stopped with micbias(>2.5v) */
|
||||
snd_soc_component_update_bits(component, RK730_MIC_BIAS,
|
||||
RK730_MIC_BIAS_VOLT_MASK,
|
||||
RK730_MIC_BIAS_VOLT_2_2V);
|
||||
/* PF: Use the maximum bias current for better performance */
|
||||
snd_soc_component_update_bits(component, RK730_HK_TOP_1,
|
||||
RK730_HK_TOP_1_IBIAS_STD_SEL_MASK |
|
||||
RK730_HK_TOP_1_IBIAS_GAIN_SEL_MASK,
|
||||
RK730_HK_TOP_1_IBIAS_STD_SEL_27_5UA |
|
||||
RK730_HK_TOP_1_IBIAS_GAIN_SEL_200);
|
||||
/* PF: Use the chop 400kHz for better ADC noise performance */
|
||||
snd_soc_component_update_bits(component, RK730_MIC_BOOST_3,
|
||||
RK730_MIC_BOOST_3_MIC_CHOP_MASK,
|
||||
RK730_MIC_BOOST_3_MIC_CHOP(RK730_CHOP_FREQ_400KHZ));
|
||||
snd_soc_component_update_bits(component, RK730_ADC_PGA_BLOCK_1,
|
||||
RK730_ADC_PGA_BLOCK_1_PGA_CHOP_MASK,
|
||||
RK730_ADC_PGA_BLOCK_1_PGA_CHOP(RK730_CHOP_FREQ_400KHZ));
|
||||
|
||||
clk_disable_unprepare(rk730->mclk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk730_probe(struct snd_soc_component *component)
|
||||
{
|
||||
struct rk730_priv *rk730 = snd_soc_component_get_drvdata(component);
|
||||
int ret = 0;
|
||||
|
||||
regcache_mark_dirty(rk730->regmap);
|
||||
|
||||
/* initialize private data */
|
||||
atomic_set(&rk730->mix_mode, RK730_MIX_MODE_1_PATH);
|
||||
|
||||
ret = snd_soc_component_read(component, RK730_HK_TOP_0);
|
||||
if (ret < 0) {
|
||||
dev_err(component->dev, "Failed to read register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rk730_reset(component);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct snd_soc_component_driver rk730_component_driver = {
|
||||
.probe = rk730_probe,
|
||||
.set_bias_level = rk730_set_bias_level,
|
||||
.controls = rk730_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(rk730_snd_controls),
|
||||
.dapm_widgets = rk730_dapm_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(rk730_dapm_widgets),
|
||||
.dapm_routes = rk730_dapm_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(rk730_dapm_routes),
|
||||
.suspend_bias_off = 1,
|
||||
.idle_bias_on = 1,
|
||||
.use_pmdown_time = 1,
|
||||
.endianness = 1,
|
||||
.non_legacy_dai_naming = 1,
|
||||
};
|
||||
|
||||
static const struct reg_default rk730_reg_defaults[] = {
|
||||
{ 0x00, 0x40 },
|
||||
{ 0x02, 0x17 },
|
||||
{ 0x05, 0x03 },
|
||||
{ 0x06, 0x22 },
|
||||
{ 0x07, 0x02 },
|
||||
{ 0x08, 0x07 },
|
||||
{ 0x09, 0x01 },
|
||||
{ 0x0a, 0x01 },
|
||||
{ 0x0b, 0x01 },
|
||||
{ 0x0c, 0x01 },
|
||||
{ 0x0d, 0x01 },
|
||||
{ 0x0e, 0x01 },
|
||||
{ 0x0f, 0x07 },
|
||||
{ 0x10, 0x07 },
|
||||
{ 0x11, 0xff },
|
||||
{ 0x12, 0x07 },
|
||||
{ 0x13, 0x54 },
|
||||
{ 0x14, 0x04 },
|
||||
{ 0x15, 0x23 },
|
||||
{ 0x16, 0x35 },
|
||||
{ 0x17, 0x67 },
|
||||
{ 0x18, 0x1e },
|
||||
{ 0x19, 0xc0 },
|
||||
{ 0x1a, 0x13 },
|
||||
{ 0x1b, 0x04 },
|
||||
{ 0x1c, 0x20 },
|
||||
{ 0x1f, 0x90 },
|
||||
{ 0x20, 0x11 },
|
||||
{ 0x21, 0x09 },
|
||||
{ 0x22, 0x33 },
|
||||
{ 0x24, 0x11 },
|
||||
{ 0x25, 0x11 },
|
||||
{ 0x26, 0x09 },
|
||||
{ 0x27, 0x02 },
|
||||
{ 0x28, 0x2c },
|
||||
{ 0x2a, 0x0c },
|
||||
{ 0x2b, 0x80 },
|
||||
{ 0x40, 0x03 },
|
||||
{ 0x42, 0x20 },
|
||||
{ 0x47, 0xe6 },
|
||||
{ 0x48, 0xd0 },
|
||||
{ 0x49, 0x17 },
|
||||
{ 0x4a, 0x26 },
|
||||
{ 0x4b, 0x01 },
|
||||
{ 0x4c, 0x05 },
|
||||
{ 0x4d, 0x0e },
|
||||
{ 0x4e, 0x09 },
|
||||
{ 0x4f, 0x02 },
|
||||
{ 0x5b, 0xe6 },
|
||||
{ 0x5c, 0xd0 },
|
||||
{ 0x5d, 0x17 },
|
||||
{ 0x5e, 0x26 },
|
||||
{ 0x5f, 0x01 },
|
||||
{ 0x60, 0x05 },
|
||||
{ 0x61, 0x0e },
|
||||
{ 0x62, 0x09 },
|
||||
{ 0x63, 0x20 },
|
||||
{ 0x66, 0x01 },
|
||||
{ 0x69, 0x17 },
|
||||
{ 0x6c, 0x17 },
|
||||
};
|
||||
|
||||
static bool rk730_volatile_register(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case RK730_DTOP_LPT_SRST:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regmap_config rk730_regmap = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.volatile_reg = rk730_volatile_register,
|
||||
.max_register = RK730_DAC_ATTN,
|
||||
.reg_defaults = rk730_reg_defaults,
|
||||
.num_reg_defaults = ARRAY_SIZE(rk730_reg_defaults),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int rk730_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct rk730_priv *rk730;
|
||||
int ret;
|
||||
|
||||
rk730 = devm_kzalloc(&i2c->dev, sizeof(struct rk730_priv), GFP_KERNEL);
|
||||
if (!rk730)
|
||||
return -ENOMEM;
|
||||
|
||||
rk730->regmap = devm_regmap_init_i2c(i2c, &rk730_regmap);
|
||||
if (IS_ERR(rk730->regmap))
|
||||
return PTR_ERR(rk730->regmap);
|
||||
|
||||
rk730->mclk = devm_clk_get(&i2c->dev, "mclk");
|
||||
if (IS_ERR(rk730->mclk))
|
||||
return PTR_ERR(rk730->mclk);
|
||||
|
||||
i2c_set_clientdata(i2c, rk730);
|
||||
|
||||
ret = devm_snd_soc_register_component(&i2c->dev,
|
||||
&rk730_component_driver, &rk730_dai, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rk730_i2c_id[] = {
|
||||
{ "rk730", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rk730_i2c_id);
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id rk730_of_match[] = {
|
||||
{ .compatible = "rockchip,rk730" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rk730_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver rk730_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rk730",
|
||||
.of_match_table = of_match_ptr(rk730_of_match),
|
||||
},
|
||||
.probe = rk730_i2c_probe,
|
||||
.id_table = rk730_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(rk730_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ASoC RK730 driver");
|
||||
MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
239
sound/soc/codecs/rk730.h
Normal file
239
sound/soc/codecs/rk730.h
Normal file
@@ -0,0 +1,239 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* rk730.h -- RK730 ALSA SoC Audio driver
|
||||
*
|
||||
* Copyright (C) 2022 Rockchip Electronics Co.,Ltd
|
||||
*/
|
||||
|
||||
#ifndef _RK730_H
|
||||
#define _RK730_H
|
||||
|
||||
/* RK730 Analog Registers Definition */
|
||||
#define RK730_HK_TOP_0 0x00
|
||||
#define RK730_HK_TOP_1 0x01
|
||||
#define RK730_HK_TOP_2 0x02
|
||||
#define RK730_HK_TRIM_0 0x03
|
||||
#define RK730_HK_TRIM_1 0x04
|
||||
#define RK730_ADC_0 0x05
|
||||
#define RK730_ADC_1 0x06
|
||||
#define RK730_ADC_2 0x07
|
||||
#define RK730_DAC_0 0x08
|
||||
#define RK730_DAC_1 0x09
|
||||
#define RK730_DAC_2 0x0a
|
||||
#define RK730_MIC_BOOST_0 0x0b
|
||||
#define RK730_MIC_BOOST_1 0x0c
|
||||
#define RK730_MIC_BOOST_2 0x0d
|
||||
#define RK730_MIC_BOOST_3 0x0e
|
||||
#define RK730_ADC_PGA_BLOCK_0 0x0f
|
||||
#define RK730_ADC_PGA_BLOCK_1 0x10
|
||||
#define RK730_SYSPLL_0 0x11
|
||||
#define RK730_SYSPLL_1 0x12
|
||||
#define RK730_SYSPLL_2 0x13
|
||||
#define RK730_SYSPLL_3 0x14
|
||||
#define RK730_SYSPLL_LOOP_0 0x15
|
||||
#define RK730_SYSPLL_LOOP_1 0x16
|
||||
#define RK730_SYSPLL_LOOP_2 0x17
|
||||
#define RK730_SYSPLL_LOOP_3 0x18
|
||||
#define RK730_SYSPLL_RVCO_0 0x19
|
||||
#define RK730_SYSPLL_RVCO_1 0x1a
|
||||
#define RK730_SYSPLL_RVCO_2 0x1b
|
||||
#define RK730_SYSPLL_RVCO_3 0x1c
|
||||
#define RK730_SYSPLL_FRACT_0 0x1d
|
||||
#define RK730_SYSPLL_FRACT_1 0x1e
|
||||
#define RK730_SYSPLL_FRACT_2 0x1f
|
||||
#define RK730_LDO 0x20
|
||||
#define RK730_MIC_BIAS 0x21
|
||||
#define RK730_MUXER_0 0x22
|
||||
#define RK730_MUXER_1 0x23
|
||||
#define RK730_MIXER_0 0x24
|
||||
#define RK730_MIXER_1 0x25
|
||||
#define RK730_MIXER_2 0x26
|
||||
#define RK730_CHARGE_PUMP 0x27
|
||||
#define RK730_HP_0 0x28
|
||||
#define RK730_HP_1 0x29
|
||||
#define RK730_LINEOUT_0 0x2a
|
||||
#define RK730_LINEOUT_1 0x2b
|
||||
|
||||
/* RK730 Digital Registers Definition */
|
||||
#define RK730_DTOP_VUCTL 0x40
|
||||
#define RK730_DTOP_VUCTIME 0x41
|
||||
#define RK730_DTOP_LPT_SRST 0x42
|
||||
#define RK730_DTOP_DIGEN_CLKE 0x43
|
||||
#define RK730_DADC_VOLL 0x44
|
||||
#define RK730_DADC_VOLR 0x45
|
||||
#define RK730_DADC_SR_ACL 0x46
|
||||
#define RK730_DADC_PR_0 0x47
|
||||
#define RK730_DADC_PR_1 0x48
|
||||
#define RK730_DADC_PR_2 0x49
|
||||
#define RK730_DADC_PR_3 0x4a
|
||||
#define RK730_DADC_NG_0 0x4b
|
||||
#define RK730_DADC_NG_1 0x4c
|
||||
#define RK730_DADC_NG_2 0x4d
|
||||
#define RK730_DADC_NG_3 0x4e
|
||||
#define RK730_DADC_CICCOMP 0x4f
|
||||
#define RK730_DADC_HPF 0x50
|
||||
#define RK730_DADC_RVOLL 0x51
|
||||
#define RK730_DADC_RVOLR 0x52
|
||||
#define RK730_DMIC_LMT_1 0x53
|
||||
#define RK730_DMIC_LMT_2 0x54
|
||||
#define RK730_DMIC_NG_1 0x55
|
||||
#define RK730_DMIC_NG_2 0x56
|
||||
#define RK730_DDAC_POPD_DACST 0x57
|
||||
#define RK730_DDAC_VOLL 0x58
|
||||
#define RK730_DDAC_VOLR 0x59
|
||||
#define RK730_DDAC_SR_LMT 0x5a
|
||||
#define RK730_DDAC_PR_0 0x5b
|
||||
#define RK730_DDAC_PR_1 0x5c
|
||||
#define RK730_DDAC_PR_2 0x5d
|
||||
#define RK730_DDAC_PR_3 0x5e
|
||||
#define RK730_DDAC_NG_0 0x5f
|
||||
#define RK730_DDAC_NG_1 0x60
|
||||
#define RK730_DDAC_NG_2 0x61
|
||||
#define RK730_DDAC_NG_3 0x62
|
||||
#define RK730_DDAC_MUTE_MIXCTL 0x63
|
||||
#define RK730_DDAC_RVOLL 0x64
|
||||
#define RK730_DDAC_RVOLR 0x65
|
||||
#define RK730_DI2S_CKM 0x66
|
||||
#define RK730_DI2S_RSD 0x67
|
||||
#define RK730_DI2S_RXCR_1 0x68
|
||||
#define RK730_DI2S_RXCR_2 0x69
|
||||
#define RK730_DI2S_RXCMD_TSD 0x6a
|
||||
#define RK730_DI2S_TXCR_1 0x6b
|
||||
#define RK730_DI2S_TXCR_2 0x6c
|
||||
#define RK730_DI2S_TXCR_3_TXCMD 0x6d
|
||||
#define RK730_DAC_ATTN 0x6e
|
||||
|
||||
/* RK730_HK_TOP_1 */
|
||||
#define RK730_HK_TOP_1_DAC_REF_BUF_CHOP_MASK GENMASK(7, 6)
|
||||
#define RK730_HK_TOP_1_DAC_REF_BUF_CHOP(x) ((x) << 6)
|
||||
#define RK730_HK_TOP_1_IBIAS_STD_SEL_MASK GENMASK(5, 4)
|
||||
#define RK730_HK_TOP_1_IBIAS_STD_SEL_27_5UA (3 << 4)
|
||||
#define RK730_HK_TOP_1_IBIAS_STD_SEL_23_5UA (2 << 4)
|
||||
#define RK730_HK_TOP_1_IBIAS_STD_SEL_20UA (1 << 4)
|
||||
#define RK730_HK_TOP_1_IBIAS_STD_SEL_16_5UA (0 << 4)
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_MASK GENMASK(3, 0)
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_200 8
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_143 9
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_120 10
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_100 0
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_71_5 1
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_62_5 2
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_50 3
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_38_2 6
|
||||
#define RK730_HK_TOP_1_IBIAS_GAIN_SEL_32 7
|
||||
|
||||
/* RK730_ADC_0 */
|
||||
#define RK730_ADC_0_DEM_EN_MASK BIT(3)
|
||||
#define RK730_ADC_0_DEM_EN BIT(3)
|
||||
#define RK730_ADC_0_DEM_DIS 0
|
||||
|
||||
/* RK730_MIC_BOOST_3 */
|
||||
#define RK730_MIC_BOOST_3_MIC_CHOP_MASK GENMASK(7, 6)
|
||||
#define RK730_MIC_BOOST_3_MIC_CHOP(x) ((x) << 6)
|
||||
|
||||
/* RK730_ADC_PGA_BLOCK_1 */
|
||||
#define RK730_ADC_PGA_BLOCK_1_PGA_CHOP_MASK GENMASK(7, 6)
|
||||
#define RK730_ADC_PGA_BLOCK_1_PGA_CHOP(x) ((x) << 6)
|
||||
|
||||
/* RK730_MIC_BIAS */
|
||||
#define RK730_MIC_BIAS_VOLT_MASK GENMASK(3, 2)
|
||||
#define RK730_MIC_BIAS_VOLT_2_8V (3 << 2)
|
||||
#define RK730_MIC_BIAS_VOLT_2_5V (2 << 2)
|
||||
#define RK730_MIC_BIAS_VOLT_2_2V (1 << 2)
|
||||
#define RK730_MIC_BIAS_VOLT_2_0V (0 << 2)
|
||||
|
||||
/* RK730_MUXER_1 */
|
||||
#define RK730_MUXER_1_MUX_OUT_CHOP_MASK GENMASK(1, 0)
|
||||
#define RK730_MUXER_1_MUX_OUT_CHOP(x) ((x) << 0)
|
||||
|
||||
/* RK730_MIXER_2 */
|
||||
#define RK730_MIXER_2_MIX_CHOP_MASK GENMASK(7, 6)
|
||||
#define RK730_MIXER_2_MIX_CHOP(x) ((x) << 6)
|
||||
#define RK730_MIXER_2_MIX_R_MODE_MASK GENMASK(5, 4)
|
||||
#define RK730_MIXER_2_MIX_R_MODE(x) ((x) << 4)
|
||||
#define RK730_MIXER_2_MIX_L_MODE_MASK GENMASK(2, 1)
|
||||
#define RK730_MIXER_2_MIX_L_MODE(x) ((x) << 1)
|
||||
|
||||
/* RK730_HP_1 */
|
||||
#define RK730_HP_1_HP_LO_CHOP_MASK GENMASK(6, 5)
|
||||
#define RK730_HP_1_HP_LO_CHOP(x) ((x) << 5)
|
||||
|
||||
/* RK730_DTOP_DIGEN_CLKE */
|
||||
#define RK730_DTOP_DIGEN_CLKE_ADC_CKE_MASK BIT(7)
|
||||
#define RK730_DTOP_DIGEN_CLKE_ADC_CKE_EN BIT(7)
|
||||
#define RK730_DTOP_DIGEN_CLKE_ADC_CKE_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2STX_CKE_MASK BIT(6)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2STX_CKE_EN BIT(6)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2STX_CKE_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_ADC_EN_MASK BIT(5)
|
||||
#define RK730_DTOP_DIGEN_CLKE_ADC_EN BIT(5)
|
||||
#define RK730_DTOP_DIGEN_CLKE_ADC_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2STX_EN_MASK BIT(4)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2STX_EN BIT(4)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2STX_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_DAC_CKE_MASK BIT(3)
|
||||
#define RK730_DTOP_DIGEN_CLKE_DAC_CKE_EN BIT(3)
|
||||
#define RK730_DTOP_DIGEN_CLKE_DAC_CKE_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_MASK BIT(2)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_EN BIT(2)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2SRX_CKE_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_DAC_EN_MASK BIT(1)
|
||||
#define RK730_DTOP_DIGEN_CLKE_DAC_EN BIT(1)
|
||||
#define RK730_DTOP_DIGEN_CLKE_DAC_DIS 0
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2SRX_EN_MASK BIT(0)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2SRX_EN BIT(0)
|
||||
#define RK730_DTOP_DIGEN_CLKE_I2SRX_DIS 0
|
||||
|
||||
/* RK730_DADC_SR_ACL */
|
||||
#define RK730_DADC_SR_ACL_VOLL_POL_MASK BIT(5)
|
||||
#define RK730_DADC_SR_ACL_VOLL_POS BIT(5)
|
||||
#define RK730_DADC_SR_ACL_VOLL_NEG 0
|
||||
#define RK730_DADC_SR_ACL_VOLR_POL_MASK BIT(4)
|
||||
#define RK730_DADC_SR_ACL_VOLR_POS BIT(4)
|
||||
#define RK730_DADC_SR_ACL_VOLR_NEG 0
|
||||
#define RK730_DADC_SR_ACL_SRT_MASK GENMASK(2, 0)
|
||||
#define RK730_DADC_SR_ACL_SRT(x) (x)
|
||||
|
||||
/* RK730_DDAC_SR_LMT */
|
||||
#define RK730_DDAC_SR_LMT_VOLL_POL_MASK BIT(5)
|
||||
#define RK730_DDAC_SR_LMT_VOLL_POS BIT(5)
|
||||
#define RK730_DDAC_SR_LMT_VOLL_NEG 0
|
||||
#define RK730_DDAC_SR_LMT_VOLR_POL_MASK BIT(4)
|
||||
#define RK730_DDAC_SR_LMT_VOLR_POS BIT(4)
|
||||
#define RK730_DDAC_SR_LMT_VOLR_NEG 0
|
||||
#define RK730_DDAC_SR_LMT_SRT_MASK GENMASK(2, 0)
|
||||
#define RK730_DDAC_SR_LMT_SRT(x) (x)
|
||||
|
||||
/* RK730_DDAC_MUTE_MIXCTL */
|
||||
#define RK730_DDAC_MUTE_MIXCTL_MUTE_MASK BIT(0)
|
||||
#define RK730_DDAC_MUTE_MIXCTL_MUTE BIT(0)
|
||||
#define RK730_DDAC_MUTE_MIXCTL_UNMUTE 0
|
||||
|
||||
/* RK730_DI2S_CKM */
|
||||
#define RK730_DI2S_CKM_SCLK_DIV_MASK GENMASK(7, 4)
|
||||
#define RK730_DI2S_CKM_SCLK_DIV(x) ((x - 1) << 4)
|
||||
#define RK730_DI2S_CKM_SCLK_EN_MASK BIT(2)
|
||||
#define RK730_DI2S_CKM_SCLK_EN BIT(2)
|
||||
#define RK730_DI2S_CKM_SCLK_DIS 0
|
||||
#define RK730_DI2S_CKM_SCLK_POL_MASK BIT(1)
|
||||
#define RK730_DI2S_CKM_SCLK_INVERTED BIT(1)
|
||||
#define RK730_DI2S_CKM_SCLK_NORMAL 0
|
||||
#define RK730_DI2S_CKM_MST_MASK BIT(0)
|
||||
#define RK730_DI2S_CKM_MST_MASTER BIT(0)
|
||||
#define RK730_DI2S_CKM_MST_SLAVE 0
|
||||
|
||||
/* RK730_DI2S_XCR2 */
|
||||
#define RK730_DI2S_XCR2_VDW_MASK GENMASK(4, 0)
|
||||
#define RK730_DI2S_XCR2_VDW(x) (x - 1)
|
||||
|
||||
/* RK730_DI2S_RXCMD_TSD */
|
||||
#define RK730_DI2S_RXCMD_TSD_RXS_MASK BIT(5)
|
||||
#define RK730_DI2S_RXCMD_TSD_RXS_EN BIT(5)
|
||||
#define RK730_DI2S_RXCMD_TSD_RXS_DIS 0
|
||||
|
||||
/* RK730_DI2S_TXCR_3_TXCMD */
|
||||
#define RK730_DI2S_TXCR_3_TXCMD_TXS_MASK BIT(7)
|
||||
#define RK730_DI2S_TXCR_3_TXCMD_TXS_EN BIT(7)
|
||||
#define RK730_DI2S_TXCR_3_TXCMD_TXS_DIS 0
|
||||
|
||||
#endif
|
||||
@@ -2282,6 +2282,16 @@ static int rockchip_i2s_tdm_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_i2s_tdm_platform_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rk_i2s_tdm_dev *i2s_tdm = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
pm_runtime_get_sync(i2s_tdm->dev);
|
||||
rockchip_i2s_tdm_stop(i2s_tdm, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
rockchip_i2s_tdm_stop(i2s_tdm, SNDRV_PCM_STREAM_CAPTURE);
|
||||
pm_runtime_put(i2s_tdm->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int rockchip_i2s_tdm_suspend(struct device *dev)
|
||||
{
|
||||
@@ -2317,6 +2327,7 @@ static const struct dev_pm_ops rockchip_i2s_tdm_pm_ops = {
|
||||
static struct platform_driver rockchip_i2s_tdm_driver = {
|
||||
.probe = rockchip_i2s_tdm_probe,
|
||||
.remove = rockchip_i2s_tdm_remove,
|
||||
.shutdown = rockchip_i2s_tdm_platform_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = of_match_ptr(rockchip_i2s_tdm_match),
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define PDM_START_DELAY_MS_MAX (1000)
|
||||
#define PDM_FILTER_DELAY_MS_MIN (20)
|
||||
#define PDM_FILTER_DELAY_MS_MAX (1000)
|
||||
#define PDM_CLK_SHIFT_PPM_MAX (1000000) /* 1 ppm */
|
||||
|
||||
enum rk_pdm_version {
|
||||
RK_PDM_RK3229,
|
||||
@@ -89,7 +90,7 @@ static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
|
||||
unsigned int *clk_src, unsigned int *clk_out,
|
||||
unsigned int signoff)
|
||||
{
|
||||
unsigned int i, count, clk, div, rate;
|
||||
unsigned int i, count, clk, div, rate, delta;
|
||||
|
||||
clk = 0;
|
||||
if (!sr)
|
||||
@@ -103,7 +104,9 @@ static unsigned int get_pdm_clk(struct rk_pdm_dev *pdm, unsigned int sr,
|
||||
if ((div & (div - 1)) == 0) {
|
||||
*clk_out = clkref[i].clk_out;
|
||||
rate = clk_round_rate(pdm->clk, clkref[i].clk);
|
||||
if (rate != clkref[i].clk)
|
||||
delta = clkref[i].clk / PDM_CLK_SHIFT_PPM_MAX;
|
||||
if (rate < clkref[i].clk - delta ||
|
||||
rate > clkref[i].clk + delta)
|
||||
continue;
|
||||
clk = clkref[i].clk;
|
||||
*clk_src = clkref[i].clk;
|
||||
@@ -610,6 +613,7 @@ static int rockchip_pdm_runtime_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
rockchip_pdm_rxctrl(pdm, 0);
|
||||
regcache_cache_only(pdm->regmap, false);
|
||||
regcache_mark_dirty(pdm->regmap);
|
||||
ret = regcache_sync(pdm->regmap);
|
||||
|
||||
Reference in New Issue
Block a user