media_modules: sc2 encoder bringup [1/1]
authorRico Yang <wei.yang@amlogic.com>
Fri, 3 Jul 2020 13:45:33 +0000 (21:45 +0800)
committerZhi Zhou <zhi.zhou@amlogic.com>
Tue, 28 Jul 2020 03:28:59 +0000 (20:28 -0700)
PD#SWPL-25846

Problem:
sc2 bringup

Solution:
sc2 bringup

Verify:
verified on AH219

#Signed-off-by: Rico Yang <wei.yang@amlogic.com>
#Change-Id: Ie7f65deda5e580424f7e593115feb98181733581

media_modules: h265enc: set wave_clok_a to 667 and add interface
for setting clock speed [1/1]

PD#SWPL-25846

Problem:
wave420 run underclocked

Solution:
set wave_clock_a to 667M

Verify:
verified on AH219

#Signed-off-by: Rico Yang <wei.yang@amlogic.com>
#Change-Id: I6f1b6b067ca5196476cc674540e0ef079c52530f

Signed-off-by: Rico Yang <wei.yang@amlogic.com>
Change-Id: Ie7f65deda5e580424f7e593115feb98181733581

drivers/frame_sink/encoder/h264/encoder.c
drivers/frame_sink/encoder/h265/vpu.c
drivers/frame_sink/encoder/jpeg/jpegenc.c

index 49a70881f9b2be2994f089179fe486380112cf8b..549788d036fd1babc0bc9be7ac2a56833ffcada3 100644 (file)
  *
 */
 
+#define LOG_LINE() pr_err("[%s:%d]\n", __FUNCTION__, __LINE__);
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/clk.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/reset.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/amlogic/media/utils/amports_config.h>
 #include "encoder.h"
 #include "../../../frame_provider/decoder/utils/amvdec.h"
+#include "../../../frame_provider/decoder/utils/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/utils/amlog.h>
 #include "../../../stream_input/amports/amports_priv.h"
 #include "../../../frame_provider/decoder/utils/firmware.h"
 #include "jpegenc.h"
 #endif
 
+#define MHz (1000000)
+
+#define CHECK_RET(_ret) if (ret) {enc_pr(LOG_ERROR, \
+               "%s:%d:function call failed with result: %d\n",\
+               __FUNCTION__, __LINE__, _ret);}
+
 #define ENCODE_NAME "encoder"
 #define AMVENC_CANVAS_INDEX 0xE4
 #define AMVENC_CANVAS_MAX_INDEX 0xEF
@@ -93,12 +108,23 @@ static u32 encode_print_level = LOG_DEBUG;
 static u32 no_timeout;
 static int nr_mode = -1;
 static u32 qp_table_debug;
+static u32 use_reset_control;
+static u32 use_ge2d;
 
 #ifdef H264_ENC_SVC
 static u32 svc_enable = 0; /* Enable sac feature or not */
 static u32 svc_ref_conf = 0; /* Continuous no reference numbers */
 #endif
 
+struct hcodec_clks {
+       struct clk *hcodec_aclk;
+       //struct clk *hcodec_bclk;
+       //struct clk *hcodec_cclk;
+};
+
+static struct hcodec_clks s_hcodec_clks;
+struct reset_control *hcodec_rst;
+
 static u32 me_mv_merge_ctl =
        (0x1 << 31)  |  /* [31] me_merge_mv_en_16 */
        (0x1 << 30)  |  /* [30] me_merge_small_mv_en_16 */
@@ -430,6 +456,64 @@ static void cache_flush(u32 buf_start, u32 buf_size);
 static int enc_dma_buf_get_phys(struct enc_dma_cfg *cfg, unsigned long *addr);
 static void enc_dma_buf_unmap(struct enc_dma_cfg *cfg);
 
+s32 hcodec_hw_reset(void)
+{
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2 && use_reset_control) {
+               reset_control_reset(hcodec_rst);
+               enc_pr(LOG_DEBUG, "request hcodec reset from application.\n");
+       }
+       return 0;
+}
+
+s32 hcodec_clk_prepare(struct device *dev, struct hcodec_clks *clks)
+{
+       int ret;
+
+       clks->hcodec_aclk = devm_clk_get(dev, "cts_hcodec_aclk");
+
+       if (IS_ERR_OR_NULL(clks->hcodec_aclk)) {
+               enc_pr(LOG_ERROR, "failed to get hcodec aclk\n");
+               return -1;
+       }
+
+       ret = clk_set_rate(clks->hcodec_aclk, 667 * MHz);
+       CHECK_RET(ret);
+
+       ret = clk_prepare(clks->hcodec_aclk);
+       CHECK_RET(ret);
+
+       enc_pr(LOG_ERROR, "hcodec_clk_a: %lu MHz\n", clk_get_rate(clks->hcodec_aclk) / 1000000);
+
+       return 0;
+}
+
+void hcodec_clk_unprepare(struct device *dev, struct hcodec_clks *clks)
+{
+       clk_unprepare(clks->hcodec_aclk);
+       devm_clk_put(dev, clks->hcodec_aclk);
+
+       //clk_unprepare(clks->wave_bclk);
+       //devm_clk_put(dev, clks->wave_bclk);
+
+       //clk_unprepare(clks->wave_aclk);
+       //devm_clk_put(dev, clks->wave_aclk);
+}
+
+s32 hcodec_clk_config(u32 enable)
+{
+       if (enable) {
+               clk_enable(s_hcodec_clks.hcodec_aclk);
+               //clk_enable(s_hcodec_clks.wave_bclk);
+               //clk_enable(s_hcodec_clks.wave_cclk);
+       } else {
+               clk_disable(s_hcodec_clks.hcodec_aclk);
+               //clk_disable(s_hcodec_clks.wave_bclk);
+               //clk_disable(s_hcodec_clks.wave_aclk);
+       }
+
+       return 0;
+}
+
 static const char *select_ucode(u32 ucode_index)
 {
        enum ucode_type_e ucode = UCODE_GXL;
@@ -1001,8 +1085,14 @@ static void mfdin_basic(u32 input, u8 iformat,
                        (interp_en << 9) | (r2y_en << 12) |
                        (r2y_mode << 13) | (ifmt_extra << 16) |
                        (nr_enable << 19));
-               WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
-                       (picsize_x << 14) | (picsize_y << 0));
+
+               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+                       WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
+                               (picsize_x << 16) | (picsize_y << 0));
+               } else {
+                       WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
+                               (picsize_x << 14) | (picsize_y << 0));
+               }
        } else {
                reg_offset = 0;
                WRITE_HREG((HCODEC_MFDIN_REG1_CTRL + reg_offset),
@@ -1010,6 +1100,7 @@ static void mfdin_basic(u32 input, u8 iformat,
                        (dsample_en << 6) | (y_size << 8) |
                        (interp_en << 9) | (r2y_en << 12) |
                        (r2y_mode << 13));
+
                WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
                        (picsize_x << 12) | (picsize_y << 0));
        }
