summaryrefslogtreecommitdiff
authorRico Yang <wei.yang@amlogic.com>2020-07-03 13:45:33 (GMT)
committer Zhi Zhou <zhi.zhou@amlogic.com>2020-07-28 03:28:59 (GMT)
commit5054b6df8bcdb0badae4ebe1acbc9b7ab67a4270 (patch)
treefd69bb4421af5b9a07a221891e3de1b736538f8e
parentaab26b14f6b78a6f2fc8b4f48be9ab4875d50236 (diff)
downloadmedia_modules-5054b6df8bcdb0badae4ebe1acbc9b7ab67a4270.zip
media_modules-5054b6df8bcdb0badae4ebe1acbc9b7ab67a4270.tar.gz
media_modules-5054b6df8bcdb0badae4ebe1acbc9b7ab67a4270.tar.bz2
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 <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
Diffstat
-rw-r--r--drivers/frame_sink/encoder/h264/encoder.c372
-rw-r--r--drivers/frame_sink/encoder/h265/vpu.c240
-rw-r--r--drivers/frame_sink/encoder/jpeg/jpegenc.c140
3 files changed, 614 insertions, 138 deletions
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 <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>
@@ -45,6 +48,12 @@
#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"
@@ -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, &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");
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 <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
@@ -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 <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>
@@ -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 <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__);