From: Rico Yang Date: Fri, 3 Jul 2020 13:45:33 +0000 (+0800) Subject: media_modules: sc2 encoder bringup [1/1] X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=5054b6df8bcdb0badae4ebe1acbc9b7ab67a4270;p=GitHub%2FLineageOS%2FG12%2Fandroid_hardware_amlogic_kernel-modules_media.git media_modules: sc2 encoder bringup [1/1] PD#SWPL-25846 Problem: sc2 bringup Solution: sc2 bringup Verify: verified on AH219 #Signed-off-by: Rico Yang #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 #Change-Id: I6f1b6b067ca5196476cc674540e0ef079c52530f Signed-off-by: Rico Yang Change-Id: Ie7f65deda5e580424f7e593115feb98181733581 --- diff --git a/drivers/frame_sink/encoder/h264/encoder.c b/drivers/frame_sink/encoder/h264/encoder.c index 49a7088..549788d 100644 --- a/drivers/frame_sink/encoder/h264/encoder.c +++ b/drivers/frame_sink/encoder/h264/encoder.c @@ -15,14 +15,17 @@ * */ +#define LOG_LINE() pr_err("[%s:%d]\n", __FUNCTION__, __LINE__); #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -45,6 +48,12 @@ #include #include "encoder.h" #include "../../../frame_provider/decoder/utils/amvdec.h" +#include "../../../frame_provider/decoder/utils/vdec_power_ctrl.h" +#include +#include +#include +#include + #include #include "../../../stream_input/amports/amports_priv.h" #include "../../../frame_provider/decoder/utils/firmware.h" @@ -55,6 +64,12 @@ #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, ¶m); 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"); diff --git a/drivers/frame_sink/encoder/h265/vpu.c b/drivers/frame_sink/encoder/h265/vpu.c index 40b47d0..f1d4bc0 100644 --- a/drivers/frame_sink/encoder/h265/vpu.c +++ b/drivers/frame_sink/encoder/h265/vpu.c @@ -41,6 +41,16 @@ #include #include #include +#include +#include +#include "../../../frame_provider/decoder/utils/vdec_power_ctrl.h" +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,1) +#include +#endif #include #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 @@ -76,6 +91,10 @@ 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); diff --git a/drivers/frame_sink/encoder/jpeg/jpegenc.c b/drivers/frame_sink/encoder/jpeg/jpegenc.c index 0052fd2..8878fc9 100644 --- a/drivers/frame_sink/encoder/jpeg/jpegenc.c +++ b/drivers/frame_sink/encoder/jpeg/jpegenc.c @@ -14,12 +14,14 @@ * more details. * */ - +#define LOG_LINE() pr_err("[%s:%d]\n", __FUNCTION__, __LINE__); #include #include #include #include #include +#include +#include #include #include #include @@ -43,6 +45,13 @@ #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 +#include +#include +#include + #include //#include "amports_priv.h" #include @@ -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__);