@@ -1302,6 +1393,7 @@ static s32 set_input_format(struct encode_wq_s *wq,
                        src_addr = input;
                        picsize_y = wq->pic.encoder_height;
                }
+
                if (request->scale_enable) {
 #ifdef CONFIG_AMLOGIC_MEDIA_GE2D
                        struct config_para_ex_s ge2d_config;
@@ -2331,32 +2423,43 @@ static void avc_prot_init(struct encode_wq_s *wq,
 
 void amvenc_reset(void)
 {
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       WRITE_VREG(DOS_SW_RESET1,
-               (1 << 2) | (1 << 6) |
-               (1 << 7) | (1 << 8) |
-               (1 << 14) | (1 << 16) |
-               (1 << 17));
-       WRITE_VREG(DOS_SW_RESET1, 0);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2 &&
+                       use_reset_control) {
+               hcodec_hw_reset();
+       } else {
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               WRITE_VREG(DOS_SW_RESET1,
+                       (1 << 2) | (1 << 6) |
+                       (1 << 7) | (1 << 8) |
+                       (1 << 14) | (1 << 16) |
+                       (1 << 17));
+               WRITE_VREG(DOS_SW_RESET1, 0);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+       }
 }
 
 void amvenc_start(void)
 {
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       WRITE_VREG(DOS_SW_RESET1,
-               (1 << 12) | (1 << 11));
-       WRITE_VREG(DOS_SW_RESET1, 0);
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2 &&
+                       use_reset_control) {
+               hcodec_hw_reset();
+       } else {
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
 
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
+               WRITE_VREG(DOS_SW_RESET1,
+                       (1 << 12) | (1 << 11));
+               WRITE_VREG(DOS_SW_RESET1, 0);
+
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+       }
 
        WRITE_HREG(HCODEC_MPSR, 0x0001);
 }
@@ -2367,26 +2470,34 @@ void amvenc_stop(void)
 
        WRITE_HREG(HCODEC_MPSR, 0);
        WRITE_HREG(HCODEC_CPSR, 0);
+
        while (READ_HREG(HCODEC_IMEM_DMA_CTRL) & 0x8000) {
                if (time_after(jiffies, timeout))
                        break;
        }
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-
-       WRITE_VREG(DOS_SW_RESET1,
-               (1 << 12) | (1 << 11) |
-               (1 << 2) | (1 << 6) |
-               (1 << 7) | (1 << 8) |
-               (1 << 14) | (1 << 16) |
-               (1 << 17));
 
-       WRITE_VREG(DOS_SW_RESET1, 0);
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2 &&
+                       use_reset_control) {
+               hcodec_hw_reset();
+       } else {
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+
+               WRITE_VREG(DOS_SW_RESET1,
+                       (1 << 12) | (1 << 11) |
+                       (1 << 2) | (1 << 6) |
+                       (1 << 7) | (1 << 8) |
+                       (1 << 14) | (1 << 16) |
+                       (1 << 17));
+
+               WRITE_VREG(DOS_SW_RESET1, 0);
+
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+               READ_VREG(DOS_SW_RESET1);
+       }
 
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
-       READ_VREG(DOS_SW_RESET1);
 }
 
 static void __iomem *mc_addr;
@@ -2466,7 +2577,7 @@ const u32 fix_mc[] __aligned(8) = {
  * If hcodec is not running, then a ucode is loaded and executed
  * instead.
  */
-void amvenc_dos_top_reg_fix(void)
+/*void amvenc_dos_top_reg_fix(void)
 {
        bool hcodec_on;
        ulong flags;
@@ -2511,6 +2622,7 @@ bool amvenc_avc_on(void)
        spin_unlock_irqrestore(&lock, flags);
        return hcodec_on;
 }
+*/
 
 static s32 avc_poweron(u32 clock)
 {
@@ -2523,18 +2635,29 @@ static s32 avc_poweron(u32 clock)
 
        spin_lock_irqsave(&lock, flags);
 
-       WRITE_AOREG(AO_RTI_PWR_CNTL_REG0,
-               (READ_AOREG(AO_RTI_PWR_CNTL_REG0) & (~0x18)));
-       udelay(10);
-       /* Powerup HCODEC */
-       /* [1:0] HCODEC */
-       WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
-                       READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
-                       ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
-                        get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
-                       ? ~0x1 : ~0x3));
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               hcodec_clk_config(1);
+               udelay(20);
 
-       udelay(10);
+               pwr_ctrl_psci_smc(PDID_DOS_HCODEC, PWR_ON);
+               udelay(20);
+               pr_err("hcodec powered on, hcodec clk rate:%ld, pwr_state:%d\n",
+                       clk_get_rate(s_hcodec_clks.hcodec_aclk),
+                       !pwr_ctrl_status_psci_smc(PDID_DOS_HCODEC));
+       } else {
+               WRITE_AOREG(AO_RTI_PWR_CNTL_REG0,
+                       (READ_AOREG(AO_RTI_PWR_CNTL_REG0) & (~0x18)));
+               udelay(10);
+               /* Powerup HCODEC */
+               /* [1:0] HCODEC */
+               WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+                               READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
+                               ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
+                                get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
+                               ? ~0x1 : ~0x3));
+
+               udelay(10);
+       }
 
        WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
        WRITE_VREG(DOS_SW_RESET1, 0);
@@ -2545,12 +2668,16 @@ static s32 avc_poweron(u32 clock)
        /* Powerup HCODEC memories */
        WRITE_VREG(DOS_MEM_PD_HCODEC, 0x0);
 
-       /* Remove HCODEC ISO */
-       WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
-                       READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
-                       ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
-                         get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
-                       ? ~0x1 : ~0x30));
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+
+       } else  {
+               /* Remove HCODEC ISO */
+               WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+                               READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
+                               ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
+                                 get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
+                               ? ~0x1 : ~0x30));
+       }
 
        udelay(10);
        /* Disable auto-clock gate */
@@ -2571,25 +2698,35 @@ static s32 avc_poweroff(void)
 
        spin_lock_irqsave(&lock, flags);
 
-       /* enable HCODEC isolation */
-       WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
-                       READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
-                       ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
-                         get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
-                       ? 0x1 : 0x30));
-
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               hcodec_clk_config(0);
+               udelay(20);
+               pwr_ctrl_psci_smc(PDID_DOS_HCODEC, PWR_OFF);
+               udelay(20);
+       } else {
+               /* enable HCODEC isolation */
+               WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+                               READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
+                               ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
+                                 get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
+                               ? 0x1 : 0x30));
+       }
        /* power off HCODEC memories */
        WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL);
 
        /* disable HCODEC clock */
        hvdec_clock_disable();
 
