summaryrefslogtreecommitdiff
authorNanxin Qin <nanxin.qin@amlogic.com>2020-06-26 07:19:35 (GMT)
committer Hui Zhang <hui.zhang@amlogic.com>2020-07-22 06:17:18 (GMT)
commit67585e1a0082a6ffe26569e2853c1b48f1e8f46b (patch)
tree868217cb6e7b310bf36529fd67bdd393376238c6
parent1e292335528ad03ba40f251a97dc48c5d66086e0 (diff)
downloadmedia_modules-amlogic-5.4-dev.zip
media_modules-amlogic-5.4-dev.tar.gz
media_modules-amlogic-5.4-dev.tar.bz2
vdec: support power manager for vdec. [1/1]
PD#SWPL-28425 Problem: SC2 DOS power domain management Solution: 1. unite interface for vdec power ctrl. 2. support config power ctrl mode from dts. 3. 5 modes can be used: a. legacy b.power-ctrl-api c.power-domain d.pd-sec-api e.pd-non-sec-api Verify: u212, ac214 Change-Id: Ie7e8ab6ec15eb5175bfe28e134423489d5ceae15 Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
Diffstat
-rw-r--r--drivers/frame_provider/decoder/utils/Makefile1
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.c689
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_power_ctrl.c801
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_power_ctrl.h107
-rw-r--r--drivers/stream_input/amports/amstream.c1
5 files changed, 935 insertions, 664 deletions
diff --git a/drivers/frame_provider/decoder/utils/Makefile b/drivers/frame_provider/decoder/utils/Makefile
index 07edbe3..4f23c05 100644
--- a/drivers/frame_provider/decoder/utils/Makefile
+++ b/drivers/frame_provider/decoder/utils/Makefile
@@ -5,4 +5,5 @@ decoder_common-objs += config_parser.o secprot.o vdec_profile.o
decoder_common-objs += amstream_profile.o
decoder_common-objs += frame_check.o amlogic_fbc_hook.o
decoder_common-objs += vdec_v4l2_buffer_ops.o
+decoder_common-objs += vdec_power_ctrl.o
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c
index a8a4b74..e219e44 100644
--- a/drivers/frame_provider/decoder/utils/vdec.c
+++ b/drivers/frame_provider/decoder/utils/vdec.c
@@ -83,12 +83,10 @@
#ifdef CONFIG_AMLOGIC_IONVIDEO
#include <linux/amlogic/media/video_sink/ionvideo_ext.h>
#endif
-#include <linux/pm.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_runtime.h>
-
-/* wait other module to support this function */
-#define is_support_power_ctrl() 0
+//#include <dt-bindings/power/sc2-pd.h>
+#include <linux/amlogic/pwr_ctrl.h>
+#include <linux/of_device.h>
+#include "vdec_power_ctrl.h"
static DEFINE_MUTEX(vdec_mutex);
@@ -109,9 +107,11 @@ static unsigned int clk_config;
*/
static unsigned int debug;
-static int hevc_max_reset_count;
+int hevc_max_reset_count;
+EXPORT_SYMBOL(hevc_max_reset_count);
-static int no_powerdown;
+int no_powerdown;
+EXPORT_SYMBOL(no_powerdown);
static int parallel_decode = 1;
static int fps_detection;
static int fps_clear;
@@ -136,8 +136,6 @@ static int enable_mvdec_info = 1;
int decode_underflow = 0;
-static bool disable_power_domain;
-
#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
struct am_reg {
@@ -161,27 +159,6 @@ struct decode_fps_s {
u32 fps;
};
-enum vdec_pd_e {
- PD_VDEC,
- PD_HCODEC,
- PD_HEVC,
- PD_WAVE,
- PD_MAX
-};
-
-struct vdec_pwrc_s {
- u8 *name;
- struct device *dev;
- struct device_link *link;
-};
-
-static struct vdec_pwrc_s vdec_pd[] = {
- { .name = "pwrc-vdec", },
- { .name = "pwrc-hcodec",},
- { .name = "pwrc-hevc", },
- { .name = "pwrc-wave", },
-};
-
struct vdec_core_s {
struct list_head connected_vdec_list;
spinlock_t lock;
@@ -210,7 +187,7 @@ struct vdec_core_s {
struct decode_fps_s decode_fps[MAX_INSTANCE_MUN];
unsigned long buff_flag;
unsigned long stream_buff_flag;
- struct vdec_pwrc_s *pd;
+ struct power_manager_s *pm;
};
struct canvas_status_s {
@@ -862,13 +839,6 @@ void update_vdec_clk_config_settings(unsigned int config)
}
EXPORT_SYMBOL(update_vdec_clk_config_settings);
-static bool hevc_workaround_needed(void)
-{
- return (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) &&
- (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR)
- == GXBB_REV_A_MINOR);
-}
-
struct device *get_codec_cma_device(void)
{
return vdec_core->cma_dev;
@@ -1071,8 +1041,9 @@ struct vdec_s *vdec_create(struct stream_port_s *port,
}
}
- pr_debug("vdec_create instance %p, total %d\n", vdec,
- atomic_read(&vdec_core->vdec_nr));
+ pr_debug("vdec_create instance %p, total %d, PM: %s\n", vdec,
+ atomic_read(&vdec_core->vdec_nr),
+ get_pm_name(vdec_core->pm->pm_type));
//trace_vdec_create(vdec); /*DEBUG_TMP*/
@@ -3161,66 +3132,6 @@ static int vdec_core_thread(void *data)
}
#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
-static bool test_hevc(u32 decomp_addr, u32 us_delay)
-{
- int i;
-
- /* SW_RESET IPP */
- WRITE_VREG(HEVCD_IPP_TOP_CNTL, 1);
- WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0);
-
- /* initialize all canvas table */
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0);
- for (i = 0; i < 32; i++)
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
- 0x1 | (i << 8) | decomp_addr);
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1);
- WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1);
- for (i = 0; i < 32; i++)
- WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
-
- /* Initialize mcrcc */
- WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2);
- WRITE_VREG(HEVCD_MCRCC_CTL2, 0x0);
- WRITE_VREG(HEVCD_MCRCC_CTL3, 0x0);
- WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
-
- /* Decomp initialize */
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x0);
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0);
-
- /* Frame level initialization */
- WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG, 0x100 | (0x100 << 16));
- WRITE_VREG(HEVCD_IPP_TOP_TILECONFIG3, 0x0);
- WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 0x1 << 5);
- WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x2 | (0x2 << 2));
-
- WRITE_VREG(HEVCD_IPP_CONFIG, 0x0);
- WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, 0x0);
-
- /* Enable SWIMP mode */
- WRITE_VREG(HEVCD_IPP_SWMPREDIF_CONFIG, 0x1);
-
- /* Enable frame */
- WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x2);
- WRITE_VREG(HEVCD_IPP_TOP_FRMCTL, 0x1);
-
- /* Send SW-command CTB info */
- WRITE_VREG(HEVCD_IPP_SWMPREDIF_CTBINFO, 0x1 << 31);
-
- /* Send PU_command */
- WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO0, (0x4 << 9) | (0x4 << 16));
- WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO1, 0x1 << 3);
- WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO2, 0x0);
- WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO3, 0x0);
-
- udelay(us_delay);
-
- WRITE_VREG(HEVCD_IPP_DBG_SEL, 0x2 << 4);
-
- return (READ_VREG(HEVCD_IPP_DBG_DATA) & 3) == 1;
-}
-
void vdec_power_reset(void)
{
/* enable vdec1 isolation */
@@ -3267,17 +3178,9 @@ void vdec_power_reset(void)
}
EXPORT_SYMBOL(vdec_power_reset);
-static void vdec_power_switch(struct vdec_pwrc_s *pd, int id, bool on);
void vdec_poweron(enum vdec_type_e core)
{
- void *decomp_addr = NULL;
- dma_addr_t decomp_dma_addr;
- u32 decomp_addr_aligned = 0;
- int hevc_loop = 0;
- int sleep_val, iso_val;
- bool is_power_ctrl_ver2 = false;
-
if (core >= VDEC_MAX)
return;
@@ -3294,270 +3197,7 @@ void vdec_poweron(enum vdec_type_e core)
return;
}
- /* power domain check. */
- if (!disable_power_domain && vdec_core->pd) {
- int pd_id = 0;
-
- if (core == VDEC_1) {
- amports_switch_gate("clk_vdec_mux", 1);
- vdec_clock_hi_enable();
- pd_id = PD_VDEC;
- } else if (core == VDEC_HCODEC) {
- hcodec_clock_enable();
- pd_id = PD_HCODEC;
- } else if (core == VDEC_HEVC) {
- /* enable hevc clock */
- amports_switch_gate("clk_hevc_mux", 1);
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
- amports_switch_gate("clk_hevcb_mux", 1);
- hevc_clock_hi_enable();
- hevc_back_clock_hi_enable();
- pd_id = PD_HEVC;
- }
-
- vdec_power_switch(vdec_core->pd, pd_id, true);
- mutex_unlock(&vdec_mutex);
-
- return;
- }
-
- is_power_ctrl_ver2 =
- ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false;
-
- if (hevc_workaround_needed() &&
- (core == VDEC_HEVC)) {
- decomp_addr = codec_mm_dma_alloc_coherent(MEM_NAME,
- SZ_64K + SZ_4K, &decomp_dma_addr, GFP_KERNEL, 0);
-
- if (decomp_addr) {
- decomp_addr_aligned = ALIGN(decomp_dma_addr, SZ_64K);
- memset((u8 *)decomp_addr +
- (decomp_addr_aligned - decomp_dma_addr),
- 0xff, SZ_4K);
- } else
- pr_err("vdec: alloc HEVC gxbb decomp buffer failed.\n");
- }
-
- if (core == VDEC_1) {
- sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc;
- iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0;
-
- /* vdec1 power on */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_sleep_mask(true, sleep_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("vdec-1 power on ctrl sleep fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
-#endif
- /* wait 10uS */
- udelay(10);
- /* vdec1 soft reset */
- WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
- WRITE_VREG(DOS_SW_RESET0, 0);
- /* enable vdec1 clock */
- /*
- *add power on vdec clock level setting,only for m8 chip,
- * m8baby and m8m2 can dynamic adjust vdec clock,
- * power on with default clock level
- */
- amports_switch_gate("clk_vdec_mux", 1);
- vdec_clock_hi_enable();
- /* power up vdec memories */
- WRITE_VREG(DOS_MEM_PD_VDEC, 0);
-
- /* remove vdec1 isolation */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_iso_mask(true, iso_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("vdec-1 power on ctrl iso fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
-#endif
- /* reset DOS top registers */
- WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0);
- } else if (core == VDEC_2) {
- if (has_vdec2()) {
- /* vdec2 power on */
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
- ~0x30);
- /* wait 10uS */
- udelay(10);
- /* vdec2 soft reset */
- WRITE_VREG(DOS_SW_RESET2, 0xffffffff);
- WRITE_VREG(DOS_SW_RESET2, 0);
- /* enable vdec1 clock */
- vdec2_clock_hi_enable();
- /* power up vdec memories */
- WRITE_VREG(DOS_MEM_PD_VDEC2, 0);
- /* remove vdec2 isolation */
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
- ~0x300);
- /* reset DOS top registers */
- WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0);
- }
- } else if (core == VDEC_HCODEC) {
- if (has_hdec()) {
- sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3;
- iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30;
- /* hcodec power on */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_sleep_mask(true, sleep_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hcodec power on ctrl sleep fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
-#endif
- /* wait 10uS */
- udelay(10);
- /* hcodec soft reset */
- WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
- WRITE_VREG(DOS_SW_RESET1, 0);
- /* enable hcodec clock */
- hcodec_clock_enable();
- /* power up hcodec memories */
- WRITE_VREG(DOS_MEM_PD_HCODEC, 0);
- /* remove hcodec isolation */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_iso_mask(true, iso_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hcodec power on ctrl iso fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
-#endif
- }
- } else if (core == VDEC_HEVC) {
- if (has_hevc_vdec()) {
- bool hevc_fixed = false;
-
- sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0;
- iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00;
-
- while (!hevc_fixed) {
- /* hevc power on */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_sleep_mask(true, sleep_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hevc power on ctrl sleep fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
-#endif
- /* wait 10uS */
- udelay(10);
- /* hevc soft reset */
- WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
- WRITE_VREG(DOS_SW_RESET3, 0);
- /* enable hevc clock */
- amports_switch_gate("clk_hevc_mux", 1);
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
- amports_switch_gate("clk_hevcb_mux", 1);
- hevc_clock_hi_enable();
- hevc_back_clock_hi_enable();
- /* power up hevc memories */
- WRITE_VREG(DOS_MEM_PD_HEVC, 0);
- /* remove hevc isolation */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_iso_mask(true, iso_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hevc power on ctrl iso fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
-#endif
- if (!hevc_workaround_needed())
- break;
-
- if (decomp_addr)
- hevc_fixed = test_hevc(
- decomp_addr_aligned, 20);
-
- if (!hevc_fixed) {
- hevc_loop++;
-
- mutex_unlock(&vdec_mutex);
-
- if (hevc_loop >= HEVC_TEST_LIMIT) {
- pr_warn("hevc power sequence over limit\n");
- pr_warn("=====================================================\n");
- pr_warn(" This chip is identified to have HW failure.\n");
- pr_warn(" Please contact sqa-platform to replace the platform.\n");
- pr_warn("=====================================================\n");
-
- panic("Force panic for chip detection !!!\n");
-
- break;
- }
-
- vdec_poweroff(VDEC_HEVC);
-
- mdelay(10);
-
- mutex_lock(&vdec_mutex);
- }
- }
-
- if (hevc_loop > hevc_max_reset_count)
- hevc_max_reset_count = hevc_loop;
-
- WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
- udelay(10);
- WRITE_VREG(DOS_SW_RESET3, 0);
- }
- }
-
- if (decomp_addr)
- codec_mm_dma_free_coherent(MEM_NAME,
- SZ_64K + SZ_4K, decomp_addr, decomp_dma_addr, 0);
+ vdec_core->pm->power_on(vdec_core->cma_dev, core);
mutex_unlock(&vdec_mutex);
}
@@ -3565,8 +3205,6 @@ EXPORT_SYMBOL(vdec_poweron);
void vdec_poweroff(enum vdec_type_e core)
{
- int sleep_val, iso_val;
- bool is_power_ctrl_ver2 = false;
if (core >= VDEC_MAX)
return;
@@ -3578,226 +3216,15 @@ void vdec_poweroff(enum vdec_type_e core)
return;
}
- /* power domain check. */
- if (!disable_power_domain && vdec_core->pd) {
- int pd_id = 0;
-
- if (core == VDEC_1) {
- vdec_clock_off();
- pd_id = PD_VDEC;
- } else if (core == VDEC_HCODEC) {
- hcodec_clock_off();
- pd_id = PD_HCODEC;
- } else if (core == VDEC_HEVC) {
- /* disable hevc clock */
- hevc_clock_off();
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
- hevc_back_clock_off();
- pd_id = PD_HEVC;
- }
-
- vdec_power_switch(vdec_core->pd, pd_id, false);
- mutex_unlock(&vdec_mutex);
-
- return;
- }
-
- is_power_ctrl_ver2 =
- ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false;
-
- if (core == VDEC_1) {
- sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc;
- iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0;
-
- /* disable VDEC_1 DMC REQ*/
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_iso_mask(false, iso_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("vdec-1 power off ctrl iso fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
-#endif
- /* power off vdec1 memories */
- WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
- /* disable vdec1 clock */
- vdec_clock_off();
- /* vdec1 power off */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_sleep_mask(false, sleep_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("vdec-1 power off ctrl sleep fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
-#endif
- } else if (core == VDEC_2) {
- if (has_vdec2()) {
- /* enable vdec2 isolation */
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
- 0x300);
- /* power off vdec2 memories */
- WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL);
- /* disable vdec2 clock */
- vdec2_clock_off();
- /* vdec2 power off */
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
- 0x30);
- }
- } else if (core == VDEC_HCODEC) {
- if (has_hdec()) {
- sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3;
- iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30;
-
- /* enable hcodec isolation */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_iso_mask(false, iso_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hcodec power off ctrl iso fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
-#endif
- /* power off hcodec memories */
- WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL);
- /* disable hcodec clock */
- hcodec_clock_off();
- /* hcodec power off */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_sleep_mask(false, sleep_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hcodec power off ctrl sleep fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
-#endif
- }
- } else if (core == VDEC_HEVC) {
- if (has_hevc_vdec()) {
- sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0;
- iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00;
-
- if (no_powerdown == 0) {
- /* enable hevc isolation */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_iso_mask(false, iso_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hevc power off ctrl iso fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
- READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
-#endif
- /* power off hevc memories */
- WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
-
- /* disable hevc clock */
- hevc_clock_off();
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
- hevc_back_clock_off();
+ vdec_core->pm->power_off(vdec_core->cma_dev, core);
- /* hevc power off */
-#ifdef CONFIG_AMLOGIC_POWER
- if (is_support_power_ctrl()) {
- if (power_ctrl_sleep_mask(false, sleep_val, 0)) {
- mutex_unlock(&vdec_mutex);
- pr_err("hevc power off ctrl sleep fail.\n");
- return;
- }
- } else {
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
- }
-#else
- WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
- READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
-#endif
- } else {
- pr_info("!!!!!!!!not power down\n");
- hevc_reset_core(NULL);
- no_powerdown = 0;
- }
- }
- }
mutex_unlock(&vdec_mutex);
}
EXPORT_SYMBOL(vdec_poweroff);
bool vdec_on(enum vdec_type_e core)
{
- bool ret = false;
-
- if (core == VDEC_1) {
- if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
- (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1))
- ? 0x2 : 0xc)) == 0) &&
- (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100))
- ret = true;
- } else if (core == VDEC_2) {
- if (has_vdec2()) {
- if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x30) == 0) &&
- (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100))
- ret = true;
- }
- } else if (core == VDEC_HCODEC) {
- if (has_hdec()) {
- if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
- (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1))
- ? 0x1 : 0x3)) == 0) &&
- (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000))
- ret = true;
- }
- } else if (core == VDEC_HEVC) {
- if (has_hevc_vdec()) {
- if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
- (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1))
- ? 0x4 : 0xc0)) == 0) &&
- (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000))
- ret = true;
- }
- }
-
- return ret;
+ return vdec_core->pm->power_state(vdec_core->cma_dev, core);
}
EXPORT_SYMBOL(vdec_on);
@@ -4989,65 +4416,6 @@ struct device *get_vdec_device(void)
}
EXPORT_SYMBOL(get_vdec_device);
-static void vdec_power_switch(struct vdec_pwrc_s *pd, int id, bool on)
-{
- struct device *dev = pd[id].dev;
-
- if (on)
- pm_runtime_get_sync(dev);
- else
- pm_runtime_put_sync(dev);
-
- pr_debug("the %-15s power %s\n",
- pd[id].name, on ? "on" : "off");
-}
-
-static int vdec_power_domain_init(struct device *dev,
- struct vdec_pwrc_s **pd_out)
-{
- int i, err;
- struct vdec_pwrc_s *pd = vdec_pd;
-
- for (i = 0; i < ARRAY_SIZE(vdec_pd); i++) {
- pd[i].dev = dev_pm_domain_attach_by_name(dev, pd[i].name);
- if (IS_ERR_OR_NULL(pd[i].dev)) {
- err = PTR_ERR(pd[i].dev);
- dev_err(dev, "Get %s failed, pm-domain: %d\n",
- pd[i].name, err);
- continue;
- }
-
- pd[i].link = device_link_add(dev, pd[i].dev,
- DL_FLAG_PM_RUNTIME |
- DL_FLAG_STATELESS);
- if (IS_ERR_OR_NULL(pd[i].link)) {
- dev_err(dev, "Adding %s device link failed!\n",
- pd[i].name);
- return -ENODEV;
- }
-
- pr_debug("power domain: name: %s, dev: %px, link: %px\n",
- pd[i].name, pd[i].dev, pd[i].link);
- }
-
- *pd_out = pd;
-
- return 0;
-}
-
-static void vdec_power_domain_remove(struct vdec_pwrc_s *pd)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(vdec_pd); i++) {
- if (!IS_ERR_OR_NULL(pd[i].link))
- device_link_del(pd[i].link);
-
- if (!IS_ERR_OR_NULL(pd[i].dev))
- dev_pm_domain_detach(pd[i].dev, true);
- }
-}
-
static int vdec_probe(struct platform_device *pdev)
{
s32 i, r;
@@ -5128,12 +4496,13 @@ static int vdec_probe(struct platform_device *pdev)
WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work");
/*work queue priority lower than vdec-core.*/
- /* init power domains. */
- if (of_property_read_bool(pdev->dev.of_node, "power-domains")) {
- r = vdec_power_domain_init(&pdev->dev, &vdec_core->pd);
+ /* power manager init. */
+ vdec_core->pm = (struct power_manager_s *)
+ of_device_get_match_data(&pdev->dev);
+ if (vdec_core->pm->init) {
+ r = vdec_core->pm->init(&pdev->dev);
if (r) {
- vdec_power_domain_remove(vdec_core->pd);
- pr_err("vdec power domain init failed\n");
+ pr_err("vdec power manager init failed\n");
return r;
}
}
@@ -5160,21 +4529,14 @@ static int vdec_remove(struct platform_device *pdev)
destroy_workqueue(vdec_core->vdec_core_wq);
- if (vdec_core->pd)
- vdec_power_domain_remove(vdec_core->pd);
+ if (vdec_core->pm->release)
+ vdec_core->pm->release(&pdev->dev);
class_unregister(&vdec_class);
return 0;
}
-static const struct of_device_id amlogic_vdec_dt_match[] = {
- {
- .compatible = "amlogic, vdec",
- },
- {},
-};
-
static struct mconfig vdec_configs[] = {
MC_PU32("debug_trace_num", &debug_trace_num),
MC_PI32("hevc_max_reset_count", &hevc_max_reset_count),
@@ -5184,12 +4546,14 @@ static struct mconfig vdec_configs[] = {
};
static struct mconfig_node vdec_node;
+extern const struct of_device_id amlogic_vdec_matches[];
+
static struct platform_driver vdec_driver = {
.probe = vdec_probe,
.remove = vdec_remove,
.driver = {
.name = "vdec",
- .of_match_table = amlogic_vdec_dt_match,
+ .of_match_table = amlogic_vdec_matches,
}
};
@@ -5377,7 +4741,6 @@ module_param(fps_detection, int, 0664);
module_param(fps_clear, int, 0664);
module_param(force_nosecure_even_drm, int, 0664);
module_param(disable_switch_single_to_mult, int, 0664);
-module_param(disable_power_domain, bool, 0664);
module_param(frameinfo_flag, int, 0664);
MODULE_PARM_DESC(frameinfo_flag,
diff --git a/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c
new file mode 100644
index 0000000..36fe9d0
--- a/dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c
@@ -0,0 +1,801 @@
+/*
+ * drivers/amlogic/media/frame_provider/decoder/utils/vdec_power_ctrl.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#define DEBUG
+#include "vdec_power_ctrl.h"
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include <linux/amlogic/power_ctrl.h>
+//#include <dt-bindings/power/sc2-pd.h>
+#include <linux/amlogic/pwr_ctrl.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../../../common/media_clock/switch/amports_gate.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "../../../common/media_clock/clk/clk.h"
+
+#define HEVC_TEST_LIMIT (100)
+#define GXBB_REV_A_MINOR (0xa)
+
+/* wait other module to support this function */
+bool is_support_power_ctrl(void) { return 0; }
+
+extern int no_powerdown;
+extern int hevc_max_reset_count;
+
+struct pm_name_s {
+ int type;
+ const char *name;
+};
+
+static const struct pm_name_s pm_name[] = {
+ {PM_POWER_CTRL_RW_REG, "legacy"},
+ {PM_POWER_CTRL_API, "power-ctrl-api"},
+ {PM_POWER_DOMAIN, "power-domain"},
+ {PM_POWER_DOMAIN_SEC_API, "pd-sec-api"},
+ {PM_POWER_DOMAIN_NONSEC_API, "pd-non-sec-api"},
+};
+
+const char *get_pm_name(int type)
+{
+ const char *name = "unknown";
+ int i, size = ARRAY_SIZE(pm_name);
+
+ for (i = 0; i < size; i++) {
+ if (type == pm_name[i].type)
+ name = pm_name[i].name;
+ }
+
+ return name;
+}
+EXPORT_SYMBOL(get_pm_name);
+
+static struct pm_pd_s pm_domain_data[] = {
+ { .name = "pwrc-vdec", },
+ { .name = "pwrc-hcodec",},
+ { .name = "pwrc-vdec-2", },
+ { .name = "pwrc-hevc", },
+ { .name = "pwrc-hevc-b", },
+ { .name = "pwrc-wave", },
+};
+
+static void pm_vdec_power_switch(struct pm_pd_s *pd, int id, bool on)
+{
+ struct device *dev = pd[id].dev;
+
+ if (on)
+ pm_runtime_get_sync(dev);
+ else
+ pm_runtime_put_sync(dev);
+
+ pr_debug("the %-15s power %s\n",
+ pd[id].name, on ? "on" : "off");
+}
+
+static int pm_vdec_power_domain_init(struct device *dev)
+{
+ int i, err;
+ const struct power_manager_s *pm = of_device_get_match_data(dev);
+ struct pm_pd_s *pd = pm->pd_data;
+
+ for (i = 0; i < ARRAY_SIZE(pm_domain_data); i++) {
+ pd[i].dev = dev_pm_domain_attach_by_name(dev, pd[i].name);
+ if (IS_ERR_OR_NULL(pd[i].dev)) {
+ err = PTR_ERR(pd[i].dev);
+ dev_err(dev, "Get %s failed, pm-domain: %d\n",
+ pd[i].name, err);
+ continue;
+ }
+
+ pd[i].link = device_link_add(dev, pd[i].dev,
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_STATELESS);
+ if (IS_ERR_OR_NULL(pd[i].link)) {
+ dev_err(dev, "Adding %s device link failed!\n",
+ pd[i].name);
+ return -ENODEV;
+ }
+
+ pr_debug("power domain: name: %s, dev: %px, link: %px\n",
+ pd[i].name, pd[i].dev, pd[i].link);
+ }
+
+ return 0;
+}
+
+static void pm_vdec_power_domain_relese(struct device *dev)
+{
+ int i;
+ const struct power_manager_s *pm = of_device_get_match_data(dev);
+ struct pm_pd_s *pd = pm->pd_data;
+
+ for (i = 0; i < ARRAY_SIZE(pm_domain_data); i++) {
+ if (!IS_ERR_OR_NULL(pd[i].link))
+ device_link_del(pd[i].link);
+
+ if (!IS_ERR_OR_NULL(pd[i].dev))
+ dev_pm_domain_detach(pd[i].dev, true);
+ }
+}
+
+static void pm_vdec_clock_on(int id)
+{
+ if (id == VDEC_1) {
+ amports_switch_gate("clk_vdec_mux", 1);
+ vdec_clock_hi_enable();
+ } else if (id == VDEC_HCODEC) {
+ hcodec_clock_enable();
+ } else if (id == VDEC_HEVC) {
+ /* enable hevc clock */
+ amports_switch_gate("clk_hevc_mux", 1);
+ if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+ amports_switch_gate("clk_hevcb_mux", 1);
+ hevc_clock_hi_enable();
+ hevc_back_clock_hi_enable();
+ }
+}
+
+static void pm_vdec_clock_off(int id)
+{
+ if (id == VDEC_1) {
+ vdec_clock_off();
+ } else if (id == VDEC_HCODEC) {
+ hcodec_clock_off();
+ } else if (id == VDEC_HEVC) {
+ /* disable hevc clock */
+ hevc_clock_off();
+ if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+ hevc_back_clock_off();
+ }
+}
+
+static void pm_vdec_power_domain_power_on(struct device *dev, int id)
+{
+ const struct power_manager_s *pm = of_device_get_match_data(dev);
+
+ pm_vdec_clock_on(id);
+ pm_vdec_power_switch(pm->pd_data, id, true);
+}
+
+static void pm_vdec_power_domain_power_off(struct device *dev, int id)
+{
+ const struct power_manager_s *pm = of_device_get_match_data(dev);
+
+ pm_vdec_clock_off(id);
+ pm_vdec_power_switch(pm->pd_data, id, false);
+}
+
+static bool pm_vdec_power_domain_power_state(struct device *dev, int id)
+{
+ const struct power_manager_s *pm = of_device_get_match_data(dev);
+
+ return pm_runtime_active(pm->pd_data[id].dev);
+}
+
+static bool test_hevc(u32 decomp_addr, u32 us_delay)
+{
+ int i;
+
+ /* SW_RESET IPP */
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL, 1);
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0);
+
+ /* initialize all canvas table */
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0);
+ for (i = 0; i < 32; i++)
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ 0x1 | (i << 8) | decomp_addr);
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1);
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1);
+ for (i = 0; i < 32; i++)
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
+
+ /* Initialize mcrcc */
+ WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2);
+ WRITE_VREG(HEVCD_MCRCC_CTL2, 0x0);
+ WRITE_VREG(HEVCD_MCRCC_CTL3, 0x0);
+ WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
+
+ /* Decomp initialize */
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x0);
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0);
+
+ /* Frame level initialization */
+ WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG, 0x100 | (0x100 << 16));
+ WRITE_VREG(HEVCD_IPP_TOP_TILECONFIG3, 0x0);
+ WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 0x1 << 5);
+ WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x2 | (0x2 << 2));
+
+ WRITE_VREG(HEVCD_IPP_CONFIG, 0x0);
+ WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, 0x0);
+
+ /* Enable SWIMP mode */
+ WRITE_VREG(HEVCD_IPP_SWMPREDIF_CONFIG, 0x1);
+
+ /* Enable frame */
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x2);
+ WRITE_VREG(HEVCD_IPP_TOP_FRMCTL, 0x1);
+
+ /* Send SW-command CTB info */
+ WRITE_VREG(HEVCD_IPP_SWMPREDIF_CTBINFO, 0x1 << 31);
+
+ /* Send PU_command */
+ WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO0, (0x4 << 9) | (0x4 << 16));
+ WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO1, 0x1 << 3);
+ WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO2, 0x0);
+ WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO3, 0x0);
+
+ udelay(us_delay);
+
+ WRITE_VREG(HEVCD_IPP_DBG_SEL, 0x2 << 4);
+
+ return (READ_VREG(HEVCD_IPP_DBG_DATA) & 3) == 1;
+}
+
+static bool hevc_workaround_needed(void)
+{
+ return (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) &&
+ (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR)
+ == GXBB_REV_A_MINOR);
+}
+
+static void pm_vdec_legacy_power_off(struct device *dev, int id);
+
+static void pm_vdec_legacy_power_on(struct device *dev, int id)
+{
+ void *decomp_addr = NULL;
+ dma_addr_t decomp_dma_addr;
+ u32 decomp_addr_aligned = 0;
+ int hevc_loop = 0;
+ int sleep_val, iso_val;
+ bool is_power_ctrl_ver2 = false;
+
+ is_power_ctrl_ver2 =
+ ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false;
+
+ if (hevc_workaround_needed() &&
+ (id == VDEC_HEVC)) {
+ decomp_addr = codec_mm_dma_alloc_coherent("vdec_prealloc",
+ SZ_64K + SZ_4K, &decomp_dma_addr, GFP_KERNEL, 0);
+
+ if (decomp_addr) {
+ decomp_addr_aligned = ALIGN(decomp_dma_addr, SZ_64K);
+ memset((u8 *)decomp_addr +
+ (decomp_addr_aligned - decomp_dma_addr),
+ 0xff, SZ_4K);
+ } else
+ pr_err("vdec: alloc HEVC gxbb decomp buffer failed.\n");
+ }
+
+ if (id == VDEC_1) {
+ sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc;
+ iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0;
+
+ /* vdec1 power on */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_sleep_mask(true, sleep_val, 0)) {
+ pr_err("vdec-1 power on ctrl sleep fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
+#endif
+ /* wait 10uS */
+ udelay(10);
+ /* vdec1 soft reset */
+ WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
+ WRITE_VREG(DOS_SW_RESET0, 0);
+ /* enable vdec1 clock */
+ /*
+ *add power on vdec clock level setting,only for m8 chip,
+ * m8baby and m8m2 can dynamic adjust vdec clock,
+ * power on with default clock level
+ */
+ amports_switch_gate("clk_vdec_mux", 1);
+ vdec_clock_hi_enable();
+ /* power up vdec memories */
+ WRITE_VREG(DOS_MEM_PD_VDEC, 0);
+
+ /* remove vdec1 isolation */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_iso_mask(true, iso_val, 0)) {
+ pr_err("vdec-1 power on ctrl iso fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
+#endif
+ /* reset DOS top registers */
+ WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0);
+ } else if (id == VDEC_2) {
+ if (has_vdec2()) {
+ /* vdec2 power on */
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
+ ~0x30);
+ /* wait 10uS */
+ udelay(10);
+ /* vdec2 soft reset */
+ WRITE_VREG(DOS_SW_RESET2, 0xffffffff);
+ WRITE_VREG(DOS_SW_RESET2, 0);
+ /* enable vdec1 clock */
+ vdec2_clock_hi_enable();
+ /* power up vdec memories */
+ WRITE_VREG(DOS_MEM_PD_VDEC2, 0);
+ /* remove vdec2 isolation */
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
+ ~0x300);
+ /* reset DOS top registers */
+ WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0);
+ }
+ } else if (id == VDEC_HCODEC) {
+ if (has_hdec()) {
+ sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3;
+ iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30;
+
+ /* hcodec power on */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_sleep_mask(true, sleep_val, 0)) {
+ pr_err("hcodec power on ctrl sleep fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
+#endif
+ /* wait 10uS */
+ udelay(10);
+ /* hcodec soft reset */
+ WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
+ WRITE_VREG(DOS_SW_RESET1, 0);
+ /* enable hcodec clock */
+ hcodec_clock_enable();
+ /* power up hcodec memories */
+ WRITE_VREG(DOS_MEM_PD_HCODEC, 0);
+ /* remove hcodec isolation */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_iso_mask(true, iso_val, 0)) {
+ pr_err("hcodec power on ctrl iso fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
+#endif
+ }
+ } else if (id == VDEC_HEVC) {
+ if (has_hevc_vdec()) {
+ bool hevc_fixed = false;
+
+ sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0;
+ iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00;
+
+ while (!hevc_fixed) {
+ /* hevc power on */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_sleep_mask(true, sleep_val, 0)) {
+ pr_err("hevc power on ctrl sleep fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & ~sleep_val);
+#endif
+ /* wait 10uS */
+ udelay(10);
+ /* hevc soft reset */
+ WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
+ WRITE_VREG(DOS_SW_RESET3, 0);
+ /* enable hevc clock */
+ amports_switch_gate("clk_hevc_mux", 1);
+ if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+ amports_switch_gate("clk_hevcb_mux", 1);
+ hevc_clock_hi_enable();
+ hevc_back_clock_hi_enable();
+ /* power up hevc memories */
+ WRITE_VREG(DOS_MEM_PD_HEVC, 0);
+ /* remove hevc isolation */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_iso_mask(true, iso_val, 0)) {
+ pr_err("hevc power on ctrl iso fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) & ~iso_val);
+#endif
+ if (!hevc_workaround_needed())
+ break;
+
+ if (decomp_addr)
+ hevc_fixed = test_hevc(
+ decomp_addr_aligned, 20);
+
+ if (!hevc_fixed) {
+ hevc_loop++;
+ if (hevc_loop >= HEVC_TEST_LIMIT) {
+ pr_warn("hevc power sequence over limit\n");
+ pr_warn("=====================================================\n");
+ pr_warn(" This chip is identified to have HW failure.\n");
+ pr_warn(" Please contact sqa-platform to replace the platform.\n");
+ pr_warn("=====================================================\n");
+
+ panic("Force panic for chip detection !!!\n");
+
+ break;
+ }
+
+ pm_vdec_legacy_power_off(NULL, VDEC_HEVC);
+
+ mdelay(10);
+ }
+ }
+
+ if (hevc_loop > hevc_max_reset_count)
+ hevc_max_reset_count = hevc_loop;
+
+ WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
+ udelay(10);
+ WRITE_VREG(DOS_SW_RESET3, 0);
+ }
+ }
+
+ if (decomp_addr)
+ codec_mm_dma_free_coherent("vdec_prealloc",
+ SZ_64K + SZ_4K, decomp_addr, decomp_dma_addr, 0);
+}
+
+static void pm_vdec_legacy_power_off(struct device *dev, int id)
+{
+ int sleep_val, iso_val;
+ bool is_power_ctrl_ver2 = false;
+
+ is_power_ctrl_ver2 =
+ ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)) ? true : false;
+
+ if (id == VDEC_1) {
+ sleep_val = is_power_ctrl_ver2 ? 0x2 : 0xc;
+ iso_val = is_power_ctrl_ver2 ? 0x2 : 0xc0;
+
+ /* enable vdec1 isolation */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_iso_mask(false, iso_val, 0)) {
+ pr_err("vdec-1 power off ctrl iso fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
+#endif
+ /* power off vdec1 memories */
+ WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
+ /* disable vdec1 clock */
+ vdec_clock_off();
+ /* vdec1 power off */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_sleep_mask(false, sleep_val, 0)) {
+ pr_err("vdec-1 power off ctrl sleep fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
+#endif
+ } else if (id == VDEC_2) {
+ if (has_vdec2()) {
+ /* enable vdec2 isolation */
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
+ 0x300);
+ /* power off vdec2 memories */
+ WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL);
+ /* disable vdec2 clock */
+ vdec2_clock_off();
+ /* vdec2 power off */
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
+ 0x30);
+ }
+ } else if (id == VDEC_HCODEC) {
+ if (has_hdec()) {
+ sleep_val = is_power_ctrl_ver2 ? 0x1 : 0x3;
+ iso_val = is_power_ctrl_ver2 ? 0x1 : 0x30;
+
+ /* enable hcodec isolation */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_iso_mask(false, iso_val, 0)) {
+ pr_err("hcodec power off ctrl iso fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
+#endif
+ /* power off hcodec memories */
+ WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL);
+ /* disable hcodec clock */
+ hcodec_clock_off();
+ /* hcodec power off */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_sleep_mask(false, sleep_val, 0)) {
+ pr_err("hcodec power off ctrl sleep fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
+#endif
+ }
+ } else if (id == VDEC_HEVC) {
+ if (has_hevc_vdec()) {
+ sleep_val = is_power_ctrl_ver2 ? 0x4 : 0xc0;
+ iso_val = is_power_ctrl_ver2 ? 0x4 : 0xc00;
+
+ if (no_powerdown == 0) {
+ /* enable hevc isolation */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_iso_mask(false, iso_val, 0)) {
+ pr_err("hevc power off ctrl iso fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+ READ_AOREG(AO_RTI_GEN_PWR_ISO0) | iso_val);
+#endif
+ /* power off hevc memories */
+ WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
+
+ /* disable hevc clock */
+ hevc_clock_off();
+ if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+ hevc_back_clock_off();
+
+ /* hevc power off */
+#ifdef CONFIG_AMLOGIC_POWER
+ if (is_support_power_ctrl()) {
+ if (power_ctrl_sleep_mask(false, sleep_val, 0)) {
+ pr_err("hevc power off ctrl sleep fail.\n");
+ return;
+ }
+ } else {
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
+ }
+#else
+ WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+ READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | sleep_val);
+#endif
+ } else {
+ pr_info("!!!!!!!!not power down\n");
+ hevc_reset_core(NULL);
+ no_powerdown = 0;
+ }
+ }
+ }
+}
+
+static bool pm_vdec_legacy_power_state(struct device *dev, int id)
+{
+ bool ret = false;
+
+ if (id == VDEC_1) {
+ if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
+ (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1))
+ ? 0x2 : 0xc)) == 0) &&
+ (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100))
+ ret = true;
+ } else if (id == VDEC_2) {
+ if (has_vdec2()) {
+ if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x30) == 0) &&
+ (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100))
+ ret = true;
+ }
+ } else if (id == VDEC_HCODEC) {
+ if (has_hdec()) {
+ if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
+ (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1))
+ ? 0x1 : 0x3)) == 0) &&
+ (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000))
+ ret = true;
+ }
+ } else if (id == VDEC_HEVC) {
+ if (has_hevc_vdec()) {
+ if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
+ (((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1))
+ ? 0x4 : 0xc0)) == 0) &&
+ (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000))
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+static void pm_vdec_pd_sec_api_power_on(struct device *dev, int id)
+{
+#if 0
+ int pd_id = (id == VDEC_1) ? PDID_DOS_VDEC :
+ (id == VDEC_HEVC) ? PDID_DOS_HEVC :
+ PDID_DOS_HCODEC;
+
+ pm_vdec_clock_on(id);
+ pwr_ctrl_psci_smc(pd_id, PWR_ON);
+#endif
+}
+
+static void pm_vdec_pd_sec_api_power_off(struct device *dev, int id)
+{
+#if 0
+ int pd_id = (id == VDEC_1) ? PDID_DOS_VDEC :
+ (id == VDEC_HEVC) ? PDID_DOS_HEVC :
+ PDID_DOS_HCODEC;
+
+ pm_vdec_clock_off(id);
+ pwr_ctrl_psci_smc(pd_id, PWR_OFF);
+#endif
+}
+
+static bool pm_vdec_pd_sec_api_power_state(struct device *dev, int id)
+{
+#if 0
+ int pd_id = (id == VDEC_1) ? PDID_DOS_VDEC :
+ (id == VDEC_HEVC) ? PDID_DOS_HEVC :
+ PDID_DOS_HCODEC;
+
+ return !pwr_ctrl_status_psci_smc(pd_id);
+#endif
+ return 0;
+}
+
+static void pm_vdec_pd_nosec_api_power_on(struct device *dev, int id)
+{
+#if 0
+ int pd_id = (id == VDEC_1) ? PM_DOS_VDEC :
+ (id == VDEC_HEVC) ? PM_DOS_HEVC :
+ PM_DOS_HCODEC;
+
+ pm_vdec_clock_on(id);
+ power_domain_switch(pd_id, PWR_ON);
+#endif
+}
+
+static void pm_vdec_pd_nosec_api_power_off(struct device *dev, int id)
+{
+#if 0
+ int pd_id = (id == VDEC_1) ? PM_DOS_VDEC :
+ (id == VDEC_HEVC) ? PM_DOS_HEVC :
+ PM_DOS_HCODEC;
+
+ pm_vdec_clock_off(id);
+ power_domain_switch(pd_id, PWR_OFF);
+#endif
+}
+
+static bool pm_vdec_pd_nosec_api_power_state(struct device *dev, int id)
+{
+ return pm_vdec_legacy_power_state(dev, id);
+}
+
+static const struct power_manager_s pm_rw_reg_data = {
+ .pm_type = PM_POWER_CTRL_RW_REG,
+ .power_on = pm_vdec_legacy_power_on,
+ .power_off = pm_vdec_legacy_power_off,
+ .power_state = pm_vdec_legacy_power_state,
+};
+
+static const struct power_manager_s pm_ctrl_api_data = {
+ .pm_type = PM_POWER_CTRL_API,
+ .power_on = pm_vdec_legacy_power_on,
+ .power_off = pm_vdec_legacy_power_off,
+ .power_state = pm_vdec_legacy_power_state,
+};
+
+static const struct power_manager_s pm_pd_data = {
+ .pm_type = PM_POWER_DOMAIN,
+ .pd_data = pm_domain_data,
+ .init = pm_vdec_power_domain_init,
+ .release = pm_vdec_power_domain_relese,
+ .power_on = pm_vdec_power_domain_power_on,
+ .power_off = pm_vdec_power_domain_power_off,
+ .power_state = pm_vdec_power_domain_power_state,
+};
+
+static const struct power_manager_s pm_pd_sec_api_data = {
+ .pm_type = PM_POWER_DOMAIN_SEC_API,
+ .power_on = pm_vdec_pd_sec_api_power_on,
+ .power_off = pm_vdec_pd_sec_api_power_off,
+ .power_state = pm_vdec_pd_sec_api_power_state,
+};
+
+static const struct power_manager_s pm_pd_nosec_api_data = {
+ .pm_type = PM_POWER_DOMAIN_NONSEC_API,
+ .power_on = pm_vdec_pd_nosec_api_power_on,
+ .power_off = pm_vdec_pd_nosec_api_power_off,
+ .power_state = pm_vdec_pd_nosec_api_power_state,
+};
+
+const struct of_device_id amlogic_vdec_matches[] = {
+ { .compatible = "amlogic, vdec", .data = &pm_rw_reg_data },
+ { .compatible = "amlogic, vdec-pm-api", .data = &pm_ctrl_api_data },
+ { .compatible = "amlogic, vdec-pm-pd", .data = &pm_pd_data },
+ { .compatible = "amlogic, vdec-pm-pd-sec-api", .data = &pm_pd_sec_api_data },
+ { .compatible = "amlogic, vdec-pm-pd-nsec-api", .data = &pm_pd_nosec_api_data },
+ {},
+};
+EXPORT_SYMBOL(amlogic_vdec_matches);
+
diff --git a/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h
new file mode 100644
index 0000000..e7ab77e
--- a/dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h
@@ -0,0 +1,107 @@
+/*
+ * drivers/amlogic/media/frame_provider/decoder/utils/vdec_power_ctrl.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include "vdec.h"
+
+/* Directly controlled by reading and writing registers. */
+#define PM_POWER_CTRL_RW_REG (0)
+
+/* Use power_ctrl_xxx family of interface controls. */
+#define PM_POWER_CTRL_API (1)
+
+/*
+ * Power Domain interface control, currently supported
+ * in versions 4.19 and above.
+ */
+#define PM_POWER_DOMAIN (2)
+
+/*
+ * Controlled by the secure API provided by power domain,
+ * version 4.9 supports currently supported platforms (SC2).
+ */
+#define PM_POWER_DOMAIN_SEC_API (3)
+
+/*
+ * Use non-secure API control through power domain, version 4.9 support,
+ * currently supported platforms (SM1, TM2, TM2-revB).
+ */
+#define PM_POWER_DOMAIN_NONSEC_API (4)
+
+enum pm_pd_e {
+ PD_VDEC,
+ PD_HCODEC,
+ PD_VDEC2,
+ PD_HEVC,
+ PD_HEVCB,
+ PD_WAVE,
+ PD_MAX
+};
+
+struct pm_pd_s {
+ u8 *name;
+ struct device *dev;
+ struct device_link *link;
+};
+
+struct power_manager_s {
+ int pm_type;
+ struct pm_pd_s *pd_data;
+ int (*init) (struct device *dev);
+ void (*release) (struct device *dev);
+ void (*power_on) (struct device *dev, int id);
+ void (*power_off) (struct device *dev, int id);
+ bool (*power_state) (struct device *dev, int id);
+};
+
+const char *get_pm_name(int type);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
+#define DL_FLAG_STATELESS BIT(0)
+#define DL_FLAG_AUTOREMOVE_CONSUMER BIT(1)
+#define DL_FLAG_PM_RUNTIME BIT(2)
+#define DL_FLAG_RPM_ACTIVE BIT(3)
+#define DL_FLAG_AUTOREMOVE_SUPPLIER BIT(4)
+
+struct device_link {
+ u32 flags;
+ /* ... */
+};
+
+static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
+ const char *name)
+ { return NULL; }
+static inline struct device_link *device_link_add(struct device *consumer,
+ struct device *supplier, u32 flags)
+ { return NULL; }
+static inline void device_link_del(struct device_link *link) { return; }
+static inline void device_link_remove(void *consumer, struct device *supplier) { return; }
+#endif
+
diff --git a/drivers/stream_input/amports/amstream.c b/drivers/stream_input/amports/amstream.c
index b1c74ed..8f0139d 100644
--- a/drivers/stream_input/amports/amstream.c
+++ b/drivers/stream_input/amports/amstream.c
@@ -1336,7 +1336,6 @@ static void set_userdata_poc(struct userdata_poc_info_t poc)
if (userdata_poc_wi == USERDATA_FIFO_NUM)
userdata_poc_wi = 0;
}
-EXPORT_SYMBOL(set_userdata_poc);
void init_userdata_fifo(void)
{