-       /* HCODEC power off */
-       WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
-                       READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
-                       ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
-                         get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
-                       ? 0x1 : 0x3));
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+
+       } else {
+               /* HCODEC power off */
+               WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+                               READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
+                               ((get_cpu_type() == MESON_CPU_MAJOR_ID_SM1 ||
+                                 get_cpu_type() >= MESON_CPU_MAJOR_ID_TM2)
+                               ? 0x1 : 0x3));
+       }
 
        spin_unlock_irqrestore(&lock, flags);
 
@@ -2604,8 +2741,12 @@ static s32 reload_mc(struct encode_wq_s *wq)
 
        amvenc_stop();
 
-       WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
-       WRITE_VREG(DOS_SW_RESET1, 0);
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2 && use_reset_control) {
+               hcodec_hw_reset();
+       } else {
+               WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
+               WRITE_VREG(DOS_SW_RESET1, 0);
+       }
 
        udelay(10);
 
@@ -2621,7 +2762,7 @@ static void encode_isr_tasklet(ulong data)
 {
        struct encode_manager_s *manager = (struct encode_manager_s *)data;
 
-       enc_pr(LOG_INFO, "encoder is done %d\n", manager->encode_hw_status);
+       enc_pr(LOG_ERROR, "encoder is done %d\n", manager->encode_hw_status);
        if (((manager->encode_hw_status == ENCODER_IDR_DONE)
                || (manager->encode_hw_status == ENCODER_NON_IDR_DONE)
                || (manager->encode_hw_status == ENCODER_SEQUENCE_DONE)
@@ -2636,6 +2777,7 @@ static irqreturn_t enc_isr(s32 irq_number, void *para)
 {
        struct encode_manager_s *manager = (struct encode_manager_s *)para;
 
+       enc_pr(LOG_INFO, "*****ENC_ISR*****\n");
        WRITE_HREG(HCODEC_IRQ_MBOX_CLR, 1);
 
        manager->encode_hw_status  = READ_HREG(ENCODER_STATUS);
@@ -2713,7 +2855,12 @@ static s32 convert_request(struct encode_wq_s *wq, u32 *cmd_info)
                        wq->request.scale_enable = 1;
                        wq->request.src_w = wq->pic.encoder_width;
                        wq->request.src_h = wq->pic.encoder_height;
-                       enc_pr(LOG_DEBUG, "hwenc: force wq->request.scale_enable=%d\n", wq->request.scale_enable);
+                       enc_pr(LOG_INFO, "hwenc: force wq->request.scale_enable=%d\n", wq->request.scale_enable);
+               }
+
+               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+                       enc_pr(LOG_INFO, "disable ge2d scale for sc2\n");
+                       wq->request.scale_enable = 0;
                }
 
                wq->request.nr_mode =
@@ -2850,6 +2997,7 @@ void amvenc_avc_start_cmd(struct encode_wq_s *wq,
        wq->ucode_index = encode_manager.ucode_index;
 
        ie_me_mode = (0 & ME_PIXEL_MODE_MASK) << ME_PIXEL_MODE_SHIFT;
+
        if (encode_manager.need_reset) {
                amvenc_stop();
                reload_flag = 1;
@@ -2857,23 +3005,28 @@ void amvenc_avc_start_cmd(struct encode_wq_s *wq,
                encode_manager.encode_hw_status = ENCODER_IDLE;
                amvenc_reset();
                avc_canvas_init(wq);
-               avc_init_encoder(wq,
-                       (request->cmd == ENCODER_IDR) ? true : false);
+               avc_init_encoder(wq, (request->cmd == ENCODER_IDR) ? true : false);
                avc_init_input_buffer(wq);
                avc_init_output_buffer(wq);
-               avc_prot_init(wq, request, request->quant,
+
+               avc_prot_init(
+                       wq, request, request->quant,
                        (request->cmd == ENCODER_IDR) ? true : false);
+
                avc_init_assit_buffer(wq);
+
                enc_pr(LOG_INFO,
                        "begin to new frame, request->cmd: %d, ucode mode: %d, wq:%p\n",
                        request->cmd, request->ucode_mode, (void *)wq);
        }
+
        if ((request->cmd == ENCODER_IDR) ||
                (request->cmd == ENCODER_NON_IDR)) {
 #ifdef H264_ENC_SVC
                /* encode non reference frame or not */
                if (request->cmd == ENCODER_IDR)
                        wq->pic.non_ref_cnt = 0; //IDR reset counter
+
                if (wq->pic.enable_svc && wq->pic.non_ref_cnt) {
                        enc_pr(LOG_INFO,
                                "PIC is NON REF cmd %d cnt %d value 0x%x\n",
@@ -3009,6 +3162,7 @@ s32 amvenc_avc_start(struct encode_wq_s *wq, u32 clock)
 
        ie_me_mode = (0 & ME_PIXEL_MODE_MASK) << ME_PIXEL_MODE_SHIFT;
        avc_prot_init(wq, NULL, wq->pic.init_qppicture, true);
+
        if (request_irq(encode_manager.irq_num, enc_isr, IRQF_SHARED,
                "enc-irq", (void *)&encode_manager) == 0)
                encode_manager.irq_requested = true;
@@ -3061,7 +3215,7 @@ static s32 avc_init(struct encode_wq_s *wq)
        r = amvenc_avc_start(wq, clock_level);
 
        enc_pr(LOG_DEBUG,
-               "init avc encode. microcode %d, ret=%d, wq:%p.\n",
+               "init avc encode. microcode %d, ret=%d, wq:%px\n",
                encode_manager.ucode_index, r, (void *)wq);
        return 0;
 }
@@ -3078,7 +3232,7 @@ static s32 amvenc_avc_light_reset(struct encode_wq_s *wq, u32 value)
        r = amvenc_avc_start(wq, clock_level);
 
        enc_pr(LOG_DEBUG,
-               "amvenc_avc_light_reset finish, wq:%p. ret=%d\n",
+               "amvenc_avc_light_reset finish, wq:%px, ret=%d\n",
                 (void *)wq, r);
        return r;
 }
@@ -3252,7 +3406,7 @@ static long amvenc_avc_ioctl(struct file *file, u32 cmd, ulong arg)
                        wq->pic.rows_per_slice, (void *)wq);
 #endif
                enc_pr(LOG_DEBUG,
-                       "avc init as mode %d, wq: %p.\n",
+                       "avc init as mode %d, wq: %px.\n",
                        wq->ucode_index, (void *)wq);
 
                if (addr_info[2] > wq->mem.bufspec.max_width ||
@@ -3468,6 +3622,7 @@ static u32 amvenc_avc_poll(struct file *file, poll_table *wait_table)
                atomic_dec(&wq->request_ready);
                return POLLIN | POLLRDNORM;
        }
+
        return 0;
 }
 
@@ -3490,8 +3645,10 @@ static s32 encode_process_request(struct encode_manager_s *manager,
        s32 ret = 0;
        struct encode_wq_s *wq = pitem->request.parent;
        struct encode_request_s *request = &pitem->request;
+
        u32 timeout = (request->timeout == 0) ?
                1 : msecs_to_jiffies(request->timeout);
+
        u32 buf_start = 0;
        u32 size = 0;
        u32 flush_size = ((wq->pic.encoder_width + 31) >> 5 << 5) *
@@ -3549,31 +3706,31 @@ Again:
                wq->output_size = (wq->sps_size << 16) | wq->pps_size;
        } else {
                wq->hw_status = manager->encode_hw_status;
+
                if ((manager->encode_hw_status == ENCODER_IDR_DONE) ||
                    (manager->encode_hw_status == ENCODER_NON_IDR_DONE)) {
                        wq->output_size = READ_HREG(HCODEC_VLC_TOTAL_BYTES);
+
                        if (request->flush_flag & AMVENC_FLUSH_FLAG_OUTPUT) {
-                               buf_start = getbuffer(wq,
-                                       ENCODER_BUFFER_OUTPUT);
+                               buf_start = getbuffer(wq, ENCODER_BUFFER_OUTPUT);
                                cache_flush(buf_start, wq->output_size);
                        }
-                       if (request->flush_flag &
-                               AMVENC_FLUSH_FLAG_DUMP) {
-                               buf_start = getbuffer(wq,
-                                       ENCODER_BUFFER_DUMP);
+
+                       if (request->flush_flag & AMVENC_FLUSH_FLAG_DUMP) {
+                               buf_start = getbuffer(wq, ENCODER_BUFFER_DUMP);
                                size = wq->mem.dump_info_ddr_size;
                                cache_flush(buf_start, size);
-                       //enc_pr(LOG_DEBUG, "CBR flush dump_info done");
+                               //enc_pr(LOG_DEBUG, "CBR flush dump_info done");
                        }
-                       if (request->flush_flag &
-                               AMVENC_FLUSH_FLAG_REFERENCE) {
+
+                       if (request->flush_flag & AMVENC_FLUSH_FLAG_REFERENCE) {
                                u32 ref_id = ENCODER_BUFFER_REF0;
 
-                               if ((wq->mem.ref_buf_canvas & 0xff) ==
-                                       (ENC_CANVAS_OFFSET))
+                               if ((wq->mem.ref_buf_canvas & 0xff) == (ENC_CANVAS_OFFSET))
                                        ref_id = ENCODER_BUFFER_REF0;
                                else
                                        ref_id = ENCODER_BUFFER_REF1;
+
                                buf_start = getbuffer(wq, ref_id);
                                cache_flush(buf_start, flush_size);
                        }
@@ -3581,7 +3738,7 @@ Again:
                        manager->encode_hw_status = ENCODER_ERROR;
                        enc_pr(LOG_DEBUG, "avc encode light reset --- ");
                        enc_pr(LOG_DEBUG,
-                               "frame type: %s, size: %dx%d, wq: %p\n",
+                               "frame type: %s, size: %dx%d, wq: %px\n",
                                (request->cmd == ENCODER_IDR) ? "IDR" : "P",
                                wq->pic.encoder_width,
                                wq->pic.encoder_height, (void *)wq);
@@ -3598,6 +3755,7 @@ Again:
                                READ_HREG(DEBUG_REG));
                        amvenc_avc_light_reset(wq, 30);
                }
+
                for (i = 0; i < request->plane_num; i++) {
                        cfg = &request->dma_cfg[i];
                        enc_pr(LOG_INFO, "request vaddr %p, paddr %p\n",
@@ -3642,6 +3800,7 @@ s32 encode_wq_add_request(struct encode_wq_s *wq)
 
        pitem = list_entry(encode_manager.free_queue.next,
                struct encode_queue_item_s, list);
+
        if (IS_ERR(pitem))
                goto error;
 
@@ -3843,6 +4002,7 @@ static s32 encode_monitor_thread(void *data)
        enc_pr(LOG_DEBUG, "encode workqueue monitor start.\n");
        sched_setscheduler(current, SCHED_FIFO, &param);
        allow_signal(SIGTERM);
+
        /* setup current_wq here. */
        while (manager->process_queue_state != ENCODE_PROCESS_QUEUE_STOP) {
                if (kthread_should_stop())
@@ -3856,14 +4016,17 @@ static s32 encode_monitor_thread(void *data)
 
                if (kthread_should_stop())
                        break;
+
                if (manager->inited == false) {
                        spin_lock(&manager->event.sem_lock);
+
                        if (!list_empty(&manager->wq)) {
                                struct encode_wq_s *first_wq =
                                        list_entry(manager->wq.next,
                                        struct encode_wq_s, list);
                                manager->current_wq = first_wq;
                                spin_unlock(&manager->event.sem_lock);
+
                                if (first_wq) {
 #ifdef CONFIG_AMLOGIC_MEDIA_GE2D
                                        if (!manager->context)
@@ -3889,16 +4052,19 @@ static s32 encode_monitor_thread(void *data)
 
                spin_lock(&manager->event.sem_lock);
                pitem = NULL;
+
                if (list_empty(&manager->wq)) {
                        spin_unlock(&manager->event.sem_lock);
                        manager->inited = false;
                        amvenc_avc_stop();
+
 #ifdef CONFIG_AMLOGIC_MEDIA_GE2D
                        if (manager->context) {
                                destroy_ge2d_work_queue(manager->context);
                                manager->context = NULL;
                        }
 #endif
+
                        enc_pr(LOG_DEBUG, "power off encode.\n");
                        continue;
                } else if (!list_empty(&manager->process_queue)) {
@@ -3908,6 +4074,7 @@ static s32 encode_monitor_thread(void *data)
                        manager->current_item = pitem;
                        manager->current_wq = pitem->request.parent;
                }
+
                spin_unlock(&manager->event.sem_lock);
 
                if (pitem) {
@@ -3919,6 +4086,7 @@ static s32 encode_monitor_thread(void *data)
                        manager->current_wq = NULL;
                        spin_unlock(&manager->event.sem_lock);
                }
+
                if (manager->remove_flag) {
                        complete(&manager->event.process_complete);
                        manager->remove_flag = false;
@@ -4298,7 +4466,7 @@ static s32 amvenc_avc_probe(struct platform_device *pdev)
        s32 idx;
        s32 r;
 
-       enc_pr(LOG_INFO, "amvenc_avc probe start.\n");
+       enc_pr(LOG_ERROR, "amvenc_avc probe start.\n");
 
        encode_manager.this_pdev = pdev;
 #ifdef CONFIG_CMA
@@ -4311,11 +4479,13 @@ static s32 amvenc_avc_probe(struct platform_device *pdev)
        encode_manager.reserve_buff = NULL;
 
        idx = of_reserved_mem_device_init(&pdev->dev);
+
        if (idx != 0) {
                enc_pr(LOG_DEBUG,
                        "amvenc_avc_probe -- reserved memory config fail.\n");
        }
 
+
        if (encode_manager.use_reserve == false) {
 #ifndef CONFIG_CMA
                enc_pr(LOG_ERROR,
@@ -4331,6 +4501,19 @@ static s32 amvenc_avc_probe(struct platform_device *pdev)
 #endif
        }
 
+       if (hcodec_clk_prepare(&pdev->dev, &s_hcodec_clks)) {
+               //err = -ENOENT;
+               enc_pr(LOG_ERROR, "[%s:%d] probe hcodec enc failed\n", __FUNCTION__, __LINE__);
+               //goto ERROR_PROBE_DEVICE;
+               return -EINVAL;
+       }
+
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               hcodec_rst = devm_reset_control_get(&pdev->dev, "hcodec_rst");
+               if (IS_ERR(hcodec_rst))
+                       pr_err("amvenc probe, hcodec get reset failed: %ld\n", PTR_ERR(hcodec_rst));
+       }
+
        res_irq = platform_get_irq(pdev, 0);
        if (res_irq < 0) {
                enc_pr(LOG_ERROR, "[%s] get irq error!", __func__);
@@ -4357,6 +4540,7 @@ static s32 amvenc_avc_remove(struct platform_device *pdev)
        if (encode_wq_uninit())
                enc_pr(LOG_ERROR, "encode work queue uninit error.\n");
        uninit_avc_device();
+       hcodec_clk_unprepare(&pdev->dev, &s_hcodec_clks);
        enc_pr(LOG_INFO, "amvenc_avc remove.\n");
        return 0;
 }
@@ -4564,6 +4748,12 @@ MODULE_PARM_DESC(nr_mode, "\n nr_mode option\n");
 module_param(qp_table_debug, uint, 0664);
 MODULE_PARM_DESC(qp_table_debug, "\n print qp table\n");
 
+module_param(use_reset_control, uint, 0664);
+MODULE_PARM_DESC(use_reset_control, "\n use_reset_control\n");
+
+module_param(use_ge2d, uint, 0664);
+MODULE_PARM_DESC(use_ge2d, "\n use_ge2d\n");
+
 #ifdef H264_ENC_SVC
 module_param(svc_enable, uint, 0664);
 MODULE_PARM_DESC(svc_enable, "\n svc enable\n");
index 40b47d0586966487bb9d18857c7818aaba8bc95e..f1d4bc0ccf8b2459460c36e8924c837243051ed9 100644 (file)
 #include <linux/of_reserved_mem.h>
 #include <linux/of_address.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/cpu_version.h>
+#include <linux/version.h>
+#include "../../../frame_provider/decoder/utils/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>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,1)
+#include <linux/sched/signal.h>
+#endif
 
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "../../../common/media_clock/switch/amports_gate.h"
@@ -52,6 +62,9 @@
 /* if you want to have clock gating scheme frame by frame */
 /* #define VPU_SUPPORT_CLOCK_CONTROL */
 
+#define VPU_SUPPORT_CLOCK_CONTROL
+
+
 #define VPU_PLATFORM_DEVICE_NAME "HevcEnc"
 #define VPU_DEV_NAME "HevcEnc"
 #define VPU_CLASS_NAME "HevcEnc"
@@ -60,6 +73,8 @@
 #define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
 #endif
 
+#define MHz (1000000)
+
 #define VPU_INIT_VIDEO_MEMORY_SIZE_IN_BYTE (64 * SZ_1M)
 
 #define LOG_ALL 0
 static s32 print_level = LOG_DEBUG;
 static s32 clock_level = 4;
 
+static s32 wave_clocka;
+static s32 wave_clockb;
+static s32 wave_clockc;
+
 static struct video_mm_t s_vmem;
 static struct vpudrv_buffer_t s_video_memory = {0};
 static bool use_reserve;
@@ -108,6 +127,18 @@ static struct vpu_bit_firmware_info_t s_bit_firmware_info[MAX_NUM_VPU_CORE];
 
 static struct vpu_dma_cfg dma_cfg[3];
 
+struct vpu_clks {
+       struct clk *wave_aclk;
+       struct clk *wave_bclk;
+       struct clk *wave_cclk;
+};
+
+static struct vpu_clks s_vpu_clks;
+
+#define CHECK_RET(_ret) if (ret) {enc_pr(LOG_ERROR, \
+               "%s:%d:function call failed with result: %d\n",\
+               __FUNCTION__, __LINE__, _ret);}
+
 static u32 vpu_src_addr_config(struct vpu_dma_buf_info_t);
 static void vpu_dma_buffer_unmap(struct vpu_dma_cfg *cfg);
 
@@ -133,17 +164,84 @@ s32 vpu_hw_reset(void)
        return 0;
 }
 
+s32 vpu_clk_prepare(struct device *dev, struct vpu_clks *clks)
+{
+       int ret;
+
+       s32 new_clocka = 667;
+       s32 new_clockb = 400;
+       s32 new_clockc = 400;
+
+       if (wave_clocka > 0)
+               new_clocka = wave_clocka;
+       if (wave_clockb > 0)
+               new_clockb = wave_clockb;
+       if (wave_clockc > 0)
+               new_clockc = wave_clockc;
+
+       clks->wave_aclk = devm_clk_get(dev, "cts_wave420_aclk");
+       if (IS_ERR_OR_NULL(clks->wave_aclk)) {
+               enc_pr(LOG_ERROR, "failed to get wave aclk\n");
+               return -1;
+       }
+
+       clks->wave_bclk = devm_clk_get(dev, "cts_wave420_bclk");
+       if (IS_ERR_OR_NULL(clks->wave_aclk)) {
+               enc_pr(LOG_ERROR, "failed to get wave aclk\n");
+               return -1;
+       }
+
+       clks->wave_cclk = devm_clk_get(dev, "cts_wave420_cclk");
+       if (IS_ERR_OR_NULL(clks->wave_aclk)) {
+               enc_pr(LOG_ERROR, "failed to get wave aclk\n");
+               return -1;
+       }
+
+       ret = clk_set_rate(clks->wave_aclk, new_clocka * MHz);
+       CHECK_RET(ret);
+       ret = clk_set_rate(clks->wave_bclk, new_clockb * MHz);
+       CHECK_RET(ret);
+       ret = clk_set_rate(clks->wave_cclk, new_clockc * MHz);
+
+       CHECK_RET(ret);
+       ret = clk_prepare(clks->wave_aclk);
+       CHECK_RET(ret);
+       ret = clk_prepare(clks->wave_bclk);
+       CHECK_RET(ret);
+       ret = clk_prepare(clks->wave_cclk);
+       CHECK_RET(ret);
+
+       enc_pr(LOG_ERROR, "wave_clk_a: %lu MHz\n", clk_get_rate(clks->wave_aclk) / 1000000);
+       enc_pr(LOG_ERROR, "wave_clk_b: %lu MHz\n", clk_get_rate(clks->wave_bclk) / 1000000);
+       enc_pr(LOG_ERROR, "wave_clk_c: %lu MHz\n", clk_get_rate(clks->wave_cclk) / 1000000);
+
+       return 0;
+}
+
+void vpu_clk_unprepare(struct device *dev, struct vpu_clks *clks)
+{
+       clk_unprepare(clks->wave_cclk);
+       devm_clk_put(dev, clks->wave_cclk);
+
+       clk_unprepare(clks->wave_bclk);
+       devm_clk_put(dev, clks->wave_bclk);
+
+       clk_unprepare(clks->wave_aclk);
+       devm_clk_put(dev, clks->wave_aclk);
+}
+
 s32 vpu_clk_config(u32 enable)
 {
        if (enable) {
-               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
-                       HevcEnc_MoreClock_enable();
-               HevcEnc_clock_enable(clock_level);
+               clk_enable(s_vpu_clks.wave_aclk);
+               clk_enable(s_vpu_clks.wave_bclk);
+               clk_enable(s_vpu_clks.wave_cclk);
        } else {
-               HevcEnc_clock_disable();
-               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
-                       HevcEnc_MoreClock_disable();
+               clk_disable(s_vpu_clks.wave_cclk);
+               clk_disable(s_vpu_clks.wave_bclk);
+               clk_disable(s_vpu_clks.wave_aclk);
        }
+
        return 0;
 }
 
@@ -387,12 +485,18 @@ static s32 vpu_open(struct inode *inode, struct file *filp)
                        }
                        s_vpu_irq_requested = true;
                }
-               amports_switch_gate("vdec", 1);
+
                spin_lock_irqsave(&s_vpu_lock, flags);
-               WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
-                       READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
-                       (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
-                       ? ~0x8 : ~(0x3<<24)));
+
+               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+                       //vpu_clk_config(1);
+                       pwr_ctrl_psci_smc(PDID_DOS_WAVE, PWR_ON);
+               } else {
+                       WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+                               READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
+                               (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
+                               ? ~0x8 : ~(0x3<<24)));
+               }
                udelay(10);
 
                if (get_cpu_type() <= MESON_CPU_MAJOR_ID_TXLX) {
@@ -409,12 +513,17 @@ static s32 vpu_open(struct inode *inode, struct file *filp)
                        WRITE_VREG(DOS_SW_RESET4, data32);
                }
 
-               WRITE_MPEG_REG(RESET0_REGISTER, data32 & ~(1<<21));
-               WRITE_MPEG_REG(RESET0_REGISTER, data32 | (1<<21));
-               READ_MPEG_REG(RESET0_REGISTER);
-               READ_MPEG_REG(RESET0_REGISTER);
-               READ_MPEG_REG(RESET0_REGISTER);
-               READ_MPEG_REG(RESET0_REGISTER);
+               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+                       pr_err("consider using reset control\n");
+               } else {
+                       WRITE_MPEG_REG(RESET0_REGISTER, data32 & ~(1<<21));
+                       WRITE_MPEG_REG(RESET0_REGISTER, data32 | (1<<21));
+                       READ_MPEG_REG(RESET0_REGISTER);
+                       READ_MPEG_REG(RESET0_REGISTER);
+                       READ_MPEG_REG(RESET0_REGISTER);
+                       READ_MPEG_REG(RESET0_REGISTER);
+               }
+
 #ifndef VPU_SUPPORT_CLOCK_CONTROL
                vpu_clk_config(1);
 #endif
@@ -424,12 +533,14 @@ static s32 vpu_open(struct inode *inode, struct file *filp)
                WRITE_VREG(DOS_WAVE420L_CNTL_STAT, 0x1);
                WRITE_VREG(DOS_MEM_PD_WAVE420L, 0x0);
 
-               WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
-                       READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
-                       (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
-                       ? ~0x8 : ~(0x3<<12)));
-               udelay(10);
+               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
 
+               } else {
+                       WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+                               READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
+                               (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
+                               ? ~0x8 : ~(0x3<<12)));
+               }
                spin_unlock_irqrestore(&s_vpu_lock, flags);
        }
        memset(dma_cfg, 0, sizeof(dma_cfg));
@@ -1415,28 +1526,41 @@ static s32 vpu_release(struct inode *inode, struct file *filp)
                                memset(&s_vmem,
                                        0, sizeof(struct video_mm_t));
                        }
+
                        if ((s_vpu_irq >= 0) && (s_vpu_irq_requested == true)) {
                                free_irq(s_vpu_irq, &s_vpu_drv_context);
                                s_vpu_irq_requested = false;
                        }
                        spin_lock_irqsave(&s_vpu_lock, flags);
-                       WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
-                               READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
-                               (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
-                               ? 0x8 : (0x3<<12)));
+
+                       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+                               //vpu_clk_config(0);
+                               pwr_ctrl_psci_smc(PDID_DOS_WAVE, PWR_OFF);
+                       } else {
+                               WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
+                                       READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
+                                       (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
+                                       ? 0x8 : (0x3<<12)));
+                       }
+
                        udelay(10);
 
                        WRITE_VREG(DOS_MEM_PD_WAVE420L, 0xffffffff);
 #ifndef VPU_SUPPORT_CLOCK_CONTROL
                        vpu_clk_config(0);
 #endif
-                       WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
-                               READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
-                               (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
-                               ? 0x8 : (0x3<<24)));
+
+                       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+
+                       } else {
+                               WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
+                                       READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
+                                       (get_cpu_type() == MESON_CPU_MAJOR_ID_SM1
+                                       ? 0x8 : (0x3<<24)));
+                       }
+
                        udelay(10);
                        spin_unlock_irqrestore(&s_vpu_lock, flags);
-                       amports_switch_gate("vdec", 0);
                }
        }
        up(&s_vpu_sem);
@@ -1736,6 +1860,7 @@ static ssize_t hevcenc_status_show(struct class *cla,
        return snprintf(buf, 40, "hevcenc_status_show\n");
 }
 
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(4,13,1)
 static struct class_attribute hevcenc_class_attrs[] = {
        __ATTR(encode_status,
        S_IRUGO | S_IWUSR,
@@ -1748,6 +1873,23 @@ static struct class hevcenc_class = {
        .name = VPU_CLASS_NAME,
        .class_attrs = hevcenc_class_attrs,
 };
+#else /* LINUX_VERSION_CODE <= KERNEL_VERSION(4,13,1) */
+
+static CLASS_ATTR_RO(hevcenc_status);
+
+static struct attribute *hevcenc_class_attrs[] = {
+       &class_attr_hevcenc_status.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(hevcenc_class);
+
+static struct class hevcenc_class = {
+       .name = VPU_CLASS_NAME,
+       .class_groups = hevcenc_class_groups,
+};
+#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(4,13,1) */
+
 
 s32 init_HevcEnc_device(void)
 {
@@ -1823,7 +1965,8 @@ static s32 vpu_probe(struct platform_device *pdev)
        struct resource res;
        struct device_node *np, *child;
 
-       enc_pr(LOG_DEBUG, "vpu_probe\n");
+       enc_pr(LOG_DEBUG, "vpu_probe, clock_a: %d, clock_b: %d, clock_c: %d\n",
+               wave_clocka, wave_clockb, wave_clockc);
 
        s_vpu_major = 0;
        use_reserve = false;
@@ -1840,6 +1983,7 @@ static s32 vpu_probe(struct platform_device *pdev)
        memset(&res, 0, sizeof(struct resource));
 
        idx = of_reserved_mem_device_init(&pdev->dev);
+
        if (idx != 0) {
                enc_pr(LOG_DEBUG,
                        "HevcEnc reserved memory config fail.\n");
@@ -1896,8 +2040,12 @@ static s32 vpu_probe(struct platform_device *pdev)
        s_vpu_clk = clk;
 #endif
 
-#ifdef VPU_SUPPORT_CLOCK_CONTROL
-#else
+       if (vpu_clk_prepare(&pdev->dev, &s_vpu_clks)) {
+               err = -ENOENT;
+               goto ERROR_PROVE_DEVICE;
+       }
+
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
        vpu_clk_config(1);
 #endif
 
@@ -1947,7 +2095,7 @@ static s32 vpu_probe(struct platform_device *pdev)
                enc_pr(LOG_ERROR, "could not allocate major number\n");
                goto ERROR_PROVE_DEVICE;
        }
-       enc_pr(LOG_INFO, "SUCCESS alloc_chrdev_region\n");
+       enc_pr(LOG_DEBUG, "SUCCESS alloc_chrdev_region\n");
 
        init_waitqueue_head(&s_interrupt_wait_q);
        tasklet_init(&hevc_tasklet,
@@ -1986,7 +2134,10 @@ ERROR_PROVE_DEVICE:
                memset(&s_vmem, 0, sizeof(struct video_mm_t));
        }
 
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
        vpu_clk_config(0);
+#endif
+       vpu_clk_unprepare(&pdev->dev, &s_vpu_clks);
 
        if (s_vpu_irq_requested == true) {
                if (s_vpu_irq >= 0) {
@@ -2040,8 +2191,10 @@ static s32 vpu_remove(struct platform_device *pdev)
                        0, sizeof(struct vpudrv_buffer_t));
        }
        hevc_pdev = NULL;
+#ifndef VPU_SUPPORT_CLOCK_CONTROL
        vpu_clk_config(0);
-
+#endif
+       vpu_clk_unprepare(&pdev->dev, &s_vpu_clks);
        uninit_HevcEnc_device();
        return 0;
 }
@@ -2230,7 +2383,8 @@ static s32 __init vpu_init(void)
                && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A)
                        && (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX)
                                && (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B)
-                               && (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) {
+                               && (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)
+                               && (get_cpu_type() != MESON_CPU_MAJOR_ID_SC2)) {
                enc_pr(LOG_DEBUG,
                        "The chip is not support hevc encoder\n");
                return -1;
@@ -2256,6 +2410,7 @@ static void __exit vpu_exit(void)
                (get_cpu_type() != MESON_CPU_MAJOR_ID_G12A) &&
                (get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX) &&
                (get_cpu_type() != MESON_CPU_MAJOR_ID_G12B) &&
+               (get_cpu_type() != MESON_CPU_MAJOR_ID_SC2) &&
                (get_cpu_type() != MESON_CPU_MAJOR_ID_SM1)) {
                enc_pr(LOG_INFO,
                        "The chip is not support hevc encoder\n");
@@ -2281,10 +2436,19 @@ MODULE_PARM_DESC(print_level, "\n print_level\n");
 module_param(clock_level, uint, 0664);
 MODULE_PARM_DESC(clock_level, "\n clock_level\n");
 
+module_param(wave_clocka, uint, 0664);
+MODULE_PARM_DESC(wave_clocka, "\n wave_clocka\n");
+
+module_param(wave_clockb, uint, 0664);
+MODULE_PARM_DESC(wave_clockb, "\n wave_clockb\n");
+
+module_param(wave_clockc, uint, 0664);
+MODULE_PARM_DESC(wave_clockc, "\n wave_clockc\n");
+
 MODULE_AUTHOR("Amlogic using C&M VPU, Inc.");
 MODULE_DESCRIPTION("VPU linux driver");
 MODULE_LICENSE("GPL");
 
 module_init(vpu_init);
 module_exit(vpu_exit);
-RESERVEDMEM_OF_DECLARE(cnm_hevc, "cnm, HevcEnc-memory", hevc_mem_setup);
+RESERVEDMEM_OF_DECLARE(amlogic, "amlogic, HevcEnc-memory", hevc_mem_setup);
index 0052fd287d914409d2b8993529a06c33e99dd8f8..8878fc91cb4b7461a98018ab4968aeffcaf2de21 100644 (file)
  * more details.
  *
 */
-
+#define LOG_LINE() pr_err("[%s:%d]\n", __FUNCTION__, __LINE__);
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include "../../../frame_provider/decoder/utils/firmware.h"
 #include "../../../frame_provider/decoder/utils/amvdec.h"
 #include "jpegenc.h"
+
+#include "../../../frame_provider/decoder/utils/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/utils/amlog.h>
 //#include "amports_priv.h"
 #include <linux/of_reserved_mem.h>
@@ -76,7 +85,7 @@
 
 static s32 jpegenc_device_major;
 static struct device *jpegenc_dev;
-static u32 jpegenc_print_level = LOG_DEBUG;
+static u32 jpegenc_print_level = 0;
 
 static u32 clock_level = 1;
 static u16 gQuantTable[2][DCTSIZE2];
@@ -95,6 +104,86 @@ static DEFINE_SPINLOCK(lock);
 #define JPEGENC_BUFFER_LEVEL_13M   5
 #define JPEGENC_BUFFER_LEVEL_HD     6
 
+
+#define MHz (1000000)
+
+#define CHECK_RET(_ret) if (ret) {pr_err(\
+               "%s:%d:function call failed with result: %d\n",\
+               __FUNCTION__, __LINE__, _ret);}
+
+
+struct jpegenc_clks {
+       struct clk *jpegenc_aclk;
+       //struct clk *hcodec_bclk;
+       //struct clk *hcodec_cclk;
+};
+
+static struct jpegenc_clks s_jpegenc_clks;
+struct reset_control *jpegenc_rst;
+
+/*
+s32 jpegenc_hw_reset(void)
+{
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               reset_control_reset(jpegenc_rst);
+               pr_err("request jpegenc reset from application.\n");
+       }
+       return 0;
+}
+*/
+
+s32 jpegenc_clk_prepare(struct device *dev, struct jpegenc_clks *clks)
+{
+       int ret;
+
+       clks->jpegenc_aclk = devm_clk_get(dev, "cts_jpegenc_aclk");
+
+       if (IS_ERR_OR_NULL(clks->jpegenc_aclk)) {
+               pr_err("failed to get jpegenc aclk: %px, %ld, dev=%px\n",
+                               clks->jpegenc_aclk,
+                               PTR_ERR(clks->jpegenc_aclk),
+                               dev);
+               return -1;
+       }
+
+       ret = clk_set_rate(clks->jpegenc_aclk, 667 * MHz);
+       CHECK_RET(ret);
+
+       ret = clk_prepare(clks->jpegenc_aclk);
+       CHECK_RET(ret);
+
+       pr_err("jpegenc_clk_a: %lu MHz\n", clk_get_rate(clks->jpegenc_aclk) / 1000000);
+
+       return 0;
+}
+
+void jpegenc_clk_unprepare(struct device *dev, struct jpegenc_clks *clks)
+{
+       clk_unprepare(clks->jpegenc_aclk);
+       devm_clk_put(dev, clks->jpegenc_aclk);
+
+       //clk_unprepare(clks->wave_bclk);
+       //devm_clk_put(dev, clks->wave_bclk);
+
+       //clk_unprepare(clks->wave_aclk);
+       //devm_clk_put(dev, clks->wave_aclk);
+}
+
+static s32 jpegenc_clk_config(u32 enable)
+{
+       if (enable) {
+               clk_enable(s_jpegenc_clks.jpegenc_aclk);
+               //clk_enable(s_hcodec_clks.wave_bclk);
+               //clk_enable(s_hcodec_clks.wave_cclk);
+       } else {
+               clk_disable(s_jpegenc_clks.jpegenc_aclk);
+               //clk_disable(s_hcodec_clks.wave_bclk);
+               //clk_disable(s_hcodec_clks.wave_aclk);
+       }
+
+       return 0;
+}
+
 const s8 *glevel_str[] = {
        "VGA",
        "2M",
@@ -2358,8 +2447,14 @@ static void mfdin_basic_jpeg(
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB) {
                reg_offset = -8;
-               WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
-                       (picsize_x << 14) | (picsize_y << 0));
+               
+               if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+                       WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
+                               (picsize_x << 16) | (picsize_y << 0));
+               } else {
+                       WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
+                               (picsize_x << 14) | (picsize_y << 0));
+               }
        } else {
                reg_offset = 0;
                WRITE_HREG((HCODEC_MFDIN_REG8_DMBL + reg_offset),
@@ -2606,6 +2701,7 @@ static void jpegenc_isr_tasklet(ulong data)
 static irqreturn_t jpegenc_isr(s32 irq_number, void *para)
 {
        struct jpegenc_manager_s *manager = (struct jpegenc_manager_s *)para;
+       jenc_pr(LOG_INFO, "*****JPEGENC_ISR*****");
        WRITE_HREG(HCODEC_ASSIST_MBOX2_CLR_REG, 1);
        manager->encode_hw_status  = READ_HREG(JPEGENC_ENCODER_STATUS);
        if (manager->encode_hw_status == JPEGENC_ENCODER_DONE) {
@@ -2620,16 +2716,15 @@ static void jpegenc_start(void)
        READ_VREG(DOS_SW_RESET1);
        READ_VREG(DOS_SW_RESET1);
        READ_VREG(DOS_SW_RESET1);
-
        WRITE_VREG(DOS_SW_RESET1, (1 << 12) | (1 << 11));
        WRITE_VREG(DOS_SW_RESET1, 0);
-
        READ_VREG(DOS_SW_RESET1);
        READ_VREG(DOS_SW_RESET1);
        READ_VREG(DOS_SW_RESET1);
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB)
                WRITE_HREG((HCODEC_MFDIN_REG7_SCMD - 8), (1 << 28)),
+
        WRITE_HREG(HCODEC_MPSR, 0x0001);
 }
 
@@ -2731,6 +2826,7 @@ s32 jpegenc_loadmc(const char *p)
        return ret;
 }
 
+/*
 bool jpegenc_on(void)
 {
        bool hcodec_on;
@@ -2744,7 +2840,7 @@ bool jpegenc_on(void)
        spin_unlock_irqrestore(&lock, flags);
        return hcodec_on;
 }
-
+*/
 static s32 jpegenc_poweron(u32 clock)
 {
        ulong flags;
@@ -2756,7 +2852,13 @@ static s32 jpegenc_poweron(u32 clock)
 
        spin_lock_irqsave(&lock, flags);
 
-       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) {
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               jpegenc_clk_config(1);
+
+               pwr_ctrl_psci_smc(PDID_DOS_HCODEC, PWR_ON);
+
+               //hvdec_clock_enable(clock);
+       } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) {
                WRITE_AOREG(AO_RTI_PWR_CNTL_REG0,
                        (READ_AOREG(AO_RTI_PWR_CNTL_REG0) & (~0x18)));
                udelay(10);
@@ -2804,7 +2906,12 @@ static s32 jpegenc_poweroff(void)
 
        spin_lock_irqsave(&lock, flags);
 
-       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) {
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               jpegenc_clk_config(0);
+               pwr_ctrl_psci_smc(PDID_DOS_HCODEC, PWR_OFF);
+               //hvdec_clock_disable();
+               LOG_LINE();
+       } else if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) {
                /* enable HCODEC isolation */
                WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
                        READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30);
@@ -3522,6 +3629,21 @@ static s32 jpegenc_probe(struct platform_device *pdev)
                return -EFAULT;
        }
 
+       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+               if (jpegenc_clk_prepare(&pdev->dev, &s_jpegenc_clks)) {
+                       //err = -ENOENT;
+                       pr_err("[%s:%d] prepare jpegenc clk failed\n", __FUNCTION__, __LINE__);
+                       //goto ERROR_PROBE_DEVICE;
+                       return -EINVAL;
+               }
+       }
+
+       //if (get_cpu_type() >= MESON_CPU_MAJOR_ID_SC2) {
+       //      jpegenc_rst = devm_reset_control_get(&pdev->dev, "jpegenc_rst");
+       //      if (IS_ERR(jpegenc_rst))
+       //              pr_err("amvenc probe, jpegenc get reset failed: %ld\n", PTR_ERR(jpegenc_rst));
+       //}
+
        res_irq = platform_get_irq(pdev, 0);
        if (res_irq < 0) {
                jenc_pr(LOG_ERROR, "[%s] get irq error!", __func__);